Skip to content

Commit 2e9eb8f

Browse files
committed
feat(model): ValidationScheme implements pflag.Value and json.Marshaler/Unmarshaler interfaces
Signed-off-by: Julius Hinze <[email protected]>
1 parent c79a891 commit 2e9eb8f

File tree

2 files changed

+132
-8
lines changed

2 files changed

+132
-8
lines changed

model/metric.go

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package model
1515

1616
import (
17+
"encoding/json"
1718
"errors"
1819
"fmt"
1920
"regexp"
@@ -77,10 +78,13 @@ const (
7778
UTF8Validation
7879
)
7980

80-
var (
81-
_ yaml.Marshaler = UnsetValidation
82-
_ fmt.Stringer = UnsetValidation
83-
)
81+
var _ interface {
82+
yaml.Marshaler
83+
yaml.Unmarshaler
84+
json.Marshaler
85+
json.Unmarshaler
86+
fmt.Stringer
87+
} = new(ValidationScheme)
8488

8589
// String returns the string representation of s.
8690
func (s ValidationScheme) String() string {
@@ -114,15 +118,41 @@ func (s *ValidationScheme) UnmarshalYAML(unmarshal func(any) error) error {
114118
if err := unmarshal(&scheme); err != nil {
115119
return err
116120
}
117-
switch scheme {
121+
return s.Set(scheme)
122+
}
123+
124+
// MarshalJSON implements the json.Marshaler interface.
125+
func (s ValidationScheme) MarshalJSON() ([]byte, error) {
126+
switch s {
127+
case UnsetValidation:
128+
return json.Marshal("")
129+
case UTF8Validation, LegacyValidation:
130+
return json.Marshal(s.String())
131+
default:
132+
return nil, fmt.Errorf("unhandled ValidationScheme: %d", s)
133+
}
134+
}
135+
136+
// UnmarshalJSON implements the json.Unmarshaler interface.
137+
func (s *ValidationScheme) UnmarshalJSON(bytes []byte) error {
138+
var repr string
139+
if err := json.Unmarshal(bytes, &repr); err != nil {
140+
return err
141+
}
142+
return s.Set(repr)
143+
}
144+
145+
// Set implements the pflag.Value interface.
146+
func (s *ValidationScheme) Set(text string) error {
147+
switch text {
118148
case "":
119149
// Don't change the value.
120-
case "legacy":
150+
case LegacyValidation.String():
121151
*s = LegacyValidation
122-
case "utf8":
152+
case UTF8Validation.String():
123153
*s = UTF8Validation
124154
default:
125-
return fmt.Errorf("unrecognized ValidationScheme: %q", scheme)
155+
return fmt.Errorf("unrecognized ValidationScheme: %q", text)
126156
}
127157
return nil
128158
}
@@ -174,6 +204,11 @@ func (s ValidationScheme) IsValidLabelName(labelName string) bool {
174204
}
175205
}
176206

207+
// Type implements the pflag.Value interface.
208+
func (s ValidationScheme) Type() string {
209+
return "validationScheme"
210+
}
211+
177212
type EscapingScheme int
178213

179214
const (

model/metric_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package model
1515

1616
import (
17+
"encoding/json"
1718
"errors"
1819
"fmt"
1920
"strings"
@@ -203,6 +204,94 @@ func TestValidationScheme_UnmarshalYAML(t *testing.T) {
203204
}
204205
}
205206

207+
func TestValidationScheme_UnmarshalJSON(t *testing.T) {
208+
testCases := []struct {
209+
name string
210+
input string
211+
want ValidationScheme
212+
wantErr bool
213+
}{
214+
{
215+
name: "invalid",
216+
input: `invalid`,
217+
wantErr: true,
218+
},
219+
{
220+
name: "empty",
221+
input: `""`,
222+
want: UnsetValidation,
223+
},
224+
{
225+
name: "legacy validation",
226+
input: `"legacy"`,
227+
want: LegacyValidation,
228+
},
229+
{
230+
name: "utf8 validation",
231+
input: `"utf8"`,
232+
want: UTF8Validation,
233+
},
234+
}
235+
for _, tc := range testCases {
236+
t.Run(tc.name, func(t *testing.T) {
237+
var got ValidationScheme
238+
err := json.Unmarshal([]byte(tc.input), &got)
239+
if tc.wantErr {
240+
require.Error(t, err)
241+
return
242+
}
243+
require.NoError(t, err)
244+
require.Equal(t, tc.want, ValidationScheme(got))
245+
246+
output, err := json.Marshal(got)
247+
require.NoError(t, err)
248+
require.Equal(t, tc.input, string(output))
249+
})
250+
}
251+
}
252+
253+
func TestValidationScheme_Set(t *testing.T) {
254+
testCases := []struct {
255+
name string
256+
input string
257+
want ValidationScheme
258+
wantErr bool
259+
}{
260+
{
261+
name: "invalid",
262+
input: `invalid`,
263+
wantErr: true,
264+
},
265+
{
266+
name: "empty",
267+
input: ``,
268+
want: UnsetValidation,
269+
},
270+
{
271+
name: "legacy validation",
272+
input: `legacy`,
273+
want: LegacyValidation,
274+
},
275+
{
276+
name: "utf8 validation",
277+
input: `utf8`,
278+
want: UTF8Validation,
279+
},
280+
}
281+
for _, tc := range testCases {
282+
t.Run(tc.name, func(t *testing.T) {
283+
var got ValidationScheme
284+
err := got.Set(tc.input)
285+
if tc.wantErr {
286+
require.Error(t, err)
287+
return
288+
}
289+
require.NoError(t, err)
290+
require.Equal(t, tc.want, ValidationScheme(got))
291+
})
292+
}
293+
}
294+
206295
func TestValidationScheme_IsMetricNameValid(t *testing.T) {
207296
scenarios := []struct {
208297
mn string

0 commit comments

Comments
 (0)