increase dive tag performance.

pull/256/head
joeybloggs 8 years ago
parent dcdba454d7
commit ecad6333b1
  1. 13
      cache.go
  2. 77
      validator.go
  3. 2
      validator_instance.go

@ -69,15 +69,16 @@ func (tc *tagCache) Set(key string, value *cTag) {
} }
type cStruct struct { type cStruct struct {
Name string name string
fields map[int]*cField fields map[int]*cField
fn StructLevelFunc fn StructLevelFunc
} }
type cField struct { type cField struct {
Idx int idx int
Name string name string
AltName string altName string
namesEqual bool
cTags *cTag cTags *cTag
} }
@ -107,7 +108,7 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
return cs return cs
} }
cs = &cStruct{Name: sName, fields: make(map[int]*cField), fn: v.structLevelFuncs[typ]} cs = &cStruct{name: sName, fields: make(map[int]*cField), fn: v.structLevelFuncs[typ]}
numFields := current.NumField() numFields := current.NumField()
@ -152,7 +153,7 @@ func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStr
ctag = new(cTag) ctag = new(cTag)
} }
cs.fields[i] = &cField{Idx: i, Name: fld.Name, AltName: customName, cTags: ctag} cs.fields[i] = &cField{idx: i, name: fld.Name, altName: customName, cTags: ctag, namesEqual: fld.Name == customName}
} }
v.structCache.Set(typ, cs) v.structCache.Set(typ, cs)

