@cryptotaxi247 / kubo / commits / ac81804c8

go-ipfs-config: feat: add an OptionalInteger type

Adin Schmahmann committed Aug 16, 2021 at 00:01 UTC ac81804c8c4b76aa1de7358abdd45c69ed53978a
2 files changed +142
config/types.go
+52
@@ -232,3 +232,55 @@ func (d Duration) String() string {
232
233 var _ encoding.TextUnmarshaler = (*Duration)(nil)
234 var _ encoding.TextMarshaler = (*Duration)(nil)
235 +
236 +// OptionalInteger represents an integer that has a default value
237 +//
238 +// When encoded in json, Default is encoded as "null"
239 +type OptionalInteger struct {
240 + value *int64
241 +}
242 +
243 +// WithDefault resolves the integer with the given default.
244 +func (p OptionalInteger) WithDefault(defaultValue int64) (value int64) {
245 + if p.value == nil {
246 + return defaultValue
247 + }
248 + return *p.value
249 +}
250 +
251 +// IsDefault returns if this is a default optional integer
252 +func (p OptionalInteger) IsDefault() bool {
253 + return p.value == nil
254 +}
255 +
256 +func (p OptionalInteger) MarshalJSON() ([]byte, error) {
257 + if p.value != nil {
258 + return json.Marshal(p.value)
259 + }
260 + return json.Marshal(nil)
261 +}
262 +
263 +func (p *OptionalInteger) UnmarshalJSON(input []byte) error {
264 + switch string(input) {
265 + case "null", "undefined":
266 + *p = OptionalInteger{}
267 + default:
268 + var value int64
269 + err := json.Unmarshal(input, &value)
270 + if err != nil {
271 + return err
272 + }
273 + *p = OptionalInteger{value: &value}
274 + }
275 + return nil
276 +}
277 +
278 +func (p OptionalInteger) String() string {
279 + if p.value == nil {
280 + return "default"
281 + }
282 + return fmt.Sprintf("%d", p.value)
283 +}
284 +
285 +var _ json.Unmarshaler = (*OptionalInteger)(nil)
286 +var _ json.Marshaler = (*OptionalInteger)(nil)
config/types_test.go
+90
@@ -218,3 +218,93 @@ func TestPriority(t *testing.T) {
218 }
219 }
220 }
221 +
222 +func TestOptionalInteger(t *testing.T) {
223 + makeInt64Pointer := func(v int64) *int64 {
224 + return &v
225 + }
226 +
227 + var defaultOptionalInt OptionalInteger
228 + if !defaultOptionalInt.IsDefault() {
229 + t.Fatal("should be the default")
230 + }
231 + if val := defaultOptionalInt.WithDefault(0); val != 0 {
232 + t.Errorf("optional integer should have been 0, got %d", val)
233 + }
234 +
235 + if val := defaultOptionalInt.WithDefault(1); val != 1 {
236 + t.Errorf("optional integer should have been 1, got %d", val)
237 + }
238 +
239 + if val := defaultOptionalInt.WithDefault(-1); val != -1 {
240 + t.Errorf("optional integer should have been -1, got %d", val)
241 + }
242 +
243 + var filledInt OptionalInteger
244 + filledInt = OptionalInteger{value: makeInt64Pointer(1)}
245 + if filledInt.IsDefault() {
246 + t.Fatal("should not be the default")
247 + }
248 + if val := filledInt.WithDefault(0); val != 1 {
249 + t.Errorf("optional integer should have been 1, got %d", val)
250 + }
251 +
252 + if val := filledInt.WithDefault(-1); val != 1 {
253 + t.Errorf("optional integer should have been 1, got %d", val)
254 + }
255 +
256 + filledInt = OptionalInteger{value: makeInt64Pointer(0)}
257 + if val := filledInt.WithDefault(1); val != 0 {
258 + t.Errorf("optional integer should have been 0, got %d", val)
259 + }
260 +
261 + for jsonStr, goValue := range map[string]OptionalInteger{
262 + "null": {},
263 + "0": {value: makeInt64Pointer(0)},
264 + "1": {value: makeInt64Pointer(1)},
265 + "-1": {value: makeInt64Pointer(-1)},
266 + } {
267 + var d OptionalInteger
268 + err := json.Unmarshal([]byte(jsonStr), &d)
269 + if err != nil {
270 + t.Fatal(err)
271 + }
272 +
273 + if goValue.value == nil && d.value == nil {
274 + } else if goValue.value == nil && d.value != nil {
275 + t.Errorf("expected default, got %s", d)
276 + } else if *d.value != *goValue.value {
277 + t.Fatalf("expected %s, got %s", goValue, d)
278 + }
279 +
280 + // Reverse
281 + out, err := json.Marshal(goValue)
282 + if err != nil {
283 + t.Fatal(err)
284 + }
285 + if string(out) != jsonStr {
286 + t.Fatalf("expected %s, got %s", jsonStr, string(out))
287 + }
288 + }
289 +
290 + type Foo struct {
291 + I *OptionalInteger `json:",omitempty"`
292 + }
293 + out, err := json.Marshal(new(Foo))
294 + if err != nil {
295 + t.Fatal(err)
296 + }
297 + expected := "{}"
298 + if string(out) != expected {
299 + t.Fatal("expected omitempty to omit the optional integer")
300 + }
301 + for _, invalid := range []string{
302 + "foo", "-1.1", "1.1", "0.0", "[]",
303 + } {
304 + var p Priority
305 + err := json.Unmarshal([]byte(invalid), &p)
306 + if err == nil {
307 + t.Errorf("expected to fail to decode %s as a priority", invalid)
308 + }
309 + }
310 +}