1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 package proto
38
39
40
41 import (
42 "bufio"
43 "bytes"
44 "encoding"
45 "errors"
46 "fmt"
47 "io"
48 "log"
49 "math"
50 "reflect"
51 "sort"
52 "strings"
53 "sync"
54 "time"
55 )
56
57 var (
58 newline = []byte("\n")
59 spaces = []byte(" ")
60 endBraceNewline = []byte("}\n")
61 backslashN = []byte{'\\', 'n'}
62 backslashR = []byte{'\\', 'r'}
63 backslashT = []byte{'\\', 't'}
64 backslashDQ = []byte{'\\', '"'}
65 backslashBS = []byte{'\\', '\\'}
66 posInf = []byte("inf")
67 negInf = []byte("-inf")
68 nan = []byte("nan")
69 )
70
71 type writer interface {
72 io.Writer
73 WriteByte(byte) error
74 }
75
76
77 type textWriter struct {
78 ind int
79 complete bool
80 compact bool
81 w writer
82 }
83
84 func (w *textWriter) WriteString(s string) (n int, err error) {
85 if !strings.Contains(s, "\n") {
86 if !w.compact && w.complete {
87 w.writeIndent()
88 }
89 w.complete = false
90 return io.WriteString(w.w, s)
91 }
92
93
94
95 return w.Write([]byte(s))
96 }
97
98 func (w *textWriter) Write(p []byte) (n int, err error) {
99 newlines := bytes.Count(p, newline)
100 if newlines == 0 {
101 if !w.compact && w.complete {
102 w.writeIndent()
103 }
104 n, err = w.w.Write(p)
105 w.complete = false
106 return n, err
107 }
108
109 frags := bytes.SplitN(p, newline, newlines+1)
110 if w.compact {
111 for i, frag := range frags {
112 if i > 0 {
113 if err := w.w.WriteByte(' '); err != nil {
114 return n, err
115 }
116 n++
117 }
118 nn, err := w.w.Write(frag)
119 n += nn
120 if err != nil {
121 return n, err
122 }
123 }
124 return n, nil
125 }
126
127 for i, frag := range frags {
128 if w.complete {
129 w.writeIndent()
130 }
131 nn, err := w.w.Write(frag)
132 n += nn
133 if err != nil {
134 return n, err
135 }
136 if i+1 < len(frags) {
137 if err := w.w.WriteByte('\n'); err != nil {
138 return n, err
139 }
140 n++
141 }
142 }
143 w.complete = len(frags[len(frags)-1]) == 0
144 return n, nil
145 }
146
147 func (w *textWriter) WriteByte(c byte) error {
148 if w.compact && c == '\n' {
149 c = ' '
150 }
151 if !w.compact && w.complete {
152 w.writeIndent()
153 }
154 err := w.w.WriteByte(c)
155 w.complete = c == '\n'
156 return err
157 }
158
159 func (w *textWriter) indent() { w.ind++ }
160
161 func (w *textWriter) unindent() {
162 if w.ind == 0 {
163 log.Print("proto: textWriter unindented too far")
164 return
165 }
166 w.ind--
167 }
168
169 func writeName(w *textWriter, props *Properties) error {
170 if _, err := w.WriteString(props.OrigName); err != nil {
171 return err
172 }
173 if props.Wire != "group" {
174 return w.WriteByte(':')
175 }
176 return nil
177 }
178
179 func requiresQuotes(u string) bool {
180
181 for _, ch := range u {
182 switch {
183 case ch == '.' || ch == '/' || ch == '_':
184 continue
185 case '0' <= ch && ch <= '9':
186 continue
187 case 'A' <= ch && ch <= 'Z':
188 continue
189 case 'a' <= ch && ch <= 'z':
190 continue
191 default:
192 return true
193 }
194 }
195 return false
196 }
197
198
199 func isAny(sv reflect.Value) bool {
200 type wkt interface {
201 XXX_WellKnownType() string
202 }
203 t, ok := sv.Addr().Interface().(wkt)
204 return ok && t.XXX_WellKnownType() == "Any"
205 }
206
207
208
209
210
211
212
213
214 func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
215 turl := sv.FieldByName("TypeUrl")
216 val := sv.FieldByName("Value")
217 if !turl.IsValid() || !val.IsValid() {
218 return true, errors.New("proto: invalid google.protobuf.Any message")
219 }
220
221 b, ok := val.Interface().([]byte)
222 if !ok {
223 return true, errors.New("proto: invalid google.protobuf.Any message")
224 }
225
226 parts := strings.Split(turl.String(), "/")
227 mt := MessageType(parts[len(parts)-1])
228 if mt == nil {
229 return false, nil
230 }
231 m := reflect.New(mt.Elem())
232 if err := Unmarshal(b, m.Interface().(Message)); err != nil {
233 return false, nil
234 }
235 w.Write([]byte("["))
236 u := turl.String()
237 if requiresQuotes(u) {
238 writeString(w, u)
239 } else {
240 w.Write([]byte(u))
241 }
242 if w.compact {
243 w.Write([]byte("]:<"))
244 } else {
245 w.Write([]byte("]: <\n"))
246 w.ind++
247 }
248 if err := tm.writeStruct(w, m.Elem()); err != nil {
249 return true, err
250 }
251 if w.compact {
252 w.Write([]byte("> "))
253 } else {
254 w.ind--
255 w.Write([]byte(">\n"))
256 }
257 return true, nil
258 }
259
260 func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
261 if tm.ExpandAny && isAny(sv) {
262 if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
263 return err
264 }
265 }
266 st := sv.Type()
267 sprops := GetProperties(st)
268 for i := 0; i < sv.NumField(); i++ {
269 fv := sv.Field(i)
270 props := sprops.Prop[i]
271 name := st.Field(i).Name
272
273 if name == "XXX_NoUnkeyedLiteral" {
274 continue
275 }
276
277 if strings.HasPrefix(name, "XXX_") {
278
279
280
281
282
283 if name == "XXX_unrecognized" && !fv.IsNil() {
284 if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
285 return err
286 }
287 }
288 continue
289 }
290 if fv.Kind() == reflect.Ptr && fv.IsNil() {
291
292
293
294 continue
295 }
296 if fv.Kind() == reflect.Slice && fv.IsNil() {
297
298 continue
299 }
300
301 if props.Repeated && fv.Kind() == reflect.Slice {
302
303 for j := 0; j < fv.Len(); j++ {
304 if err := writeName(w, props); err != nil {
305 return err
306 }
307 if !w.compact {
308 if err := w.WriteByte(' '); err != nil {
309 return err
310 }
311 }
312 v := fv.Index(j)
313 if v.Kind() == reflect.Ptr && v.IsNil() {
314
315
316 if _, err := w.Write([]byte("<nil>\n")); err != nil {
317 return err
318 }
319 continue
320 }
321 if len(props.Enum) > 0 {
322 if err := tm.writeEnum(w, v, props); err != nil {
323 return err
324 }
325 } else if err := tm.writeAny(w, v, props); err != nil {
326 return err
327 }
328 if err := w.WriteByte('\n'); err != nil {
329 return err
330 }
331 }
332 continue
333 }
334 if fv.Kind() == reflect.Map {
335
336 keys := fv.MapKeys()
337 sort.Sort(mapKeys(keys))
338 for _, key := range keys {
339 val := fv.MapIndex(key)
340 if err := writeName(w, props); err != nil {
341 return err
342 }
343 if !w.compact {
344 if err := w.WriteByte(' '); err != nil {
345 return err
346 }
347 }
348
349 if err := w.WriteByte('<'); err != nil {
350 return err
351 }
352 if !w.compact {
353 if err := w.WriteByte('\n'); err != nil {
354 return err
355 }
356 }
357 w.indent()
358
359 if _, err := w.WriteString("key:"); err != nil {
360 return err
361 }
362 if !w.compact {
363 if err := w.WriteByte(' '); err != nil {
364 return err
365 }
366 }
367 if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
368 return err
369 }
370 if err := w.WriteByte('\n'); err != nil {
371 return err
372 }
373
374 if val.Kind() != reflect.Ptr || !val.IsNil() {
375
376 if _, err := w.WriteString("value:"); err != nil {
377 return err
378 }
379 if !w.compact {
380 if err := w.WriteByte(' '); err != nil {
381 return err
382 }
383 }
384 if err := tm.writeAny(w, val, props.MapValProp); err != nil {
385 return err
386 }
387 if err := w.WriteByte('\n'); err != nil {
388 return err
389 }
390 }
391
392 w.unindent()
393 if err := w.WriteByte('>'); err != nil {
394 return err
395 }
396 if err := w.WriteByte('\n'); err != nil {
397 return err
398 }
399 }
400 continue
401 }
402 if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
403
404 continue
405 }
406 if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
407
408 if isProto3Zero(fv) {
409 continue
410 }
411 }
412
413 if fv.Kind() == reflect.Interface {
414
415 if st.Field(i).Tag.Get("protobuf_oneof") != "" {
416
417
418
419 if fv.IsNil() {
420 continue
421 }
422 inner := fv.Elem().Elem()
423 tag := inner.Type().Field(0).Tag.Get("protobuf")
424 props = new(Properties)
425 props.Parse(tag)
426
427 fv = inner.Field(0)
428
429
430
431
432 if fv.Kind() == reflect.Ptr && fv.IsNil() {
433
434 msg := errors.New("/* nil */")
435 fv = reflect.ValueOf(&msg).Elem()
436 }
437 }
438 }
439
440 if err := writeName(w, props); err != nil {
441 return err
442 }
443 if !w.compact {
444 if err := w.WriteByte(' '); err != nil {
445 return err
446 }
447 }
448
449 if len(props.Enum) > 0 {
450 if err := tm.writeEnum(w, fv, props); err != nil {
451 return err
452 }
453 } else if err := tm.writeAny(w, fv, props); err != nil {
454 return err
455 }
456
457 if err := w.WriteByte('\n'); err != nil {
458 return err
459 }
460 }
461
462
463 pv := sv
464 if pv.CanAddr() {
465 pv = sv.Addr()
466 } else {
467 pv = reflect.New(sv.Type())
468 pv.Elem().Set(sv)
469 }
470 if _, err := extendable(pv.Interface()); err == nil {
471 if err := tm.writeExtensions(w, pv); err != nil {
472 return err
473 }
474 }
475
476 return nil
477 }
478
479 var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
480
481
482 func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
483 v = reflect.Indirect(v)
484
485 if props != nil {
486 if len(props.CustomType) > 0 {
487 custom, ok := v.Interface().(Marshaler)
488 if ok {
489 data, err := custom.Marshal()
490 if err != nil {
491 return err
492 }
493 if err := writeString(w, string(data)); err != nil {
494 return err
495 }
496 return nil
497 }
498 } else if len(props.CastType) > 0 {
499 if _, ok := v.Interface().(interface {
500 String() string
501 }); ok {
502 switch v.Kind() {
503 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
504 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
505 _, err := fmt.Fprintf(w, "%d", v.Interface())
506 return err
507 }
508 }
509 } else if props.StdTime {
510 t, ok := v.Interface().(time.Time)
511 if !ok {
512 return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface())
513 }
514 tproto, err := timestampProto(t)
515 if err != nil {
516 return err
517 }
518 propsCopy := *props
519 propsCopy.StdTime = false
520 err = tm.writeAny(w, reflect.ValueOf(tproto), &propsCopy)
521 return err
522 } else if props.StdDuration {
523 d, ok := v.Interface().(time.Duration)
524 if !ok {
525 return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface())
526 }
527 dproto := durationProto(d)
528 propsCopy := *props
529 propsCopy.StdDuration = false
530 err := tm.writeAny(w, reflect.ValueOf(dproto), &propsCopy)
531 return err
532 }
533 }
534
535
536 if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
537 x := v.Float()
538 var b []byte
539 switch {
540 case math.IsInf(x, 1):
541 b = posInf
542 case math.IsInf(x, -1):
543 b = negInf
544 case math.IsNaN(x):
545 b = nan
546 }
547 if b != nil {
548 _, err := w.Write(b)
549 return err
550 }
551
552 }
553
554
555
556 switch v.Kind() {
557 case reflect.Slice:
558
559 if err := writeString(w, string(v.Bytes())); err != nil {
560 return err
561 }
562 case reflect.String:
563 if err := writeString(w, v.String()); err != nil {
564 return err
565 }
566 case reflect.Struct:
567
568 var bra, ket byte = '<', '>'
569 if props != nil && props.Wire == "group" {
570 bra, ket = '{', '}'
571 }
572 if err := w.WriteByte(bra); err != nil {
573 return err
574 }
575 if !w.compact {
576 if err := w.WriteByte('\n'); err != nil {
577 return err
578 }
579 }
580 w.indent()
581 if v.CanAddr() {
582
583
584
585
586
587
588
589
590
591
592 v = v.Addr()
593 }
594 if v.Type().Implements(textMarshalerType) {
595 text, err := v.Interface().(encoding.TextMarshaler).MarshalText()
596 if err != nil {
597 return err
598 }
599 if _, err = w.Write(text); err != nil {
600 return err
601 }
602 } else {
603 if v.Kind() == reflect.Ptr {
604 v = v.Elem()
605 }
606 if err := tm.writeStruct(w, v); err != nil {
607 return err
608 }
609 }
610 w.unindent()
611 if err := w.WriteByte(ket); err != nil {
612 return err
613 }
614 default:
615 _, err := fmt.Fprint(w, v.Interface())
616 return err
617 }
618 return nil
619 }
620
621
622 func isprint(c byte) bool {
623 return c >= 0x20 && c < 0x7f
624 }
625
626
627
628
629
630
631 func writeString(w *textWriter, s string) error {
632
633 if err := w.WriteByte('"'); err != nil {
634 return err
635 }
636
637 for i := 0; i < len(s); i++ {
638 var err error
639
640
641
642 switch c := s[i]; c {
643 case '\n':
644 _, err = w.w.Write(backslashN)
645 case '\r':
646 _, err = w.w.Write(backslashR)
647 case '\t':
648 _, err = w.w.Write(backslashT)
649 case '"':
650 _, err = w.w.Write(backslashDQ)
651 case '\\':
652 _, err = w.w.Write(backslashBS)
653 default:
654 if isprint(c) {
655 err = w.w.WriteByte(c)
656 } else {
657 _, err = fmt.Fprintf(w.w, "\\%03o", c)
658 }
659 }
660 if err != nil {
661 return err
662 }
663 }
664 return w.WriteByte('"')
665 }
666
667 func writeUnknownStruct(w *textWriter, data []byte) (err error) {
668 if !w.compact {
669 if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
670 return err
671 }
672 }
673 b := NewBuffer(data)
674 for b.index < len(b.buf) {
675 x, err := b.DecodeVarint()
676 if err != nil {
677 _, ferr := fmt.Fprintf(w, "/* %v */\n", err)
678 return ferr
679 }
680 wire, tag := x&7, x>>3
681 if wire == WireEndGroup {
682 w.unindent()
683 if _, werr := w.Write(endBraceNewline); werr != nil {
684 return werr
685 }
686 continue
687 }
688 if _, ferr := fmt.Fprint(w, tag); ferr != nil {
689 return ferr
690 }
691 if wire != WireStartGroup {
692 if err = w.WriteByte(':'); err != nil {
693 return err
694 }
695 }
696 if !w.compact || wire == WireStartGroup {
697 if err = w.WriteByte(' '); err != nil {
698 return err
699 }
700 }
701 switch wire {
702 case WireBytes:
703 buf, e := b.DecodeRawBytes(false)
704 if e == nil {
705 _, err = fmt.Fprintf(w, "%q", buf)
706 } else {
707 _, err = fmt.Fprintf(w, "/* %v */", e)
708 }
709 case WireFixed32:
710 x, err = b.DecodeFixed32()
711 err = writeUnknownInt(w, x, err)
712 case WireFixed64:
713 x, err = b.DecodeFixed64()
714 err = writeUnknownInt(w, x, err)
715 case WireStartGroup:
716 err = w.WriteByte('{')
717 w.indent()
718 case WireVarint:
719 x, err = b.DecodeVarint()
720 err = writeUnknownInt(w, x, err)
721 default:
722 _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
723 }
724 if err != nil {
725 return err
726 }
727 if err := w.WriteByte('\n'); err != nil {
728 return err
729 }
730 }
731 return nil
732 }
733
734 func writeUnknownInt(w *textWriter, x uint64, err error) error {
735 if err == nil {
736 _, err = fmt.Fprint(w, x)
737 } else {
738 _, err = fmt.Fprintf(w, "/* %v */", err)
739 }
740 return err
741 }
742
743 type int32Slice []int32
744
745 func (s int32Slice) Len() int { return len(s) }
746 func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
747 func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
748
749
750
751 func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
752 emap := extensionMaps[pv.Type().Elem()]
753 e := pv.Interface().(Message)
754
755 var m map[int32]Extension
756 var mu sync.Locker
757 if em, ok := e.(extensionsBytes); ok {
758 eb := em.GetExtensions()
759 var err error
760 m, err = BytesToExtensionsMap(*eb)
761 if err != nil {
762 return err
763 }
764 mu = notLocker{}
765 } else if _, ok := e.(extendableProto); ok {
766 ep, _ := extendable(e)
767 m, mu = ep.extensionsRead()
768 if m == nil {
769 return nil
770 }
771 }
772
773
774
775
776
777 mu.Lock()
778 ids := make([]int32, 0, len(m))
779 for id := range m {
780 ids = append(ids, id)
781 }
782 sort.Sort(int32Slice(ids))
783 mu.Unlock()
784
785 for _, extNum := range ids {
786 ext := m[extNum]
787 var desc *ExtensionDesc
788 if emap != nil {
789 desc = emap[extNum]
790 }
791 if desc == nil {
792
793 if err := writeUnknownStruct(w, ext.enc); err != nil {
794 return err
795 }
796 continue
797 }
798
799 pb, err := GetExtension(e, desc)
800 if err != nil {
801 return fmt.Errorf("failed getting extension: %v", err)
802 }
803
804
805 if !desc.repeated() {
806 if err := tm.writeExtension(w, desc.Name, pb); err != nil {
807 return err
808 }
809 } else {
810 v := reflect.ValueOf(pb)
811 for i := 0; i < v.Len(); i++ {
812 if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
813 return err
814 }
815 }
816 }
817 }
818 return nil
819 }
820
821 func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
822 if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
823 return err
824 }
825 if !w.compact {
826 if err := w.WriteByte(' '); err != nil {
827 return err
828 }
829 }
830 if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
831 return err
832 }
833 if err := w.WriteByte('\n'); err != nil {
834 return err
835 }
836 return nil
837 }
838
839 func (w *textWriter) writeIndent() {
840 if !w.complete {
841 return
842 }
843 remain := w.ind * 2
844 for remain > 0 {
845 n := remain
846 if n > len(spaces) {
847 n = len(spaces)
848 }
849 w.w.Write(spaces[:n])
850 remain -= n
851 }
852 w.complete = false
853 }
854
855
856 type TextMarshaler struct {
857 Compact bool
858 ExpandAny bool
859 }
860
861
862
863 func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
864 val := reflect.ValueOf(pb)
865 if pb == nil || val.IsNil() {
866 w.Write([]byte("<nil>"))
867 return nil
868 }
869 var bw *bufio.Writer
870 ww, ok := w.(writer)
871 if !ok {
872 bw = bufio.NewWriter(w)
873 ww = bw
874 }
875 aw := &textWriter{
876 w: ww,
877 complete: true,
878 compact: tm.Compact,
879 }
880
881 if etm, ok := pb.(encoding.TextMarshaler); ok {
882 text, err := etm.MarshalText()
883 if err != nil {
884 return err
885 }
886 if _, err = aw.Write(text); err != nil {
887 return err
888 }
889 if bw != nil {
890 return bw.Flush()
891 }
892 return nil
893 }
894
895 v := reflect.Indirect(val)
896 if err := tm.writeStruct(aw, v); err != nil {
897 return err
898 }
899 if bw != nil {
900 return bw.Flush()
901 }
902 return nil
903 }
904
905
906 func (tm *TextMarshaler) Text(pb Message) string {
907 var buf bytes.Buffer
908 tm.Marshal(&buf, pb)
909 return buf.String()
910 }
911
912 var (
913 defaultTextMarshaler = TextMarshaler{}
914 compactTextMarshaler = TextMarshaler{Compact: true}
915 )
916
917
918
919
920
921 func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
922
923
924 func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
925
926
927 func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
928
929
930 func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
931
View as plain text