validator_instance.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. package validator
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "reflect"
  7. "strings"
  8. "sync"
  9. "time"
  10. ut "github.com/go-playground/universal-translator"
  11. )
  12. const (
  13. defaultTagName = "validate"
  14. utf8HexComma = "0x2C"
  15. utf8Pipe = "0x7C"
  16. tagSeparator = ","
  17. orSeparator = "|"
  18. tagKeySeparator = "="
  19. structOnlyTag = "structonly"
  20. noStructLevelTag = "nostructlevel"
  21. omitempty = "omitempty"
  22. isdefault = "isdefault"
  23. skipValidationTag = "-"
  24. diveTag = "dive"
  25. keysTag = "keys"
  26. endKeysTag = "endkeys"
  27. requiredTag = "required"
  28. namespaceSeparator = "."
  29. leftBracket = "["
  30. rightBracket = "]"
  31. restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}"
  32. restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
  33. restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation"
  34. )
  35. var (
  36. timeType = reflect.TypeOf(time.Time{})
  37. defaultCField = &cField{namesEqual: true}
  38. )
  39. // FilterFunc is the type used to filter fields using
  40. // StructFiltered(...) function.
  41. // returning true results in the field being filtered/skiped from
  42. // validation
  43. type FilterFunc func(ns []byte) bool
  44. // CustomTypeFunc allows for overriding or adding custom field type handler functions
  45. // field = field value of the type to return a value to be validated
  46. // example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
  47. type CustomTypeFunc func(field reflect.Value) interface{}
  48. // TagNameFunc allows for adding of a custom tag name parser
  49. type TagNameFunc func(field reflect.StructField) string
  50. // Validate contains the validator settings and cache
  51. type Validate struct {
  52. tagName string
  53. pool *sync.Pool
  54. hasCustomFuncs bool
  55. hasTagNameFunc bool
  56. tagNameFunc TagNameFunc
  57. structLevelFuncs map[reflect.Type]StructLevelFuncCtx
  58. customFuncs map[reflect.Type]CustomTypeFunc
  59. aliases map[string]string
  60. validations map[string]FuncCtx
  61. transTagFunc map[ut.Translator]map[string]TranslationFunc // map[<locale>]map[<tag>]TranslationFunc
  62. tagCache *tagCache
  63. structCache *structCache
  64. }
  65. // New returns a new instacne of 'validate' with sane defaults.
  66. func New() *Validate {
  67. tc := new(tagCache)
  68. tc.m.Store(make(map[string]*cTag))
  69. sc := new(structCache)
  70. sc.m.Store(make(map[reflect.Type]*cStruct))
  71. v := &Validate{
  72. tagName: defaultTagName,
  73. aliases: make(map[string]string, len(bakedInAliases)),
  74. validations: make(map[string]FuncCtx, len(bakedInValidators)),
  75. tagCache: tc,
  76. structCache: sc,
  77. }
  78. // must copy alias validators for separate validations to be used in each validator instance
  79. for k, val := range bakedInAliases {
  80. v.RegisterAlias(k, val)
  81. }
  82. // must copy validators for separate validations to be used in each instance
  83. for k, val := range bakedInValidators {
  84. // no need to error check here, baked in will always be valid
  85. v.registerValidation(k, wrapFunc(val), true)
  86. }
  87. v.pool = &sync.Pool{
  88. New: func() interface{} {
  89. return &validate{
  90. v: v,
  91. ns: make([]byte, 0, 64),
  92. actualNs: make([]byte, 0, 64),
  93. misc: make([]byte, 32),
  94. }
  95. },
  96. }
  97. return v
  98. }
  99. // SetTagName allows for changing of the default tag name of 'validate'
  100. func (v *Validate) SetTagName(name string) {
  101. v.tagName = name
  102. }
  103. // RegisterTagNameFunc registers a function to get another name from the
  104. // StructField eg. the JSON name
  105. func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) {
  106. v.tagNameFunc = fn
  107. v.hasTagNameFunc = true
  108. }
  109. // RegisterValidation adds a validation with the given tag
  110. //
  111. // NOTES:
  112. // - if the key already exists, the previous validation function will be replaced.
  113. // - this method is not thread-safe it is intended that these all be registered prior to any validation
  114. func (v *Validate) RegisterValidation(tag string, fn Func) error {
  115. return v.RegisterValidationCtx(tag, wrapFunc(fn))
  116. }
  117. // RegisterValidationCtx does the same as RegisterValidation on accepts a FuncCtx validation
  118. // allowing context.Context validation support.
  119. func (v *Validate) RegisterValidationCtx(tag string, fn FuncCtx) error {
  120. return v.registerValidation(tag, fn, false)
  121. }
  122. func (v *Validate) registerValidation(tag string, fn FuncCtx, bakedIn bool) error {
  123. if len(tag) == 0 {
  124. return errors.New("Function Key cannot be empty")
  125. }
  126. if fn == nil {
  127. return errors.New("Function cannot be empty")
  128. }
  129. _, ok := restrictedTags[tag]
  130. if !bakedIn && (ok || strings.ContainsAny(tag, restrictedTagChars)) {
  131. panic(fmt.Sprintf(restrictedTagErr, tag))
  132. }
  133. v.validations[tag] = fn
  134. return nil
  135. }
  136. // RegisterAlias registers a mapping of a single validation tag that
  137. // defines a common or complex set of validation(s) to simplify adding validation
  138. // to structs.
  139. //
  140. // NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation
  141. func (v *Validate) RegisterAlias(alias, tags string) {
  142. _, ok := restrictedTags[alias]
  143. if ok || strings.ContainsAny(alias, restrictedTagChars) {
  144. panic(fmt.Sprintf(restrictedAliasErr, alias))
  145. }
  146. v.aliases[alias] = tags
  147. }
  148. // RegisterStructValidation registers a StructLevelFunc against a number of types.
  149. //
  150. // NOTE:
  151. // - this method is not thread-safe it is intended that these all be registered prior to any validation
  152. func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) {
  153. v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...)
  154. }
  155. // RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing
  156. // of contextual validation information via context.Context.
  157. //
  158. // NOTE:
  159. // - this method is not thread-safe it is intended that these all be registered prior to any validation
  160. func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) {
  161. if v.structLevelFuncs == nil {
  162. v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx)
  163. }
  164. for _, t := range types {
  165. v.structLevelFuncs[reflect.TypeOf(t)] = fn
  166. }
  167. }
  168. // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
  169. //
  170. // NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
  171. func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) {
  172. if v.customFuncs == nil {
  173. v.customFuncs = make(map[reflect.Type]CustomTypeFunc)
  174. }
  175. for _, t := range types {
  176. v.customFuncs[reflect.TypeOf(t)] = fn
  177. }
  178. v.hasCustomFuncs = true
  179. }
  180. // RegisterTranslation registers translations against the provided tag.
  181. func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) (err error) {
  182. if v.transTagFunc == nil {
  183. v.transTagFunc = make(map[ut.Translator]map[string]TranslationFunc)
  184. }
  185. if err = registerFn(trans); err != nil {
  186. return
  187. }
  188. m, ok := v.transTagFunc[trans]
  189. if !ok {
  190. m = make(map[string]TranslationFunc)
  191. v.transTagFunc[trans] = m
  192. }
  193. m[tag] = translationFn
  194. return
  195. }
  196. // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
  197. //
  198. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  199. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  200. func (v *Validate) Struct(s interface{}) error {
  201. return v.StructCtx(context.Background(), s)
  202. }
  203. // StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
  204. // and also allows passing of context.Context for contextual validation information.
  205. //
  206. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  207. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  208. func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) {
  209. val := reflect.ValueOf(s)
  210. top := val
  211. if val.Kind() == reflect.Ptr && !val.IsNil() {
  212. val = val.Elem()
  213. }
  214. if val.Kind() != reflect.Struct || val.Type() == timeType {
  215. return &InvalidValidationError{Type: reflect.TypeOf(s)}
  216. }
  217. // good to validate
  218. vd := v.pool.Get().(*validate)
  219. vd.top = top
  220. vd.isPartial = false
  221. // vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
  222. vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
  223. if len(vd.errs) > 0 {
  224. err = vd.errs
  225. vd.errs = nil
  226. }
  227. v.pool.Put(vd)
  228. return
  229. }
  230. // StructFiltered validates a structs exposed fields, that pass the FilterFunc check and automatically validates
  231. // nested structs, unless otherwise specified.
  232. //
  233. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  234. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  235. func (v *Validate) StructFiltered(s interface{}, fn FilterFunc) error {
  236. return v.StructFilteredCtx(context.Background(), s, fn)
  237. }
  238. // StructFilteredCtx validates a structs exposed fields, that pass the FilterFunc check and automatically validates
  239. // nested structs, unless otherwise specified and also allows passing of contextual validation information via
  240. // context.Context
  241. //
  242. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  243. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  244. func (v *Validate) StructFilteredCtx(ctx context.Context, s interface{}, fn FilterFunc) (err error) {
  245. val := reflect.ValueOf(s)
  246. top := val
  247. if val.Kind() == reflect.Ptr && !val.IsNil() {
  248. val = val.Elem()
  249. }
  250. if val.Kind() != reflect.Struct || val.Type() == timeType {
  251. return &InvalidValidationError{Type: reflect.TypeOf(s)}
  252. }
  253. // good to validate
  254. vd := v.pool.Get().(*validate)
  255. vd.top = top
  256. vd.isPartial = true
  257. vd.ffn = fn
  258. // vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
  259. vd.validateStruct(context.Background(), top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
  260. if len(vd.errs) > 0 {
  261. err = vd.errs
  262. vd.errs = nil
  263. }
  264. v.pool.Put(vd)
  265. return
  266. }
  267. // StructPartial validates the fields passed in only, ignoring all others.
  268. // Fields may be provided in a namespaced fashion relative to the struct provided
  269. // eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
  270. //
  271. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  272. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  273. func (v *Validate) StructPartial(s interface{}, fields ...string) error {
  274. return v.StructPartialCtx(context.Background(), s, fields...)
  275. }
  276. // StructPartialCtx validates the fields passed in only, ignoring all others and allows passing of contextual
  277. // validation validation information via context.Context
  278. // Fields may be provided in a namespaced fashion relative to the struct provided
  279. // eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
  280. //
  281. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  282. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  283. func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
  284. val := reflect.ValueOf(s)
  285. top := val
  286. if val.Kind() == reflect.Ptr && !val.IsNil() {
  287. val = val.Elem()
  288. }
  289. if val.Kind() != reflect.Struct || val.Type() == timeType {
  290. return &InvalidValidationError{Type: reflect.TypeOf(s)}
  291. }
  292. // good to validate
  293. vd := v.pool.Get().(*validate)
  294. vd.top = top
  295. vd.isPartial = true
  296. vd.ffn = nil
  297. vd.hasExcludes = false
  298. vd.includeExclude = make(map[string]struct{})
  299. typ := val.Type()
  300. name := typ.Name()
  301. if fields != nil {
  302. for _, k := range fields {
  303. flds := strings.Split(k, namespaceSeparator)
  304. if len(flds) > 0 {
  305. vd.misc = append(vd.misc[0:0], name...)
  306. vd.misc = append(vd.misc, '.')
  307. for _, s := range flds {
  308. idx := strings.Index(s, leftBracket)
  309. if idx != -1 {
  310. for idx != -1 {
  311. vd.misc = append(vd.misc, s[:idx]...)
  312. vd.includeExclude[string(vd.misc)] = struct{}{}
  313. idx2 := strings.Index(s, rightBracket)
  314. idx2++
  315. vd.misc = append(vd.misc, s[idx:idx2]...)
  316. vd.includeExclude[string(vd.misc)] = struct{}{}
  317. s = s[idx2:]
  318. idx = strings.Index(s, leftBracket)
  319. }
  320. } else {
  321. vd.misc = append(vd.misc, s...)
  322. vd.includeExclude[string(vd.misc)] = struct{}{}
  323. }
  324. vd.misc = append(vd.misc, '.')
  325. }
  326. }
  327. }
  328. }
  329. vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
  330. if len(vd.errs) > 0 {
  331. err = vd.errs
  332. vd.errs = nil
  333. }
  334. v.pool.Put(vd)
  335. return
  336. }
  337. // StructExcept validates all fields except the ones passed in.
  338. // Fields may be provided in a namespaced fashion relative to the struct provided
  339. // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
  340. //
  341. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  342. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  343. func (v *Validate) StructExcept(s interface{}, fields ...string) error {
  344. return v.StructExceptCtx(context.Background(), s, fields...)
  345. }
  346. // StructExceptCtx validates all fields except the ones passed in and allows passing of contextual
  347. // validation validation information via context.Context
  348. // Fields may be provided in a namespaced fashion relative to the struct provided
  349. // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
  350. //
  351. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  352. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  353. func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields ...string) (err error) {
  354. val := reflect.ValueOf(s)
  355. top := val
  356. if val.Kind() == reflect.Ptr && !val.IsNil() {
  357. val = val.Elem()
  358. }
  359. if val.Kind() != reflect.Struct || val.Type() == timeType {
  360. return &InvalidValidationError{Type: reflect.TypeOf(s)}
  361. }
  362. // good to validate
  363. vd := v.pool.Get().(*validate)
  364. vd.top = top
  365. vd.isPartial = true
  366. vd.ffn = nil
  367. vd.hasExcludes = true
  368. vd.includeExclude = make(map[string]struct{})
  369. typ := val.Type()
  370. name := typ.Name()
  371. for _, key := range fields {
  372. vd.misc = vd.misc[0:0]
  373. if len(name) > 0 {
  374. vd.misc = append(vd.misc, name...)
  375. vd.misc = append(vd.misc, '.')
  376. }
  377. vd.misc = append(vd.misc, key...)
  378. vd.includeExclude[string(vd.misc)] = struct{}{}
  379. }
  380. vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil)
  381. if len(vd.errs) > 0 {
  382. err = vd.errs
  383. vd.errs = nil
  384. }
  385. v.pool.Put(vd)
  386. return
  387. }
  388. // Var validates a single variable using tag style validation.
  389. // eg.
  390. // var i int
  391. // validate.Var(i, "gt=1,lt=10")
  392. //
  393. // WARNING: a struct can be passed for validation eg. time.Time is a struct or
  394. // if you have a custom type and have registered a custom type handler, so must
  395. // allow it; however unforseen validations will occur if trying to validate a
  396. // struct that is meant to be passed to 'validate.Struct'
  397. //
  398. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  399. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  400. // validate Array, Slice and maps fields which may contain more than one error
  401. func (v *Validate) Var(field interface{}, tag string) error {
  402. return v.VarCtx(context.Background(), field, tag)
  403. }
  404. // VarCtx validates a single variable using tag style validation and allows passing of contextual
  405. // validation validation information via context.Context.
  406. // eg.
  407. // var i int
  408. // validate.Var(i, "gt=1,lt=10")
  409. //
  410. // WARNING: a struct can be passed for validation eg. time.Time is a struct or
  411. // if you have a custom type and have registered a custom type handler, so must
  412. // allow it; however unforseen validations will occur if trying to validate a
  413. // struct that is meant to be passed to 'validate.Struct'
  414. //
  415. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  416. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  417. // validate Array, Slice and maps fields which may contain more than one error
  418. func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (err error) {
  419. if len(tag) == 0 || tag == skipValidationTag {
  420. return nil
  421. }
  422. // find cached tag
  423. ctag, ok := v.tagCache.Get(tag)
  424. if !ok {
  425. v.tagCache.lock.Lock()
  426. defer v.tagCache.lock.Unlock()
  427. // could have been multiple trying to access, but once first is done this ensures tag
  428. // isn't parsed again.
  429. ctag, ok = v.tagCache.Get(tag)
  430. if !ok {
  431. ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
  432. v.tagCache.Set(tag, ctag)
  433. }
  434. }
  435. val := reflect.ValueOf(field)
  436. vd := v.pool.Get().(*validate)
  437. vd.top = val
  438. vd.isPartial = false
  439. vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
  440. if len(vd.errs) > 0 {
  441. err = vd.errs
  442. vd.errs = nil
  443. }
  444. v.pool.Put(vd)
  445. return
  446. }
  447. // VarWithValue validates a single variable, against another variable/field's value using tag style validation
  448. // eg.
  449. // s1 := "abcd"
  450. // s2 := "abcd"
  451. // validate.VarWithValue(s1, s2, "eqcsfield") // returns true
  452. //
  453. // WARNING: a struct can be passed for validation eg. time.Time is a struct or
  454. // if you have a custom type and have registered a custom type handler, so must
  455. // allow it; however unforseen validations will occur if trying to validate a
  456. // struct that is meant to be passed to 'validate.Struct'
  457. //
  458. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  459. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  460. // validate Array, Slice and maps fields which may contain more than one error
  461. func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) error {
  462. return v.VarWithValueCtx(context.Background(), field, other, tag)
  463. }
  464. // VarWithValueCtx validates a single variable, against another variable/field's value using tag style validation and
  465. // allows passing of contextual validation validation information via context.Context.
  466. // eg.
  467. // s1 := "abcd"
  468. // s2 := "abcd"
  469. // validate.VarWithValue(s1, s2, "eqcsfield") // returns true
  470. //
  471. // WARNING: a struct can be passed for validation eg. time.Time is a struct or
  472. // if you have a custom type and have registered a custom type handler, so must
  473. // allow it; however unforseen validations will occur if trying to validate a
  474. // struct that is meant to be passed to 'validate.Struct'
  475. //
  476. // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
  477. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
  478. // validate Array, Slice and maps fields which may contain more than one error
  479. func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other interface{}, tag string) (err error) {
  480. if len(tag) == 0 || tag == skipValidationTag {
  481. return nil
  482. }
  483. // find cached tag
  484. ctag, ok := v.tagCache.Get(tag)
  485. if !ok {
  486. v.tagCache.lock.Lock()
  487. defer v.tagCache.lock.Unlock()
  488. // could have been multiple trying to access, but once first is done this ensures tag
  489. // isn't parsed again.
  490. ctag, ok = v.tagCache.Get(tag)
  491. if !ok {
  492. ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
  493. v.tagCache.Set(tag, ctag)
  494. }
  495. }
  496. otherVal := reflect.ValueOf(other)
  497. vd := v.pool.Get().(*validate)
  498. vd.top = otherVal
  499. vd.isPartial = false
  500. vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
  501. if len(vd.errs) > 0 {
  502. err = vd.errs
  503. vd.errs = nil
  504. }
  505. v.pool.Put(vd)
  506. return
  507. }