diff --git a/internal/utils/serialization.go b/internal/utils/serialization.go index 80bf006..6f70cfb 100644 --- a/internal/utils/serialization.go +++ b/internal/utils/serialization.go @@ -18,12 +18,7 @@ import ( "gopkg.in/yaml.v3" ) -type ( - SerializedObject = map[string]any - Converter interface { - ConvertFrom(value any) E.Error - } -) +type SerializedObject = map[string]any var ( ErrInvalidType = E.New("invalid type") @@ -349,14 +344,11 @@ func Convert(src reflect.Value, dst reflect.Value) E.Error { } } - var converter Converter - var ok bool // check if (*T).Convertor is implemented - if converter, ok = dst.Addr().Interface().(Converter); !ok { - return ErrUnsupportedConversion.Subjectf("%s to %s", srcT, dstT) + if parser, ok := dst.Addr().Interface().(strutils.Parser); ok { + return E.From(parser.Parse(src.String())) } - - return converter.ConvertFrom(src.Interface()) + return ErrUnsupportedConversion.Subjectf("%s to %s", srcT, dstT) } func ConvertString(src string, dst reflect.Value) (convertible bool, convErr E.Error) { diff --git a/internal/utils/serialization_test.go b/internal/utils/serialization_test.go index 6ea2a70..c322a7f 100644 --- a/internal/utils/serialization_test.go +++ b/internal/utils/serialization_test.go @@ -1,11 +1,10 @@ package utils import ( - "errors" "reflect" + "strconv" "testing" - E "github.com/yusing/go-proxy/internal/error" . "github.com/yusing/go-proxy/internal/utils/testing" ) @@ -132,40 +131,23 @@ type testType struct { bar string } -var errInvalid = errors.New("invalid input type") - -func (c *testType) ConvertFrom(v any) E.Error { - switch v := v.(type) { - case string: - c.bar = v - return nil - case int: - c.foo = v - return nil - default: - return E.Errorf("%w %T", errInvalid, v) - } +func (c *testType) Parse(v string) (err error) { + c.bar = v + c.foo, err = strconv.Atoi(v) + return } func TestConvertor(t *testing.T) { - t.Run("string", func(t *testing.T) { + t.Run("valid", func(t *testing.T) { m := new(testModel) - ExpectNoError(t, Deserialize(map[string]any{"Test": "bar"}, m)) - - ExpectEqual(t, m.Test.foo, 0) - ExpectEqual(t, m.Test.bar, "bar") - }) - - t.Run("int", func(t *testing.T) { - m := new(testModel) - ExpectNoError(t, Deserialize(map[string]any{"Test": 123}, m)) + ExpectNoError(t, Deserialize(map[string]any{"Test": "123"}, m)) ExpectEqual(t, m.Test.foo, 123) - ExpectEqual(t, m.Test.bar, "") + ExpectEqual(t, m.Test.bar, "123") }) t.Run("invalid", func(t *testing.T) { m := new(testModel) - ExpectError(t, errInvalid, Deserialize(map[string]any{"Test": 123.456}, m)) + ExpectError(t, strconv.ErrSyntax, Deserialize(map[string]any{"Test": 123}, m)) }) } diff --git a/internal/utils/strutils/parser.go b/internal/utils/strutils/parser.go new file mode 100644 index 0000000..42b199b --- /dev/null +++ b/internal/utils/strutils/parser.go @@ -0,0 +1,28 @@ +package strutils + +import ( + "reflect" + + "github.com/yusing/go-proxy/internal/logging" +) + +type Parser interface { + Parse(value string) error +} + +func Parse[T Parser](from string) (t T, err error) { + tt := reflect.TypeOf(t) + if tt.Kind() == reflect.Ptr { + t = reflect.New(tt.Elem()).Interface().(T) + } + err = t.Parse(from) + return t, err +} + +func MustParse[T Parser](from string) T { + t, err := Parse[T](from) + if err != nil { + logging.Panic().Err(err).Msg("must failed") + } + return t +}