1
2
3
4
5
6
7 package tag
8
9 import (
10 "reflect"
11 "strconv"
12 "strings"
13
14 "google.golang.org/protobuf/internal/encoding/defval"
15 "google.golang.org/protobuf/internal/filedesc"
16 "google.golang.org/protobuf/internal/strs"
17 "google.golang.org/protobuf/reflect/protoreflect"
18 )
19
20 var byteType = reflect.TypeOf(byte(0))
21
22
23
24
25
26
27
28
29
30
31
32 func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor {
33 f := new(filedesc.Field)
34 f.L0.ParentFile = filedesc.SurrogateProto2
35 for len(tag) > 0 {
36 i := strings.IndexByte(tag, ',')
37 if i < 0 {
38 i = len(tag)
39 }
40 switch s := tag[:i]; {
41 case strings.HasPrefix(s, "name="):
42 f.L0.FullName = protoreflect.FullName(s[len("name="):])
43 case strings.Trim(s, "0123456789") == "":
44 n, _ := strconv.ParseUint(s, 10, 32)
45 f.L1.Number = protoreflect.FieldNumber(n)
46 case s == "opt":
47 f.L1.Cardinality = protoreflect.Optional
48 case s == "req":
49 f.L1.Cardinality = protoreflect.Required
50 case s == "rep":
51 f.L1.Cardinality = protoreflect.Repeated
52 case s == "varint":
53 switch goType.Kind() {
54 case reflect.Bool:
55 f.L1.Kind = protoreflect.BoolKind
56 case reflect.Int32:
57 f.L1.Kind = protoreflect.Int32Kind
58 case reflect.Int64:
59 f.L1.Kind = protoreflect.Int64Kind
60 case reflect.Uint32:
61 f.L1.Kind = protoreflect.Uint32Kind
62 case reflect.Uint64:
63 f.L1.Kind = protoreflect.Uint64Kind
64 }
65 case s == "zigzag32":
66 if goType.Kind() == reflect.Int32 {
67 f.L1.Kind = protoreflect.Sint32Kind
68 }
69 case s == "zigzag64":
70 if goType.Kind() == reflect.Int64 {
71 f.L1.Kind = protoreflect.Sint64Kind
72 }
73 case s == "fixed32":
74 switch goType.Kind() {
75 case reflect.Int32:
76 f.L1.Kind = protoreflect.Sfixed32Kind
77 case reflect.Uint32:
78 f.L1.Kind = protoreflect.Fixed32Kind
79 case reflect.Float32:
80 f.L1.Kind = protoreflect.FloatKind
81 }
82 case s == "fixed64":
83 switch goType.Kind() {
84 case reflect.Int64:
85 f.L1.Kind = protoreflect.Sfixed64Kind
86 case reflect.Uint64:
87 f.L1.Kind = protoreflect.Fixed64Kind
88 case reflect.Float64:
89 f.L1.Kind = protoreflect.DoubleKind
90 }
91 case s == "bytes":
92 switch {
93 case goType.Kind() == reflect.String:
94 f.L1.Kind = protoreflect.StringKind
95 case goType.Kind() == reflect.Slice && goType.Elem() == byteType:
96 f.L1.Kind = protoreflect.BytesKind
97 default:
98 f.L1.Kind = protoreflect.MessageKind
99 }
100 case s == "group":
101 f.L1.Kind = protoreflect.GroupKind
102 case strings.HasPrefix(s, "enum="):
103 f.L1.Kind = protoreflect.EnumKind
104 case strings.HasPrefix(s, "json="):
105 jsonName := s[len("json="):]
106 if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) {
107 f.L1.StringName.InitJSON(jsonName)
108 }
109 case s == "packed":
110 f.L1.HasPacked = true
111 f.L1.IsPacked = true
112 case strings.HasPrefix(s, "weak="):
113 f.L1.IsWeak = true
114 f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):]))
115 case strings.HasPrefix(s, "def="):
116
117
118 s, i = tag[len("def="):], len(tag)
119 v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag)
120 f.L1.Default = filedesc.DefaultValue(v, ev)
121 case s == "proto3":
122 f.L0.ParentFile = filedesc.SurrogateProto3
123 }
124 tag = strings.TrimPrefix(tag[i:], ",")
125 }
126
127
128
129 if f.L1.Kind == protoreflect.GroupKind {
130 f.L0.FullName = protoreflect.FullName(strings.ToLower(string(f.L0.FullName)))
131 }
132 return f
133 }
134
135
136
137
138
139
140
141
142
143 func Marshal(fd protoreflect.FieldDescriptor, enumName string) string {
144 var tag []string
145 switch fd.Kind() {
146 case protoreflect.BoolKind, protoreflect.EnumKind, protoreflect.Int32Kind, protoreflect.Uint32Kind, protoreflect.Int64Kind, protoreflect.Uint64Kind:
147 tag = append(tag, "varint")
148 case protoreflect.Sint32Kind:
149 tag = append(tag, "zigzag32")
150 case protoreflect.Sint64Kind:
151 tag = append(tag, "zigzag64")
152 case protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.FloatKind:
153 tag = append(tag, "fixed32")
154 case protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.DoubleKind:
155 tag = append(tag, "fixed64")
156 case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind:
157 tag = append(tag, "bytes")
158 case protoreflect.GroupKind:
159 tag = append(tag, "group")
160 }
161 tag = append(tag, strconv.Itoa(int(fd.Number())))
162 switch fd.Cardinality() {
163 case protoreflect.Optional:
164 tag = append(tag, "opt")
165 case protoreflect.Required:
166 tag = append(tag, "req")
167 case protoreflect.Repeated:
168 tag = append(tag, "rep")
169 }
170 if fd.IsPacked() {
171 tag = append(tag, "packed")
172 }
173 name := string(fd.Name())
174 if fd.Kind() == protoreflect.GroupKind {
175
176
177
178 name = string(fd.Message().Name())
179 }
180 tag = append(tag, "name="+name)
181 if jsonName := fd.JSONName(); jsonName != "" && jsonName != name && !fd.IsExtension() {
182
183
184 tag = append(tag, "json="+jsonName)
185 }
186 if fd.IsWeak() {
187 tag = append(tag, "weak="+string(fd.Message().FullName()))
188 }
189
190
191
192 if fd.Syntax() == protoreflect.Proto3 && !fd.IsExtension() {
193 tag = append(tag, "proto3")
194 }
195 if fd.Kind() == protoreflect.EnumKind && enumName != "" {
196 tag = append(tag, "enum="+enumName)
197 }
198 if fd.ContainingOneof() != nil {
199 tag = append(tag, "oneof")
200 }
201
202 if fd.HasDefault() {
203 def, _ := defval.Marshal(fd.Default(), fd.DefaultEnumValue(), fd.Kind(), defval.GoTag)
204 tag = append(tag, "def="+def)
205 }
206 return strings.Join(tag, ",")
207 }
208
View as plain text