diff --git a/copierutil/converters.go b/copierutil/converters.go index 946389e..9723a6e 100644 --- a/copierutil/converters.go +++ b/copierutil/converters.go @@ -41,3 +41,64 @@ var TimestamppbToTimeConverter = copier.TypeConverter{ return timeutil.TimestamppbToTime(src.(*timestamppb.Timestamp)), nil }, } + +func MakeTypeConverter(srcType, dstType interface{}, fn func(src interface{}) (interface{}, error)) copier.TypeConverter { + return copier.TypeConverter{ + SrcType: srcType, + DstType: dstType, + Fn: fn, + } +} + +func MakeTypeConverterPair(srcType, dstType interface{}, fromFn, toFn func(src interface{}) (interface{}, error)) []copier.TypeConverter { + return []copier.TypeConverter{ + { + SrcType: srcType, + DstType: dstType, + Fn: fromFn, + }, + { + SrcType: dstType, + DstType: srcType, + Fn: toFn, + }, + } +} + +func MakeGenericTypeConverterPair[A interface{}, B interface{}](srcType A, dstType B, fromFn func(src A) B, toFn func(src B) A) []copier.TypeConverter { + return []copier.TypeConverter{ + { + SrcType: srcType, + DstType: dstType, + Fn: func(src interface{}) (interface{}, error) { + return fromFn(src.(A)), nil + }, + }, + { + SrcType: dstType, + DstType: srcType, + Fn: func(src interface{}) (interface{}, error) { + return toFn(src.(B)), nil + }, + }, + } +} + +func MakeErrorHandlingTypeConverterPair[A interface{}, B interface{}](srcType A, dstType B, fromFn func(src A) (B, error), toFn func(src B) (A, error)) []copier.TypeConverter { + return []copier.TypeConverter{ + { + SrcType: srcType, + DstType: dstType, + Fn: func(src interface{}) (interface{}, error) { + return fromFn(src.(A)) + }, + }, + { + SrcType: dstType, + DstType: srcType, + Fn: func(src interface{}) (interface{}, error) { + return toFn(src.(B)) + }, + }, + } +} diff --git a/copierutil/converters_test.go b/copierutil/converters_test.go new file mode 100644 index 0000000..defeece --- /dev/null +++ b/copierutil/converters_test.go @@ -0,0 +1,152 @@ +package copierutil + +import ( + "testing" + "time" + + "github.com/tx7do/go-utils/timeutil" + "github.com/tx7do/go-utils/trans" +) + +func TestMakeTypeConverter(t *testing.T) { + srcType := &time.Time{} + dstType := trans.Ptr("") + fn := func(src interface{}) (interface{}, error) { + return timeutil.TimeToTimeString(src.(*time.Time)), nil + } + + converter := MakeTypeConverter(srcType, dstType, fn) + + // 验证转换器的类型 + if converter.SrcType != srcType || converter.DstType != dstType { + t.Errorf("converter types mismatch") + } + + // 验证转换器的功能 + result, err := converter.Fn(&time.Time{}) + if err != nil { + t.Errorf("converter function failed: %v", err) + } + if _, ok := result.(*string); !ok { + t.Errorf("converter result type mismatch") + } +} + +func TestMakeTypeConverterPair(t *testing.T) { + srcType := &time.Time{} + dstType := trans.Ptr("") + fromFn := func(src interface{}) (interface{}, error) { + return timeutil.TimeToTimeString(src.(*time.Time)), nil + } + toFn := func(src interface{}) (interface{}, error) { + return timeutil.StringTimeToTime(src.(*string)), nil + } + + converters := MakeTypeConverterPair(srcType, dstType, fromFn, toFn) + + if len(converters) != 2 { + t.Fatalf("expected 2 converters, got %d", len(converters)) + } + + // 验证第一个转换器 + if converters[0].SrcType != srcType || converters[0].DstType != dstType { + t.Errorf("first converter types mismatch") + } + result, err := converters[0].Fn(&time.Time{}) + if err != nil { + t.Errorf("first converter function failed: %v", err) + } + if _, ok := result.(*string); !ok { + t.Errorf("first converter result type mismatch") + } + + // 验证第二个转换器 + if converters[1].SrcType != dstType || converters[1].DstType != srcType { + t.Errorf("second converter types mismatch") + } + result, err = converters[1].Fn(trans.Ptr("")) + if err != nil { + t.Errorf("second converter function failed: %v", err) + } + if _, ok := result.(*time.Time); !ok { + t.Errorf("second converter result type mismatch") + } +} + +func TestMakeGenericTypeConverterPair(t *testing.T) { + srcType := &time.Time{} + dstType := trans.Ptr("") + fromFn := timeutil.TimeToTimeString + toFn := timeutil.StringTimeToTime + + converters := MakeGenericTypeConverterPair(srcType, dstType, fromFn, toFn) + + if len(converters) != 2 { + t.Fatalf("expected 2 converters, got %d", len(converters)) + } + + // 验证第一个转换器 + if converters[0].SrcType != srcType || converters[0].DstType != dstType { + t.Errorf("first converter types mismatch") + } + result, err := converters[0].Fn(&time.Time{}) + if err != nil { + t.Errorf("first converter function failed: %v", err) + } + if _, ok := result.(*string); !ok { + t.Errorf("first converter result type mismatch") + } + + // 验证第二个转换器 + if converters[1].SrcType != dstType || converters[1].DstType != srcType { + t.Errorf("second converter types mismatch") + } + result, err = converters[1].Fn(trans.Ptr("")) + if err != nil { + t.Errorf("second converter function failed: %v", err) + } + if _, ok := result.(*time.Time); !ok { + t.Errorf("second converter result type mismatch") + } +} + +func TestMakeErrorHandlingTypeConverterPair(t *testing.T) { + srcType := &time.Time{} + dstType := trans.Ptr("") + fromFn := func(src *time.Time) (*string, error) { + return timeutil.TimeToTimeString(src), nil + } + toFn := func(src *string) (*time.Time, error) { + return timeutil.StringTimeToTime(src), nil + } + + converters := MakeErrorHandlingTypeConverterPair(srcType, dstType, fromFn, toFn) + + if len(converters) != 2 { + t.Fatalf("expected 2 converters, got %d", len(converters)) + } + + // 验证第一个转换器 + if converters[0].SrcType != srcType || converters[0].DstType != dstType { + t.Errorf("first converter types mismatch") + } + result, err := converters[0].Fn(&time.Time{}) + if err != nil { + t.Errorf("first converter function failed: %v", err) + } + if _, ok := result.(*string); !ok { + t.Errorf("first converter result type mismatch") + } + + // 验证第二个转换器 + if converters[1].SrcType != dstType || converters[1].DstType != srcType { + t.Errorf("second converter types mismatch") + } + result, err = converters[1].Fn(trans.Ptr("")) + if err != nil { + t.Errorf("second converter function failed: %v", err) + } + if _, ok := result.(*time.Time); !ok { + t.Errorf("second converter result type mismatch") + } +} diff --git a/tag.bat b/tag.bat index 719b0c2..e165364 100644 --- a/tag.bat +++ b/tag.bat @@ -3,7 +3,7 @@ git tag v1.1.22 git tag bank_card/v1.1.5 git tag geoip/v1.1.5 git tag translator/v1.1.2 -git tag copierutil/v0.0.1 +git tag copierutil/v0.0.2 git tag entgo/v1.1.28 git tag gorm/v1.1.6