Browse code

Update protobufs to 8d92cf5fc15a4382f8964b08e1f42a

This syncs the protobuf version with the one that is used with
containerd.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>

Michael Crosby authored on 2016/05/10 07:21:41
Showing 9 changed files
... ...
@@ -67,7 +67,7 @@ clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c22
67 67
 clone git github.com/coreos/go-systemd v4
68 68
 clone git github.com/godbus/dbus v4.0.0
69 69
 clone git github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
70
-clone git github.com/golang/protobuf 68415e7123da32b07eab49c96d2c4d6158360e9b
70
+clone git github.com/golang/protobuf 8d92cf5fc15a4382f8964b08e1f42a75c0591aa3
71 71
 
72 72
 # gelf logging driver deps
73 73
 clone git github.com/Graylog2/go-gelf aab2f594e4585d43468ac57287b0dece9d806883
... ...
@@ -39,5 +39,5 @@ test: install generate-test-pbs
39 39
 generate-test-pbs:
40 40
 	make install
41 41
 	make -C testdata
42
-	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto
42
+	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
43 43
 	make
... ...
@@ -768,10 +768,11 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
768 768
 		}
769 769
 	}
770 770
 	keyelem, valelem := keyptr.Elem(), valptr.Elem()
771
-	if !keyelem.IsValid() || !valelem.IsValid() {
772
-		// We did not decode the key or the value in the map entry.
773
-		// Either way, it's an invalid map entry.
774
-		return fmt.Errorf("proto: bad map data: missing key/val")
771
+	if !keyelem.IsValid() {
772
+		keyelem = reflect.Zero(p.mtype.Key())
773
+	}
774
+	if !valelem.IsValid() {
775
+		valelem = reflect.Zero(p.mtype.Elem())
775 776
 	}
776 777
 
777 778
 	v.SetMapIndex(keyelem, valelem)
... ...
@@ -64,6 +64,10 @@ var (
64 64
 	// a struct with a repeated field containing a nil element.
65 65
 	errRepeatedHasNil = errors.New("proto: repeated field has nil element")
66 66
 
67
+	// errOneofHasNil is the error returned if Marshal is called with
68
+	// a struct with a oneof field containing a nil element.
69
+	errOneofHasNil = errors.New("proto: oneof field has nil value")
70
+
67 71
 	// ErrNil is the error returned if Marshal is called with nil.
68 72
 	ErrNil = errors.New("proto: Marshal called with nil")
69 73
 )
... ...
@@ -1222,7 +1226,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
1222 1222
 	// Do oneof fields.
1223 1223
 	if prop.oneofMarshaler != nil {
1224 1224
 		m := structPointer_Interface(base, prop.stype).(Message)
1225
-		if err := prop.oneofMarshaler(m, o); err != nil {
1225
+		if err := prop.oneofMarshaler(m, o); err == ErrNil {
1226
+			return errOneofHasNil
1227
+		} else if err != nil {
1226 1228
 			return err
1227 1229
 		}
1228 1230
 	}
... ...
@@ -50,7 +50,9 @@ Equality is defined in this way:
50 50
     are equal, and extensions sets are equal.
51 51
   - Two set scalar fields are equal iff their values are equal.
52 52
     If the fields are of a floating-point type, remember that
53
-    NaN != x for all x, including NaN.
53
+    NaN != x for all x, including NaN. If the message is defined
54
+    in a proto3 .proto file, fields are not "set"; specifically,
55
+    zero length proto3 "bytes" fields are equal (nil == {}).
54 56
   - Two repeated fields are equal iff their lengths are the same,
55 57
     and their corresponding elements are equal (a "bytes" field,
56 58
     although represented by []byte, is not a repeated field)
... ...
@@ -88,6 +90,7 @@ func Equal(a, b Message) bool {
88 88
 
89 89
 // v1 and v2 are known to have the same type.
90 90
 func equalStruct(v1, v2 reflect.Value) bool {
91
+	sprop := GetProperties(v1.Type())
91 92
 	for i := 0; i < v1.NumField(); i++ {
92 93
 		f := v1.Type().Field(i)
93 94
 		if strings.HasPrefix(f.Name, "XXX_") {
... ...
@@ -113,7 +116,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
113 113
 			}
114 114
 			f1, f2 = f1.Elem(), f2.Elem()
115 115
 		}
116
-		if !equalAny(f1, f2) {
116
+		if !equalAny(f1, f2, sprop.Prop[i]) {
117 117
 			return false
118 118
 		}
119 119
 	}
... ...
@@ -140,7 +143,8 @@ func equalStruct(v1, v2 reflect.Value) bool {
140 140
 }
141 141
 
142 142
 // v1 and v2 are known to have the same type.
143
-func equalAny(v1, v2 reflect.Value) bool {
143
+// prop may be nil.
144
+func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
144 145
 	if v1.Type() == protoMessageType {
145 146
 		m1, _ := v1.Interface().(Message)
146 147
 		m2, _ := v2.Interface().(Message)
... ...
@@ -163,7 +167,7 @@ func equalAny(v1, v2 reflect.Value) bool {
163 163
 		if e1.Type() != e2.Type() {
164 164
 			return false
165 165
 		}
166
-		return equalAny(e1, e2)
166
+		return equalAny(e1, e2, nil)
167 167
 	case reflect.Map:
168 168
 		if v1.Len() != v2.Len() {
169 169
 			return false
... ...
@@ -174,16 +178,22 @@ func equalAny(v1, v2 reflect.Value) bool {
174 174
 				// This key was not found in the second map.
175 175
 				return false
176 176
 			}
177
-			if !equalAny(v1.MapIndex(key), val2) {
177
+			if !equalAny(v1.MapIndex(key), val2, nil) {
178 178
 				return false
179 179
 			}
180 180
 		}
181 181
 		return true
182 182
 	case reflect.Ptr:
183
-		return equalAny(v1.Elem(), v2.Elem())
183
+		return equalAny(v1.Elem(), v2.Elem(), prop)
184 184
 	case reflect.Slice:
185 185
 		if v1.Type().Elem().Kind() == reflect.Uint8 {
186 186
 			// short circuit: []byte
187
+
188
+			// Edge case: if this is in a proto3 message, a zero length
189
+			// bytes field is considered the zero value.
190
+			if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
191
+				return true
192
+			}
187 193
 			if v1.IsNil() != v2.IsNil() {
188 194
 				return false
189 195
 			}
... ...
@@ -194,7 +204,7 @@ func equalAny(v1, v2 reflect.Value) bool {
194 194
 			return false
195 195
 		}
196 196
 		for i := 0; i < v1.Len(); i++ {
197
-			if !equalAny(v1.Index(i), v2.Index(i)) {
197
+			if !equalAny(v1.Index(i), v2.Index(i), prop) {
198 198
 				return false
199 199
 			}
200 200
 		}
... ...
@@ -229,7 +239,7 @@ func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
229 229
 
230 230
 		if m1 != nil && m2 != nil {
231 231
 			// Both are unencoded.
232
-			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) {
232
+			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
233 233
 				return false
234 234
 			}
235 235
 			continue
... ...
@@ -257,7 +267,7 @@ func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
257 257
 			log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
258 258
 			return false
259 259
 		}
260
-		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) {
260
+		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
261 261
 			return false
262 262
 		}
263 263
 	}
... ...
@@ -70,6 +70,12 @@ for a protocol buffer variable v:
70 70
 	with distinguished wrapper types for each possible field value.
71 71
   - Marshal and Unmarshal are functions to encode and decode the wire format.
72 72
 
73
+When the .proto file specifies `syntax="proto3"`, there are some differences:
74
+
75
+  - Non-repeated fields of non-message type are values instead of pointers.
76
+  - Getters are only generated for message and oneof fields.
77
+  - Enum types do not get an Enum method.
78
+
73 79
 The simplest way to describe this is to see an example.
74 80
 Given file test.proto, containing
75 81
 
... ...
@@ -229,6 +235,7 @@ To create and play with a Test object:
229 229
 		test := &pb.Test{
230 230
 			Label: proto.String("hello"),
231 231
 			Type:  proto.Int32(17),
232
+			Reps:  []int64{1, 2, 3},
232 233
 			Optionalgroup: &pb.Test_OptionalGroup{
233 234
 				RequiredField: proto.String("good bye"),
234 235
 			},
... ...
@@ -881,3 +888,7 @@ func isProto3Zero(v reflect.Value) bool {
881 881
 	}
882 882
 	return false
883 883
 }
884
+
885
+// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
886
+// to assert that that code is compatible with this version of the proto package.
887
+const ProtoPackageIsVersion1 = true
... ...
@@ -173,6 +173,7 @@ func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order
173 173
 type Properties struct {
174 174
 	Name     string // name of the field, for error messages
175 175
 	OrigName string // original name before protocol compiler (always set)
176
+	JSONName string // name to use for JSON; determined by protoc
176 177
 	Wire     string
177 178
 	WireType int
178 179
 	Tag      int
... ...
@@ -229,8 +230,9 @@ func (p *Properties) String() string {
229 229
 	if p.Packed {
230 230
 		s += ",packed"
231 231
 	}
232
-	if p.OrigName != p.Name {
233
-		s += ",name=" + p.OrigName
232
+	s += ",name=" + p.OrigName
233
+	if p.JSONName != p.OrigName {
234
+		s += ",json=" + p.JSONName
234 235
 	}
235 236
 	if p.proto3 {
236 237
 		s += ",proto3"
... ...
@@ -310,6 +312,8 @@ func (p *Properties) Parse(s string) {
310 310
 			p.Packed = true
311 311
 		case strings.HasPrefix(f, "name="):
312 312
 			p.OrigName = f[5:]
313
+		case strings.HasPrefix(f, "json="):
314
+			p.JSONName = f[5:]
313 315
 		case strings.HasPrefix(f, "enum="):
314 316
 			p.Enum = f[5:]
315 317
 		case f == "proto3":
... ...
@@ -175,7 +175,93 @@ type raw interface {
175 175
 	Bytes() []byte
176 176
 }
177 177
 
178
-func writeStruct(w *textWriter, sv reflect.Value) error {
178
+func requiresQuotes(u string) bool {
179
+	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
180
+	for _, ch := range u {
181
+		switch {
182
+		case ch == '.' || ch == '/' || ch == '_':
183
+			continue
184
+		case '0' <= ch && ch <= '9':
185
+			continue
186
+		case 'A' <= ch && ch <= 'Z':
187
+			continue
188
+		case 'a' <= ch && ch <= 'z':
189
+			continue
190
+		default:
191
+			return true
192
+		}
193
+	}
194
+	return false
195
+}
196
+
197
+// isAny reports whether sv is a google.protobuf.Any message
198
+func isAny(sv reflect.Value) bool {
199
+	type wkt interface {
200
+		XXX_WellKnownType() string
201
+	}
202
+	t, ok := sv.Addr().Interface().(wkt)
203
+	return ok && t.XXX_WellKnownType() == "Any"
204
+}
205
+
206
+// writeProto3Any writes an expanded google.protobuf.Any message.
207
+//
208
+// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
209
+// required messages are not linked in).
210
+//
211
+// It returns (true, error) when sv was written in expanded format or an error
212
+// was encountered.
213
+func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
214
+	turl := sv.FieldByName("TypeUrl")
215
+	val := sv.FieldByName("Value")
216
+	if !turl.IsValid() || !val.IsValid() {
217
+		return true, errors.New("proto: invalid google.protobuf.Any message")
218
+	}
219
+
220
+	b, ok := val.Interface().([]byte)
221
+	if !ok {
222
+		return true, errors.New("proto: invalid google.protobuf.Any message")
223
+	}
224
+
225
+	parts := strings.Split(turl.String(), "/")
226
+	mt := MessageType(parts[len(parts)-1])
227
+	if mt == nil {
228
+		return false, nil
229
+	}
230
+	m := reflect.New(mt.Elem())
231
+	if err := Unmarshal(b, m.Interface().(Message)); err != nil {
232
+		return false, nil
233
+	}
234
+	w.Write([]byte("["))
235
+	u := turl.String()
236
+	if requiresQuotes(u) {
237
+		writeString(w, u)
238
+	} else {
239
+		w.Write([]byte(u))
240
+	}
241
+	if w.compact {
242
+		w.Write([]byte("]:<"))
243
+	} else {
244
+		w.Write([]byte("]: <\n"))
245
+		w.ind++
246
+	}
247
+	if err := tm.writeStruct(w, m.Elem()); err != nil {
248
+		return true, err
249
+	}
250
+	if w.compact {
251
+		w.Write([]byte("> "))
252
+	} else {
253
+		w.ind--
254
+		w.Write([]byte(">\n"))
255
+	}
256
+	return true, nil
257
+}
258
+
259
+func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
260
+	if tm.ExpandAny && isAny(sv) {
261
+		if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
262
+			return err
263
+		}
264
+	}
179 265
 	st := sv.Type()
180 266
 	sprops := GetProperties(st)
181 267
 	for i := 0; i < sv.NumField(); i++ {
... ...
@@ -227,7 +313,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
227 227
 					}
228 228
 					continue
229 229
 				}
230
-				if err := writeAny(w, v, props); err != nil {
230
+				if err := tm.writeAny(w, v, props); err != nil {
231 231
 					return err
232 232
 				}
233 233
 				if err := w.WriteByte('\n'); err != nil {
... ...
@@ -269,7 +355,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
269 269
 						return err
270 270
 					}
271 271
 				}
272
-				if err := writeAny(w, key, props.mkeyprop); err != nil {
272
+				if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
273 273
 					return err
274 274
 				}
275 275
 				if err := w.WriteByte('\n'); err != nil {
... ...
@@ -286,7 +372,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
286 286
 							return err
287 287
 						}
288 288
 					}
289
-					if err := writeAny(w, val, props.mvalprop); err != nil {
289
+					if err := tm.writeAny(w, val, props.mvalprop); err != nil {
290 290
 						return err
291 291
 					}
292 292
 					if err := w.WriteByte('\n'); err != nil {
... ...
@@ -358,7 +444,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
358 358
 		}
359 359
 
360 360
 		// Enums have a String method, so writeAny will work fine.
361
-		if err := writeAny(w, fv, props); err != nil {
361
+		if err := tm.writeAny(w, fv, props); err != nil {
362 362
 			return err
363 363
 		}
364 364
 
... ...
@@ -370,7 +456,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
370 370
 	// Extensions (the XXX_extensions field).
371 371
 	pv := sv.Addr()
372 372
 	if pv.Type().Implements(extendableProtoType) {
373
-		if err := writeExtensions(w, pv); err != nil {
373
+		if err := tm.writeExtensions(w, pv); err != nil {
374 374
 			return err
375 375
 		}
376 376
 	}
... ...
@@ -400,7 +486,7 @@ func writeRaw(w *textWriter, b []byte) error {
400 400
 }
401 401
 
402 402
 // writeAny writes an arbitrary field.
403
-func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
403
+func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
404 404
 	v = reflect.Indirect(v)
405 405
 
406 406
 	// Floats have special cases.
... ...
@@ -449,15 +535,15 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
449 449
 			}
450 450
 		}
451 451
 		w.indent()
452
-		if tm, ok := v.Interface().(encoding.TextMarshaler); ok {
453
-			text, err := tm.MarshalText()
452
+		if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
453
+			text, err := etm.MarshalText()
454 454
 			if err != nil {
455 455
 				return err
456 456
 			}
457 457
 			if _, err = w.Write(text); err != nil {
458 458
 				return err
459 459
 			}
460
-		} else if err := writeStruct(w, v); err != nil {
460
+		} else if err := tm.writeStruct(w, v); err != nil {
461 461
 			return err
462 462
 		}
463 463
 		w.unindent()
... ...
@@ -601,7 +687,7 @@ func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
601 601
 
602 602
 // writeExtensions writes all the extensions in pv.
603 603
 // pv is assumed to be a pointer to a protocol message struct that is extendable.
604
-func writeExtensions(w *textWriter, pv reflect.Value) error {
604
+func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
605 605
 	emap := extensionMaps[pv.Type().Elem()]
606 606
 	ep := pv.Interface().(extendableProto)
607 607
 
... ...
@@ -636,13 +722,13 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
636 636
 
637 637
 		// Repeated extensions will appear as a slice.
638 638
 		if !desc.repeated() {
639
-			if err := writeExtension(w, desc.Name, pb); err != nil {
639
+			if err := tm.writeExtension(w, desc.Name, pb); err != nil {
640 640
 				return err
641 641
 			}
642 642
 		} else {
643 643
 			v := reflect.ValueOf(pb)
644 644
 			for i := 0; i < v.Len(); i++ {
645
-				if err := writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
645
+				if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
646 646
 					return err
647 647
 				}
648 648
 			}
... ...
@@ -651,7 +737,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
651 651
 	return nil
652 652
 }
653 653
 
654
-func writeExtension(w *textWriter, name string, pb interface{}) error {
654
+func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
655 655
 	if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
656 656
 		return err
657 657
 	}
... ...
@@ -660,7 +746,7 @@ func writeExtension(w *textWriter, name string, pb interface{}) error {
660 660
 			return err
661 661
 		}
662 662
 	}
663
-	if err := writeAny(w, reflect.ValueOf(pb), nil); err != nil {
663
+	if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
664 664
 		return err
665 665
 	}
666 666
 	if err := w.WriteByte('\n'); err != nil {
... ...
@@ -685,7 +771,15 @@ func (w *textWriter) writeIndent() {
685 685
 	w.complete = false
686 686
 }
687 687
 
688
-func marshalText(w io.Writer, pb Message, compact bool) error {
688
+// TextMarshaler is a configurable text format marshaler.
689
+type TextMarshaler struct {
690
+	Compact   bool // use compact text format (one line).
691
+	ExpandAny bool // expand google.protobuf.Any messages of known types
692
+}
693
+
694
+// Marshal writes a given protocol buffer in text format.
695
+// The only errors returned are from w.
696
+func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
689 697
 	val := reflect.ValueOf(pb)
690 698
 	if pb == nil || val.IsNil() {
691 699
 		w.Write([]byte("<nil>"))
... ...
@@ -700,11 +794,11 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
700 700
 	aw := &textWriter{
701 701
 		w:        ww,
702 702
 		complete: true,
703
-		compact:  compact,
703
+		compact:  tm.Compact,
704 704
 	}
705 705
 
706
-	if tm, ok := pb.(encoding.TextMarshaler); ok {
707
-		text, err := tm.MarshalText()
706
+	if etm, ok := pb.(encoding.TextMarshaler); ok {
707
+		text, err := etm.MarshalText()
708 708
 		if err != nil {
709 709
 			return err
710 710
 		}
... ...
@@ -718,7 +812,7 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
718 718
 	}
719 719
 	// Dereference the received pointer so we don't have outer < and >.
720 720
 	v := reflect.Indirect(val)
721
-	if err := writeStruct(aw, v); err != nil {
721
+	if err := tm.writeStruct(aw, v); err != nil {
722 722
 		return err
723 723
 	}
724 724
 	if bw != nil {
... ...
@@ -727,25 +821,29 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
727 727
 	return nil
728 728
 }
729 729
 
730
+// Text is the same as Marshal, but returns the string directly.
731
+func (tm *TextMarshaler) Text(pb Message) string {
732
+	var buf bytes.Buffer
733
+	tm.Marshal(&buf, pb)
734
+	return buf.String()
735
+}
736
+
737
+var (
738
+	defaultTextMarshaler = TextMarshaler{}
739
+	compactTextMarshaler = TextMarshaler{Compact: true}
740
+)
741
+
742
+// TODO: consider removing some of the Marshal functions below.
743
+
730 744
 // MarshalText writes a given protocol buffer in text format.
731 745
 // The only errors returned are from w.
732
-func MarshalText(w io.Writer, pb Message) error {
733
-	return marshalText(w, pb, false)
734
-}
746
+func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
735 747
 
736 748
 // MarshalTextString is the same as MarshalText, but returns the string directly.
737
-func MarshalTextString(pb Message) string {
738
-	var buf bytes.Buffer
739
-	marshalText(&buf, pb, false)
740
-	return buf.String()
741
-}
749
+func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
742 750
 
743 751
 // CompactText writes a given protocol buffer in compact text format (one line).
744
-func CompactText(w io.Writer, pb Message) error { return marshalText(w, pb, true) }
752
+func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
745 753
 
746 754
 // CompactTextString is the same as CompactText, but returns the string directly.
747
-func CompactTextString(pb Message) string {
748
-	var buf bytes.Buffer
749
-	marshalText(&buf, pb, true)
750
-	return buf.String()
751
-}
755
+func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
... ...
@@ -119,6 +119,14 @@ func isWhitespace(c byte) bool {
119 119
 	return false
120 120
 }
121 121
 
122
+func isQuote(c byte) bool {
123
+	switch c {
124
+	case '"', '\'':
125
+		return true
126
+	}
127
+	return false
128
+}
129
+
122 130
 func (p *textParser) skipWhitespace() {
123 131
 	i := 0
124 132
 	for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
... ...
@@ -155,7 +163,7 @@ func (p *textParser) advance() {
155 155
 	p.cur.offset, p.cur.line = p.offset, p.line
156 156
 	p.cur.unquoted = ""
157 157
 	switch p.s[0] {
158
-	case '<', '>', '{', '}', ':', '[', ']', ';', ',':
158
+	case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
159 159
 		// Single symbol
160 160
 		p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
161 161
 	case '"', '\'':
... ...
@@ -333,13 +341,13 @@ func (p *textParser) next() *token {
333 333
 	p.advance()
334 334
 	if p.done {
335 335
 		p.cur.value = ""
336
-	} else if len(p.cur.value) > 0 && p.cur.value[0] == '"' {
336
+	} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
337 337
 		// Look for multiple quoted strings separated by whitespace,
338 338
 		// and concatenate them.
339 339
 		cat := p.cur
340 340
 		for {
341 341
 			p.skipWhitespace()
342
-			if p.done || p.s[0] != '"' {
342
+			if p.done || !isQuote(p.s[0]) {
343 343
 				break
344 344
 			}
345 345
 			p.advance()
... ...
@@ -443,7 +451,10 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
443 443
 	fieldSet := make(map[string]bool)
444 444
 	// A struct is a sequence of "name: value", terminated by one of
445 445
 	// '>' or '}', or the end of the input.  A name may also be
446
-	// "[extension]".
446
+	// "[extension]" or "[type/url]".
447
+	//
448
+	// The whole struct can also be an expanded Any message, like:
449
+	// [type/url] < ... struct contents ... >
447 450
 	for {
448 451
 		tok := p.next()
449 452
 		if tok.err != nil {
... ...
@@ -453,33 +464,66 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
453 453
 			break
454 454
 		}
455 455
 		if tok.value == "[" {
456
-			// Looks like an extension.
456
+			// Looks like an extension or an Any.
457 457
 			//
458 458
 			// TODO: Check whether we need to handle
459 459
 			// namespace rooted names (e.g. ".something.Foo").
460
-			tok = p.next()
461
-			if tok.err != nil {
462
-				return tok.err
460
+			extName, err := p.consumeExtName()
461
+			if err != nil {
462
+				return err
463
+			}
464
+
465
+			if s := strings.LastIndex(extName, "/"); s >= 0 {
466
+				// If it contains a slash, it's an Any type URL.
467
+				messageName := extName[s+1:]
468
+				mt := MessageType(messageName)
469
+				if mt == nil {
470
+					return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
471
+				}
472
+				tok = p.next()
473
+				if tok.err != nil {
474
+					return tok.err
475
+				}
476
+				// consume an optional colon
477
+				if tok.value == ":" {
478
+					tok = p.next()
479
+					if tok.err != nil {
480
+						return tok.err
481
+					}
482
+				}
483
+				var terminator string
484
+				switch tok.value {
485
+				case "<":
486
+					terminator = ">"
487
+				case "{":
488
+					terminator = "}"
489
+				default:
490
+					return p.errorf("expected '{' or '<', found %q", tok.value)
491
+				}
492
+				v := reflect.New(mt.Elem())
493
+				if pe := p.readStruct(v.Elem(), terminator); pe != nil {
494
+					return pe
495
+				}
496
+				b, err := Marshal(v.Interface().(Message))
497
+				if err != nil {
498
+					return p.errorf("failed to marshal message of type %q: %v", messageName, err)
499
+				}
500
+				sv.FieldByName("TypeUrl").SetString(extName)
501
+				sv.FieldByName("Value").SetBytes(b)
502
+				continue
463 503
 			}
504
+
464 505
 			var desc *ExtensionDesc
465 506
 			// This could be faster, but it's functional.
466 507
 			// TODO: Do something smarter than a linear scan.
467 508
 			for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
468
-				if d.Name == tok.value {
509
+				if d.Name == extName {
469 510
 					desc = d
470 511
 					break
471 512
 				}
472 513
 			}
473 514
 			if desc == nil {
474
-				return p.errorf("unrecognized extension %q", tok.value)
475
-			}
476
-			// Check the extension terminator.
477
-			tok = p.next()
478
-			if tok.err != nil {
479
-				return tok.err
480
-			}
481
-			if tok.value != "]" {
482
-				return p.errorf("unrecognized extension terminator %q", tok.value)
515
+				return p.errorf("unrecognized extension %q", extName)
483 516
 			}
484 517
 
485 518
 			props := &Properties{}
... ...
@@ -635,6 +679,35 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
635 635
 	return reqFieldErr
636 636
 }
637 637
 
638
+// consumeExtName consumes extension name or expanded Any type URL and the
639
+// following ']'. It returns the name or URL consumed.
640
+func (p *textParser) consumeExtName() (string, error) {
641
+	tok := p.next()
642
+	if tok.err != nil {
643
+		return "", tok.err
644
+	}
645
+
646
+	// If extension name or type url is quoted, it's a single token.
647
+	if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
648
+		name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
649
+		if err != nil {
650
+			return "", err
651
+		}
652
+		return name, p.consumeToken("]")
653
+	}
654
+
655
+	// Consume everything up to "]"
656
+	var parts []string
657
+	for tok.value != "]" {
658
+		parts = append(parts, tok.value)
659
+		tok = p.next()
660
+		if tok.err != nil {
661
+			return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
662
+		}
663
+	}
664
+	return strings.Join(parts, ""), nil
665
+}
666
+
638 667
 // consumeOptionalSeparator consumes an optional semicolon or comma.
639 668
 // It is used in readStruct to provide backward compatibility.
640 669
 func (p *textParser) consumeOptionalSeparator() error {