27 // represented by []T, but the Go type passed in is just T). |
27 // represented by []T, but the Go type passed in is just T). |
28 // A list of enum value descriptors must be provided for enum fields. |
28 // A list of enum value descriptors must be provided for enum fields. |
29 // This does not populate the Enum or Message (except for weak message). |
29 // This does not populate the Enum or Message (except for weak message). |
30 // |
30 // |
31 // This function is a best effort attempt; parsing errors are ignored. |
31 // This function is a best effort attempt; parsing errors are ignored. |
32 func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) pref.FieldDescriptor { |
32 func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor { |
33 f := new(fdesc.Field) |
33 f := new(filedesc.Field) |
34 f.L0.ParentFile = fdesc.SurrogateProto2 |
34 f.L0.ParentFile = filedesc.SurrogateProto2 |
35 for len(tag) > 0 { |
35 for len(tag) > 0 { |
36 i := strings.IndexByte(tag, ',') |
36 i := strings.IndexByte(tag, ',') |
37 if i < 0 { |
37 if i < 0 { |
38 i = len(tag) |
38 i = len(tag) |
39 } |
39 } |
40 switch s := tag[:i]; { |
40 switch s := tag[:i]; { |
41 case strings.HasPrefix(s, "name="): |
41 case strings.HasPrefix(s, "name="): |
42 f.L0.FullName = pref.FullName(s[len("name="):]) |
42 f.L0.FullName = protoreflect.FullName(s[len("name="):]) |
43 case strings.Trim(s, "0123456789") == "": |
43 case strings.Trim(s, "0123456789") == "": |
44 n, _ := strconv.ParseUint(s, 10, 32) |
44 n, _ := strconv.ParseUint(s, 10, 32) |
45 f.L1.Number = pref.FieldNumber(n) |
45 f.L1.Number = protoreflect.FieldNumber(n) |
46 case s == "opt": |
46 case s == "opt": |
47 f.L1.Cardinality = pref.Optional |
47 f.L1.Cardinality = protoreflect.Optional |
48 case s == "req": |
48 case s == "req": |
49 f.L1.Cardinality = pref.Required |
49 f.L1.Cardinality = protoreflect.Required |
50 case s == "rep": |
50 case s == "rep": |
51 f.L1.Cardinality = pref.Repeated |
51 f.L1.Cardinality = protoreflect.Repeated |
52 case s == "varint": |
52 case s == "varint": |
53 switch goType.Kind() { |
53 switch goType.Kind() { |
54 case reflect.Bool: |
54 case reflect.Bool: |
55 f.L1.Kind = pref.BoolKind |
55 f.L1.Kind = protoreflect.BoolKind |
56 case reflect.Int32: |
56 case reflect.Int32: |
57 f.L1.Kind = pref.Int32Kind |
57 f.L1.Kind = protoreflect.Int32Kind |
58 case reflect.Int64: |
58 case reflect.Int64: |
59 f.L1.Kind = pref.Int64Kind |
59 f.L1.Kind = protoreflect.Int64Kind |
60 case reflect.Uint32: |
60 case reflect.Uint32: |
61 f.L1.Kind = pref.Uint32Kind |
61 f.L1.Kind = protoreflect.Uint32Kind |
62 case reflect.Uint64: |
62 case reflect.Uint64: |
63 f.L1.Kind = pref.Uint64Kind |
63 f.L1.Kind = protoreflect.Uint64Kind |
64 } |
64 } |
65 case s == "zigzag32": |
65 case s == "zigzag32": |
66 if goType.Kind() == reflect.Int32 { |
66 if goType.Kind() == reflect.Int32 { |
67 f.L1.Kind = pref.Sint32Kind |
67 f.L1.Kind = protoreflect.Sint32Kind |
68 } |
68 } |
69 case s == "zigzag64": |
69 case s == "zigzag64": |
70 if goType.Kind() == reflect.Int64 { |
70 if goType.Kind() == reflect.Int64 { |
71 f.L1.Kind = pref.Sint64Kind |
71 f.L1.Kind = protoreflect.Sint64Kind |
72 } |
72 } |
73 case s == "fixed32": |
73 case s == "fixed32": |
74 switch goType.Kind() { |
74 switch goType.Kind() { |
75 case reflect.Int32: |
75 case reflect.Int32: |
76 f.L1.Kind = pref.Sfixed32Kind |
76 f.L1.Kind = protoreflect.Sfixed32Kind |
77 case reflect.Uint32: |
77 case reflect.Uint32: |
78 f.L1.Kind = pref.Fixed32Kind |
78 f.L1.Kind = protoreflect.Fixed32Kind |
79 case reflect.Float32: |
79 case reflect.Float32: |
80 f.L1.Kind = pref.FloatKind |
80 f.L1.Kind = protoreflect.FloatKind |
81 } |
81 } |
82 case s == "fixed64": |
82 case s == "fixed64": |
83 switch goType.Kind() { |
83 switch goType.Kind() { |
84 case reflect.Int64: |
84 case reflect.Int64: |
85 f.L1.Kind = pref.Sfixed64Kind |
85 f.L1.Kind = protoreflect.Sfixed64Kind |
86 case reflect.Uint64: |
86 case reflect.Uint64: |
87 f.L1.Kind = pref.Fixed64Kind |
87 f.L1.Kind = protoreflect.Fixed64Kind |
88 case reflect.Float64: |
88 case reflect.Float64: |
89 f.L1.Kind = pref.DoubleKind |
89 f.L1.Kind = protoreflect.DoubleKind |
90 } |
90 } |
91 case s == "bytes": |
91 case s == "bytes": |
92 switch { |
92 switch { |
93 case goType.Kind() == reflect.String: |
93 case goType.Kind() == reflect.String: |
94 f.L1.Kind = pref.StringKind |
94 f.L1.Kind = protoreflect.StringKind |
95 case goType.Kind() == reflect.Slice && goType.Elem() == byteType: |
95 case goType.Kind() == reflect.Slice && goType.Elem() == byteType: |
96 f.L1.Kind = pref.BytesKind |
96 f.L1.Kind = protoreflect.BytesKind |
97 default: |
97 default: |
98 f.L1.Kind = pref.MessageKind |
98 f.L1.Kind = protoreflect.MessageKind |
99 } |
99 } |
100 case s == "group": |
100 case s == "group": |
101 f.L1.Kind = pref.GroupKind |
101 f.L1.Kind = protoreflect.GroupKind |
102 case strings.HasPrefix(s, "enum="): |
102 case strings.HasPrefix(s, "enum="): |
103 f.L1.Kind = pref.EnumKind |
103 f.L1.Kind = protoreflect.EnumKind |
104 case strings.HasPrefix(s, "json="): |
104 case strings.HasPrefix(s, "json="): |
105 jsonName := s[len("json="):] |
105 jsonName := s[len("json="):] |
106 if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) { |
106 if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) { |
107 f.L1.StringName.InitJSON(jsonName) |
107 f.L1.StringName.InitJSON(jsonName) |
108 } |
108 } |
109 case s == "packed": |
109 case s == "packed": |
110 f.L1.HasPacked = true |
110 f.L1.HasPacked = true |
111 f.L1.IsPacked = true |
111 f.L1.IsPacked = true |
112 case strings.HasPrefix(s, "weak="): |
112 case strings.HasPrefix(s, "weak="): |
113 f.L1.IsWeak = true |
113 f.L1.IsWeak = true |
114 f.L1.Message = fdesc.PlaceholderMessage(pref.FullName(s[len("weak="):])) |
114 f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):])) |
115 case strings.HasPrefix(s, "def="): |
115 case strings.HasPrefix(s, "def="): |
116 // The default tag is special in that everything afterwards is the |
116 // The default tag is special in that everything afterwards is the |
117 // default regardless of the presence of commas. |
117 // default regardless of the presence of commas. |
118 s, i = tag[len("def="):], len(tag) |
118 s, i = tag[len("def="):], len(tag) |
119 v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag) |
119 v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag) |
120 f.L1.Default = fdesc.DefaultValue(v, ev) |
120 f.L1.Default = filedesc.DefaultValue(v, ev) |
121 case s == "proto3": |
121 case s == "proto3": |
122 f.L0.ParentFile = fdesc.SurrogateProto3 |
122 f.L0.ParentFile = filedesc.SurrogateProto3 |
123 } |
123 } |
124 tag = strings.TrimPrefix(tag[i:], ",") |
124 tag = strings.TrimPrefix(tag[i:], ",") |
125 } |
125 } |
126 |
126 |
127 // The generator uses the group message name instead of the field name. |
127 // The generator uses the group message name instead of the field name. |
128 // We obtain the real field name by lowercasing the group name. |
128 // We obtain the real field name by lowercasing the group name. |
129 if f.L1.Kind == pref.GroupKind { |
129 if f.L1.Kind == protoreflect.GroupKind { |
130 f.L0.FullName = pref.FullName(strings.ToLower(string(f.L0.FullName))) |
130 f.L0.FullName = protoreflect.FullName(strings.ToLower(string(f.L0.FullName))) |
131 } |
131 } |
132 return f |
132 return f |
133 } |
133 } |
134 |
134 |
135 // Marshal encodes the protoreflect.FieldDescriptor as a tag. |
135 // Marshal encodes the protoreflect.FieldDescriptor as a tag. |
138 // Historically, the formulation of the enum "name" was the proto package |
138 // Historically, the formulation of the enum "name" was the proto package |
139 // dot-concatenated with the generated Go identifier for the enum type. |
139 // dot-concatenated with the generated Go identifier for the enum type. |
140 // Depending on the context on how Marshal is called, there are different ways |
140 // Depending on the context on how Marshal is called, there are different ways |
141 // through which that information is determined. As such it is the caller's |
141 // through which that information is determined. As such it is the caller's |
142 // responsibility to provide a function to obtain that information. |
142 // responsibility to provide a function to obtain that information. |
143 func Marshal(fd pref.FieldDescriptor, enumName string) string { |
143 func Marshal(fd protoreflect.FieldDescriptor, enumName string) string { |
144 var tag []string |
144 var tag []string |
145 switch fd.Kind() { |
145 switch fd.Kind() { |
146 case pref.BoolKind, pref.EnumKind, pref.Int32Kind, pref.Uint32Kind, pref.Int64Kind, pref.Uint64Kind: |
146 case protoreflect.BoolKind, protoreflect.EnumKind, protoreflect.Int32Kind, protoreflect.Uint32Kind, protoreflect.Int64Kind, protoreflect.Uint64Kind: |
147 tag = append(tag, "varint") |
147 tag = append(tag, "varint") |
148 case pref.Sint32Kind: |
148 case protoreflect.Sint32Kind: |
149 tag = append(tag, "zigzag32") |
149 tag = append(tag, "zigzag32") |
150 case pref.Sint64Kind: |
150 case protoreflect.Sint64Kind: |
151 tag = append(tag, "zigzag64") |
151 tag = append(tag, "zigzag64") |
152 case pref.Sfixed32Kind, pref.Fixed32Kind, pref.FloatKind: |
152 case protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.FloatKind: |
153 tag = append(tag, "fixed32") |
153 tag = append(tag, "fixed32") |
154 case pref.Sfixed64Kind, pref.Fixed64Kind, pref.DoubleKind: |
154 case protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.DoubleKind: |
155 tag = append(tag, "fixed64") |
155 tag = append(tag, "fixed64") |
156 case pref.StringKind, pref.BytesKind, pref.MessageKind: |
156 case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind: |
157 tag = append(tag, "bytes") |
157 tag = append(tag, "bytes") |
158 case pref.GroupKind: |
158 case protoreflect.GroupKind: |
159 tag = append(tag, "group") |
159 tag = append(tag, "group") |
160 } |
160 } |
161 tag = append(tag, strconv.Itoa(int(fd.Number()))) |
161 tag = append(tag, strconv.Itoa(int(fd.Number()))) |
162 switch fd.Cardinality() { |
162 switch fd.Cardinality() { |
163 case pref.Optional: |
163 case protoreflect.Optional: |
164 tag = append(tag, "opt") |
164 tag = append(tag, "opt") |
165 case pref.Required: |
165 case protoreflect.Required: |
166 tag = append(tag, "req") |
166 tag = append(tag, "req") |
167 case pref.Repeated: |
167 case protoreflect.Repeated: |
168 tag = append(tag, "rep") |
168 tag = append(tag, "rep") |
169 } |
169 } |
170 if fd.IsPacked() { |
170 if fd.IsPacked() { |
171 tag = append(tag, "packed") |
171 tag = append(tag, "packed") |
172 } |
172 } |
173 name := string(fd.Name()) |
173 name := string(fd.Name()) |
174 if fd.Kind() == pref.GroupKind { |
174 if fd.Kind() == protoreflect.GroupKind { |
175 // The name of the FieldDescriptor for a group field is |
175 // The name of the FieldDescriptor for a group field is |
176 // lowercased. To find the original capitalization, we |
176 // lowercased. To find the original capitalization, we |
177 // look in the field's MessageType. |
177 // look in the field's MessageType. |
178 name = string(fd.Message().Name()) |
178 name = string(fd.Message().Name()) |
179 } |
179 } |