buildDesignType builds a user type that represents the given external type. ref is the user type the data type being built is converted to or created from. It's used to compute the non-generated type field names and can be nil if no matching attribute exists.
(dt *expr.DataType, t reflect.Type, ref expr.DataType, recs ...dtRec)
| 659 | // from. It's used to compute the non-generated type field names and can be nil |
| 660 | // if no matching attribute exists. |
| 661 | func buildDesignType(dt *expr.DataType, t reflect.Type, ref expr.DataType, recs ...dtRec) error { |
| 662 | // check compatibility |
| 663 | if ref != nil { |
| 664 | if err := compatible(ref, t); err != nil { |
| 665 | return fmt.Errorf("%q: %w", t.Name(), err) |
| 666 | } |
| 667 | } |
| 668 | |
| 669 | // handle recursive data structures |
| 670 | var rec dtRec |
| 671 | if recs != nil { |
| 672 | rec = recs[0] |
| 673 | if s, ok := rec.seen[t.Name()]; ok { |
| 674 | *dt = s |
| 675 | return nil |
| 676 | } |
| 677 | } else { |
| 678 | rec.path = "<value>" |
| 679 | rec.seen = make(map[string]expr.DataType) |
| 680 | } |
| 681 | |
| 682 | switch t.Kind() { |
| 683 | case reflect.Bool: |
| 684 | *dt = expr.Boolean |
| 685 | |
| 686 | case reflect.Int: |
| 687 | *dt = expr.Int |
| 688 | |
| 689 | case reflect.Int32: |
| 690 | *dt = expr.Int32 |
| 691 | |
| 692 | case reflect.Int64: |
| 693 | *dt = expr.Int64 |
| 694 | |
| 695 | case reflect.Uint: |
| 696 | *dt = expr.UInt |
| 697 | |
| 698 | case reflect.Uint32: |
| 699 | *dt = expr.UInt32 |
| 700 | |
| 701 | case reflect.Uint64: |
| 702 | *dt = expr.UInt64 |
| 703 | |
| 704 | case reflect.Float32: |
| 705 | *dt = expr.Float32 |
| 706 | |
| 707 | case reflect.Float64: |
| 708 | *dt = expr.Float64 |
| 709 | |
| 710 | case reflect.String: |
| 711 | *dt = expr.String |
| 712 | |
| 713 | case reflect.Slice: |
| 714 | e := t.Elem() |
| 715 | if e.Kind() == reflect.Uint8 { |
| 716 | *dt = expr.Bytes |
| 717 | return nil |
| 718 | } |