Skip to content

Commit

Permalink
Improved default tag for durations (#464)
Browse files Browse the repository at this point in the history
  • Loading branch information
riptl authored Jan 21, 2021
1 parent 652b9f8 commit a713a3e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 15 deletions.
16 changes: 15 additions & 1 deletion marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,21 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V
case reflect.Int32:
val, err = strconv.ParseInt(opts.defaultValue, 10, 32)
case reflect.Int64:
val, err = strconv.ParseInt(opts.defaultValue, 10, 64)
// Check if the provided number has a non-numeric extension.
var hasExtension bool
if len(opts.defaultValue) > 0 {
lastChar := opts.defaultValue[len(opts.defaultValue)-1]
if lastChar < '0' || lastChar > '9' {
hasExtension = true
}
}
// If the value is a time.Duration with extension, parse as duration.
// If the value is an int64 or a time.Duration without extension, parse as number.
if hasExtension && mvalf.Type().String() == "time.Duration" {
val, err = time.ParseDuration(opts.defaultValue)
} else {
val, err = strconv.ParseInt(opts.defaultValue, 10, 64)
}
case reflect.Float32:
val, err = strconv.ParseFloat(opts.defaultValue, 32)
case reflect.Float64:
Expand Down
47 changes: 33 additions & 14 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2286,20 +2286,22 @@ func TestUnmarshalDefault(t *testing.T) {
type aliasUint uint

var doc struct {
StringField string `default:"a"`
BoolField bool `default:"true"`
UintField uint `default:"1"`
Uint8Field uint8 `default:"8"`
Uint16Field uint16 `default:"16"`
Uint32Field uint32 `default:"32"`
Uint64Field uint64 `default:"64"`
IntField int `default:"-1"`
Int8Field int8 `default:"-8"`
Int16Field int16 `default:"-16"`
Int32Field int32 `default:"-32"`
Int64Field int64 `default:"-64"`
Float32Field float32 `default:"32.1"`
Float64Field float64 `default:"64.1"`
StringField string `default:"a"`
BoolField bool `default:"true"`
UintField uint `default:"1"`
Uint8Field uint8 `default:"8"`
Uint16Field uint16 `default:"16"`
Uint32Field uint32 `default:"32"`
Uint64Field uint64 `default:"64"`
IntField int `default:"-1"`
Int8Field int8 `default:"-8"`
Int16Field int16 `default:"-16"`
Int32Field int32 `default:"-32"`
Int64Field int64 `default:"-64"`
Float32Field float32 `default:"32.1"`
Float64Field float64 `default:"64.1"`
DurationField time.Duration `default:"120ms"`
DurationField2 time.Duration `default:"120000000"`
NonEmbeddedStruct struct {
StringField string `default:"b"`
}
Expand Down Expand Up @@ -2353,6 +2355,12 @@ func TestUnmarshalDefault(t *testing.T) {
if doc.Float64Field != 64.1 {
t.Errorf("Float64Field should be 64.1, not %f", doc.Float64Field)
}
if doc.DurationField != 120*time.Millisecond {
t.Errorf("DurationField should be 120ms, not %s", doc.DurationField.String())
}
if doc.DurationField2 != 120*time.Millisecond {
t.Errorf("DurationField2 should be 120000000, not %d", doc.DurationField2)
}
if doc.NonEmbeddedStruct.StringField != "b" {
t.Errorf("StringField should be \"b\", not %s", doc.NonEmbeddedStruct.StringField)
}
Expand Down Expand Up @@ -2408,6 +2416,17 @@ func TestUnmarshalDefaultFailureFloat64(t *testing.T) {
}
}

func TestUnmarshalDefaultFailureDuration(t *testing.T) {
var doc struct {
Field time.Duration `default:"blah"`
}

err := Unmarshal([]byte(``), &doc)
if err == nil {
t.Fatal("should error")
}
}

func TestUnmarshalDefaultFailureUnsupported(t *testing.T) {
var doc struct {
Field struct{} `default:"blah"`
Expand Down

0 comments on commit a713a3e

Please sign in to comment.