(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool)
| 475 | } |
| 476 | |
| 477 | func constructStructType(t reflect.Type, seen map[reflect.Type]*structType, canAddr bool) *structType { |
| 478 | // Used for preventing infinite recursion on types that have pointers to |
| 479 | // themselves. |
| 480 | st := seen[t] |
| 481 | |
| 482 | if st == nil { |
| 483 | st = &structType{ |
| 484 | fields: make([]structField, 0, t.NumField()), |
| 485 | fieldsIndex: make(map[string]*structField), |
| 486 | ficaseIndex: make(map[string]*structField), |
| 487 | typ: t, |
| 488 | } |
| 489 | |
| 490 | seen[t] = st |
| 491 | st.fields = appendStructFields(st.fields, t, 0, seen, canAddr) |
| 492 | |
| 493 | for i := range st.fields { |
| 494 | f := &st.fields[i] |
| 495 | s := strings.ToLower(f.name) |
| 496 | st.fieldsIndex[f.name] = f |
| 497 | // When there is ambiguity because multiple fields have the same |
| 498 | // case-insensitive representation, the first field must win. |
| 499 | if _, exists := st.ficaseIndex[s]; !exists { |
| 500 | st.ficaseIndex[s] = f |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | // At a certain point the linear scan provided by keyset is less |
| 505 | // efficient than a map. The 32 was chosen based on benchmarks in the |
| 506 | // segmentio/asm repo run with an Intel Kaby Lake processor and go1.17. |
| 507 | if len(st.fields) <= 32 { |
| 508 | keys := make([][]byte, len(st.fields)) |
| 509 | for i, f := range st.fields { |
| 510 | keys[i] = []byte(f.name) |
| 511 | } |
| 512 | st.keyset = keyset.New(keys) |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | return st |
| 517 | } |
| 518 | |
| 519 | func constructStructEncodeFunc(st *structType) encodeFunc { |
| 520 | return func(e encoder, b []byte, p unsafe.Pointer) ([]byte, error) { |
no test coverage detected
searching dependent graphs…