(ctx context.Context, dst reflect.Value, depth int, m map[string][]graph.Ref, tagPref string)
| 287 | } |
| 288 | |
| 289 | func (l *loader) loadToValue(ctx context.Context, dst reflect.Value, depth int, m map[string][]graph.Ref, tagPref string) error { |
| 290 | if ctx == nil { |
| 291 | ctx = context.TODO() |
| 292 | } |
| 293 | for dst.Kind() == reflect.Ptr { |
| 294 | dst = dst.Elem() |
| 295 | } |
| 296 | rt := dst.Type() |
| 297 | if rt.Kind() != reflect.Struct { |
| 298 | return fmt.Errorf("expected struct, got %v", rt) |
| 299 | } |
| 300 | var fields fieldRules |
| 301 | if v := ctx.Value(fieldsCtxKey{}); v != nil { |
| 302 | fields = v.(fieldRules) |
| 303 | } else { |
| 304 | nfields, err := l.c.rulesFor(rt) |
| 305 | if err != nil { |
| 306 | return err |
| 307 | } |
| 308 | fields = nfields |
| 309 | } |
| 310 | if depth != 0 { // do not check required fields if depth limit is reached |
| 311 | for name, field := range fields { |
| 312 | if r, ok := field.(saveRule); ok && !r.Opt { |
| 313 | if vals := m[name]; len(vals) == 0 { |
| 314 | return errRequiredFieldIsMissing |
| 315 | } |
| 316 | } |
| 317 | } |
| 318 | } |
| 319 | for i := 0; i < rt.NumField(); i++ { |
| 320 | select { |
| 321 | case <-ctx.Done(): |
| 322 | return ctx.Err() |
| 323 | default: |
| 324 | } |
| 325 | f := rt.Field(i) |
| 326 | name := f.Name |
| 327 | if err := checkFieldType(f.Type); err != nil { |
| 328 | return err |
| 329 | } |
| 330 | df := dst.Field(i) |
| 331 | if f.Anonymous { |
| 332 | if err := l.loadToValue(ctx, df, depth, m, tagPref+name+"."); err != nil { |
| 333 | return fmt.Errorf("load anonymous field %s failed: %v", f.Name, err) |
| 334 | } |
| 335 | continue |
| 336 | } |
| 337 | rules := fields[tagPref+name] |
| 338 | if rules == nil { |
| 339 | continue |
| 340 | } |
| 341 | arr, ok := m[tagPref+name] |
| 342 | if !ok || len(arr) == 0 { |
| 343 | continue |
| 344 | } |
| 345 | ft := f.Type |
| 346 | native := isNative(ft) |
no test coverage detected