1
1
package refhints
2
2
3
3
import (
4
+ "encoding/json"
4
5
"maps"
5
6
"slices"
6
7
"strings"
@@ -35,12 +36,6 @@ const (
35
36
IMPLICIT_TRUE = "true"
36
37
)
37
38
38
- func MatchType (typs ... string ) matcher.Matcher [ReferenceHint ] {
39
- return func (h ReferenceHint ) bool {
40
- return slices .Contains (typs , h .GetType ())
41
- }
42
- }
43
-
44
39
// ReferenceHints is list of hints.
45
40
// Notaion: a sequence of hint notations separated by a ;.
46
41
type ReferenceHints []ReferenceHint
@@ -50,7 +45,7 @@ func NewHints(f func(ref string, implicit ...bool) ReferenceHint, ref string, im
50
45
}
51
46
52
47
func (h * ReferenceHints ) Add (hints ... ReferenceHint ) {
53
- * h = sliceutils . AppendUniqueFunc ( * h , runtime . MatchType [ ReferenceHint ] , hints ... )
48
+ AddUnique ( h , hints ... )
54
49
}
55
50
56
51
func (h ReferenceHints ) Copy () ReferenceHints {
@@ -75,7 +70,7 @@ func (h ReferenceHints) GetReferenceHint(typs ...string) ReferenceHint {
75
70
if len (typs ) == 0 {
76
71
return nil
77
72
}
78
- hints := sliceutils . Filter (h , MatchType (typs ... ))
73
+ hints := Filter (h , MatchType (typs ... ))
79
74
if len (hints ) == 0 {
80
75
return nil
81
76
}
@@ -128,18 +123,55 @@ type ReferenceHint interface {
128
123
AsDefault () DefaultReferenceHint
129
124
}
130
125
131
- func IsImplicitHint (h ReferenceHint ) bool {
126
+ func MatchType (typs ... string ) matcher.Matcher [ReferenceHint ] {
127
+ return func (h ReferenceHint ) bool {
128
+ return slices .Contains (typs , h .GetType ())
129
+ }
130
+ }
131
+
132
+ func Equal (o ReferenceHint ) matcher.Matcher [ReferenceHint ] {
133
+ d := o .Serialize ()
134
+ return func (h ReferenceHint ) bool {
135
+ return h .Serialize () == d
136
+ }
137
+ }
138
+
139
+ func IsImplicit (h ReferenceHint ) bool {
132
140
if h == nil {
133
141
return false
134
142
}
135
143
return h .GetProperty (HINT_IMPLICIT ) == IMPLICIT_TRUE
136
144
}
137
145
138
- func FilterImplicit (hints []ReferenceHint ) ReferenceHints {
146
+ func IsExplicit (h ReferenceHint ) bool {
147
+ if h == nil {
148
+ return false
149
+ }
150
+ return ! IsImplicit (h )
151
+ }
152
+
153
+ func Filter (hints []ReferenceHint , cond matcher.Matcher [ReferenceHint ]) ReferenceHints {
139
154
if len (hints ) == 0 {
140
155
return nil
141
156
}
142
- return sliceutils .Filter (hints , IsImplicitHint )
157
+ return sliceutils .Filter (hints , cond )
158
+ }
159
+
160
+ func FilterImplicit (hints []ReferenceHint ) ReferenceHints {
161
+ return Filter (hints , IsImplicit )
162
+ }
163
+
164
+ func AsImplicit [S ~ []T , T ReferenceHint ](hints S ) DefaultReferenceHints {
165
+ var result DefaultReferenceHints
166
+
167
+ for _ , h := range hints {
168
+ if IsImplicit (h ) {
169
+ result .Add (h )
170
+ } else {
171
+ result .Add (h .AsDefault ().SetProperty (HINT_IMPLICIT , IMPLICIT_TRUE ))
172
+ }
173
+ }
174
+ return result
143
175
}
144
176
145
177
// GetReference returns the default reference hint attribute
@@ -245,6 +277,57 @@ func (h DefaultReferenceHint) Serialize(implicit ...bool) string {
245
277
return s
246
278
}
247
279
280
+ ////////////////////////////////////////////////////////////////////////////////
281
+
282
+ type DefaultReferenceHints []DefaultReferenceHint
283
+
284
+ func (h * DefaultReferenceHints ) Add (hints ... ReferenceHint ) {
285
+ AddUnique (h , sliceutils .Transform (hints , AsDefault )... )
286
+ }
287
+
288
+ func (h DefaultReferenceHints ) Copy () ReferenceHints {
289
+ var result ReferenceHints
290
+
291
+ for _ , v := range h {
292
+ result = append (result , v .Copy ())
293
+ }
294
+ return result
295
+ }
296
+
297
+ // Serialize provides a string representation. The implicit
298
+ // attribute is only serialized, if it is called with true.
299
+ func (h DefaultReferenceHints ) Serialize (implicit ... bool ) string {
300
+ return HintsToString (sliceutils.Convert [ReferenceHint ](h ), implicit ... )
301
+ }
302
+
303
+ var _ json.Marshaler = DefaultReferenceHints {}
304
+
305
+ func (h DefaultReferenceHints ) MarshalJSON () ([]byte , error ) {
306
+ return json .Marshal (([]DefaultReferenceHint )(h ))
307
+ }
308
+
309
+ var _ json.Unmarshaler = & DefaultReferenceHints {}
310
+
311
+ // UnmarshalJSON excepts the serialized form or the list form.
312
+ func (h * DefaultReferenceHints ) UnmarshalJSON (data []byte ) error {
313
+ var in []DefaultReferenceHint
314
+
315
+ err := json .Unmarshal (data , & in )
316
+ if err == nil {
317
+ * h = DefaultReferenceHints (in )
318
+ return nil
319
+ }
320
+ var s string
321
+ err = json .Unmarshal (data , & s )
322
+ if err != nil {
323
+ return err
324
+ }
325
+ * h = sliceutils .Transform (ParseHints (s ), AsDefault )
326
+ return nil
327
+ }
328
+
329
+ ////////////////////////////////////////////////////////////////////////////////
330
+
248
331
func escapeHintValue (v string ) string {
249
332
if ! strings .ContainsAny (v , "\" ,;" ) {
250
333
return v
@@ -413,10 +496,23 @@ func ParseHints(v string, implicit ...bool) ReferenceHints {
413
496
return hints
414
497
}
415
498
416
- func Join (hints ... []ReferenceHint ) ReferenceHints {
499
+ // JoinUnique joins multiple hint lists, where the first occurrence of a
500
+ // hint type takes precedence.
501
+ func JoinUnique (hints ... []ReferenceHint ) ReferenceHints {
417
502
var result []ReferenceHint
418
503
for _ , h := range hints {
419
- result = sliceutils . AppendUniqueFunc ( result , runtime . MatchType [ ReferenceHint ] , h ... )
504
+ AddUnique ( & result , h ... )
420
505
}
421
506
return result
422
507
}
508
+
509
+ // AddUnique adds hints to hint list, whode type is not yet present in the list.
510
+ func AddUnique [S ~ []T , T ReferenceHint ](hints * S , add ... T ) {
511
+ * hints = sliceutils .AppendUniqueFunc (* hints , runtime .MatchType [T ], add ... )
512
+ }
513
+
514
+ // AsDefault transforms a generic hint into a default hint.
515
+ // It can be used by sliceutils.Transform.
516
+ func AsDefault (h ReferenceHint ) DefaultReferenceHint {
517
+ return h .AsDefault ()
518
+ }
0 commit comments