Mike Schwörer
9e5b8c5277
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m25s
105 lines
3.0 KiB
Go
105 lines
3.0 KiB
Go
package sq
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
|
"reflect"
|
|
)
|
|
|
|
type DBTypeConverter interface {
|
|
ModelTypeString() string
|
|
DBTypeString() string
|
|
ModelToDB(v any) (any, error)
|
|
DBToModel(v any) (any, error)
|
|
}
|
|
|
|
type DBDataConstraint interface {
|
|
string | langext.NumberConstraint | []byte
|
|
}
|
|
|
|
type DatabaseConvertible[TModelData any, TDBData DBDataConstraint] interface {
|
|
MarshalToDB(v TModelData) (TDBData, error)
|
|
UnmarshalToModel(v TDBData) (TModelData, error)
|
|
}
|
|
|
|
type dbTypeConverterImpl[TModelData any, TDBData DBDataConstraint] struct {
|
|
dbTypeString string
|
|
modelTypeString string
|
|
todb func(v TModelData) (TDBData, error)
|
|
tomodel func(v TDBData) (TModelData, error)
|
|
}
|
|
|
|
func (t *dbTypeConverterImpl[TModelData, TDBData]) ModelTypeString() string {
|
|
return t.modelTypeString
|
|
}
|
|
|
|
func (t *dbTypeConverterImpl[TModelData, TDBData]) DBTypeString() string {
|
|
return t.dbTypeString
|
|
}
|
|
|
|
func (t *dbTypeConverterImpl[TModelData, TDBData]) ModelToDB(v any) (any, error) {
|
|
if vv, ok := v.(TModelData); ok {
|
|
return t.todb(vv)
|
|
}
|
|
return nil, errors.New(fmt.Sprintf("Unexpected value in DBTypeConverter, expected '%s', found '%T'", t.modelTypeString, v))
|
|
}
|
|
|
|
func (t *dbTypeConverterImpl[TModelData, TDBData]) DBToModel(v any) (any, error) {
|
|
if vv, ok := v.(TDBData); ok {
|
|
return t.tomodel(vv)
|
|
}
|
|
return nil, errors.New(fmt.Sprintf("Unexpected value in DBTypeConverter, expected '%s', found '%T'", t.dbTypeString, v))
|
|
}
|
|
|
|
func NewDBTypeConverter[TModelData any, TDBData DBDataConstraint](todb func(v TModelData) (TDBData, error), tomodel func(v TDBData) (TModelData, error)) DBTypeConverter {
|
|
return &dbTypeConverterImpl[TModelData, TDBData]{
|
|
dbTypeString: fmt.Sprintf("%T", *new(TDBData)),
|
|
modelTypeString: fmt.Sprintf("%T", *new(TModelData)),
|
|
todb: todb,
|
|
tomodel: tomodel,
|
|
}
|
|
}
|
|
|
|
func NewAutoDBTypeConverter[TDBData DBDataConstraint, TModelData DatabaseConvertible[TModelData, TDBData]](obj TModelData) DBTypeConverter {
|
|
return &dbTypeConverterImpl[TModelData, TDBData]{
|
|
dbTypeString: fmt.Sprintf("%T", *new(TDBData)),
|
|
modelTypeString: fmt.Sprintf("%T", *new(TModelData)),
|
|
todb: obj.MarshalToDB,
|
|
tomodel: obj.UnmarshalToModel,
|
|
}
|
|
}
|
|
|
|
func convertValueToDB(q Queryable, value any) (any, error) {
|
|
modelTypeStr := fmt.Sprintf("%T", value)
|
|
|
|
for _, conv := range q.ListConverter() {
|
|
if conv.ModelTypeString() == modelTypeStr {
|
|
return conv.ModelToDB(value)
|
|
}
|
|
}
|
|
|
|
if value != nil && reflect.TypeOf(value).Kind() == reflect.Ptr {
|
|
vof := reflect.ValueOf(value)
|
|
if vof.IsNil() {
|
|
return nil, nil
|
|
} else {
|
|
return convertValueToDB(q, vof.Elem().Interface())
|
|
}
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
func convertValueToModel(q Queryable, value any, destinationType string) (any, error) {
|
|
dbTypeString := fmt.Sprintf("%T", value)
|
|
|
|
for _, conv := range q.ListConverter() {
|
|
if conv.ModelTypeString() == destinationType && conv.DBTypeString() == dbTypeString {
|
|
return conv.DBToModel(value)
|
|
}
|
|
}
|
|
|
|
return value, nil
|
|
}
|