@ -35,10 +35,10 @@ func (v *validate) validateStruct(parent reflect.Value, current reflect.Value, t
if len(ns) == 0 { if len(ns) == 0 {
ns = append(ns, cs.Name...) ns = append(ns, cs.name...)
ns = append(ns, '.') ns = append(ns, '.')
structNs = append(structNs, cs.Name...) structNs = append(structNs, cs.name...)
structNs = append(structNs, '.') structNs = append(structNs, '.')
} }
@ -50,14 +50,14 @@ func (v *validate) validateStruct(parent reflect.Value, current reflect.Value, t
if v.isPartial { if v.isPartial {
_, ok = v.includeExclude[string(append(structNs, f.Name...))] _, ok = v.includeExclude[string(append(structNs, f.name...))]
if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) { if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) {
continue continue
} }
} }
v.traverseField(parent, current.Field(f.Idx), ns, structNs, f, f.cTags) v.traverseField(parent, current.Field(f.idx), ns, structNs, f, f.cTags)
} }
} }
@ -103,10 +103,10 @@ func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns
&fieldError{ &fieldError{
tag: ct.aliasTag, tag: ct.aliasTag,
actualTag: ct.tag, actualTag: ct.tag,
ns: string(append(ns, cf.AltName...)), ns: string(append(ns, cf.altName...)),
structNs: string(append(structNs, cf.Name...)), structNs: string(append(structNs, cf.name...)),
field: cf.AltName, field: cf.altName,
structField: cf.Name, structField: cf.name,
param: ct.param, param: ct.param,
kind: kind, kind: kind,
}, },
@ -119,10 +119,10 @@ func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns
&fieldError{ &fieldError{
tag: ct.aliasTag, tag: ct.aliasTag,
actualTag: ct.tag, actualTag: ct.tag,
ns: string(append(ns, cf.AltName...)), ns: string(append(ns, cf.altName...)),
structNs: string(append(structNs, cf.Name...)), structNs: string(append(structNs, cf.name...)),
field: cf.AltName, field: cf.altName,
structField: cf.Name, structField: cf.name,
value: current.Interface(), value: current.Interface(),
param: ct.param, param: ct.param,
kind: kind, kind: kind,
@ -152,8 +152,8 @@ func (v *validate) traverseField(parent reflect.Value, current reflect.Value, ns
// VarWithField - this allows for validating against each field withing the struct against a specific value // VarWithField - this allows for validating against each field withing the struct against a specific value
// pretty handly in certain situations // pretty handly in certain situations
if len(ns) > 0 { if len(ns) > 0 {
ns = append(append(ns, cf.AltName...), '.') ns = append(append(ns, cf.altName...), '.')
structNs = append(append(structNs, cf.Name...), '.') structNs = append(append(structNs, cf.name...), '.')
} }
v.validateStruct(current, current, typ, ns, structNs, ct) v.validateStruct(current, current, typ, ns, structNs, ct)
@ -205,19 +205,24 @@ OUTER:
i64 = int64(i) i64 = int64(i)
v.misc = append(v.misc[0:0], cf.Name...) v.misc = append(v.misc[0:0], cf.name...)
v.misc = append(v.misc, '[') v.misc = append(v.misc, '[')
v.misc = strconv.AppendInt(v.misc, i64, 10) v.misc = strconv.AppendInt(v.misc, i64, 10)
v.misc = append(v.misc, ']') v.misc = append(v.misc, ']')
reusableCF.Name = string(v.misc) reusableCF.name = string(v.misc)
v.misc = append(v.misc[0:0], cf.AltName...) if cf.namesEqual {
reusableCF.altName = reusableCF.name
} else {
v.misc = append(v.misc[0:0], cf.altName...)
v.misc = append(v.misc, '[') v.misc = append(v.misc, '[')
v.misc = strconv.AppendInt(v.misc, i64, 10) v.misc = strconv.AppendInt(v.misc, i64, 10)
v.misc = append(v.misc, ']') v.misc = append(v.misc, ']')
reusableCF.AltName = string(v.misc) reusableCF.altName = string(v.misc)
}
v.traverseField(parent, current.Index(i), ns, structNs, reusableCF, ct) v.traverseField(parent, current.Index(i), ns, structNs, reusableCF, ct)
} }
@ -231,19 +236,23 @@ OUTER:
pv = fmt.Sprintf("%v", key.Interface()) pv = fmt.Sprintf("%v", key.Interface())
v.misc = append(v.misc[0:0], cf.Name...) v.misc = append(v.misc[0:0], cf.name...)
v.misc = append(v.misc, '[') v.misc = append(v.misc, '[')
v.misc = append(v.misc, pv...) v.misc = append(v.misc, pv...)
v.misc = append(v.misc, ']') v.misc = append(v.misc, ']')
reusableCF.Name = string(v.misc) reusableCF.name = string(v.misc)
v.misc = append(v.misc[0:0], cf.AltName...) if cf.namesEqual {
reusableCF.altName = reusableCF.name
} else {
v.misc = append(v.misc[0:0], cf.altName...)
v.misc = append(v.misc, '[') v.misc = append(v.misc, '[')
v.misc = append(v.misc, pv...) v.misc = append(v.misc, pv...)
v.misc = append(v.misc, ']') v.misc = append(v.misc, ']')
reusableCF.AltName = string(v.misc) reusableCF.altName = string(v.misc)
}
v.traverseField(parent, current.MapIndex(key), ns, structNs, reusableCF, ct) v.traverseField(parent, current.MapIndex(key), ns, structNs, reusableCF, ct)
} }
@ -296,10 +305,10 @@ OUTER:
&fieldError{ &fieldError{
tag: ct.aliasTag, tag: ct.aliasTag,
actualTag: ct.actualAliasTag, actualTag: ct.actualAliasTag,
ns: string(append(ns, cf.AltName...)), ns: string(append(ns, cf.altName...)),
structNs: string(append(structNs, cf.Name...)), structNs: string(append(structNs, cf.name...)),
field: cf.AltName, field: cf.altName,
structField: cf.Name, structField: cf.name,
value: current.Interface(), value: current.Interface(),
param: ct.param, param: ct.param,
kind: kind, kind: kind,
@ -313,10 +322,10 @@ OUTER:
&fieldError{ &fieldError{
tag: string(v.misc)[1:], tag: string(v.misc)[1:],
actualTag: string(v.misc)[1:], actualTag: string(v.misc)[1:],
ns: string(append(ns, cf.AltName...)), ns: string(append(ns, cf.altName...)),
structNs: string(append(structNs, cf.Name...)), structNs: string(append(structNs, cf.name...)),
field: cf.AltName, field: cf.altName,
structField: cf.Name, structField: cf.name,
value: current.Interface(), value: current.Interface(),
param: ct.param, param: ct.param,
kind: kind, kind: kind,
@ -344,10 +353,10 @@ OUTER:
&fieldError{ &fieldError{
tag: ct.aliasTag, tag: ct.aliasTag,
actualTag: ct.tag, actualTag: ct.tag,
ns: string(append(ns, cf.AltName...)), ns: string(append(ns, cf.altName...)),
structNs: string(append(structNs, cf.Name...)), structNs: string(append(structNs, cf.name...)),
field: cf.AltName, field: cf.altName,
structField: cf.Name, structField: cf.name,
value: current.Interface(), value: current.Interface(),
param: ct.param, param: ct.param,
kind: kind, kind: kind,

@ -31,7 +31,7 @@ const (
var ( var (
timeType = reflect.TypeOf(time.Time{}) timeType = reflect.TypeOf(time.Time{})
defaultCField = new(cField) defaultCField = &cField{namesEqual: true}
) )
// CustomTypeFunc allows for overriding or adding custom field type handler functions // CustomTypeFunc allows for overriding or adding custom field type handler functions

Loading…
Cancel
Save