-
Notifications
You must be signed in to change notification settings - Fork 14
/
filter.go
217 lines (182 loc) · 4.92 KB
/
filter.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package eacl
import (
"strconv"
v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
)
// Filter defines check conditions if request header is matched or not. Matched
// header means that request should be processed according to ContainerEACL action.
//
// Filter is compatible with v2 acl.EACLRecord.Filter message.
type Filter struct {
from FilterHeaderType
matcher Match
key filterKey
value stringEncoder
}
type staticStringer string
type u64Stringer uint64
type filterKey struct {
typ filterKeyType
str string
}
// enumeration of reserved filter keys.
type filterKeyType int
const (
_ filterKeyType = iota
fKeyObjVersion
fKeyObjID
fKeyObjContainerID
fKeyObjOwnerID
fKeyObjCreationEpoch
fKeyObjPayloadLength
fKeyObjPayloadHash
fKeyObjType
fKeyObjHomomorphicHash
fKeyObjLast // helper, used in tests
)
func (s staticStringer) EncodeToString() string {
return string(s)
}
func (u u64Stringer) EncodeToString() string {
return strconv.FormatUint(uint64(u), 10)
}
// CopyTo writes deep copy of the [Filter] to dst.
func (f Filter) CopyTo(dst *Filter) {
dst.from = f.from
dst.matcher = f.matcher
dst.key = f.key
dst.value = f.value
}
// Value returns filtered string value.
func (f Filter) Value() string {
return f.value.EncodeToString()
}
// Matcher returns filter Match type.
func (f Filter) Matcher() Match {
return f.matcher
}
// Key returns key to the filtered header.
func (f Filter) Key() string {
return f.key.String()
}
// From returns FilterHeaderType that defined which header will be filtered.
func (f Filter) From() FilterHeaderType {
return f.from
}
// ToV2 converts Filter to v2 acl.EACLRecord.Filter message.
//
// Nil Filter converts to nil.
func (f *Filter) ToV2() *v2acl.HeaderFilter {
if f == nil {
return nil
}
filter := new(v2acl.HeaderFilter)
filter.SetValue(f.value.EncodeToString())
filter.SetKey(f.key.String())
filter.SetMatchType(f.matcher.ToV2())
filter.SetHeaderType(f.from.ToV2())
return filter
}
func (k filterKey) String() string {
switch k.typ {
default:
return k.str
case fKeyObjVersion:
return v2acl.FilterObjectVersion
case fKeyObjID:
return v2acl.FilterObjectID
case fKeyObjContainerID:
return v2acl.FilterObjectContainerID
case fKeyObjOwnerID:
return v2acl.FilterObjectOwnerID
case fKeyObjCreationEpoch:
return v2acl.FilterObjectCreationEpoch
case fKeyObjPayloadLength:
return v2acl.FilterObjectPayloadLength
case fKeyObjPayloadHash:
return v2acl.FilterObjectPayloadHash
case fKeyObjType:
return v2acl.FilterObjectType
case fKeyObjHomomorphicHash:
return v2acl.FilterObjectHomomorphicHash
}
}
func (k *filterKey) fromString(s string) {
switch s {
default:
k.typ, k.str = 0, s
case v2acl.FilterObjectVersion:
k.typ, k.str = fKeyObjVersion, ""
case v2acl.FilterObjectID:
k.typ, k.str = fKeyObjID, ""
case v2acl.FilterObjectContainerID:
k.typ, k.str = fKeyObjContainerID, ""
case v2acl.FilterObjectOwnerID:
k.typ, k.str = fKeyObjOwnerID, ""
case v2acl.FilterObjectCreationEpoch:
k.typ, k.str = fKeyObjCreationEpoch, ""
case v2acl.FilterObjectPayloadLength:
k.typ, k.str = fKeyObjPayloadLength, ""
case v2acl.FilterObjectPayloadHash:
k.typ, k.str = fKeyObjPayloadHash, ""
case v2acl.FilterObjectType:
k.typ, k.str = fKeyObjType, ""
case v2acl.FilterObjectHomomorphicHash:
k.typ, k.str = fKeyObjHomomorphicHash, ""
}
}
// NewFilter creates, initializes and returns blank Filter instance.
//
// Defaults:
// - header type: HeaderTypeUnknown;
// - matcher: MatchUnknown;
// - key: "";
// - value: "".
func NewFilter() *Filter {
return NewFilterFromV2(new(v2acl.HeaderFilter))
}
// NewFilterFromV2 converts v2 acl.EACLRecord.Filter message to Filter.
func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter {
f := new(Filter)
if filter == nil {
return f
}
f.from = FilterHeaderTypeFromV2(filter.GetHeaderType())
f.matcher = MatchFromV2(filter.GetMatchType())
f.key.fromString(filter.GetKey())
f.value = staticStringer(filter.GetValue())
return f
}
// Marshal marshals Filter into a protobuf binary form.
func (f *Filter) Marshal() ([]byte, error) {
return f.ToV2().StableMarshal(nil), nil
}
// Unmarshal unmarshals protobuf binary representation of Filter.
func (f *Filter) Unmarshal(data []byte) error {
fV2 := new(v2acl.HeaderFilter)
if err := fV2.Unmarshal(data); err != nil {
return err
}
*f = *NewFilterFromV2(fV2)
return nil
}
// MarshalJSON encodes Filter to protobuf JSON format.
func (f *Filter) MarshalJSON() ([]byte, error) {
return f.ToV2().MarshalJSON()
}
// UnmarshalJSON decodes Filter from protobuf JSON format.
func (f *Filter) UnmarshalJSON(data []byte) error {
fV2 := new(v2acl.HeaderFilter)
if err := fV2.UnmarshalJSON(data); err != nil {
return err
}
*f = *NewFilterFromV2(fV2)
return nil
}
// equalFilters compares Filter with each other.
func equalFilters(f1, f2 Filter) bool {
return f1.From() == f2.From() &&
f1.Matcher() == f2.Matcher() &&
f1.Key() == f2.Key() &&
f1.Value() == f2.Value()
}