...
1
2
3
4
5 package protopath
6
7 import (
8 "fmt"
9 "strconv"
10 "strings"
11
12 "google.golang.org/protobuf/internal/encoding/text"
13 "google.golang.org/protobuf/reflect/protoreflect"
14 )
15
16
17
18 type StepKind int
19
20 const (
21 invalidStep StepKind = iota
22
23 RootStep
24
25 FieldAccessStep
26
27 UnknownAccessStep
28
29 ListIndexStep
30
31 MapIndexStep
32
33 AnyExpandStep
34 )
35
36 func (k StepKind) String() string {
37 switch k {
38 case invalidStep:
39 return "<invalid>"
40 case RootStep:
41 return "Root"
42 case FieldAccessStep:
43 return "FieldAccess"
44 case UnknownAccessStep:
45 return "UnknownAccess"
46 case ListIndexStep:
47 return "ListIndex"
48 case MapIndexStep:
49 return "MapIndex"
50 case AnyExpandStep:
51 return "AnyExpand"
52 default:
53 return fmt.Sprintf("<unknown:%d>", k)
54 }
55 }
56
57
58
59
60 type Step struct {
61 kind StepKind
62 desc protoreflect.Descriptor
63 key protoreflect.Value
64 }
65
66
67
68 func Root(md protoreflect.MessageDescriptor) Step {
69 if md == nil {
70 panic("nil message descriptor")
71 }
72 return Step{kind: RootStep, desc: md}
73 }
74
75
76
77
78
79
80
81
82 func FieldAccess(fd protoreflect.FieldDescriptor) Step {
83 if fd == nil {
84 panic("nil field descriptor")
85 } else if _, ok := fd.(protoreflect.ExtensionTypeDescriptor); !ok && fd.IsExtension() {
86 panic(fmt.Sprintf("extension field %q must implement protoreflect.ExtensionTypeDescriptor", fd.FullName()))
87 }
88 return Step{kind: FieldAccessStep, desc: fd}
89 }
90
91
92
93
94
95
96 func UnknownAccess() Step {
97 return Step{kind: UnknownAccessStep}
98 }
99
100
101
102
103
104
105
106 func ListIndex(i int) Step {
107 if i < 0 {
108 panic(fmt.Sprintf("invalid list index: %v", i))
109 }
110 return Step{kind: ListIndexStep, key: protoreflect.ValueOfInt64(int64(i))}
111 }
112
113
114
115
116
117
118
119
120 func MapIndex(k protoreflect.MapKey) Step {
121 if !k.IsValid() {
122 panic("invalid map index")
123 }
124 return Step{kind: MapIndexStep, key: k.Value()}
125 }
126
127
128
129
130
131
132
133 func AnyExpand(md protoreflect.MessageDescriptor) Step {
134 if md == nil {
135 panic("nil message descriptor")
136 }
137 return Step{kind: AnyExpandStep, desc: md}
138 }
139
140
141
142 func (s Step) MessageDescriptor() protoreflect.MessageDescriptor {
143 switch s.kind {
144 case RootStep, AnyExpandStep:
145 return s.desc.(protoreflect.MessageDescriptor)
146 default:
147 return nil
148 }
149 }
150
151
152
153 func (s Step) FieldDescriptor() protoreflect.FieldDescriptor {
154 switch s.kind {
155 case FieldAccessStep:
156 return s.desc.(protoreflect.FieldDescriptor)
157 default:
158 return nil
159 }
160 }
161
162
163
164 func (s Step) ListIndex() int {
165 switch s.kind {
166 case ListIndexStep:
167 return int(s.key.Int())
168 default:
169 return 0
170 }
171 }
172
173
174
175 func (s Step) MapIndex() protoreflect.MapKey {
176 switch s.kind {
177 case MapIndexStep:
178 return s.key.MapKey()
179 default:
180 return protoreflect.MapKey{}
181 }
182 }
183
184
185 func (s Step) Kind() StepKind {
186 return s.kind
187 }
188
189 func (s Step) String() string {
190 return string(s.appendString(nil))
191 }
192
193 func (s Step) appendString(b []byte) []byte {
194 switch s.kind {
195 case RootStep:
196 b = append(b, '(')
197 b = append(b, s.desc.FullName()...)
198 b = append(b, ')')
199 case FieldAccessStep:
200 b = append(b, '.')
201 if fd := s.desc.(protoreflect.FieldDescriptor); fd.IsExtension() {
202 b = append(b, '(')
203 b = append(b, strings.Trim(fd.TextName(), "[]")...)
204 b = append(b, ')')
205 } else {
206 b = append(b, fd.TextName()...)
207 }
208 case UnknownAccessStep:
209 b = append(b, '.')
210 b = append(b, '?')
211 case ListIndexStep:
212 b = append(b, '[')
213 b = strconv.AppendInt(b, s.key.Int(), 10)
214 b = append(b, ']')
215 case MapIndexStep:
216 b = append(b, '[')
217 switch k := s.key.Interface().(type) {
218 case bool:
219 b = strconv.AppendBool(b, bool(k))
220 case int32:
221 b = strconv.AppendInt(b, int64(k), 10)
222 case int64:
223 b = strconv.AppendInt(b, int64(k), 10)
224 case uint32:
225 b = strconv.AppendUint(b, uint64(k), 10)
226 case uint64:
227 b = strconv.AppendUint(b, uint64(k), 10)
228 case string:
229 b = text.AppendString(b, k)
230 }
231 b = append(b, ']')
232 case AnyExpandStep:
233 b = append(b, '.')
234 b = append(b, '(')
235 b = append(b, s.desc.FullName()...)
236 b = append(b, ')')
237 default:
238 b = append(b, "<invalid>"...)
239 }
240 return b
241 }
242
View as plain text