parent and current will be the same the first run of validateStruct
(ctx context.Context, parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag)
| 32 | |
| 33 | // parent and current will be the same the first run of validateStruct |
| 34 | func (v *validate) validateStruct(ctx context.Context, parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) { |
| 35 | cs, ok := v.v.structCache.Get(typ) |
| 36 | if !ok { |
| 37 | cs = v.v.extractStructCache(current, typ.Name()) |
| 38 | } |
| 39 | |
| 40 | if len(ns) == 0 && len(cs.name) != 0 { |
| 41 | ns = append(ns, cs.name...) |
| 42 | ns = append(ns, '.') |
| 43 | |
| 44 | structNs = append(structNs, cs.name...) |
| 45 | structNs = append(structNs, '.') |
| 46 | } |
| 47 | |
| 48 | // ct is nil on top level struct, and structs as fields that have no tag info |
| 49 | // so if nil or if not nil and the structonly tag isn't present |
| 50 | if ct == nil || ct.typeof != typeStructOnly { |
| 51 | var f *cField |
| 52 | |
| 53 | for i := 0; i < len(cs.fields); i++ { |
| 54 | f = cs.fields[i] |
| 55 | |
| 56 | if v.isPartial { |
| 57 | if v.ffn != nil { |
| 58 | // used with StructFiltered |
| 59 | if v.ffn(append(structNs, f.name...)) { |
| 60 | continue |
| 61 | } |
| 62 | } else { |
| 63 | // used with StructPartial & StructExcept |
| 64 | _, ok = v.includeExclude[string(append(structNs, f.name...))] |
| 65 | |
| 66 | if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) { |
| 67 | continue |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | // check if any struct level validations, after all field validations already checked. |
| 77 | // first iteration will have no info about nostructlevel tag, and is checked prior to |
| 78 | // calling the next iteration of validateStruct called from traverseField. |
| 79 | if cs.fn != nil { |
| 80 | v.slflParent = parent |
| 81 | v.slCurrent = current |
| 82 | v.ns = ns |
| 83 | v.actualNs = structNs |
| 84 | |
| 85 | cs.fn(ctx, v) |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | // traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options |
| 90 | func (v *validate) traverseField(ctx context.Context, parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) { |
no test coverage detected