-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathobject.go
165 lines (133 loc) · 3.97 KB
/
object.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright (c) The RPSL Go Authors.
// SPDX-License-Identifier: Apache-2.0
package rpsl
import (
"fmt"
"strings"
)
type Object struct {
Attributes []Attribute
}
// Returns a slice of unique keys present in the Object.
// If a key appears multiple times in the Object, it will only be included once in the returned slice.
func (o *Object) Keys() []string {
keyPresent := make(map[string]struct{})
keyList := make([]string, 0)
for _, attr := range o.Attributes {
if _, exists := keyPresent[attr.Name]; !exists {
keyPresent[attr.Name] = struct{}{}
keyList = append(keyList, attr.Name)
}
}
return keyList
}
// Returns the number of attributes in the Object.
func (o *Object) Len() int {
return len(o.Attributes)
}
// Returns the first value for a given key in the Object.
// If the key is not present in the Object, an empty string will be returned.
// If a key appears multiple times in the Object, only the first value will be returned.
func (o *Object) GetFirst(key string) *string {
key = strings.ToLower(key)
for _, attr := range o.Attributes {
if attr.Name == key {
return &attr.Value
}
}
return nil
}
// Returns a slice of values for a given key in the Object.
// If the key is not present in the Object, an empty slice will be returned.
// If a key appears multiple times in the Object, all values will be included in the returned slice.
func (o *Object) GetAll(key string) []string {
attributes := make([]string, 0)
for _, attr := range o.Attributes {
if attr.Name == key {
attributes = append(attributes, attr.Value)
}
}
return attributes
}
// Returns true if the Object contains a given key.
func (o *Object) Exists(key string) bool {
key = strings.ToLower(key)
for _, attr := range o.Attributes {
if attr.Name == key {
return true
}
}
return false
}
// Returns a string representation of the Object.
func (o *Object) String() string {
var str strings.Builder
var attributes []string
for _, attr := range o.Attributes {
attributes = append(attributes, attr.String())
}
str.WriteString(strings.Join(attributes, "\n"))
return str.String()
}
// Ensures that the first attribute in the Object is of a given class.
func (o *Object) EnsureClass(class string) error {
if len(o.Attributes) == 0 {
return fmt.Errorf("object has no attributes")
}
first := o.Attributes[0].Name
if first != class {
return fmt.Errorf("attribute '%s' should be the first, but found '%s' instead", class, first)
}
return nil
}
// Ensures that the Object has at least one attribute with a given key.
func (o *Object) EnsureAtLeastOne(key string) error {
if !o.Exists(key) {
return fmt.Errorf("attribute '%s' is (mandatory, multiple) but found none", key)
}
return nil
}
// Ensures that the Object has at most one attribute with a given key.
func (o *Object) EnsureAtMostOne(key string) error {
if len(o.GetAll(key)) > 1 {
return fmt.Errorf("attribute '%s' is (optional, single) but found multiple", key)
}
return nil
}
// Ensures that the Object has exactly one attribute with a given key.
func (o *Object) EnsureOne(key string) error {
if err := o.EnsureAtLeastOne(key); err != nil {
return fmt.Errorf("attribute '%s' is (mandatory, single) but found none", key)
}
if err := o.EnsureAtMostOne(key); err != nil {
return fmt.Errorf("attribute '%s' is (mandatory, single) but found multiple", key)
}
return nil
}
func parseObjects(buf string) ([]Object, error) {
objects := []Object{}
if buf == "" {
return objects, nil
}
lines := strings.Split(buf, "\n")
for i, line := range lines {
if strings.HasPrefix(line, "%") || strings.HasPrefix(line, "#") {
lines[i] = ""
}
}
buf = strings.Join(lines, "\n")
for _, part := range strings.Split(buf, "\n\n") {
part = strings.TrimPrefix(part, "\n")
part = strings.TrimSuffix(part, "\n")
if part == "" {
continue
}
attributes, err := parseAttributes(part)
if err != nil {
return nil, err
}
object := Object{Attributes: attributes}
objects = append(objects, object)
}
return objects, nil
}