JCS-pub/hub/internal/pubshards/string_serializer.go

100 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package pubshards
import (
"context"
"fmt"
"reflect"
"gorm.io/gorm/schema"
)
// 必须给结构体而不是指针实现此接口。FromString实现为静态方法
type StringDBValuer interface {
ToString() (string, error)
FromString(str string) (any, error)
}
type StringSerializer struct {
}
func (StringSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
if dbValue == nil {
fieldValue := reflect.New(field.FieldType)
field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
return nil
}
str := ""
switch v := dbValue.(type) {
case []byte:
str = string(v)
case string:
str = v
default:
return fmt.Errorf("expected []byte or string, got: %T", dbValue)
}
if field.FieldType.Kind() == reflect.Struct {
val := reflect.Zero(field.FieldType)
sv, ok := val.Interface().(StringDBValuer)
if !ok {
return fmt.Errorf("ref of field type %v is not StringDBValuer", field.FieldType)
}
v2, err := sv.FromString(str)
if err != nil {
return err
}
field.ReflectValueOf(ctx, dst).Set(reflect.ValueOf(v2))
return nil
}
if field.FieldType.Kind() == reflect.Ptr {
val := reflect.Zero(field.FieldType.Elem())
sv, ok := val.Interface().(StringDBValuer)
if !ok {
return fmt.Errorf("field type %v is not StringDBValuer", field.FieldType)
}
v2, err := sv.FromString(str)
if err != nil {
return err
}
field.ReflectValueOf(ctx, dst).Set(reflect.ValueOf(v2))
return nil
}
return fmt.Errorf("unsupported field type: %v", field.FieldType)
}
func (StringSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
val := reflect.ValueOf(fieldValue)
if val.Kind() == reflect.Struct {
sv, ok := val.Interface().(StringDBValuer)
if !ok {
return nil, fmt.Errorf("ref of field type %v is not StringDBValuer", field.FieldType)
}
return sv.ToString()
}
if val.Kind() == reflect.Ptr {
sv, ok := val.Elem().Interface().(StringDBValuer)
if !ok {
return nil, fmt.Errorf("field type %v is not StringDBValuer", field.FieldType)
}
return sv.ToString()
}
return nil, fmt.Errorf("unsupported field type: %v", field.FieldType)
}
func init() {
schema.RegisterSerializer("string", StringSerializer{})
}