diff --git a/cache.go b/cache.go index 6445b78..400dd45 100644 --- a/cache.go +++ b/cache.go @@ -8,6 +8,18 @@ import ( "sync/atomic" ) +type tagType uint8 + +const ( + typeDefault tagType = iota + typeOmitEmpty + typeNoStructLevel + typeStructOnly + typeDive + typeOr + typeExists +) + type structCache struct { lock sync.Mutex m atomic.Value // map[reflect.Type]*cStruct @@ -68,20 +80,15 @@ type cField struct { // TODO: investigate using enum instead of so many booleans, may be faster // but let's get the new cache system working first type cTag struct { - tag string - aliasTag string - actualAliasTag string - param string - hasAlias bool - isOmitEmpty bool - isNoStructLevel bool - isStructOnly bool - isDive bool - isOrVal bool - exists bool - hasTag bool - fn Func - next *cTag + tag string + aliasTag string + actualAliasTag string + param string + hasAlias bool + typeof tagType + hasTag bool + fn Func + next *cTag } // TODO: eliminate get and set functions from cache, they are pure overhead for nicer syntax. @@ -198,23 +205,23 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s switch t { case diveTag: - current.isDive = true + current.typeof = typeDive continue case omitempty: - current.isOmitEmpty = true + current.typeof = typeOmitEmpty continue case structOnlyTag: - current.isStructOnly = true + current.typeof = typeStructOnly continue case noStructLevelTag: - current.isNoStructLevel = true + current.typeof = typeNoStructLevel continue case existsTag: - current.exists = true + current.typeof = typeExists continue default: @@ -247,7 +254,9 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, fieldName))) } - current.isOrVal = len(orVals) > 1 + if len(orVals) > 1 { + current.typeof = typeOr + } if len(vals) > 1 { current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1) diff --git a/validator.go b/validator.go index 2ab85a3..fe3019e 100644 --- a/validator.go +++ b/validator.go @@ -548,7 +548,7 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec // structonly tag present don't tranverseFields // but must still check and run below struct level validation // if present - if first || ct == nil || !ct.isStructOnly { + if first || ct == nil || ct.typeof != typeStructOnly { for _, f := range cs.fields { @@ -584,7 +584,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect. return } - if ct.isOmitEmpty { + if ct.typeof == typeOmitEmpty { return } @@ -631,7 +631,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect. ct = ct.next } - if ct != nil && ct.isNoStructLevel { + if ct != nil && ct.typeof == typeNoStructLevel { return } @@ -652,12 +652,13 @@ OUTER: return } - if ct.exists { + switch ct.typeof { + + case typeExists: ct = ct.next continue - } - if ct.isOmitEmpty { + case typeOmitEmpty: if !HasValue(v, topStruct, currentStruct, current, typ, kind, blank) { return @@ -665,9 +666,8 @@ OUTER: ct = ct.next continue - } - if ct.isDive { + case typeDive: ct = ct.next @@ -692,9 +692,8 @@ OUTER: } return - } - if ct.isOrVal { + case typeOr: errTag := blank @@ -711,7 +710,7 @@ OUTER: return } - if !ct.isOrVal { + if ct.typeof != typeOr { continue OUTER } } @@ -755,29 +754,30 @@ OUTER: ct = ct.next } - } - if !ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) { + default: + if !ct.fn(v, topStruct, currentStruct, current, typ, kind, ct.param) { - ns := errPrefix + cf.Name + ns := errPrefix + cf.Name - errs[ns] = &FieldError{ - FieldNamespace: ns, - NameNamespace: nsPrefix + cf.AltName, - Name: cf.AltName, - Field: cf.Name, - Tag: ct.aliasTag, - ActualTag: ct.tag, - Value: current.Interface(), - Param: ct.param, - Type: typ, - Kind: kind, - } + errs[ns] = &FieldError{ + FieldNamespace: ns, + NameNamespace: nsPrefix + cf.AltName, + Name: cf.AltName, + Field: cf.Name, + Tag: ct.aliasTag, + ActualTag: ct.tag, + Value: current.Interface(), + Param: ct.param, + Type: typ, + Kind: kind, + } - return + return - } + } - ct = ct.next + ct = ct.next + } } }