replace Converter interface with string parser interface

This commit is contained in:
yusing 2024-12-17 09:45:37 +08:00
parent c5d96f96e1
commit 0aa00ab226
3 changed files with 41 additions and 39 deletions

View file

@ -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) {

View file

@ -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:
func (c *testType) Parse(v string) (err error) {
c.bar = v
return nil
case int:
c.foo = v
return nil
default:
return E.Errorf("%w %T", errInvalid, 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))
})
}

View file

@ -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
}