1
2
3
4
5 package protorange_test
6
7 import (
8 "fmt"
9 "strings"
10 "time"
11
12 "google.golang.org/protobuf/encoding/protojson"
13 "google.golang.org/protobuf/internal/detrand"
14 "google.golang.org/protobuf/proto"
15 "google.golang.org/protobuf/reflect/protopath"
16 "google.golang.org/protobuf/reflect/protorange"
17 "google.golang.org/protobuf/reflect/protoreflect"
18 "google.golang.org/protobuf/testing/protopack"
19 "google.golang.org/protobuf/types/known/anypb"
20 "google.golang.org/protobuf/types/known/timestamppb"
21
22 newspb "google.golang.org/protobuf/internal/testprotos/news"
23 )
24
25 func init() {
26 detrand.Disable()
27 }
28
29 func mustMarshal(m proto.Message) []byte {
30 b, err := proto.Marshal(m)
31 if err != nil {
32 panic(err)
33 }
34 return b
35 }
36
37
38 func Example_discardUnknown() {
39
40 m := &newspb.Article{}
41 m.ProtoReflect().SetUnknown(protopack.Message{
42 protopack.Tag{1000, protopack.BytesType}, protopack.String("Hello, world!"),
43 }.Marshal())
44 fmt.Println("has unknown fields?", len(m.ProtoReflect().GetUnknown()) > 0)
45
46
47 fmt.Println("clear unknown fields")
48 protorange.Range(m.ProtoReflect(), func(proto protopath.Values) error {
49 m, ok := proto.Index(-1).Value.Interface().(protoreflect.Message)
50 if ok && len(m.GetUnknown()) > 0 {
51 m.SetUnknown(nil)
52 }
53 return nil
54 })
55 fmt.Println("has unknown fields?", len(m.ProtoReflect().GetUnknown()) > 0)
56
57
58
59
60
61 }
62
63
64
65 func Example_printPaths() {
66 m := &newspb.Article{
67 Author: "Russ Cox",
68 Date: timestamppb.New(time.Date(2019, time.November, 8, 0, 0, 0, 0, time.UTC)),
69 Title: "Go Turns 10",
70 Content: "Happy birthday, Go! This weekend we celebrate the 10th anniversary of the Go release...",
71 Status: newspb.Article_PUBLISHED,
72 Tags: []string{"community", "birthday"},
73 Attachments: []*anypb.Any{{
74 TypeUrl: "google.golang.org.BinaryAttachment",
75 Value: mustMarshal(&newspb.BinaryAttachment{
76 Name: "gopher-birthday.png",
77 Data: []byte("<binary data>"),
78 }),
79 }},
80 }
81
82
83 protorange.Range(m.ProtoReflect(), func(p protopath.Values) error {
84 fmt.Println(p.Path[1:])
85 return nil
86 })
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 }
104
105
106
107 func Example_formatText() {
108 m := &newspb.Article{
109 Author: "Brad Fitzpatrick",
110 Date: timestamppb.New(time.Date(2018, time.February, 16, 0, 0, 0, 0, time.UTC)),
111 Title: "Go 1.10 is released",
112 Content: "Happy Friday, happy weekend! Today the Go team is happy to announce the release of Go 1.10...",
113 Status: newspb.Article_PUBLISHED,
114 Tags: []string{"go1.10", "release"},
115 Attachments: []*anypb.Any{{
116 TypeUrl: "google.golang.org.KeyValueAttachment",
117 Value: mustMarshal(&newspb.KeyValueAttachment{
118 Name: "checksums.txt",
119 Data: map[string]string{
120 "go1.10.src.tar.gz": "07cbb9d0091b846c6aea40bf5bc0cea7",
121 "go1.10.darwin-amd64.pkg": "cbb38bb6ff6ea86279e01745984445bf",
122 "go1.10.linux-amd64.tar.gz": "6b3d0e4a5c77352cf4275573817f7566",
123 "go1.10.windows-amd64.msi": "57bda02030f58f5d2bf71943e1390123",
124 },
125 }),
126 }},
127 }
128
129
130 var indent []byte
131 protorange.Options{
132 Stable: true,
133 }.Range(m.ProtoReflect(),
134 func(p protopath.Values) error {
135
136 var fd protoreflect.FieldDescriptor
137 last := p.Index(-1)
138 beforeLast := p.Index(-2)
139 switch last.Step.Kind() {
140 case protopath.FieldAccessStep:
141 fd = last.Step.FieldDescriptor()
142 fmt.Printf("%s%s: ", indent, fd.Name())
143 case protopath.ListIndexStep:
144 fd = beforeLast.Step.FieldDescriptor()
145 fmt.Printf("%s%d: ", indent, last.Step.ListIndex())
146 case protopath.MapIndexStep:
147 fd = beforeLast.Step.FieldDescriptor()
148 fmt.Printf("%s%v: ", indent, last.Step.MapIndex().Interface())
149 case protopath.AnyExpandStep:
150 fmt.Printf("%s[%v]: ", indent, last.Value.Message().Descriptor().FullName())
151 case protopath.UnknownAccessStep:
152 fmt.Printf("%s?: ", indent)
153 }
154
155
156 switch v := last.Value.Interface().(type) {
157 case protoreflect.Message:
158 fmt.Printf("{\n")
159 indent = append(indent, '\t')
160 case protoreflect.List:
161 fmt.Printf("[\n")
162 indent = append(indent, '\t')
163 case protoreflect.Map:
164 fmt.Printf("{\n")
165 indent = append(indent, '\t')
166 case protoreflect.EnumNumber:
167 var ev protoreflect.EnumValueDescriptor
168 if fd != nil {
169 ev = fd.Enum().Values().ByNumber(v)
170 }
171 if ev != nil {
172 fmt.Printf("%v\n", ev.Name())
173 } else {
174 fmt.Printf("%v\n", v)
175 }
176 case string, []byte:
177 fmt.Printf("%q\n", v)
178 default:
179 fmt.Printf("%v\n", v)
180 }
181 return nil
182 },
183 func(p protopath.Values) error {
184
185 last := p.Index(-1)
186 switch last.Value.Interface().(type) {
187 case protoreflect.Message:
188 indent = indent[:len(indent)-1]
189 fmt.Printf("%s}\n", indent)
190 case protoreflect.List:
191 indent = indent[:len(indent)-1]
192 fmt.Printf("%s]\n", indent)
193 case protoreflect.Map:
194 indent = indent[:len(indent)-1]
195 fmt.Printf("%s}\n", indent)
196 }
197 return nil
198 },
199 )
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 }
229
230
231
232 func Example_sanitizeStrings() {
233 m := &newspb.Article{
234 Author: "Hermione Granger",
235 Date: timestamppb.New(time.Date(1998, time.May, 2, 0, 0, 0, 0, time.UTC)),
236 Title: "Harry Potter vanquishes Voldemort once and for all!",
237 Content: "In a final duel between Harry Potter and Lord Voldemort earlier this evening...",
238 Tags: []string{"HarryPotter", "LordVoldemort"},
239 Attachments: []*anypb.Any{{
240 TypeUrl: "google.golang.org.KeyValueAttachment",
241 Value: mustMarshal(&newspb.KeyValueAttachment{
242 Name: "aliases.txt",
243 Data: map[string]string{
244 "Harry Potter": "The Boy Who Lived",
245 "Tom Riddle": "Lord Voldemort",
246 },
247 }),
248 }},
249 }
250
251 protorange.Range(m.ProtoReflect(), func(p protopath.Values) error {
252 const (
253 sensitive = "Voldemort"
254 alternative = "[He-Who-Must-Not-Be-Named]"
255 )
256
257
258 last := p.Index(-1)
259 s, ok := last.Value.Interface().(string)
260 if !ok || !strings.Contains(s, sensitive) {
261 return nil
262 }
263 s = strings.Replace(s, sensitive, alternative, -1)
264
265
266 beforeLast := p.Index(-2)
267 switch last.Step.Kind() {
268 case protopath.FieldAccessStep:
269 m := beforeLast.Value.Message()
270 fd := last.Step.FieldDescriptor()
271 m.Set(fd, protoreflect.ValueOfString(s))
272 case protopath.ListIndexStep:
273 ls := beforeLast.Value.List()
274 i := last.Step.ListIndex()
275 ls.Set(i, protoreflect.ValueOfString(s))
276 case protopath.MapIndexStep:
277 ms := beforeLast.Value.Map()
278 k := last.Step.MapIndex()
279 ms.Set(k, protoreflect.ValueOfString(s))
280 }
281 return nil
282 })
283
284 fmt.Println(protojson.Format(m))
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 }
308
View as plain text