mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-27 10:47:06 +02:00
refactor(serialization): small optimization
This commit is contained in:
@@ -135,7 +135,9 @@ func fnv1IgnoreCaseSnake(s string) uint32 {
|
|||||||
prime32 uint32 = 16777619
|
prime32 uint32 = 16777619
|
||||||
)
|
)
|
||||||
hash := offset32
|
hash := offset32
|
||||||
for _, r := range s {
|
// range over bytes instead of runes
|
||||||
|
for i := range s {
|
||||||
|
r := s[i]
|
||||||
if r == '_' {
|
if r == '_' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -202,7 +204,10 @@ func initTypeKeyFieldIndexesMap(t reflect.Type) typeInfo {
|
|||||||
|
|
||||||
for i := range numFields {
|
for i := range numFields {
|
||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
if field.Tag.Get(tagDeserialize) == "-" || field.Tag.Get(tagJSON) == "-" {
|
deserializeTag := field.Tag.Get(tagDeserialize)
|
||||||
|
jsonTag := field.Tag.Get(tagJSON)
|
||||||
|
|
||||||
|
if deserializeTag == "-" || jsonTag == "-" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,10 +234,7 @@ func initTypeKeyFieldIndexesMap(t reflect.Type) typeInfo {
|
|||||||
}
|
}
|
||||||
notAnonymousStruct:
|
notAnonymousStruct:
|
||||||
var key string
|
var key string
|
||||||
if jsonTag, ok := field.Tag.Lookup(tagJSON); ok {
|
if jsonTag != "" {
|
||||||
if jsonTag == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key = jsonTag
|
key = jsonTag
|
||||||
if idxComma := strings.Index(key, ","); idxComma != -1 {
|
if idxComma := strings.Index(key, ","); idxComma != -1 {
|
||||||
key = key[:idxComma]
|
key = key[:idxComma]
|
||||||
@@ -247,8 +249,8 @@ func initTypeKeyFieldIndexesMap(t reflect.Type) typeInfo {
|
|||||||
_, hasValidateTag = field.Tag.Lookup(tagValidate)
|
_, hasValidateTag = field.Tag.Lookup(tagValidate)
|
||||||
}
|
}
|
||||||
|
|
||||||
aliases, ok := field.Tag.Lookup(tagAliases)
|
aliases := field.Tag.Get(tagAliases)
|
||||||
if ok {
|
if aliases != "" {
|
||||||
for alias := range strings.SplitSeq(aliases, ",") {
|
for alias := range strings.SplitSeq(aliases, ",") {
|
||||||
keyFieldIndexes[fnv1IgnoreCaseSnake(alias)] = field.Index
|
keyFieldIndexes[fnv1IgnoreCaseSnake(alias)] = field.Index
|
||||||
fieldNames[alias] = struct{}{}
|
fieldNames[alias] = struct{}{}
|
||||||
@@ -500,12 +502,15 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
|
|||||||
dst.SetString(src)
|
dst.SetString(src)
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
switch dstT {
|
|
||||||
case reflect.TypeFor[time.Duration]():
|
// Early return for empty string
|
||||||
if src == "" {
|
if src == "" {
|
||||||
dst.SetZero()
|
dst.SetZero()
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch dstT {
|
||||||
|
case reflect.TypeFor[time.Duration]():
|
||||||
d, err := time.ParseDuration(src)
|
d, err := time.ParseDuration(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, gperr.Wrap(err)
|
return true, gperr.Wrap(err)
|
||||||
@@ -514,6 +519,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
|
|||||||
return true, nil
|
return true, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if gi.ReflectIsNumeric(dst) || dst.Kind() == reflect.Bool {
|
if gi.ReflectIsNumeric(dst) || dst.Kind() == reflect.Bool {
|
||||||
err := gi.ReflectStrToNumBool(dst, src)
|
err := gi.ReflectStrToNumBool(dst, src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -521,17 +527,32 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
|
|||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if (*T).Convertor is implemented
|
// check if (*T).Convertor is implemented
|
||||||
if dst.Addr().Type().Implements(parserType) {
|
if dst.Addr().Type().Implements(parserType) {
|
||||||
parser := dst.Addr().Interface().(strutils.Parser)
|
parser := dst.Addr().Interface().(strutils.Parser)
|
||||||
return true, gperr.Wrap(parser.Parse(src))
|
return true, gperr.Wrap(parser.Parse(src))
|
||||||
}
|
}
|
||||||
|
|
||||||
// yaml like
|
// yaml like
|
||||||
var tmp any
|
var tmp any
|
||||||
switch dst.Kind() {
|
switch dst.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
src = strings.TrimSpace(src)
|
// Avoid unnecessary TrimSpace if we can detect the format early
|
||||||
isMultiline := strings.ContainsRune(src, '\n')
|
srcLen := len(src)
|
||||||
|
if srcLen == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for multiline without allocating
|
||||||
|
isMultiline := false
|
||||||
|
for i := range srcLen {
|
||||||
|
if src[i] == '\n' {
|
||||||
|
isMultiline = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// one liner is comma separated list
|
// one liner is comma separated list
|
||||||
if !isMultiline && src[0] != '-' {
|
if !isMultiline && src[0] != '-' {
|
||||||
values := strutils.CommaSeperatedList(src)
|
values := strutils.CommaSeperatedList(src)
|
||||||
@@ -548,6 +569,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
|
|||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sl := []any{}
|
sl := []any{}
|
||||||
err := yaml.Unmarshal([]byte(src), &sl)
|
err := yaml.Unmarshal([]byte(src), &sl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user