18
18
19
19
package resolver
20
20
21
+ import (
22
+ "encoding/base64"
23
+ "sort"
24
+ "strings"
25
+ )
26
+
21
27
type addressMapEntry struct {
22
28
addr Address
23
29
value any
@@ -137,66 +143,61 @@ func (a *AddressMap) Values() []any {
137
143
return ret
138
144
}
139
145
140
- type endpointNode struct {
141
- addrs map [string ]struct {}
142
- }
143
-
144
- // Equal returns whether the unordered set of addrs are the same between the
145
- // endpoint nodes.
146
- func (en * endpointNode ) Equal (en2 * endpointNode ) bool {
147
- if len (en .addrs ) != len (en2 .addrs ) {
148
- return false
149
- }
150
- for addr := range en .addrs {
151
- if _ , ok := en2 .addrs [addr ]; ! ok {
152
- return false
153
- }
154
- }
155
- return true
156
- }
157
-
158
- func toEndpointNode (endpoint Endpoint ) endpointNode {
159
- en := make (map [string ]struct {})
160
- for _ , addr := range endpoint .Addresses {
161
- en [addr .Addr ] = struct {}{}
162
- }
163
- return endpointNode {
164
- addrs : en ,
165
- }
166
- }
146
+ type endpointMapKey string
167
147
168
148
// EndpointMap is a map of endpoints to arbitrary values keyed on only the
169
149
// unordered set of address strings within an endpoint. This map is not thread
170
150
// safe, thus it is unsafe to access concurrently. Must be created via
171
151
// NewEndpointMap; do not construct directly.
172
152
type EndpointMap struct {
173
- endpoints map [* endpointNode ]any
153
+ endpoints map [endpointMapKey ]endpointData
154
+ }
155
+
156
+ type endpointData struct {
157
+ // decodedKey stores the original key to avoid decoding when iterating on
158
+ // EndpointMap keys.
159
+ decodedKey Endpoint
160
+ value any
174
161
}
175
162
176
163
// NewEndpointMap creates a new EndpointMap.
177
164
func NewEndpointMap () * EndpointMap {
178
165
return & EndpointMap {
179
- endpoints : make (map [* endpointNode ]any ),
166
+ endpoints : make (map [endpointMapKey ]endpointData ),
167
+ }
168
+ }
169
+
170
+ // encodeEndpoint returns a string that uniquely identifies the unordered set of
171
+ // addresses within an endpoint.
172
+ func encodeEndpoint (e Endpoint ) endpointMapKey {
173
+ addrs := make ([]string , 0 , len (e .Addresses ))
174
+ // base64 encoding the address strings restricts the characters present
175
+ // within the strings. This allows us to use a delimiter without the need of
176
+ // escape characters.
177
+ for _ , addr := range e .Addresses {
178
+ addrs = append (addrs , base64 .StdEncoding .EncodeToString ([]byte (addr .Addr )))
180
179
}
180
+ sort .Strings (addrs )
181
+ // " " should not appear in base64 encoded strings.
182
+ return endpointMapKey (strings .Join (addrs , " " ))
181
183
}
182
184
183
185
// Get returns the value for the address in the map, if present.
184
186
func (em * EndpointMap ) Get (e Endpoint ) (value any , ok bool ) {
185
- en := toEndpointNode (e )
186
- if endpoint := em . find ( en ); endpoint != nil {
187
- return em . endpoints [ endpoint ] , true
187
+ val , found := em . endpoints [ encodeEndpoint (e )]
188
+ if found {
189
+ return val . value , true
188
190
}
189
191
return nil , false
190
192
}
191
193
192
194
// Set updates or adds the value to the address in the map.
193
195
func (em * EndpointMap ) Set (e Endpoint , value any ) {
194
- en := toEndpointNode (e )
195
- if endpoint := em .find ( en ); endpoint != nil {
196
- em . endpoints [ endpoint ] = value
197
- return
196
+ en := encodeEndpoint (e )
197
+ em .endpoints [ en ] = endpointData {
198
+ decodedKey : Endpoint { Addresses : e . Addresses },
199
+ value : value ,
198
200
}
199
- em .endpoints [& en ] = value
200
201
}
201
202
202
203
// Len returns the number of entries in the map.
@@ -211,12 +212,8 @@ func (em *EndpointMap) Len() int {
211
212
// used for EndpointMap accesses.
212
213
func (em * EndpointMap ) Keys () []Endpoint {
213
214
ret := make ([]Endpoint , 0 , len (em .endpoints ))
214
- for en := range em .endpoints {
215
- var endpoint Endpoint
216
- for addr := range en .addrs {
217
- endpoint .Addresses = append (endpoint .Addresses , Address {Addr : addr })
218
- }
219
- ret = append (ret , endpoint )
215
+ for _ , en := range em .endpoints {
216
+ ret = append (ret , en .decodedKey )
220
217
}
221
218
return ret
222
219
}
@@ -225,27 +222,13 @@ func (em *EndpointMap) Keys() []Endpoint {
225
222
func (em * EndpointMap ) Values () []any {
226
223
ret := make ([]any , 0 , len (em .endpoints ))
227
224
for _ , val := range em .endpoints {
228
- ret = append (ret , val )
225
+ ret = append (ret , val . value )
229
226
}
230
227
return ret
231
228
}
232
229
233
- // find returns a pointer to the endpoint node in em if the endpoint node is
234
- // already present. If not found, nil is returned. The comparisons are done on
235
- // the unordered set of addresses within an endpoint.
236
- func (em EndpointMap ) find (e endpointNode ) * endpointNode {
237
- for endpoint := range em .endpoints {
238
- if e .Equal (endpoint ) {
239
- return endpoint
240
- }
241
- }
242
- return nil
243
- }
244
-
245
230
// Delete removes the specified endpoint from the map.
246
231
func (em * EndpointMap ) Delete (e Endpoint ) {
247
- en := toEndpointNode (e )
248
- if entry := em .find (en ); entry != nil {
249
- delete (em .endpoints , entry )
250
- }
232
+ en := encodeEndpoint (e )
233
+ delete (em .endpoints , en )
251
234
}
0 commit comments