Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
feat: make it possible to define optional durations
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed Oct 24, 2021
1 parent a412831 commit d62365e
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 34 deletions.
2 changes: 1 addition & 1 deletion autonat.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ type AutoNATThrottleConfig struct {
// global/peer dialback limits.
//
// When unset, this defaults to 1 minute.
Interval Duration `json:",omitempty"`
Interval Duration
}
40 changes: 34 additions & 6 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,20 +214,48 @@ var _ json.Marshaler = (*Priority)(nil)
// Duration wraps time.Duration to provide json serialization and deserialization.
//
// NOTE: the zero value encodes to an empty string.
type Duration time.Duration
type Duration struct {
value *time.Duration
}

func (d *Duration) UnmarshalText(text []byte) error {
dur, err := time.ParseDuration(string(text))
*d = Duration(dur)
return err
switch string(text) {
case "null", "undefined":
*d = Duration{}
return nil
default:
value, err := time.ParseDuration(string(text))
if err != nil {
return err
}
*d = Duration{value: &value}
return nil
}
}

func (d *Duration) IsDefault() bool {
return d.value == nil
}

func (d *Duration) WithDefault(defaultValue time.Duration) time.Duration {
if d.value == nil {
return defaultValue
}
return *d.value
}

func (d Duration) MarshalText() ([]byte, error) {
return []byte(time.Duration(d).String()), nil
if d.value != nil {
return []byte(d.value.String()), nil
}
return json.Marshal(nil)
}

func (d Duration) String() string {
return time.Duration(d).String()
if d.value == nil {
return "defaults"
}
return d.value.String()
}

var _ encoding.TextUnmarshaler = (*Duration)(nil)
Expand Down
75 changes: 48 additions & 27 deletions types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,55 @@ import (
)

func TestDuration(t *testing.T) {
out, err := json.Marshal(Duration(time.Second))
if err != nil {
t.Fatal(err)
makeDurationPointer := func(d time.Duration) *time.Duration { return &d }

}
expected := "\"1s\""
if string(out) != expected {
t.Fatalf("expected %s, got %s", expected, string(out))
}
var d Duration
err = json.Unmarshal(out, &d)
if err != nil {
t.Fatal(err)
}
if time.Duration(d) != time.Second {
t.Fatal("expected a second")
}
type Foo struct {
D Duration `json:",omitempty"`
}
out, err = json.Marshal(new(Foo))
if err != nil {
t.Fatal(err)
}
expected = "{}"
if string(out) != expected {
t.Fatal("expected omitempty to omit the duration")
}
t.Run("marshalling and unmarshalling", func(t *testing.T) {
out, err := json.Marshal(Duration{value: makeDurationPointer(time.Second)})
if err != nil {
t.Fatal(err)
}
expected := "\"1s\""
if string(out) != expected {
t.Fatalf("expected %s, got %s", expected, string(out))
}
var d Duration

if err := json.Unmarshal(out, &d); err != nil {
t.Fatal(err)
}
if *d.value != time.Second {
t.Fatal("expected a second")
}
})

t.Run("default value", func(t *testing.T) {
var d Duration
if !d.IsDefault() {
t.Fatal("expected value to be the default initially")
}
if err := json.Unmarshal([]byte("null"), &d); err != nil {
t.Fatal(err)
}
if dur := d.WithDefault(time.Hour); dur != time.Hour {
t.Fatalf("expected default value to be used, got %s", dur)
}
if !d.IsDefault() {
t.Fatal("expected value to be the default")
}
})

t.Run("omitempyt", func(t *testing.T) {
type Foo struct {
D *Duration `json:",omitempty"`
}
out, err := json.Marshal(new(Foo))
if err != nil {
t.Fatal(err)
}
if string(out) != "{}" {
t.Fatalf("expected omitempty to omit the duration, got %s", out)
}
})
}

func TestOneStrings(t *testing.T) {
Expand Down

0 comments on commit d62365e

Please sign in to comment.