From 8c4db8b7c1453fd873753f49bdf7fb12ec1a9501 Mon Sep 17 00:00:00 2001 From: Oleg Tsarev Date: Wed, 15 Jul 2020 19:44:33 +0200 Subject: [PATCH] Supported assign parsed value not only to value types (string, bool, etcetera) but also to pointer types (*string, *bool, etcetera). It's very useful to distinguish missed in config value from present in config --- value.go | 101 +++++++++++++++++++++++++++++++++++++++++++------- value_test.go | 8 ++++ 2 files changed, 95 insertions(+), 14 deletions(-) diff --git a/value.go b/value.go index 5184aa8b..3286a217 100644 --- a/value.go +++ b/value.go @@ -353,34 +353,107 @@ func (val *value) setStruct(k string, v interface{}, targetValue reflect.Value) func castValue(f interface{}, v interface{}) interface{} { switch f.(type) { + // string + case *string: + value := cast.ToString(v) + return &value case string: return cast.ToString(v) + // bool + case *bool: + value := cast.ToBool(v) + return &value case bool: return cast.ToBool(v) + // int + case *int: + value := cast.ToInt(v) + return &value case int: return cast.ToInt(v) - case int64: - return cast.ToInt64(v) + // uint + case *uint: + value := cast.ToUint(v) + return &value + case uint: + return cast.ToUint(v) + // int8 + case *int8: + value := cast.ToInt8(v) + return &value + case int8: + return cast.ToInt8(v) + // unt8 + case *uint8: + value := cast.ToUint8(v) + return &value + case uint8: + return cast.ToUint8(v) + // int16 + case *int16: + value := cast.ToInt16(v) + return &value + case int16: + return cast.ToInt16(v) + // unit16 + case *uint16: + value := cast.ToUint16(v) + return &value + case uint16: + return cast.ToUint16(v) + // int32 + case *int32: + value := cast.ToInt32(v) + return &value case int32: return cast.ToInt32(v) - case float64: - return cast.ToFloat64(v) - case float32: - return cast.ToFloat32(v) - case uint64: - return cast.ToUint64(v) + // uint32 + case *uint32: + value := cast.ToUint32(v) + return &value case uint32: return cast.ToUint32(v) - case uint8: - return cast.ToUint8(v) - case []string: - return cast.ToStringSlice(v) - case []int: - return cast.ToIntSlice(v) + // int64 + case *int64: + value := cast.ToInt64(v) + return &value + case int64: + return cast.ToInt64(v) + // uint64 + case *uint64: + value := cast.ToUint64(v) + return &value + case uint64: + return cast.ToUint64(v) + // float32 + case *float32: + value := cast.ToFloat32(v) + return &value + case float32: + return cast.ToFloat32(v) + // float64 + case *float64: + value := cast.ToFloat64(v) + return &value + case float64: + return cast.ToFloat64(v) + // time.Time + case *time.Time: + value := cast.ToTime(v) + return &value case time.Time: return cast.ToTime(v) + // time.Duration + case *time.Duration: + value := cast.ToDuration(v) + return &value case time.Duration: return cast.ToDuration(v) + // rest + case []string: + return cast.ToStringSlice(v) + case []int: + return cast.ToIntSlice(v) case map[string]string: return cast.ToStringMapString(v) } diff --git a/value_test.go b/value_test.go index f4a66ae6..31941036 100644 --- a/value_test.go +++ b/value_test.go @@ -142,6 +142,8 @@ func TestSetStruct(t *testing.T) { func(t *testing.T) { type TestConfigSub struct { VV string `konfig:"vv"` + PS1 *string `konfig:"ps1"` + PS2 *string `konfig:"ps2"` TT int `konfig:"tt"` B bool `konfig:"bool"` F float64 `konfig:"float64"` @@ -156,10 +158,12 @@ func TestSetStruct(t *testing.T) { SubMapT map[string]TestConfigSub `konfig:"submapt"` } + var ps1 = "test3" var expectedConfig = TestConfig{ V: "test", T: TestConfigSub{ VV: "test2", + PS1: &ps1, TT: 1, B: true, F: 1.9, @@ -200,6 +204,7 @@ func TestSetStruct(t *testing.T) { var v = Values{ "v": "test", "sub.vv": "test2", + "sub.ps1": ps1, "sub.tt": 1, "subt.tt": 2, "sub.bool": true, @@ -223,6 +228,9 @@ func TestSetStruct(t *testing.T) { var configValue = Value().(TestConfig) require.Equal(t, "test", configValue.V) require.Equal(t, "test2", configValue.T.VV) + require.NotNil(t, configValue.T.PS1) + require.Equal(t, "test3", *configValue.T.PS1) + require.Nil(t, configValue.T.PS2) require.Equal(t, 1, configValue.T.TT) require.Equal(t, 2, configValue.SubT.TT) require.Equal(t, true, configValue.T.B)