@@ -10,11 +10,12 @@ import (
10
10
"errors"
11
11
"net/netip"
12
12
13
+ "golang.org/x/exp/maps"
13
14
"golang.org/x/exp/slices"
14
15
"tailscale.com/net/tsaddr"
15
16
)
16
17
17
- func unmarshalJSON [T any ](b []byte , x * []T ) error {
18
+ func unmarshalSliceFromJSON [T any ](b []byte , x * []T ) error {
18
19
if * x != nil {
19
20
return errors .New ("already initialized" )
20
21
}
@@ -64,7 +65,7 @@ type SliceView[T ViewCloner[T, V], V StructView[T]] struct {
64
65
func (v SliceView [T , V ]) MarshalJSON () ([]byte , error ) { return json .Marshal (v .ж ) }
65
66
66
67
// UnmarshalJSON implements json.Unmarshaler.
67
- func (v * SliceView [T , V ]) UnmarshalJSON (b []byte ) error { return unmarshalJSON (b , & v .ж ) }
68
+ func (v * SliceView [T , V ]) UnmarshalJSON (b []byte ) error { return unmarshalSliceFromJSON (b , & v .ж ) }
68
69
69
70
// IsNil reports whether the underlying slice is nil.
70
71
func (v SliceView [T , V ]) IsNil () bool { return v .ж == nil }
@@ -119,7 +120,7 @@ func (v Slice[T]) MarshalJSON() ([]byte, error) {
119
120
120
121
// UnmarshalJSON implements json.Unmarshaler.
121
122
func (v * Slice [T ]) UnmarshalJSON (b []byte ) error {
122
- return unmarshalJSON (b , & v .ж )
123
+ return unmarshalSliceFromJSON (b , & v .ж )
123
124
}
124
125
125
126
// IsNil reports whether the underlying slice is nil.
@@ -332,6 +333,30 @@ func (m Map[K, V]) GetOk(k K) (V, bool) {
332
333
return v , ok
333
334
}
334
335
336
+ // MarshalJSON implements json.Marshaler.
337
+ func (m Map [K , V ]) MarshalJSON () ([]byte , error ) {
338
+ return json .Marshal (m .ж )
339
+ }
340
+
341
+ // UnmarshalJSON implements json.Unmarshaler.
342
+ // It should only be called on an uninitialized Map.
343
+ func (m * Map [K , V ]) UnmarshalJSON (b []byte ) error {
344
+ if m .ж != nil {
345
+ return errors .New ("already initialized" )
346
+ }
347
+ return json .Unmarshal (b , & m .ж )
348
+ }
349
+
350
+ // AsMap returns a shallow-clone of the underlying map.
351
+ // If V is a pointer type, it is the caller's responsibility to make sure
352
+ // the values are immutable.
353
+ func (m * Map [K , V ]) AsMap () map [K ]V {
354
+ if m == nil {
355
+ return nil
356
+ }
357
+ return maps .Clone (m .ж )
358
+ }
359
+
335
360
// MapRangeFn is the func called from a Map.Range call.
336
361
// Implementations should return false to stop range.
337
362
type MapRangeFn [K comparable , V any ] func (k K , v V ) (cont bool )
0 commit comments