Support time.duration (#248)

This commit is contained in:
Andriy Senyshyn
2018-11-12 19:02:56 +02:00
committed by Thomas Pelletier
parent 81a861c69d
commit aa79e12a97
2 changed files with 128 additions and 0 deletions
+10
View File
@@ -352,6 +352,9 @@ func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface
case reflect.Bool:
return mval.Bool(), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) {
return fmt.Sprint(mval), nil
}
return mval.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return mval.Uint(), nil
@@ -566,6 +569,13 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.V
return val.Convert(mtype), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
val := reflect.ValueOf(tval)
if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) && val.Kind() == reflect.String {
d, err := time.ParseDuration(val.String())
if err != nil {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v. %s", tval, tval, mtype.String(), err)
}
return reflect.ValueOf(d), nil
}
if !val.Type().ConvertibleTo(mtype) {
return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
}
+118
View File
@@ -1002,3 +1002,121 @@ func TestMarshalMap(t *testing.T) {
t.Fail()
}
}
type testDuration struct {
Nanosec time.Duration `toml:"nanosec"`
Microsec1 time.Duration `toml:"microsec1"`
Microsec2 *time.Duration `toml:"microsec2"`
Millisec time.Duration `toml:"millisec"`
Sec time.Duration `toml:"sec"`
Min time.Duration `toml:"min"`
Hour time.Duration `toml:"hour"`
Mixed time.Duration `toml:"mixed"`
AString string `toml:"a_string"`
}
var testDurationToml = []byte(`
nanosec = "1ns"
microsec1 = "1us"
microsec2 = "1µs"
millisec = "1ms"
sec = "1s"
min = "1m"
hour = "1h"
mixed = "1h1m1s1ms1µs1ns"
a_string = "15s"
`)
func TestUnmarshalDuration(t *testing.T) {
buf := bytes.NewBuffer(testDurationToml)
result := testDuration{}
err := NewDecoder(buf).Decode(&result)
if err != nil {
t.Fatal(err)
}
ms := time.Duration(1) * time.Microsecond
expected := testDuration{
Nanosec: 1,
Microsec1: time.Microsecond,
Microsec2: &ms,
Millisec: time.Millisecond,
Sec: time.Second,
Min: time.Minute,
Hour: time.Hour,
Mixed: time.Hour +
time.Minute +
time.Second +
time.Millisecond +
time.Microsecond +
time.Nanosecond,
AString: "15s",
}
if !reflect.DeepEqual(result, expected) {
resStr, _ := json.MarshalIndent(result, "", " ")
expStr, _ := json.MarshalIndent(expected, "", " ")
t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
}
}
var testDurationToml2 = []byte(`a_string = "15s"
hour = "1h0m0s"
microsec1 = "1µs"
microsec2 = "1µs"
millisec = "1ms"
min = "1m0s"
mixed = "1h1m1.001001001s"
nanosec = "1ns"
sec = "1s"
`)
func TestMarshalDuration(t *testing.T) {
ms := time.Duration(1) * time.Microsecond
data := testDuration{
Nanosec: 1,
Microsec1: time.Microsecond,
Microsec2: &ms,
Millisec: time.Millisecond,
Sec: time.Second,
Min: time.Minute,
Hour: time.Hour,
Mixed: time.Hour +
time.Minute +
time.Second +
time.Millisecond +
time.Microsecond +
time.Nanosecond,
AString: "15s",
}
var buf bytes.Buffer
err := NewEncoder(&buf).Encode(data)
if err != nil {
t.Fatal(err)
}
expected := testDurationToml2
result := buf.Bytes()
if !bytes.Equal(result, expected) {
t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
}
}
type testBadDuration struct {
Val time.Duration `toml:"val"`
}
var testBadDurationToml = []byte(`val = "1z"`)
func TestUnmarshalBadDuration(t *testing.T) {
buf := bytes.NewBuffer(testBadDurationToml)
result := testBadDuration{}
err := NewDecoder(buf).Decode(&result)
if err == nil {
t.Fatal()
}
if err.Error() != "(1, 1): Can't convert 1z(string) to time.Duration. time: unknown unit z in duration 1z" {
t.Fatalf("unexpected error: %s", err)
}
}