MCPcopy Create free account
hub / github.com/brimdata/super / structToUnpackRule

Function structToUnpackRule

pkg/unpack/tag.go:46–102  ·  view source on GitHub ↗

structToRule looks through the tags in a struct to (1) make sure there are no duplicate tags since package json doesn't do this and it results in hard-to-debug behaviors, and (2) it finds an "unpack" tag which indicates which field of the struct to use as the key and what value to match for unmarshl

(typ reflect.Type)

Source from the content-addressed store, hash-verified

44// tag, then an error is returned.
45// unpack="key,skip" unpack="key", unpack="", or unpack="skip"
46func structToUnpackRule(typ reflect.Type) (string, string, bool, error) {
47 if typ.Kind() != reflect.Struct {
48 return "", "", false, fmt.Errorf("cannot unpack into non-struct type '%s'", typ)
49 }
50 names := make(map[string]struct{})
51 var unpackKey string
52 var unpackVal string
53 var unpackSkip bool
54 for k := range typ.NumField() {
55 field := typ.Field(k)
56 jsonField, jsonOk, _ := parseTag(tagJSON, field)
57 if jsonOk {
58 if _, ok := names[jsonField]; ok {
59 return "", "", false, fmt.Errorf("JSON field tag '%s' in struct type '%s' not unique", jsonField, typ.Name())
60 }
61 names[jsonField] = struct{}{}
62 }
63 unpackOpt, unpackOk, opts := parseTag(tagUnpack, field)
64 if !unpackOk {
65 continue
66 }
67 if jsonField == "-" {
68 return "", "", false, fmt.Errorf("unpack: cannot unpack field '%s' of struct type '%s' with JSON tag '-'", field.Name, typ.Name())
69 }
70 if len(opts) > 1 {
71 return "", "", false, fmt.Errorf("unpack: too many tag options in field '%s' of struct type '%s'", field.Name, typ.Name())
72 }
73 var skip bool
74 if len(opts) == 1 {
75 if opts[0] != "skip" {
76 return "", "", false, fmt.Errorf("unpack: second tag option in field '%s' of struct type '%s' may only be 'skip'", field.Name, typ.Name())
77 }
78 skip = true
79 }
80 if skip {
81 if unpackSkip {
82 return "", "", false, ErrSkip
83 }
84 unpackSkip = true
85 }
86 if unpackKey != "" {
87 return "", "", false, fmt.Errorf("unpack key appears twice in field '%s' of struct type '%s' may only be 'skip'", field.Name, typ.Name())
88 }
89 if jsonField == "" {
90 jsonField = field.Name
91 }
92 if unpackOpt == "" {
93 unpackOpt = typ.Name()
94 if unpackOpt == "" {
95 return "", "", false, fmt.Errorf("unpack tag missing value struct type is nameless in field '%s' of struct '%s' may only be 'skip'", field.Name, typ.String())
96 }
97 }
98 unpackKey = jsonField
99 unpackVal = unpackOpt
100 }
101 return unpackKey, unpackVal, unpackSkip, nil
102}

Callers 1

AddAsMethod · 0.85

Calls 3

parseTagFunction · 0.85
KindMethod · 0.65
StringMethod · 0.65

Tested by

no test coverage detected