Ver Fonte

Godeps: update gRPC w/ related packages

Gyu-Ho Lee há 10 anos atrás
pai
commit
4bb0481115
100 ficheiros alterados com 6334 adições e 2402 exclusões
  1. 13 16
      Godeps/Godeps.json
  2. 0 1
      Godeps/_workspace/src/github.com/bradfitz/http2/.gitignore
  3. 0 19
      Godeps/_workspace/src/github.com/bradfitz/http2/AUTHORS
  4. 0 19
      Godeps/_workspace/src/github.com/bradfitz/http2/CONTRIBUTORS
  5. 0 5
      Godeps/_workspace/src/github.com/bradfitz/http2/HACKING
  6. 0 7
      Godeps/_workspace/src/github.com/bradfitz/http2/LICENSE
  7. 0 75
      Godeps/_workspace/src/github.com/bradfitz/http2/buffer.go
  8. 0 73
      Godeps/_workspace/src/github.com/bradfitz/http2/buffer_test.go
  9. 0 5
      Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/Makefile
  10. 0 43
      Godeps/_workspace/src/github.com/bradfitz/http2/pipe.go
  11. 0 24
      Godeps/_workspace/src/github.com/bradfitz/http2/pipe_test.go
  12. 0 553
      Godeps/_workspace/src/github.com/bradfitz/http2/transport.go
  13. 0 168
      Godeps/_workspace/src/github.com/bradfitz/http2/transport_test.go
  14. 36 0
      Godeps/_workspace/src/github.com/gogo/protobuf/LICENSE
  15. 1 1
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/Makefile
  16. 109 11
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/all_test.go
  17. 33 7
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone.go
  18. 41 0
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone_test.go
  19. 51 5
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/decode.go
  20. 60 13
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/encode.go
  21. 11 1
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal.go
  22. 18 0
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal_test.go
  23. 39 1
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions.go
  24. 139 0
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions_test.go
  25. 367 274
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/lib.go
  26. 17 24
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set.go
  27. 1 1
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set_test.go
  28. 2 2
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/pointer_reflect.go
  29. 2 2
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/pointer_unsafe.go
  30. 101 1
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/properties.go
  31. 7 0
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go
  32. 5 0
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/size_test.go
  33. 1 1
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/Makefile
  34. 620 32
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go
  35. 59 0
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.proto
  36. 67 98
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/text.go
  37. 135 94
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser.go
  38. 23 2
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser_test.go
  39. 42 3
      Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_test.go
  40. 31 0
      Godeps/_workspace/src/github.com/golang/protobuf/LICENSE
  41. 1 1
      Godeps/_workspace/src/github.com/golang/protobuf/proto/Makefile
  42. 122 12
      Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go
  43. 33 7
      Godeps/_workspace/src/github.com/golang/protobuf/proto/clone.go
  44. 41 1
      Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go
  45. 49 3
      Godeps/_workspace/src/github.com/golang/protobuf/proto/decode.go
  46. 65 23
      Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go
  47. 29 9
      Godeps/_workspace/src/github.com/golang/protobuf/proto/equal.go
  48. 22 1
      Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go
  49. 50 4
      Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions.go
  50. 294 1
      Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go
  51. 396 261
      Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go
  52. 17 24
      Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set.go
  53. 1 1
      Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go
  54. 2 2
      Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_reflect.go
  55. 2 2
      Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_unsafe.go
  56. 125 7
      Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go
  57. 0 44
      Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/Makefile
  58. 122 0
      Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
  59. 10 0
      Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
  60. 33 1
      Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go
  61. 31 2
      Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go
  62. 1095 118
      Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go
  63. 101 0
      Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto
  64. 44 82
      Godeps/_workspace/src/github.com/golang/protobuf/proto/text.go
  65. 135 94
      Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser.go
  66. 25 4
      Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go
  67. 43 5
      Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go
  68. 1 1
      Godeps/_workspace/src/golang.org/x/net/LICENSE
  69. 22 0
      Godeps/_workspace/src/golang.org/x/net/PATENTS
  70. 1 1
      Godeps/_workspace/src/golang.org/x/net/context/context.go
  71. 2 2
      Godeps/_workspace/src/golang.org/x/net/context/context_test.go
  72. 19 0
      Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go
  73. 23 0
      Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
  74. 140 0
      Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp.go
  75. 176 0
      Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp_test.go
  76. 2 0
      Godeps/_workspace/src/golang.org/x/net/http2/.gitignore
  77. 11 4
      Godeps/_workspace/src/golang.org/x/net/http2/Dockerfile
  78. 0 0
      Godeps/_workspace/src/golang.org/x/net/http2/Makefile
  79. 5 2
      Godeps/_workspace/src/golang.org/x/net/http2/README
  80. 225 0
      Godeps/_workspace/src/golang.org/x/net/http2/client_conn_pool.go
  81. 89 0
      Godeps/_workspace/src/golang.org/x/net/http2/configure_transport.go
  82. 16 4
      Godeps/_workspace/src/golang.org/x/net/http2/errors.go
  83. 0 3
      Godeps/_workspace/src/golang.org/x/net/http2/errors_test.go
  84. 60 0
      Godeps/_workspace/src/golang.org/x/net/http2/fixed_buffer.go
  85. 128 0
      Godeps/_workspace/src/golang.org/x/net/http2/fixed_buffer_test.go
  86. 3 4
      Godeps/_workspace/src/golang.org/x/net/http2/flow.go
  87. 3 4
      Godeps/_workspace/src/golang.org/x/net/http2/flow_test.go
  88. 182 26
      Godeps/_workspace/src/golang.org/x/net/http2/frame.go
  89. 157 0
      Godeps/_workspace/src/golang.org/x/net/http2/frame_test.go
  90. 11 0
      Godeps/_workspace/src/golang.org/x/net/http2/go15.go
  91. 5 4
      Godeps/_workspace/src/golang.org/x/net/http2/gotrack.go
  92. 3 3
      Godeps/_workspace/src/golang.org/x/net/http2/gotrack_test.go
  93. 0 0
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/.gitignore
  94. 8 0
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/Makefile
  95. 0 0
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/README
  96. 78 32
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/h2demo.go
  97. 45 22
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/launch.go
  98. 0 0
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/rootCA.key
  99. 0 0
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/rootCA.pem
  100. 0 0
      Godeps/_workspace/src/golang.org/x/net/http2/h2demo/rootCA.srl

+ 13 - 16
Godeps/Godeps.json

@@ -27,10 +27,6 @@
 			"Comment": "v1.1.0-19-g0b00eff",
 			"Rev": "0b00effdd7a8270ebd91c24297e51643e370dd52"
 		},
-		{
-			"ImportPath": "github.com/bradfitz/http2",
-			"Rev": "3e36af6d3af0e56fa3da71099f864933dea3d9fb"
-		},
 		{
 			"ImportPath": "github.com/cheggaaa/pb",
 			"Rev": "da1f27ad1d9509b16f65f52fd9d8138b0f2dc7b2"
@@ -74,7 +70,8 @@
 		},
 		{
 			"ImportPath": "github.com/gogo/protobuf/proto",
-			"Rev": "64f27bf06efee53589314a6e5a4af34cdd85adf6"
+			"Comment": "v0.1-118-ge8904f5",
+			"Rev": "e8904f58e872a473a5b91bc9bf3377d223555263"
 		},
 		{
 			"ImportPath": "github.com/golang/glog",
@@ -82,7 +79,7 @@
 		},
 		{
 			"ImportPath": "github.com/golang/protobuf/proto",
-			"Rev": "5677a0e3d5e89854c9974e1256839ee23f8233ca"
+			"Rev": "6aaa8d47701fa6cf07e914ec01fde3d4a1fe79c3"
 		},
 		{
 			"ImportPath": "github.com/google/btree",
@@ -178,27 +175,27 @@
 		},
 		{
 			"ImportPath": "golang.org/x/net/context",
-			"Rev": "7dbad50ab5b31073856416cdcfeb2796d682f844"
+			"Rev": "04b9de9b512f58addf28c9853d50ebef61c3953e"
 		},
 		{
-			"ImportPath": "golang.org/x/oauth2",
-			"Rev": "3046bc76d6dfd7d3707f6640f85e42d9c4050f50"
+			"ImportPath": "golang.org/x/net/http2",
+			"Rev": "04b9de9b512f58addf28c9853d50ebef61c3953e"
 		},
 		{
-			"ImportPath": "golang.org/x/sys/unix",
-			"Rev": "9c60d1c508f5134d1ca726b4641db998f2523357"
+			"ImportPath": "golang.org/x/net/internal/timeseries",
+			"Rev": "04b9de9b512f58addf28c9853d50ebef61c3953e"
 		},
 		{
-			"ImportPath": "google.golang.org/cloud/compute/metadata",
-			"Rev": "f20d6dcccb44ed49de45ae3703312cb46e627db1"
+			"ImportPath": "golang.org/x/net/trace",
+			"Rev": "04b9de9b512f58addf28c9853d50ebef61c3953e"
 		},
 		{
-			"ImportPath": "google.golang.org/cloud/internal",
-			"Rev": "f20d6dcccb44ed49de45ae3703312cb46e627db1"
+			"ImportPath": "golang.org/x/sys/unix",
+			"Rev": "9c60d1c508f5134d1ca726b4641db998f2523357"
 		},
 		{
 			"ImportPath": "google.golang.org/grpc",
-			"Rev": "f5ebd86be717593ab029545492c93ddf8914832b"
+			"Rev": "e29d659177655e589850ba7d3d83f7ce12ef23dd"
 		}
 	]
 }

+ 0 - 1
Godeps/_workspace/src/github.com/bradfitz/http2/.gitignore

@@ -1 +0,0 @@
-*~

+ 0 - 19
Godeps/_workspace/src/github.com/bradfitz/http2/AUTHORS

@@ -1,19 +0,0 @@
-# This file is like Go's AUTHORS file: it lists Copyright holders.
-# The list of humans who have contributd is in the CONTRIBUTORS file.
-#
-# To contribute to this project, because it will eventually be folded
-# back in to Go itself, you need to submit a CLA:
-#
-#    http://golang.org/doc/contribute.html#copyright
-#
-# Then you get added to CONTRIBUTORS and you or your company get added
-# to the AUTHORS file.
-
-Blake Mizerany <blake.mizerany@gmail.com> github=bmizerany
-Daniel Morsing <daniel.morsing@gmail.com> github=DanielMorsing
-Gabriel Aszalos <gabriel.aszalos@gmail.com> github=gbbr
-Google, Inc.
-Keith Rarick <kr@xph.us> github=kr
-Matthew Keenan <tank.en.mate@gmail.com> <github@mattkeenan.net> github=mattkeenan
-Matt Layher <mdlayher@gmail.com> github=mdlayher
-Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> github=tatsuhiro-t

+ 0 - 19
Godeps/_workspace/src/github.com/bradfitz/http2/CONTRIBUTORS

@@ -1,19 +0,0 @@
-# This file is like Go's CONTRIBUTORS file: it lists humans.
-# The list of copyright holders (which may be companies) are in the AUTHORS file.
-#
-# To contribute to this project, because it will eventually be folded
-# back in to Go itself, you need to submit a CLA:
-#
-#    http://golang.org/doc/contribute.html#copyright
-#
-# Then you get added to CONTRIBUTORS and you or your company get added
-# to the AUTHORS file.
-
-Blake Mizerany <blake.mizerany@gmail.com> github=bmizerany
-Brad Fitzpatrick <bradfitz@golang.org> github=bradfitz
-Daniel Morsing <daniel.morsing@gmail.com> github=DanielMorsing
-Gabriel Aszalos <gabriel.aszalos@gmail.com> github=gbbr
-Keith Rarick <kr@xph.us> github=kr
-Matthew Keenan <tank.en.mate@gmail.com> <github@mattkeenan.net> github=mattkeenan
-Matt Layher <mdlayher@gmail.com> github=mdlayher
-Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> github=tatsuhiro-t

+ 0 - 5
Godeps/_workspace/src/github.com/bradfitz/http2/HACKING

@@ -1,5 +0,0 @@
-We only accept contributions from users who have gone through Go's
-contribution process (signed a CLA).
-
-Please acknowledge whether you have (and use the same email) if
-sending a pull request.

+ 0 - 7
Godeps/_workspace/src/github.com/bradfitz/http2/LICENSE

@@ -1,7 +0,0 @@
-Copyright 2014 Google & the Go AUTHORS
-
-Go AUTHORS are:
-See https://code.google.com/p/go/source/browse/AUTHORS
-
-Licensed under the terms of Go itself:
-https://code.google.com/p/go/source/browse/LICENSE

+ 0 - 75
Godeps/_workspace/src/github.com/bradfitz/http2/buffer.go

@@ -1,75 +0,0 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
-
-package http2
-
-import (
-	"errors"
-)
-
-// buffer is an io.ReadWriteCloser backed by a fixed size buffer.
-// It never allocates, but moves old data as new data is written.
-type buffer struct {
-	buf    []byte
-	r, w   int
-	closed bool
-	err    error // err to return to reader
-}
-
-var (
-	errReadEmpty = errors.New("read from empty buffer")
-	errWriteFull = errors.New("write on full buffer")
-)
-
-// Read copies bytes from the buffer into p.
-// It is an error to read when no data is available.
-func (b *buffer) Read(p []byte) (n int, err error) {
-	n = copy(p, b.buf[b.r:b.w])
-	b.r += n
-	if b.closed && b.r == b.w {
-		err = b.err
-	} else if b.r == b.w && n == 0 {
-		err = errReadEmpty
-	}
-	return n, err
-}
-
-// Len returns the number of bytes of the unread portion of the buffer.
-func (b *buffer) Len() int {
-	return b.w - b.r
-}
-
-// Write copies bytes from p into the buffer.
-// It is an error to write more data than the buffer can hold.
-func (b *buffer) Write(p []byte) (n int, err error) {
-	if b.closed {
-		return 0, errors.New("closed")
-	}
-
-	// Slide existing data to beginning.
-	if b.r > 0 && len(p) > len(b.buf)-b.w {
-		copy(b.buf, b.buf[b.r:b.w])
-		b.w -= b.r
-		b.r = 0
-	}
-
-	// Write new data.
-	n = copy(b.buf[b.w:], p)
-	b.w += n
-	if n < len(p) {
-		err = errWriteFull
-	}
-	return n, err
-}
-
-// Close marks the buffer as closed. Future calls to Write will
-// return an error. Future calls to Read, once the buffer is
-// empty, will return err.
-func (b *buffer) Close(err error) {
-	if !b.closed {
-		b.closed = true
-		b.err = err
-	}
-}

+ 0 - 73
Godeps/_workspace/src/github.com/bradfitz/http2/buffer_test.go

@@ -1,73 +0,0 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
-
-package http2
-
-import (
-	"io"
-	"reflect"
-	"testing"
-)
-
-var bufferReadTests = []struct {
-	buf      buffer
-	read, wn int
-	werr     error
-	wp       []byte
-	wbuf     buffer
-}{
-	{
-		buffer{[]byte{'a', 0}, 0, 1, false, nil},
-		5, 1, nil, []byte{'a'},
-		buffer{[]byte{'a', 0}, 1, 1, false, nil},
-	},
-	{
-		buffer{[]byte{'a', 0}, 0, 1, true, io.EOF},
-		5, 1, io.EOF, []byte{'a'},
-		buffer{[]byte{'a', 0}, 1, 1, true, io.EOF},
-	},
-	{
-		buffer{[]byte{0, 'a'}, 1, 2, false, nil},
-		5, 1, nil, []byte{'a'},
-		buffer{[]byte{0, 'a'}, 2, 2, false, nil},
-	},
-	{
-		buffer{[]byte{0, 'a'}, 1, 2, true, io.EOF},
-		5, 1, io.EOF, []byte{'a'},
-		buffer{[]byte{0, 'a'}, 2, 2, true, io.EOF},
-	},
-	{
-		buffer{[]byte{}, 0, 0, false, nil},
-		5, 0, errReadEmpty, []byte{},
-		buffer{[]byte{}, 0, 0, false, nil},
-	},
-	{
-		buffer{[]byte{}, 0, 0, true, io.EOF},
-		5, 0, io.EOF, []byte{},
-		buffer{[]byte{}, 0, 0, true, io.EOF},
-	},
-}
-
-func TestBufferRead(t *testing.T) {
-	for i, tt := range bufferReadTests {
-		read := make([]byte, tt.read)
-		n, err := tt.buf.Read(read)
-		if n != tt.wn {
-			t.Errorf("#%d: wn = %d want %d", i, n, tt.wn)
-			continue
-		}
-		if err != tt.werr {
-			t.Errorf("#%d: werr = %v want %v", i, err, tt.werr)
-			continue
-		}
-		read = read[:n]
-		if !reflect.DeepEqual(read, tt.wp) {
-			t.Errorf("#%d: read = %+v want %+v", i, read, tt.wp)
-		}
-		if !reflect.DeepEqual(tt.buf, tt.wbuf) {
-			t.Errorf("#%d: buf = %+v want %+v", i, tt.buf, tt.wbuf)
-		}
-	}
-}

+ 0 - 5
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/Makefile

@@ -1,5 +0,0 @@
-h2demo.linux: h2demo.go
-	GOOS=linux go build --tags=h2demo -o h2demo.linux .
-
-upload: h2demo.linux
-	cat h2demo.linux | go run launch.go --write_object=http2-demo-server-tls/h2demo --write_object_is_public

+ 0 - 43
Godeps/_workspace/src/github.com/bradfitz/http2/pipe.go

@@ -1,43 +0,0 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
-
-package http2
-
-import (
-	"sync"
-)
-
-type pipe struct {
-	b buffer
-	c sync.Cond
-	m sync.Mutex
-}
-
-// Read waits until data is available and copies bytes
-// from the buffer into p.
-func (r *pipe) Read(p []byte) (n int, err error) {
-	r.c.L.Lock()
-	defer r.c.L.Unlock()
-	for r.b.Len() == 0 && !r.b.closed {
-		r.c.Wait()
-	}
-	return r.b.Read(p)
-}
-
-// Write copies bytes from p into the buffer and wakes a reader.
-// It is an error to write more data than the buffer can hold.
-func (w *pipe) Write(p []byte) (n int, err error) {
-	w.c.L.Lock()
-	defer w.c.L.Unlock()
-	defer w.c.Signal()
-	return w.b.Write(p)
-}
-
-func (c *pipe) Close(err error) {
-	c.c.L.Lock()
-	defer c.c.L.Unlock()
-	defer c.c.Signal()
-	c.b.Close(err)
-}

+ 0 - 24
Godeps/_workspace/src/github.com/bradfitz/http2/pipe_test.go

@@ -1,24 +0,0 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
-
-package http2
-
-import (
-	"errors"
-	"testing"
-)
-
-func TestPipeClose(t *testing.T) {
-	var p pipe
-	p.c.L = &p.m
-	a := errors.New("a")
-	b := errors.New("b")
-	p.Close(a)
-	p.Close(b)
-	_, err := p.Read(make([]byte, 1))
-	if err != a {
-		t.Errorf("err = %v want %v", err, a)
-	}
-}

+ 0 - 553
Godeps/_workspace/src/github.com/bradfitz/http2/transport.go

@@ -1,553 +0,0 @@
-// Copyright 2015 The Go Authors.
-// See https://go.googlesource.com/go/+/master/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://go.googlesource.com/go/+/master/LICENSE
-
-package http2
-
-import (
-	"bufio"
-	"bytes"
-	"crypto/tls"
-	"errors"
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"net/http"
-	"strconv"
-	"strings"
-	"sync"
-
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/bradfitz/http2/hpack"
-)
-
-type Transport struct {
-	Fallback http.RoundTripper
-
-	// TODO: remove this and make more general with a TLS dial hook, like http
-	InsecureTLSDial bool
-
-	connMu sync.Mutex
-	conns  map[string][]*clientConn // key is host:port
-}
-
-type clientConn struct {
-	t        *Transport
-	tconn    *tls.Conn
-	tlsState *tls.ConnectionState
-	connKey  []string // key(s) this connection is cached in, in t.conns
-
-	readerDone chan struct{} // closed on error
-	readerErr  error         // set before readerDone is closed
-	hdec       *hpack.Decoder
-	nextRes    *http.Response
-
-	mu           sync.Mutex
-	closed       bool
-	goAway       *GoAwayFrame // if non-nil, the GoAwayFrame we received
-	streams      map[uint32]*clientStream
-	nextStreamID uint32
-	bw           *bufio.Writer
-	werr         error // first write error that has occurred
-	br           *bufio.Reader
-	fr           *Framer
-	// Settings from peer:
-	maxFrameSize         uint32
-	maxConcurrentStreams uint32
-	initialWindowSize    uint32
-	hbuf                 bytes.Buffer // HPACK encoder writes into this
-	henc                 *hpack.Encoder
-}
-
-type clientStream struct {
-	ID   uint32
-	resc chan resAndError
-	pw   *io.PipeWriter
-	pr   *io.PipeReader
-}
-
-type stickyErrWriter struct {
-	w   io.Writer
-	err *error
-}
-
-func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
-	if *sew.err != nil {
-		return 0, *sew.err
-	}
-	n, err = sew.w.Write(p)
-	*sew.err = err
-	return
-}
-
-func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
-	if req.URL.Scheme != "https" {
-		if t.Fallback == nil {
-			return nil, errors.New("http2: unsupported scheme and no Fallback")
-		}
-		return t.Fallback.RoundTrip(req)
-	}
-
-	host, port, err := net.SplitHostPort(req.URL.Host)
-	if err != nil {
-		host = req.URL.Host
-		port = "443"
-	}
-
-	for {
-		cc, err := t.getClientConn(host, port)
-		if err != nil {
-			return nil, err
-		}
-		res, err := cc.roundTrip(req)
-		if shouldRetryRequest(err) { // TODO: or clientconn is overloaded (too many outstanding requests)?
-			continue
-		}
-		if err != nil {
-			return nil, err
-		}
-		return res, nil
-	}
-}
-
-// CloseIdleConnections closes any connections which were previously
-// connected from previous requests but are now sitting idle.
-// It does not interrupt any connections currently in use.
-func (t *Transport) CloseIdleConnections() {
-	t.connMu.Lock()
-	defer t.connMu.Unlock()
-	for _, vv := range t.conns {
-		for _, cc := range vv {
-			cc.closeIfIdle()
-		}
-	}
-}
-
-var errClientConnClosed = errors.New("http2: client conn is closed")
-
-func shouldRetryRequest(err error) bool {
-	// TODO: or GOAWAY graceful shutdown stuff
-	return err == errClientConnClosed
-}
-
-func (t *Transport) removeClientConn(cc *clientConn) {
-	t.connMu.Lock()
-	defer t.connMu.Unlock()
-	for _, key := range cc.connKey {
-		vv, ok := t.conns[key]
-		if !ok {
-			continue
-		}
-		newList := filterOutClientConn(vv, cc)
-		if len(newList) > 0 {
-			t.conns[key] = newList
-		} else {
-			delete(t.conns, key)
-		}
-	}
-}
-
-func filterOutClientConn(in []*clientConn, exclude *clientConn) []*clientConn {
-	out := in[:0]
-	for _, v := range in {
-		if v != exclude {
-			out = append(out, v)
-		}
-	}
-	return out
-}
-
-func (t *Transport) getClientConn(host, port string) (*clientConn, error) {
-	t.connMu.Lock()
-	defer t.connMu.Unlock()
-
-	key := net.JoinHostPort(host, port)
-
-	for _, cc := range t.conns[key] {
-		if cc.canTakeNewRequest() {
-			return cc, nil
-		}
-	}
-	if t.conns == nil {
-		t.conns = make(map[string][]*clientConn)
-	}
-	cc, err := t.newClientConn(host, port, key)
-	if err != nil {
-		return nil, err
-	}
-	t.conns[key] = append(t.conns[key], cc)
-	return cc, nil
-}
-
-func (t *Transport) newClientConn(host, port, key string) (*clientConn, error) {
-	cfg := &tls.Config{
-		ServerName:         host,
-		NextProtos:         []string{NextProtoTLS},
-		InsecureSkipVerify: t.InsecureTLSDial,
-	}
-	tconn, err := tls.Dial("tcp", host+":"+port, cfg)
-	if err != nil {
-		return nil, err
-	}
-	if err := tconn.Handshake(); err != nil {
-		return nil, err
-	}
-	if !t.InsecureTLSDial {
-		if err := tconn.VerifyHostname(cfg.ServerName); err != nil {
-			return nil, err
-		}
-	}
-	state := tconn.ConnectionState()
-	if p := state.NegotiatedProtocol; p != NextProtoTLS {
-		// TODO(bradfitz): fall back to Fallback
-		return nil, fmt.Errorf("bad protocol: %v", p)
-	}
-	if !state.NegotiatedProtocolIsMutual {
-		return nil, errors.New("could not negotiate protocol mutually")
-	}
-	if _, err := tconn.Write(clientPreface); err != nil {
-		return nil, err
-	}
-
-	cc := &clientConn{
-		t:                    t,
-		tconn:                tconn,
-		connKey:              []string{key}, // TODO: cert's validated hostnames too
-		tlsState:             &state,
-		readerDone:           make(chan struct{}),
-		nextStreamID:         1,
-		maxFrameSize:         16 << 10, // spec default
-		initialWindowSize:    65535,    // spec default
-		maxConcurrentStreams: 1000,     // "infinite", per spec. 1000 seems good enough.
-		streams:              make(map[uint32]*clientStream),
-	}
-	cc.bw = bufio.NewWriter(stickyErrWriter{tconn, &cc.werr})
-	cc.br = bufio.NewReader(tconn)
-	cc.fr = NewFramer(cc.bw, cc.br)
-	cc.henc = hpack.NewEncoder(&cc.hbuf)
-
-	cc.fr.WriteSettings()
-	// TODO: re-send more conn-level flow control tokens when server uses all these.
-	cc.fr.WriteWindowUpdate(0, 1<<30) // um, 0x7fffffff doesn't work to Google? it hangs?
-	cc.bw.Flush()
-	if cc.werr != nil {
-		return nil, cc.werr
-	}
-
-	// Read the obligatory SETTINGS frame
-	f, err := cc.fr.ReadFrame()
-	if err != nil {
-		return nil, err
-	}
-	sf, ok := f.(*SettingsFrame)
-	if !ok {
-		return nil, fmt.Errorf("expected settings frame, got: %T", f)
-	}
-	cc.fr.WriteSettingsAck()
-	cc.bw.Flush()
-
-	sf.ForeachSetting(func(s Setting) error {
-		switch s.ID {
-		case SettingMaxFrameSize:
-			cc.maxFrameSize = s.Val
-		case SettingMaxConcurrentStreams:
-			cc.maxConcurrentStreams = s.Val
-		case SettingInitialWindowSize:
-			cc.initialWindowSize = s.Val
-		default:
-			// TODO(bradfitz): handle more
-			log.Printf("Unhandled Setting: %v", s)
-		}
-		return nil
-	})
-	// TODO: figure out henc size
-	cc.hdec = hpack.NewDecoder(initialHeaderTableSize, cc.onNewHeaderField)
-
-	go cc.readLoop()
-	return cc, nil
-}
-
-func (cc *clientConn) setGoAway(f *GoAwayFrame) {
-	cc.mu.Lock()
-	defer cc.mu.Unlock()
-	cc.goAway = f
-}
-
-func (cc *clientConn) canTakeNewRequest() bool {
-	cc.mu.Lock()
-	defer cc.mu.Unlock()
-	return cc.goAway == nil &&
-		int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
-		cc.nextStreamID < 2147483647
-}
-
-func (cc *clientConn) closeIfIdle() {
-	cc.mu.Lock()
-	if len(cc.streams) > 0 {
-		cc.mu.Unlock()
-		return
-	}
-	cc.closed = true
-	// TODO: do clients send GOAWAY too? maybe? Just Close:
-	cc.mu.Unlock()
-
-	cc.tconn.Close()
-}
-
-func (cc *clientConn) roundTrip(req *http.Request) (*http.Response, error) {
-	cc.mu.Lock()
-
-	if cc.closed {
-		cc.mu.Unlock()
-		return nil, errClientConnClosed
-	}
-
-	cs := cc.newStream()
-	hasBody := false // TODO
-
-	// we send: HEADERS[+CONTINUATION] + (DATA?)
-	hdrs := cc.encodeHeaders(req)
-	first := true
-	for len(hdrs) > 0 {
-		chunk := hdrs
-		if len(chunk) > int(cc.maxFrameSize) {
-			chunk = chunk[:cc.maxFrameSize]
-		}
-		hdrs = hdrs[len(chunk):]
-		endHeaders := len(hdrs) == 0
-		if first {
-			cc.fr.WriteHeaders(HeadersFrameParam{
-				StreamID:      cs.ID,
-				BlockFragment: chunk,
-				EndStream:     !hasBody,
-				EndHeaders:    endHeaders,
-			})
-			first = false
-		} else {
-			cc.fr.WriteContinuation(cs.ID, endHeaders, chunk)
-		}
-	}
-	cc.bw.Flush()
-	werr := cc.werr
-	cc.mu.Unlock()
-
-	if hasBody {
-		// TODO: write data. and it should probably be interleaved:
-		//   go ... io.Copy(dataFrameWriter{cc, cs, ...}, req.Body) ... etc
-	}
-
-	if werr != nil {
-		return nil, werr
-	}
-
-	re := <-cs.resc
-	if re.err != nil {
-		return nil, re.err
-	}
-	res := re.res
-	res.Request = req
-	res.TLS = cc.tlsState
-	return res, nil
-}
-
-// requires cc.mu be held.
-func (cc *clientConn) encodeHeaders(req *http.Request) []byte {
-	cc.hbuf.Reset()
-
-	// TODO(bradfitz): figure out :authority-vs-Host stuff between http2 and Go
-	host := req.Host
-	if host == "" {
-		host = req.URL.Host
-	}
-
-	path := req.URL.Path
-	if path == "" {
-		path = "/"
-	}
-
-	cc.writeHeader(":authority", host) // probably not right for all sites
-	cc.writeHeader(":method", req.Method)
-	cc.writeHeader(":path", path)
-	cc.writeHeader(":scheme", "https")
-
-	for k, vv := range req.Header {
-		lowKey := strings.ToLower(k)
-		if lowKey == "host" {
-			continue
-		}
-		for _, v := range vv {
-			cc.writeHeader(lowKey, v)
-		}
-	}
-	return cc.hbuf.Bytes()
-}
-
-func (cc *clientConn) writeHeader(name, value string) {
-	log.Printf("sending %q = %q", name, value)
-	cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
-}
-
-type resAndError struct {
-	res *http.Response
-	err error
-}
-
-// requires cc.mu be held.
-func (cc *clientConn) newStream() *clientStream {
-	cs := &clientStream{
-		ID:   cc.nextStreamID,
-		resc: make(chan resAndError, 1),
-	}
-	cc.nextStreamID += 2
-	cc.streams[cs.ID] = cs
-	return cs
-}
-
-func (cc *clientConn) streamByID(id uint32, andRemove bool) *clientStream {
-	cc.mu.Lock()
-	defer cc.mu.Unlock()
-	cs := cc.streams[id]
-	if andRemove {
-		delete(cc.streams, id)
-	}
-	return cs
-}
-
-// runs in its own goroutine.
-func (cc *clientConn) readLoop() {
-	defer cc.t.removeClientConn(cc)
-	defer close(cc.readerDone)
-
-	activeRes := map[uint32]*clientStream{} // keyed by streamID
-	// Close any response bodies if the server closes prematurely.
-	// TODO: also do this if we've written the headers but not
-	// gotten a response yet.
-	defer func() {
-		err := cc.readerErr
-		if err == io.EOF {
-			err = io.ErrUnexpectedEOF
-		}
-		for _, cs := range activeRes {
-			cs.pw.CloseWithError(err)
-		}
-	}()
-
-	// continueStreamID is the stream ID we're waiting for
-	// continuation frames for.
-	var continueStreamID uint32
-
-	for {
-		f, err := cc.fr.ReadFrame()
-		if err != nil {
-			cc.readerErr = err
-			return
-		}
-		log.Printf("Transport received %v: %#v", f.Header(), f)
-
-		streamID := f.Header().StreamID
-
-		_, isContinue := f.(*ContinuationFrame)
-		if isContinue {
-			if streamID != continueStreamID {
-				log.Printf("Protocol violation: got CONTINUATION with id %d; want %d", streamID, continueStreamID)
-				cc.readerErr = ConnectionError(ErrCodeProtocol)
-				return
-			}
-		} else if continueStreamID != 0 {
-			// Continue frames need to be adjacent in the stream
-			// and we were in the middle of headers.
-			log.Printf("Protocol violation: got %T for stream %d, want CONTINUATION for %d", f, streamID, continueStreamID)
-			cc.readerErr = ConnectionError(ErrCodeProtocol)
-			return
-		}
-
-		if streamID%2 == 0 {
-			// Ignore streams pushed from the server for now.
-			// These always have an even stream id.
-			continue
-		}
-		streamEnded := false
-		if ff, ok := f.(streamEnder); ok {
-			streamEnded = ff.StreamEnded()
-		}
-
-		cs := cc.streamByID(streamID, streamEnded)
-		if cs == nil {
-			log.Printf("Received frame for untracked stream ID %d", streamID)
-			continue
-		}
-
-		switch f := f.(type) {
-		case *HeadersFrame:
-			cc.nextRes = &http.Response{
-				Proto:      "HTTP/2.0",
-				ProtoMajor: 2,
-				Header:     make(http.Header),
-			}
-			cs.pr, cs.pw = io.Pipe()
-			cc.hdec.Write(f.HeaderBlockFragment())
-		case *ContinuationFrame:
-			cc.hdec.Write(f.HeaderBlockFragment())
-		case *DataFrame:
-			log.Printf("DATA: %q", f.Data())
-			cs.pw.Write(f.Data())
-		case *GoAwayFrame:
-			cc.t.removeClientConn(cc)
-			if f.ErrCode != 0 {
-				// TODO: deal with GOAWAY more. particularly the error code
-				log.Printf("transport got GOAWAY with error code = %v", f.ErrCode)
-			}
-			cc.setGoAway(f)
-		default:
-			log.Printf("Transport: unhandled response frame type %T", f)
-		}
-		headersEnded := false
-		if he, ok := f.(headersEnder); ok {
-			headersEnded = he.HeadersEnded()
-			if headersEnded {
-				continueStreamID = 0
-			} else {
-				continueStreamID = streamID
-			}
-		}
-
-		if streamEnded {
-			cs.pw.Close()
-			delete(activeRes, streamID)
-		}
-		if headersEnded {
-			if cs == nil {
-				panic("couldn't find stream") // TODO be graceful
-			}
-			// TODO: set the Body to one which notes the
-			// Close and also sends the server a
-			// RST_STREAM
-			cc.nextRes.Body = cs.pr
-			res := cc.nextRes
-			activeRes[streamID] = cs
-			cs.resc <- resAndError{res: res}
-		}
-	}
-}
-
-func (cc *clientConn) onNewHeaderField(f hpack.HeaderField) {
-	// TODO: verifiy pseudo headers come before non-pseudo headers
-	// TODO: verifiy the status is set
-	log.Printf("Header field: %+v", f)
-	if f.Name == ":status" {
-		code, err := strconv.Atoi(f.Value)
-		if err != nil {
-			panic("TODO: be graceful")
-		}
-		cc.nextRes.Status = f.Value + " " + http.StatusText(code)
-		cc.nextRes.StatusCode = code
-		return
-	}
-	if strings.HasPrefix(f.Name, ":") {
-		// "Endpoints MUST NOT generate pseudo-header fields other than those defined in this document."
-		// TODO: treat as invalid?
-		return
-	}
-	cc.nextRes.Header.Add(http.CanonicalHeaderKey(f.Name), f.Value)
-}

+ 0 - 168
Godeps/_workspace/src/github.com/bradfitz/http2/transport_test.go

@@ -1,168 +0,0 @@
-// Copyright 2015 The Go Authors.
-// See https://go.googlesource.com/go/+/master/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://go.googlesource.com/go/+/master/LICENSE
-
-package http2
-
-import (
-	"flag"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"reflect"
-	"strings"
-	"testing"
-	"time"
-)
-
-var (
-	extNet        = flag.Bool("extnet", false, "do external network tests")
-	transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport")
-	insecure      = flag.Bool("insecure", false, "insecure TLS dials")
-)
-
-func TestTransportExternal(t *testing.T) {
-	if !*extNet {
-		t.Skip("skipping external network test")
-	}
-	req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil)
-	rt := &Transport{
-		InsecureTLSDial: *insecure,
-	}
-	res, err := rt.RoundTrip(req)
-	if err != nil {
-		t.Fatalf("%v", err)
-	}
-	res.Write(os.Stdout)
-}
-
-func TestTransport(t *testing.T) {
-	const body = "sup"
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
-		io.WriteString(w, body)
-	})
-	defer st.Close()
-
-	tr := &Transport{InsecureTLSDial: true}
-	defer tr.CloseIdleConnections()
-
-	req, err := http.NewRequest("GET", st.ts.URL, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	res, err := tr.RoundTrip(req)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer res.Body.Close()
-
-	t.Logf("Got res: %+v", res)
-	if g, w := res.StatusCode, 200; g != w {
-		t.Errorf("StatusCode = %v; want %v", g, w)
-	}
-	if g, w := res.Status, "200 OK"; g != w {
-		t.Errorf("Status = %q; want %q", g, w)
-	}
-	wantHeader := http.Header{
-		"Content-Length": []string{"3"},
-		"Content-Type":   []string{"text/plain; charset=utf-8"},
-	}
-	if !reflect.DeepEqual(res.Header, wantHeader) {
-		t.Errorf("res Header = %v; want %v", res.Header, wantHeader)
-	}
-	if res.Request != req {
-		t.Errorf("Response.Request = %p; want %p", res.Request, req)
-	}
-	if res.TLS == nil {
-		t.Errorf("Response.TLS = nil; want non-nil", res.TLS)
-	}
-	slurp, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Error("Body read: %v", err)
-	} else if string(slurp) != body {
-		t.Errorf("Body = %q; want %q", slurp, body)
-	}
-
-}
-
-func TestTransportReusesConns(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
-		io.WriteString(w, r.RemoteAddr)
-	}, optOnlyServer)
-	defer st.Close()
-	tr := &Transport{InsecureTLSDial: true}
-	defer tr.CloseIdleConnections()
-	get := func() string {
-		req, err := http.NewRequest("GET", st.ts.URL, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		res, err := tr.RoundTrip(req)
-		if err != nil {
-			t.Fatal(err)
-		}
-		defer res.Body.Close()
-		slurp, err := ioutil.ReadAll(res.Body)
-		if err != nil {
-			t.Fatalf("Body read: %v", err)
-		}
-		addr := strings.TrimSpace(string(slurp))
-		if addr == "" {
-			t.Fatalf("didn't get an addr in response")
-		}
-		return addr
-	}
-	first := get()
-	second := get()
-	if first != second {
-		t.Errorf("first and second responses were on different connections: %q vs %q", first, second)
-	}
-}
-
-func TestTransportAbortClosesPipes(t *testing.T) {
-	shutdown := make(chan struct{})
-	st := newServerTester(t,
-		func(w http.ResponseWriter, r *http.Request) {
-			w.(http.Flusher).Flush()
-			<-shutdown
-		},
-		optOnlyServer,
-	)
-	defer st.Close()
-	defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
-
-	done := make(chan struct{})
-	requestMade := make(chan struct{})
-	go func() {
-		defer close(done)
-		tr := &Transport{
-			InsecureTLSDial: true,
-		}
-		req, err := http.NewRequest("GET", st.ts.URL, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-		res, err := tr.RoundTrip(req)
-		if err != nil {
-			t.Fatal(err)
-		}
-		defer res.Body.Close()
-		close(requestMade)
-		_, err = ioutil.ReadAll(res.Body)
-		if err == nil {
-			t.Error("expected error from res.Body.Read")
-		}
-	}()
-
-	<-requestMade
-	// Now force the serve loop to end, via closing the connection.
-	st.closeConn()
-	// deadlock? that's a bug.
-	select {
-	case <-done:
-	case <-time.After(3 * time.Second):
-		t.Fatal("timeout")
-	}
-}

+ 36 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/LICENSE

@@ -0,0 +1,36 @@
+Extensions for Protocol Buffers to create more go like structures.
+
+Copyright (c) 2013, Vastech SA (PTY) LTD. All rights reserved.
+http://github.com/gogo/protobuf/gogoproto
+
+Go support for Protocol Buffers - Google's data interchange format
+
+Copyright 2010 The Go Authors.  All rights reserved.
+https://github.com/golang/protobuf
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+

+ 1 - 1
Godeps/_workspace/src/github.com/gogo/protobuf/proto/Makefile

@@ -39,5 +39,5 @@ test: install generate-test-pbs
 generate-test-pbs:
 	make install
 	make -C testdata
-	protoc-min-version --version="3.0.0" --proto_path=.:../../../../ proto3_proto/proto3.proto
+	protoc-min-version --version="3.0.0" --proto_path=.:../../../../ --gogo_out=. proto3_proto/proto3.proto
 	make

+ 109 - 11
Godeps/_workspace/src/github.com/gogo/protobuf/proto/all_test.go

@@ -401,17 +401,18 @@ type fakeMarshaler struct {
 	err error
 }
 
-func (f fakeMarshaler) Marshal() ([]byte, error) {
-	return f.b, f.err
-}
+func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err }
+func (f *fakeMarshaler) String() string           { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) }
+func (f *fakeMarshaler) ProtoMessage()            {}
+func (f *fakeMarshaler) Reset()                   {}
 
-func (f fakeMarshaler) String() string {
-	return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err)
+type msgWithFakeMarshaler struct {
+	M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"`
 }
 
-func (f fakeMarshaler) ProtoMessage() {}
-
-func (f fakeMarshaler) Reset() {}
+func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) }
+func (m *msgWithFakeMarshaler) ProtoMessage()  {}
+func (m *msgWithFakeMarshaler) Reset()         {}
 
 // Simple tests for proto messages that implement the Marshaler interface.
 func TestMarshalerEncoding(t *testing.T) {
@@ -423,7 +424,7 @@ func TestMarshalerEncoding(t *testing.T) {
 	}{
 		{
 			name: "Marshaler that fails",
-			m: fakeMarshaler{
+			m: &fakeMarshaler{
 				err: errors.New("some marshal err"),
 				b:   []byte{5, 6, 7},
 			},
@@ -431,9 +432,25 @@ func TestMarshalerEncoding(t *testing.T) {
 			want:    nil,
 			wantErr: errors.New("some marshal err"),
 		},
+		{
+			name: "Marshaler that fails with RequiredNotSetError",
+			m: &msgWithFakeMarshaler{
+				M: &fakeMarshaler{
+					err: &RequiredNotSetError{},
+					b:   []byte{5, 6, 7},
+				},
+			},
+			// Since there's an error that can be continued after,
+			// the buffer should be written.
+			want: []byte{
+				10, 3, // for &msgWithFakeMarshaler
+				5, 6, 7, // for &fakeMarshaler
+			},
+			wantErr: &RequiredNotSetError{},
+		},
 		{
 			name: "Marshaler that succeeds",
-			m: fakeMarshaler{
+			m: &fakeMarshaler{
 				b: []byte{0, 1, 2, 3, 4, 127, 255},
 			},
 			want:    []byte{0, 1, 2, 3, 4, 127, 255},
@@ -443,6 +460,10 @@ func TestMarshalerEncoding(t *testing.T) {
 	for _, test := range tests {
 		b := NewBuffer(nil)
 		err := b.Marshal(test.m)
+		if _, ok := err.(*RequiredNotSetError); ok {
+			// We're not in package proto, so we can only assert the type in this case.
+			err = &RequiredNotSetError{}
+		}
 		if !reflect.DeepEqual(test.wantErr, err) {
 			t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr)
 		}
@@ -1281,7 +1302,7 @@ func TestEnum(t *testing.T) {
 // We don't care what the value actually is, just as long as it doesn't crash.
 func TestPrintingNilEnumFields(t *testing.T) {
 	pb := new(GoEnum)
-	fmt.Sprintf("%+v", pb)
+	_ = fmt.Sprintf("%+v", pb)
 }
 
 // Verify that absent required fields cause Marshal/Unmarshal to return errors.
@@ -1925,6 +1946,83 @@ func TestMapFieldRoundTrips(t *testing.T) {
 	}
 }
 
+func TestMapFieldWithNil(t *testing.T) {
+	m := &MessageWithMap{
+		MsgMapping: map[int64]*FloatingPoint{
+			1: nil,
+		},
+	}
+	b, err := Marshal(m)
+	if err == nil {
+		t.Fatalf("Marshal of bad map should have failed, got these bytes: %v", b)
+	}
+}
+
+func TestOneof(t *testing.T) {
+	m := &Communique{}
+	b, err := Marshal(m)
+	if err != nil {
+		t.Fatalf("Marshal of empty message with oneof: %v", err)
+	}
+	if len(b) != 0 {
+		t.Errorf("Marshal of empty message yielded too many bytes: %v", b)
+	}
+
+	m = &Communique{
+		Union: &Communique_Name{"Barry"},
+	}
+
+	// Round-trip.
+	b, err = Marshal(m)
+	if err != nil {
+		t.Fatalf("Marshal of message with oneof: %v", err)
+	}
+	if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5)
+		t.Errorf("Incorrect marshal of message with oneof: %v", b)
+	}
+	m.Reset()
+	if err := Unmarshal(b, m); err != nil {
+		t.Fatalf("Unmarshal of message with oneof: %v", err)
+	}
+	if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" {
+		t.Errorf("After round trip, Union = %+v", m.Union)
+	}
+	if name := m.GetName(); name != "Barry" {
+		t.Errorf("After round trip, GetName = %q, want %q", name, "Barry")
+	}
+
+	// Let's try with a message in the oneof.
+	m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}}
+	b, err = Marshal(m)
+	if err != nil {
+		t.Fatalf("Marshal of message with oneof set to message: %v", err)
+	}
+	if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16)
+		t.Errorf("Incorrect marshal of message with oneof set to message: %v", b)
+	}
+	m.Reset()
+	if err := Unmarshal(b, m); err != nil {
+		t.Fatalf("Unmarshal of message with oneof set to message: %v", err)
+	}
+	ss, ok := m.Union.(*Communique_Msg)
+	if !ok || ss.Msg.GetStringField() != "deep deep string" {
+		t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union)
+	}
+}
+
+func TestInefficientPackedBool(t *testing.T) {
+	// https://github.com/golang/protobuf/issues/76
+	inp := []byte{
+		0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes
+		// Usually a bool should take a single byte,
+		// but it is permitted to be any varint.
+		0xb9, 0x30,
+	}
+	if err := Unmarshal(inp, new(MoreRepeated)); err != nil {
+		t.Error(err)
+	}
+}
+
 // Benchmarks
 
 func testMsg() *GoTest {

+ 33 - 7
Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone.go

@@ -30,7 +30,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Protocol buffer deep copy and merge.
-// TODO: MessageSet and RawMessage.
+// TODO: RawMessage.
 
 package proto
 
@@ -75,12 +75,13 @@ func Merge(dst, src Message) {
 }
 
 func mergeStruct(out, in reflect.Value) {
+	sprop := GetProperties(in.Type())
 	for i := 0; i < in.NumField(); i++ {
 		f := in.Type().Field(i)
 		if strings.HasPrefix(f.Name, "XXX_") {
 			continue
 		}
-		mergeAny(out.Field(i), in.Field(i))
+		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
 	}
 
 	if emIn, ok := in.Addr().Interface().(extensionsMap); ok {
@@ -103,7 +104,10 @@ func mergeStruct(out, in reflect.Value) {
 	}
 }
 
-func mergeAny(out, in reflect.Value) {
+// mergeAny performs a merge between two values of the same type.
+// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
+// prop is set if this is a struct field (it may be nil).
+func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
 	if in.Type() == protoMessageType {
 		if !in.IsNil() {
 			if out.IsNil() {
@@ -117,7 +121,21 @@ func mergeAny(out, in reflect.Value) {
 	switch in.Kind() {
 	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
 		reflect.String, reflect.Uint32, reflect.Uint64:
+		if !viaPtr && isProto3Zero(in) {
+			return
+		}
 		out.Set(in)
+	case reflect.Interface:
+		// Probably a oneof field; copy non-nil values.
+		if in.IsNil() {
+			return
+		}
+		// Allocate destination if it is not set, or set to a different type.
+		// Otherwise we will merge as normal.
+		if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
+			out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
+		}
+		mergeAny(out.Elem(), in.Elem(), false, nil)
 	case reflect.Map:
 		if in.Len() == 0 {
 			return
@@ -132,7 +150,7 @@ func mergeAny(out, in reflect.Value) {
 			switch elemKind {
 			case reflect.Ptr:
 				val = reflect.New(in.Type().Elem().Elem())
-				mergeAny(val, in.MapIndex(key))
+				mergeAny(val, in.MapIndex(key), false, nil)
 			case reflect.Slice:
 				val = in.MapIndex(key)
 				val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
@@ -148,13 +166,21 @@ func mergeAny(out, in reflect.Value) {
 		if out.IsNil() {
 			out.Set(reflect.New(in.Elem().Type()))
 		}
-		mergeAny(out.Elem(), in.Elem())
+		mergeAny(out.Elem(), in.Elem(), true, nil)
 	case reflect.Slice:
 		if in.IsNil() {
 			return
 		}
 		if in.Type().Elem().Kind() == reflect.Uint8 {
 			// []byte is a scalar bytes field, not a repeated field.
+
+			// Edge case: if this is in a proto3 message, a zero length
+			// bytes field is considered the zero value, and should not
+			// be merged.
+			if prop != nil && prop.proto3 && in.Len() == 0 {
+				return
+			}
+
 			// Make a deep copy.
 			// Append to []byte{} instead of []byte(nil) so that we never end up
 			// with a nil result.
@@ -172,7 +198,7 @@ func mergeAny(out, in reflect.Value) {
 		default:
 			for i := 0; i < n; i++ {
 				x := reflect.Indirect(reflect.New(in.Type().Elem()))
-				mergeAny(x, in.Index(i))
+				mergeAny(x, in.Index(i), false, nil)
 				out.Set(reflect.Append(out, x))
 			}
 		}
@@ -189,7 +215,7 @@ func mergeExtension(out, in map[int32]Extension) {
 		eOut := Extension{desc: eIn.desc}
 		if eIn.value != nil {
 			v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
-			mergeAny(v, reflect.ValueOf(eIn.value))
+			mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
 			eOut.value = v.Interface()
 		}
 		if eIn.enc != nil {

+ 41 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone_test.go

@@ -35,6 +35,8 @@ import (
 	"testing"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
+
+	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
 	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
 )
 
@@ -213,6 +215,45 @@ var mergeTests = []struct {
 			ByteMapping: map[bool][]byte{true: []byte("wowsa")},
 		},
 	},
+	// proto3 shouldn't merge zero values,
+	// in the same way that proto2 shouldn't merge nils.
+	{
+		src: &proto3pb.Message{
+			Name: "Aaron",
+			Data: []byte(""), // zero value, but not nil
+		},
+		dst: &proto3pb.Message{
+			HeightInCm: 176,
+			Data:       []byte("texas!"),
+		},
+		want: &proto3pb.Message{
+			Name:       "Aaron",
+			HeightInCm: 176,
+			Data:       []byte("texas!"),
+		},
+	},
+	// Oneof fields should merge by assignment.
+	{
+		src: &pb.Communique{
+			Union: &pb.Communique_Number{Number: 41},
+		},
+		dst: &pb.Communique{
+			Union: &pb.Communique_Name{Name: "Bobby Tables"},
+		},
+		want: &pb.Communique{
+			Union: &pb.Communique_Number{Number: 41},
+		},
+	},
+	// Oneof nil is the same as not set.
+	{
+		src: &pb.Communique{},
+		dst: &pb.Communique{
+			Union: &pb.Communique_Name{Name: "Bobby Tables"},
+		},
+		want: &pb.Communique{
+			Union: &pb.Communique_Name{Name: "Bobby Tables"},
+		},
+	},
 }
 
 func TestMerge(t *testing.T) {

+ 51 - 5
Godeps/_workspace/src/github.com/gogo/protobuf/proto/decode.go

@@ -46,6 +46,10 @@ import (
 // errOverflow is returned when an integer is too large to be represented.
 var errOverflow = errors.New("proto: integer overflow")
 
+// ErrInternalBadWireType is returned by generated code when an incorrect
+// wire type is encountered. It does not get returned to user code.
+var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
+
 // The fundamental decoders that interpret bytes on the wire.
 // Those that take integer types all return uint64 and are
 // therefore of type valueDecoder.
@@ -314,6 +318,24 @@ func UnmarshalMerge(buf []byte, pb Message) error {
 	return NewBuffer(buf).Unmarshal(pb)
 }
 
+// DecodeMessage reads a count-delimited message from the Buffer.
+func (p *Buffer) DecodeMessage(pb Message) error {
+	enc, err := p.DecodeRawBytes(false)
+	if err != nil {
+		return err
+	}
+	return NewBuffer(enc).Unmarshal(pb)
+}
+
+// DecodeGroup reads a tag-delimited group from the Buffer.
+func (p *Buffer) DecodeGroup(pb Message) error {
+	typ, base, err := getbase(pb)
+	if err != nil {
+		return err
+	}
+	return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+}
+
 // Unmarshal parses the protocol buffer representation in the
 // Buffer and places the decoded result in pb.  If the struct
 // underlying pb does not match the data in the buffer, the results can be
@@ -370,11 +392,11 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group
 			if prop.extendable {
 				if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) {
 					if err = o.skip(st, tag, wire); err == nil {
-						if ee, ok := e.(extensionsMap); ok {
+						if ee, eok := e.(extensionsMap); eok {
 							ext := ee.ExtensionMap()[int32(tag)] // may be missing
 							ext.enc = append(ext.enc, o.buf[oi:o.index]...)
 							ee.ExtensionMap()[int32(tag)] = ext
-						} else if ee, ok := e.(extensionsBytes); ok {
+						} else if ee, eok := e.(extensionsBytes); eok {
 							ext := ee.GetExtensions()
 							*ext = append(*ext, o.buf[oi:o.index]...)
 						}
@@ -382,6 +404,20 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group
 					continue
 				}
 			}
+			// Maybe it's a oneof?
+			if prop.oneofUnmarshaler != nil {
+				m := structPointer_Interface(base, st).(Message)
+				// First return value indicates whether tag is a oneof field.
+				ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
+				if err == ErrInternalBadWireType {
+					// Map the error to something more descriptive.
+					// Do the formatting here to save generated code space.
+					err = fmt.Errorf("bad wiretype for oneof field in %T", m)
+				}
+				if ok {
+					continue
+				}
+			}
 			err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
 			continue
 		}
@@ -566,9 +602,13 @@ func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error
 		return err
 	}
 	nb := int(nn) // number of bytes of encoded bools
+	fin := o.index + nb
+	if fin < o.index {
+		return errOverflow
+	}
 
 	y := *v
-	for i := 0; i < nb; i++ {
+	for o.index < fin {
 		u, err := p.valDec(o)
 		if err != nil {
 			return err
@@ -680,7 +720,7 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
 	oi := o.index       // index at the end of this map entry
 	o.index -= len(raw) // move buffer back to start of map entry
 
-	mptr := structPointer_Map(base, p.field, p.mtype) // *map[K]V
+	mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
 	if mptr.Elem().IsNil() {
 		mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
 	}
@@ -732,8 +772,14 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
 			return fmt.Errorf("proto: bad map data tag %d", raw[0])
 		}
 	}
+	keyelem, valelem := keyptr.Elem(), valptr.Elem()
+	if !keyelem.IsValid() || !valelem.IsValid() {
+		// We did not decode the key or the value in the map entry.
+		// Either way, it's an invalid map entry.
+		return fmt.Errorf("proto: bad map data: missing key/val")
+	}
 
-	v.SetMapIndex(keyptr.Elem(), valptr.Elem())
+	v.SetMapIndex(keyelem, valelem)
 	return nil
 }
 

+ 60 - 13
Godeps/_workspace/src/github.com/gogo/protobuf/proto/encode.go

@@ -228,6 +228,20 @@ func Marshal(pb Message) ([]byte, error) {
 	return p.buf, err
 }
 
+// EncodeMessage writes the protocol buffer to the Buffer,
+// prefixed by a varint-encoded length.
+func (p *Buffer) EncodeMessage(pb Message) error {
+	t, base, err := getbase(pb)
+	if structPointer_IsNil(base) {
+		return ErrNil
+	}
+	if err == nil {
+		var state errorState
+		err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
+	}
+	return err
+}
+
 // Marshal takes the protocol buffer
 // and encodes it into the wire format, writing the result to the
 // Buffer.
@@ -318,7 +332,7 @@ func size_bool(p *Properties, base structPointer) int {
 
 func size_proto3_bool(p *Properties, base structPointer) int {
 	v := *structPointer_BoolVal(base, p.field)
-	if !v {
+	if !v && !p.oneof {
 		return 0
 	}
 	return len(p.tagcode) + 1 // each bool takes exactly one byte
@@ -361,7 +375,7 @@ func size_int32(p *Properties, base structPointer) (n int) {
 func size_proto3_int32(p *Properties, base structPointer) (n int) {
 	v := structPointer_Word32Val(base, p.field)
 	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
-	if x == 0 {
+	if x == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -407,7 +421,7 @@ func size_uint32(p *Properties, base structPointer) (n int) {
 func size_proto3_uint32(p *Properties, base structPointer) (n int) {
 	v := structPointer_Word32Val(base, p.field)
 	x := word32Val_Get(v)
-	if x == 0 {
+	if x == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -452,7 +466,7 @@ func size_int64(p *Properties, base structPointer) (n int) {
 func size_proto3_int64(p *Properties, base structPointer) (n int) {
 	v := structPointer_Word64Val(base, p.field)
 	x := word64Val_Get(v)
-	if x == 0 {
+	if x == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -495,7 +509,7 @@ func size_string(p *Properties, base structPointer) (n int) {
 
 func size_proto3_string(p *Properties, base structPointer) (n int) {
 	v := *structPointer_StringVal(base, p.field)
-	if v == "" {
+	if v == "" && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -529,7 +543,7 @@ func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
 		}
 		o.buf = append(o.buf, p.tagcode...)
 		o.EncodeRawBytes(data)
-		return nil
+		return state.err
 	}
 
 	o.buf = append(o.buf, p.tagcode...)
@@ -667,7 +681,7 @@ func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error
 
 func size_slice_byte(p *Properties, base structPointer) (n int) {
 	s := *structPointer_Bytes(base, p.field)
-	if s == nil {
+	if s == nil && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -677,7 +691,7 @@ func size_slice_byte(p *Properties, base structPointer) (n int) {
 
 func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
 	s := *structPointer_Bytes(base, p.field)
-	if len(s) == 0 {
+	if len(s) == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -1084,7 +1098,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
 			repeated MapFieldEntry map_field = N;
 	*/
 
-	v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
+	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
 	if v.Len() == 0 {
 		return nil
 	}
@@ -1101,11 +1115,15 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
 		return nil
 	}
 
-	keys := v.MapKeys()
-	sort.Sort(mapKeys(keys))
-	for _, key := range keys {
+	// Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
+	for _, key := range v.MapKeys() {
 		val := v.MapIndex(key)
 
+		// The only illegal map entry values are nil message pointers.
+		if val.Kind() == reflect.Ptr && val.IsNil() {
+			return errors.New("proto: map has nil element")
+		}
+
 		keycopy.Set(key)
 		valcopy.Set(val)
 
@@ -1118,7 +1136,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
 }
 
 func size_new_map(p *Properties, base structPointer) int {
-	v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
+	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
 
 	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
 
@@ -1196,6 +1214,14 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
 		}
 	}
 
+	// Do oneof fields.
+	if prop.oneofMarshaler != nil {
+		m := structPointer_Interface(base, prop.stype).(Message)
+		if err := prop.oneofMarshaler(m, o); err != nil {
+			return err
+		}
+	}
+
 	// Add unrecognized fields at the end.
 	if prop.unrecField.IsValid() {
 		v := *structPointer_Bytes(base, prop.unrecField)
@@ -1221,6 +1247,27 @@ func size_struct(prop *StructProperties, base structPointer) (n int) {
 		n += len(v)
 	}
 
+	// Factor in any oneof fields.
+	// TODO: This could be faster and use less reflection.
+	if prop.oneofMarshaler != nil {
+		sv := reflect.ValueOf(structPointer_Interface(base, prop.stype)).Elem()
+		for i := 0; i < prop.stype.NumField(); i++ {
+			fv := sv.Field(i)
+			if fv.Kind() != reflect.Interface || fv.IsNil() {
+				continue
+			}
+			if prop.stype.Field(i).Tag.Get("protobuf_oneof") == "" {
+				continue
+			}
+			spv := fv.Elem()         // interface -> *T
+			sv := spv.Elem()         // *T -> T
+			sf := sv.Type().Field(0) // StructField inside T
+			var prop Properties
+			prop.Init(sf.Type, "whatever", sf.Tag.Get("protobuf"), &sf)
+			n += prop.size(&prop, toStructPointer(spv))
+		}
+	}
+
 	return
 }
 

+ 11 - 1
Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal.go

@@ -30,7 +30,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Protocol buffer comparison.
-// TODO: MessageSet.
 
 package proto
 
@@ -154,6 +153,17 @@ func equalAny(v1, v2 reflect.Value) bool {
 		return v1.Float() == v2.Float()
 	case reflect.Int32, reflect.Int64:
 		return v1.Int() == v2.Int()
+	case reflect.Interface:
+		// Probably a oneof field; compare the inner values.
+		n1, n2 := v1.IsNil(), v2.IsNil()
+		if n1 || n2 {
+			return n1 == n2
+		}
+		e1, e2 := v1.Elem(), v2.Elem()
+		if e1.Type() != e2.Type() {
+			return false
+		}
+		return equalAny(e1, e2)
 	case reflect.Map:
 		if v1.Len() != v2.Len() {
 			return false

+ 18 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal_test.go

@@ -180,6 +180,24 @@ var EqualTests = []struct {
 		&pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}},
 		false,
 	},
+	{
+		"oneof same",
+		&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
+		&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
+		true,
+	},
+	{
+		"oneof one nil",
+		&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
+		&pb.Communique{},
+		false,
+	},
+	{
+		"oneof different",
+		&pb.Communique{Union: &pb.Communique_Number{Number: 41}},
+		&pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}},
+		false,
+	},
 }
 
 func TestEqual(t *testing.T) {

+ 39 - 1
Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions.go

@@ -311,7 +311,9 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
 		emap := epb.ExtensionMap()
 		e, ok := emap[extension.Field]
 		if !ok {
-			return nil, ErrMissingExtension
+			// defaultExtensionValue returns the default value or
+			// ErrMissingExtension if there is no default.
+			return defaultExtensionValue(extension)
 		}
 		if e.value != nil {
 			// Already decoded. Check the descriptor, though.
@@ -356,10 +358,46 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
 			}
 			o += n + l
 		}
+		return defaultExtensionValue(extension)
 	}
 	panic("unreachable")
 }
 
+// defaultExtensionValue returns the default value for extension.
+// If no default for an extension is defined ErrMissingExtension is returned.
+func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+	t := reflect.TypeOf(extension.ExtensionType)
+	props := extensionProperties(extension)
+
+	sf, _, err := fieldDefault(t, props)
+	if err != nil {
+		return nil, err
+	}
+
+	if sf == nil || sf.value == nil {
+		// There is no default value.
+		return nil, ErrMissingExtension
+	}
+
+	if t.Kind() != reflect.Ptr {
+		// We do not need to return a Ptr, we can directly return sf.value.
+		return sf.value, nil
+	}
+
+	// We need to return an interface{} that is a pointer to sf.value.
+	value := reflect.New(t).Elem()
+	value.Set(reflect.New(value.Type().Elem()))
+	if sf.kind == reflect.Int32 {
+		// We may have an int32 or an enum, but the underlying data is int32.
+		// Since we can't set an int32 into a non int32 reflect.value directly
+		// set it as a int32.
+		value.Elem().SetInt(int64(sf.value.(int32)))
+	} else {
+		value.Elem().Set(reflect.ValueOf(sf.value))
+	}
+	return value.Interface(), nil
+}
+
 // decodeExtension decodes an extension encoded in b.
 func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 	o := NewBuffer(b)

+ 139 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions_test.go

@@ -32,6 +32,8 @@
 package proto_test
 
 import (
+	"fmt"
+	"reflect"
 	"testing"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
@@ -93,6 +95,143 @@ func TestGetExtensionStability(t *testing.T) {
 	}
 }
 
+func TestGetExtensionDefaults(t *testing.T) {
+	var setFloat64 float64 = 1
+	var setFloat32 float32 = 2
+	var setInt32 int32 = 3
+	var setInt64 int64 = 4
+	var setUint32 uint32 = 5
+	var setUint64 uint64 = 6
+	var setBool = true
+	var setBool2 = false
+	var setString = "Goodnight string"
+	var setBytes = []byte("Goodnight bytes")
+	var setEnum = pb.DefaultsMessage_TWO
+
+	type testcase struct {
+		ext  *proto.ExtensionDesc // Extension we are testing.
+		want interface{}          // Expected value of extension, or nil (meaning that GetExtension will fail).
+		def  interface{}          // Expected value of extension after ClearExtension().
+	}
+	tests := []testcase{
+		{pb.E_NoDefaultDouble, setFloat64, nil},
+		{pb.E_NoDefaultFloat, setFloat32, nil},
+		{pb.E_NoDefaultInt32, setInt32, nil},
+		{pb.E_NoDefaultInt64, setInt64, nil},
+		{pb.E_NoDefaultUint32, setUint32, nil},
+		{pb.E_NoDefaultUint64, setUint64, nil},
+		{pb.E_NoDefaultSint32, setInt32, nil},
+		{pb.E_NoDefaultSint64, setInt64, nil},
+		{pb.E_NoDefaultFixed32, setUint32, nil},
+		{pb.E_NoDefaultFixed64, setUint64, nil},
+		{pb.E_NoDefaultSfixed32, setInt32, nil},
+		{pb.E_NoDefaultSfixed64, setInt64, nil},
+		{pb.E_NoDefaultBool, setBool, nil},
+		{pb.E_NoDefaultBool, setBool2, nil},
+		{pb.E_NoDefaultString, setString, nil},
+		{pb.E_NoDefaultBytes, setBytes, nil},
+		{pb.E_NoDefaultEnum, setEnum, nil},
+		{pb.E_DefaultDouble, setFloat64, float64(3.1415)},
+		{pb.E_DefaultFloat, setFloat32, float32(3.14)},
+		{pb.E_DefaultInt32, setInt32, int32(42)},
+		{pb.E_DefaultInt64, setInt64, int64(43)},
+		{pb.E_DefaultUint32, setUint32, uint32(44)},
+		{pb.E_DefaultUint64, setUint64, uint64(45)},
+		{pb.E_DefaultSint32, setInt32, int32(46)},
+		{pb.E_DefaultSint64, setInt64, int64(47)},
+		{pb.E_DefaultFixed32, setUint32, uint32(48)},
+		{pb.E_DefaultFixed64, setUint64, uint64(49)},
+		{pb.E_DefaultSfixed32, setInt32, int32(50)},
+		{pb.E_DefaultSfixed64, setInt64, int64(51)},
+		{pb.E_DefaultBool, setBool, true},
+		{pb.E_DefaultBool, setBool2, true},
+		{pb.E_DefaultString, setString, "Hello, string"},
+		{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
+		{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
+	}
+
+	checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error {
+		val, err := proto.GetExtension(msg, test.ext)
+		if err != nil {
+			if valWant != nil {
+				return fmt.Errorf("GetExtension(): %s", err)
+			}
+			if want := proto.ErrMissingExtension; err != want {
+				return fmt.Errorf("Unexpected error: got %v, want %v", err, want)
+			}
+			return nil
+		}
+
+		// All proto2 extension values are either a pointer to a value or a slice of values.
+		ty := reflect.TypeOf(val)
+		tyWant := reflect.TypeOf(test.ext.ExtensionType)
+		if got, want := ty, tyWant; got != want {
+			return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want)
+		}
+		tye := ty.Elem()
+		tyeWant := tyWant.Elem()
+		if got, want := tye, tyeWant; got != want {
+			return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want)
+		}
+
+		// Check the name of the type of the value.
+		// If it is an enum it will be type int32 with the name of the enum.
+		if got, want := tye.Name(), tye.Name(); got != want {
+			return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want)
+		}
+
+		// Check that value is what we expect.
+		// If we have a pointer in val, get the value it points to.
+		valExp := val
+		if ty.Kind() == reflect.Ptr {
+			valExp = reflect.ValueOf(val).Elem().Interface()
+		}
+		if got, want := valExp, valWant; !reflect.DeepEqual(got, want) {
+			return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want)
+		}
+
+		return nil
+	}
+
+	setTo := func(test testcase) interface{} {
+		setTo := reflect.ValueOf(test.want)
+		if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr {
+			setTo = reflect.New(typ).Elem()
+			setTo.Set(reflect.New(setTo.Type().Elem()))
+			setTo.Elem().Set(reflect.ValueOf(test.want))
+		}
+		return setTo.Interface()
+	}
+
+	for _, test := range tests {
+		msg := &pb.DefaultsMessage{}
+		name := test.ext.Name
+
+		// Check the initial value.
+		if err := checkVal(test, msg, test.def); err != nil {
+			t.Errorf("%s: %v", name, err)
+		}
+
+		// Set the per-type value and check value.
+		name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want)
+		if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil {
+			t.Errorf("%s: SetExtension(): %v", name, err)
+			continue
+		}
+		if err := checkVal(test, msg, test.want); err != nil {
+			t.Errorf("%s: %v", name, err)
+			continue
+		}
+
+		// Set and check the value.
+		name += " (cleared)"
+		proto.ClearExtension(msg, test.ext)
+		if err := checkVal(test, msg, test.def); err != nil {
+			t.Errorf("%s: %v", name, err)
+		}
+	}
+}
+
 func TestExtensionsRoundTrip(t *testing.T) {
 	msg := &pb.MyMessage{}
 	ext1 := &pb.Ext{

+ 367 - 274
Godeps/_workspace/src/github.com/gogo/protobuf/proto/lib.go

@@ -30,179 +30,230 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /*
-	Package proto converts data structures to and from the wire format of
-	protocol buffers.  It works in concert with the Go source code generated
-	for .proto files by the protocol compiler.
-
-	A summary of the properties of the protocol buffer interface
-	for a protocol buffer variable v:
-
-	  - Names are turned from camel_case to CamelCase for export.
-	  - There are no methods on v to set fields; just treat
-		them as structure fields.
-	  - There are getters that return a field's value if set,
-		and return the field's default value if unset.
-		The getters work even if the receiver is a nil message.
-	  - The zero value for a struct is its correct initialization state.
-		All desired fields must be set before marshaling.
-	  - A Reset() method will restore a protobuf struct to its zero state.
-	  - Non-repeated fields are pointers to the values; nil means unset.
-		That is, optional or required field int32 f becomes F *int32.
-	  - Repeated fields are slices.
-	  - Helper functions are available to aid the setting of fields.
-		msg.Foo = proto.String("hello") // set field
-	  - Constants are defined to hold the default values of all fields that
-		have them.  They have the form Default_StructName_FieldName.
-		Because the getter methods handle defaulted values,
-		direct use of these constants should be rare.
-	  - Enums are given type names and maps from names to values.
-		Enum values are prefixed by the enclosing message's name, or by the
-		enum's type name if it is a top-level enum. Enum types have a String
-		method, and a Enum method to assist in message construction.
-	  - Nested messages, groups and enums have type names prefixed with the name of
-	  	the surrounding message type.
-	  - Extensions are given descriptor names that start with E_,
-		followed by an underscore-delimited list of the nested messages
-		that contain it (if any) followed by the CamelCased name of the
-		extension field itself.  HasExtension, ClearExtension, GetExtension
-		and SetExtension are functions for manipulating extensions.
-	  - Marshal and Unmarshal are functions to encode and decode the wire format.
-
-	The simplest way to describe this is to see an example.
-	Given file test.proto, containing
-
-		package example;
-
-		enum FOO { X = 17; }
-
-		message Test {
-		  required string label = 1;
-		  optional int32 type = 2 [default=77];
-		  repeated int64 reps = 3;
-		  optional group OptionalGroup = 4 {
-		    required string RequiredField = 5;
-		  }
-		}
-
-	The resulting file, test.pb.go, is:
-
-		package example
-
-		import proto "github.com/gogo/protobuf/proto"
-		import math "math"
-
-		type FOO int32
-		const (
-			FOO_X FOO = 17
-		)
-		var FOO_name = map[int32]string{
-			17: "X",
-		}
-		var FOO_value = map[string]int32{
-			"X": 17,
-		}
-
-		func (x FOO) Enum() *FOO {
-			p := new(FOO)
-			*p = x
-			return p
-		}
-		func (x FOO) String() string {
-			return proto.EnumName(FOO_name, int32(x))
-		}
-		func (x *FOO) UnmarshalJSON(data []byte) error {
-			value, err := proto.UnmarshalJSONEnum(FOO_value, data)
-			if err != nil {
-				return err
-			}
-			*x = FOO(value)
-			return nil
+Package proto converts data structures to and from the wire format of
+protocol buffers.  It works in concert with the Go source code generated
+for .proto files by the protocol compiler.
+
+A summary of the properties of the protocol buffer interface
+for a protocol buffer variable v:
+
+  - Names are turned from camel_case to CamelCase for export.
+  - There are no methods on v to set fields; just treat
+	them as structure fields.
+  - There are getters that return a field's value if set,
+	and return the field's default value if unset.
+	The getters work even if the receiver is a nil message.
+  - The zero value for a struct is its correct initialization state.
+	All desired fields must be set before marshaling.
+  - A Reset() method will restore a protobuf struct to its zero state.
+  - Non-repeated fields are pointers to the values; nil means unset.
+	That is, optional or required field int32 f becomes F *int32.
+  - Repeated fields are slices.
+  - Helper functions are available to aid the setting of fields.
+	msg.Foo = proto.String("hello") // set field
+  - Constants are defined to hold the default values of all fields that
+	have them.  They have the form Default_StructName_FieldName.
+	Because the getter methods handle defaulted values,
+	direct use of these constants should be rare.
+  - Enums are given type names and maps from names to values.
+	Enum values are prefixed by the enclosing message's name, or by the
+	enum's type name if it is a top-level enum. Enum types have a String
+	method, and a Enum method to assist in message construction.
+  - Nested messages, groups and enums have type names prefixed with the name of
+	the surrounding message type.
+  - Extensions are given descriptor names that start with E_,
+	followed by an underscore-delimited list of the nested messages
+	that contain it (if any) followed by the CamelCased name of the
+	extension field itself.  HasExtension, ClearExtension, GetExtension
+	and SetExtension are functions for manipulating extensions.
+  - Oneof field sets are given a single field in their message,
+	with distinguished wrapper types for each possible field value.
+  - Marshal and Unmarshal are functions to encode and decode the wire format.
+
+The simplest way to describe this is to see an example.
+Given file test.proto, containing
+
+	package example;
+
+	enum FOO { X = 17; }
+
+	message Test {
+	  required string label = 1;
+	  optional int32 type = 2 [default=77];
+	  repeated int64 reps = 3;
+	  optional group OptionalGroup = 4 {
+	    required string RequiredField = 5;
+	  }
+	  oneof union {
+	    int32 number = 6;
+	    string name = 7;
+	  }
+	}
+
+The resulting file, test.pb.go, is:
+
+	package example
+
+	import proto "github.com/gogo/protobuf/proto"
+	import math "math"
+
+	type FOO int32
+	const (
+		FOO_X FOO = 17
+	)
+	var FOO_name = map[int32]string{
+		17: "X",
+	}
+	var FOO_value = map[string]int32{
+		"X": 17,
+	}
+
+	func (x FOO) Enum() *FOO {
+		p := new(FOO)
+		*p = x
+		return p
+	}
+	func (x FOO) String() string {
+		return proto.EnumName(FOO_name, int32(x))
+	}
+	func (x *FOO) UnmarshalJSON(data []byte) error {
+		value, err := proto.UnmarshalJSONEnum(FOO_value, data)
+		if err != nil {
+			return err
 		}
+		*x = FOO(value)
+		return nil
+	}
+
+	type Test struct {
+		Label         *string             `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
+		Type          *int32              `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
+		Reps          []int64             `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
+		Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
+		// Types that are valid to be assigned to Union:
+		//	*Test_Number
+		//	*Test_Name
+		Union            isTest_Union `protobuf_oneof:"union"`
+		XXX_unrecognized []byte       `json:"-"`
+	}
+	func (m *Test) Reset()         { *m = Test{} }
+	func (m *Test) String() string { return proto.CompactTextString(m) }
+	func (*Test) ProtoMessage() {}
+
+	type isTest_Union interface {
+		isTest_Union()
+	}
 
-		type Test struct {
-			Label            *string             `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
-			Type             *int32              `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
-			Reps             []int64             `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
-			Optionalgroup    *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
-			XXX_unrecognized []byte              `json:"-"`
+	type Test_Number struct {
+		Number int32 `protobuf:"varint,6,opt,name=number"`
+	}
+	type Test_Name struct {
+		Name string `protobuf:"bytes,7,opt,name=name"`
+	}
+
+	func (*Test_Number) isTest_Union() {}
+	func (*Test_Name) isTest_Union()   {}
+
+	func (m *Test) GetUnion() isTest_Union {
+		if m != nil {
+			return m.Union
 		}
-		func (m *Test) Reset()         { *m = Test{} }
-		func (m *Test) String() string { return proto.CompactTextString(m) }
-		func (*Test) ProtoMessage()    {}
-		const Default_Test_Type int32 = 77
+		return nil
+	}
+	const Default_Test_Type int32 = 77
 
-		func (m *Test) GetLabel() string {
-			if m != nil && m.Label != nil {
-				return *m.Label
-			}
-			return ""
+	func (m *Test) GetLabel() string {
+		if m != nil && m.Label != nil {
+			return *m.Label
 		}
+		return ""
+	}
 
-		func (m *Test) GetType() int32 {
-			if m != nil && m.Type != nil {
-				return *m.Type
-			}
-			return Default_Test_Type
+	func (m *Test) GetType() int32 {
+		if m != nil && m.Type != nil {
+			return *m.Type
 		}
+		return Default_Test_Type
+	}
 
-		func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
-			if m != nil {
-				return m.Optionalgroup
-			}
-			return nil
+	func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
+		if m != nil {
+			return m.Optionalgroup
 		}
+		return nil
+	}
+
+	type Test_OptionalGroup struct {
+		RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+	}
+	func (m *Test_OptionalGroup) Reset()         { *m = Test_OptionalGroup{} }
+	func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
 
-		type Test_OptionalGroup struct {
-			RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+	func (m *Test_OptionalGroup) GetRequiredField() string {
+		if m != nil && m.RequiredField != nil {
+			return *m.RequiredField
 		}
-		func (m *Test_OptionalGroup) Reset()         { *m = Test_OptionalGroup{} }
-		func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
+		return ""
+	}
 
-		func (m *Test_OptionalGroup) GetRequiredField() string {
-			if m != nil && m.RequiredField != nil {
-				return *m.RequiredField
-			}
-			return ""
+	func (m *Test) GetNumber() int32 {
+		if x, ok := m.GetUnion().(*Test_Number); ok {
+			return x.Number
 		}
+		return 0
+	}
 
-		func init() {
-			proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+	func (m *Test) GetName() string {
+		if x, ok := m.GetUnion().(*Test_Name); ok {
+			return x.Name
 		}
+		return ""
+	}
 
-	To create and play with a Test object:
+	func init() {
+		proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+	}
 
-		package main
+To create and play with a Test object:
 
-		import (
-			"log"
+	package main
 
-			"github.com/gogo/protobuf/proto"
-			pb "./example.pb"
-		)
+	import (
+		"log"
 
-		func main() {
-			test := &pb.Test{
-				Label: proto.String("hello"),
-				Type:  proto.Int32(17),
-				Optionalgroup: &pb.Test_OptionalGroup{
-					RequiredField: proto.String("good bye"),
-				},
-			}
-			data, err := proto.Marshal(test)
-			if err != nil {
-				log.Fatal("marshaling error: ", err)
-			}
-			newTest := &pb.Test{}
-			err = proto.Unmarshal(data, newTest)
-			if err != nil {
-				log.Fatal("unmarshaling error: ", err)
-			}
-			// Now test and newTest contain the same data.
-			if test.GetLabel() != newTest.GetLabel() {
-				log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
-			}
-			// etc.
+		"github.com/gogo/protobuf/proto"
+		pb "./example.pb"
+	)
+
+	func main() {
+		test := &pb.Test{
+			Label: proto.String("hello"),
+			Type:  proto.Int32(17),
+			Optionalgroup: &pb.Test_OptionalGroup{
+				RequiredField: proto.String("good bye"),
+			},
+			Union: &pb.Test_Name{"fred"},
+		}
+		data, err := proto.Marshal(test)
+		if err != nil {
+			log.Fatal("marshaling error: ", err)
+		}
+		newTest := &pb.Test{}
+		err = proto.Unmarshal(data, newTest)
+		if err != nil {
+			log.Fatal("unmarshaling error: ", err)
+		}
+		// Now test and newTest contain the same data.
+		if test.GetLabel() != newTest.GetLabel() {
+			log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
+		}
+		// Use a type switch to determine which oneof was set.
+		switch u := test.Union.(type) {
+		case *pb.Test_Number: // u.Number contains the number.
+		case *pb.Test_Name: // u.Name contains the string.
 		}
+		// etc.
+	}
 */
 package proto
 
@@ -211,6 +262,7 @@ import (
 	"fmt"
 	"log"
 	"reflect"
+	"sort"
 	"strconv"
 	"sync"
 )
@@ -385,13 +437,13 @@ func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32,
 
 // DebugPrint dumps the encoded data in b in a debugging format with a header
 // including the string s. Used in testing but made available for general debugging.
-func (o *Buffer) DebugPrint(s string, b []byte) {
+func (p *Buffer) DebugPrint(s string, b []byte) {
 	var u uint64
 
-	obuf := o.buf
-	index := o.index
-	o.buf = b
-	o.index = 0
+	obuf := p.buf
+	index := p.index
+	p.buf = b
+	p.index = 0
 	depth := 0
 
 	fmt.Printf("\n--- %s ---\n", s)
@@ -402,12 +454,12 @@ out:
 			fmt.Print("  ")
 		}
 
-		index := o.index
-		if index == len(o.buf) {
+		index := p.index
+		if index == len(p.buf) {
 			break
 		}
 
-		op, err := o.DecodeVarint()
+		op, err := p.DecodeVarint()
 		if err != nil {
 			fmt.Printf("%3d: fetching op err %v\n", index, err)
 			break out
@@ -424,7 +476,7 @@ out:
 		case WireBytes:
 			var r []byte
 
-			r, err = o.DecodeRawBytes(false)
+			r, err = p.DecodeRawBytes(false)
 			if err != nil {
 				break out
 			}
@@ -445,7 +497,7 @@ out:
 			fmt.Printf("\n")
 
 		case WireFixed32:
-			u, err = o.DecodeFixed32()
+			u, err = p.DecodeFixed32()
 			if err != nil {
 				fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
 				break out
@@ -453,16 +505,15 @@ out:
 			fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
 
 		case WireFixed64:
-			u, err = o.DecodeFixed64()
+			u, err = p.DecodeFixed64()
 			if err != nil {
 				fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
 				break out
 			}
 			fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
-			break
 
 		case WireVarint:
-			u, err = o.DecodeVarint()
+			u, err = p.DecodeVarint()
 			if err != nil {
 				fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
 				break out
@@ -470,30 +521,22 @@ out:
 			fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
 
 		case WireStartGroup:
-			if err != nil {
-				fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
-				break out
-			}
 			fmt.Printf("%3d: t=%3d start\n", index, tag)
 			depth++
 
 		case WireEndGroup:
 			depth--
-			if err != nil {
-				fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
-				break out
-			}
 			fmt.Printf("%3d: t=%3d end\n", index, tag)
 		}
 	}
 
 	if depth != 0 {
-		fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
+		fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
 	}
 	fmt.Printf("\n")
 
-	o.buf = obuf
-	o.index = index
+	p.buf = obuf
+	p.index = index
 }
 
 // SetDefaults sets unset protocol buffer fields to their default values.
@@ -668,112 +711,118 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 		}
 		ft := t.Field(fi).Type
 
-		var canHaveDefault, nestedMessage bool
-		switch ft.Kind() {
-		case reflect.Ptr:
-			if ft.Elem().Kind() == reflect.Struct {
-				nestedMessage = true
-			} else {
-				canHaveDefault = true // proto2 scalar field
-			}
+		sf, nested, err := fieldDefault(ft, prop)
+		switch {
+		case err != nil:
+			log.Print(err)
+		case nested:
+			dm.nested = append(dm.nested, fi)
+		case sf != nil:
+			sf.index = fi
+			dm.scalars = append(dm.scalars, *sf)
+		}
+	}
 
-		case reflect.Slice:
-			switch ft.Elem().Kind() {
-			case reflect.Ptr:
-				nestedMessage = true // repeated message
-			case reflect.Uint8:
-				canHaveDefault = true // bytes field
-			}
+	return dm
+}
 
-		case reflect.Map:
-			if ft.Elem().Kind() == reflect.Ptr {
-				nestedMessage = true // map with message values
-			}
+// fieldDefault returns the scalarField for field type ft.
+// sf will be nil if the field can not have a default.
+// nestedMessage will be true if this is a nested message.
+// Note that sf.index is not set on return.
+func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
+	var canHaveDefault bool
+	switch ft.Kind() {
+	case reflect.Ptr:
+		if ft.Elem().Kind() == reflect.Struct {
+			nestedMessage = true
+		} else {
+			canHaveDefault = true // proto2 scalar field
 		}
 
-		if !canHaveDefault {
-			if nestedMessage {
-				dm.nested = append(dm.nested, fi)
-			}
-			continue
+	case reflect.Slice:
+		switch ft.Elem().Kind() {
+		case reflect.Ptr:
+			nestedMessage = true // repeated message
+		case reflect.Uint8:
+			canHaveDefault = true // bytes field
 		}
 
-		sf := scalarField{
-			index: fi,
-			kind:  ft.Elem().Kind(),
+	case reflect.Map:
+		if ft.Elem().Kind() == reflect.Ptr {
+			nestedMessage = true // map with message values
 		}
+	}
 
-		// scalar fields without defaults
-		if !prop.HasDefault {
-			dm.scalars = append(dm.scalars, sf)
-			continue
+	if !canHaveDefault {
+		if nestedMessage {
+			return nil, true, nil
 		}
+		return nil, false, nil
+	}
 
-		// a scalar field: either *T or []byte
-		switch ft.Elem().Kind() {
-		case reflect.Bool:
-			x, err := strconv.ParseBool(prop.Default)
-			if err != nil {
-				log.Printf("proto: bad default bool %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		case reflect.Float32:
-			x, err := strconv.ParseFloat(prop.Default, 32)
-			if err != nil {
-				log.Printf("proto: bad default float32 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = float32(x)
-		case reflect.Float64:
-			x, err := strconv.ParseFloat(prop.Default, 64)
-			if err != nil {
-				log.Printf("proto: bad default float64 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		case reflect.Int32:
-			x, err := strconv.ParseInt(prop.Default, 10, 32)
-			if err != nil {
-				log.Printf("proto: bad default int32 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = int32(x)
-		case reflect.Int64:
-			x, err := strconv.ParseInt(prop.Default, 10, 64)
-			if err != nil {
-				log.Printf("proto: bad default int64 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		case reflect.String:
-			sf.value = prop.Default
-		case reflect.Uint8:
-			// []byte (not *uint8)
-			sf.value = []byte(prop.Default)
-		case reflect.Uint32:
-			x, err := strconv.ParseUint(prop.Default, 10, 32)
-			if err != nil {
-				log.Printf("proto: bad default uint32 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = uint32(x)
-		case reflect.Uint64:
-			x, err := strconv.ParseUint(prop.Default, 10, 64)
-			if err != nil {
-				log.Printf("proto: bad default uint64 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		default:
-			log.Printf("proto: unhandled def kind %v", ft.Elem().Kind())
-			continue
-		}
+	// We now know that ft is a pointer or slice.
+	sf = &scalarField{kind: ft.Elem().Kind()}
 
-		dm.scalars = append(dm.scalars, sf)
+	// scalar fields without defaults
+	if !prop.HasDefault {
+		return sf, false, nil
 	}
 
-	return dm
+	// a scalar field: either *T or []byte
+	switch ft.Elem().Kind() {
+	case reflect.Bool:
+		x, err := strconv.ParseBool(prop.Default)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	case reflect.Float32:
+		x, err := strconv.ParseFloat(prop.Default, 32)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
+		}
+		sf.value = float32(x)
+	case reflect.Float64:
+		x, err := strconv.ParseFloat(prop.Default, 64)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	case reflect.Int32:
+		x, err := strconv.ParseInt(prop.Default, 10, 32)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
+		}
+		sf.value = int32(x)
+	case reflect.Int64:
+		x, err := strconv.ParseInt(prop.Default, 10, 64)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	case reflect.String:
+		sf.value = prop.Default
+	case reflect.Uint8:
+		// []byte (not *uint8)
+		sf.value = []byte(prop.Default)
+	case reflect.Uint32:
+		x, err := strconv.ParseUint(prop.Default, 10, 32)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
+		}
+		sf.value = uint32(x)
+	case reflect.Uint64:
+		x, err := strconv.ParseUint(prop.Default, 10, 64)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	default:
+		return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
+	}
+
+	return sf, false, nil
 }
 
 // Map fields may have key types of non-float scalars, strings and enums.
@@ -781,10 +830,54 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 // If this turns out to be inefficient we can always consider other options,
 // such as doing a Schwartzian transform.
 
-type mapKeys []reflect.Value
+func mapKeys(vs []reflect.Value) sort.Interface {
+	s := mapKeySorter{
+		vs: vs,
+		// default Less function: textual comparison
+		less: func(a, b reflect.Value) bool {
+			return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
+		},
+	}
 
-func (s mapKeys) Len() int      { return len(s) }
-func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s mapKeys) Less(i, j int) bool {
-	return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
+	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
+	// numeric keys are sorted numerically.
+	if len(vs) == 0 {
+		return s
+	}
+	switch vs[0].Kind() {
+	case reflect.Int32, reflect.Int64:
+		s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
+	case reflect.Uint32, reflect.Uint64:
+		s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+	}
+
+	return s
+}
+
+type mapKeySorter struct {
+	vs   []reflect.Value
+	less func(a, b reflect.Value) bool
+}
+
+func (s mapKeySorter) Len() int      { return len(s.vs) }
+func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
+func (s mapKeySorter) Less(i, j int) bool {
+	return s.less(s.vs[i], s.vs[j])
+}
+
+// isProto3Zero reports whether v is a zero proto3 value.
+func isProto3Zero(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint32, reflect.Uint64:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.String:
+		return v.String() == ""
+	}
+	return false
 }

+ 17 - 24
Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set.go

@@ -44,11 +44,11 @@ import (
 	"sort"
 )
 
-// ErrNoMessageTypeId occurs when a protocol buffer does not have a message type ID.
+// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
 // A message type ID is required for storing a protocol buffer in a message set.
-var ErrNoMessageTypeId = errors.New("proto does not have a message type ID")
+var errNoMessageTypeID = errors.New("proto does not have a message type ID")
 
-// The first two types (_MessageSet_Item and MessageSet)
+// The first two types (_MessageSet_Item and messageSet)
 // model what the protocol compiler produces for the following protocol message:
 //   message MessageSet {
 //     repeated group Item = 1 {
@@ -58,27 +58,20 @@ var ErrNoMessageTypeId = errors.New("proto does not have a message type ID")
 //   }
 // That is the MessageSet wire format. We can't use a proto to generate these
 // because that would introduce a circular dependency between it and this package.
-//
-// When a proto1 proto has a field that looks like:
-//   optional message<MessageSet> info = 3;
-// the protocol compiler produces a field in the generated struct that looks like:
-//   Info *_proto_.MessageSet  `protobuf:"bytes,3,opt,name=info"`
-// The package is automatically inserted so there is no need for that proto file to
-// import this package.
 
 type _MessageSet_Item struct {
 	TypeId  *int32 `protobuf:"varint,2,req,name=type_id"`
 	Message []byte `protobuf:"bytes,3,req,name=message"`
 }
 
-type MessageSet struct {
+type messageSet struct {
 	Item             []*_MessageSet_Item `protobuf:"group,1,rep"`
 	XXX_unrecognized []byte
 	// TODO: caching?
 }
 
-// Make sure MessageSet is a Message.
-var _ Message = (*MessageSet)(nil)
+// Make sure messageSet is a Message.
+var _ Message = (*messageSet)(nil)
 
 // messageTypeIder is an interface satisfied by a protocol buffer type
 // that may be stored in a MessageSet.
@@ -86,7 +79,7 @@ type messageTypeIder interface {
 	MessageTypeId() int32
 }
 
-func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
+func (ms *messageSet) find(pb Message) *_MessageSet_Item {
 	mti, ok := pb.(messageTypeIder)
 	if !ok {
 		return nil
@@ -100,24 +93,24 @@ func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
 	return nil
 }
 
-func (ms *MessageSet) Has(pb Message) bool {
+func (ms *messageSet) Has(pb Message) bool {
 	if ms.find(pb) != nil {
 		return true
 	}
 	return false
 }
 
-func (ms *MessageSet) Unmarshal(pb Message) error {
+func (ms *messageSet) Unmarshal(pb Message) error {
 	if item := ms.find(pb); item != nil {
 		return Unmarshal(item.Message, pb)
 	}
 	if _, ok := pb.(messageTypeIder); !ok {
-		return ErrNoMessageTypeId
+		return errNoMessageTypeID
 	}
 	return nil // TODO: return error instead?
 }
 
-func (ms *MessageSet) Marshal(pb Message) error {
+func (ms *messageSet) Marshal(pb Message) error {
 	msg, err := Marshal(pb)
 	if err != nil {
 		return err
@@ -130,7 +123,7 @@ func (ms *MessageSet) Marshal(pb Message) error {
 
 	mti, ok := pb.(messageTypeIder)
 	if !ok {
-		return ErrNoMessageTypeId
+		return errNoMessageTypeID
 	}
 
 	mtid := mti.MessageTypeId()
@@ -141,9 +134,9 @@ func (ms *MessageSet) Marshal(pb Message) error {
 	return nil
 }
 
-func (ms *MessageSet) Reset()         { *ms = MessageSet{} }
-func (ms *MessageSet) String() string { return CompactTextString(ms) }
-func (*MessageSet) ProtoMessage()     {}
+func (ms *messageSet) Reset()         { *ms = messageSet{} }
+func (ms *messageSet) String() string { return CompactTextString(ms) }
+func (*messageSet) ProtoMessage()     {}
 
 // Support for the message_set_wire_format message option.
 
@@ -169,7 +162,7 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
 	}
 	sort.Ints(ids)
 
-	ms := &MessageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
+	ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
 	for _, id := range ids {
 		e := m[int32(id)]
 		// Remove the wire type and field number varint, as well as the length varint.
@@ -186,7 +179,7 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
 // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
 func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
-	ms := new(MessageSet)
+	ms := new(messageSet)
 	if err := Unmarshal(buf, ms); err != nil {
 		return err
 	}

+ 1 - 1
Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set_test.go

@@ -38,7 +38,7 @@ import (
 
 func TestUnmarshalMessageSetWithDuplicate(t *testing.T) {
 	// Check that a repeated message set entry will be concatenated.
-	in := &MessageSet{
+	in := &messageSet{
 		Item: []*_MessageSet_Item{
 			{TypeId: Int32(12345), Message: []byte("hoo")},
 			{TypeId: Int32(12345), Message: []byte("hah")},

+ 2 - 2
Godeps/_workspace/src/github.com/gogo/protobuf/proto/pointer_reflect.go

@@ -144,8 +144,8 @@ func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
 	return structPointer_ifield(p, f).(*map[int32]Extension)
 }
 
-// Map returns the reflect.Value for the address of a map field in the struct.
-func structPointer_Map(p structPointer, f field, typ reflect.Type) reflect.Value {
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
 	return structPointer_field(p, f).Addr()
 }
 

+ 2 - 2
Godeps/_workspace/src/github.com/gogo/protobuf/proto/pointer_unsafe.go

@@ -130,8 +130,8 @@ func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
 	return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// Map returns the reflect.Value for the address of a map field in the struct.
-func structPointer_Map(p structPointer, f field, typ reflect.Type) reflect.Value {
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
 	return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
 }
 

+ 101 - 1
Godeps/_workspace/src/github.com/gogo/protobuf/proto/properties.go

@@ -42,6 +42,7 @@ package proto
 
 import (
 	"fmt"
+	"log"
 	"os"
 	"reflect"
 	"sort"
@@ -89,6 +90,12 @@ type decoder func(p *Buffer, prop *Properties, base structPointer) error
 // A valueDecoder decodes a single integer in a particular encoding.
 type valueDecoder func(o *Buffer) (x uint64, err error)
 
+// A oneofMarshaler does the marshaling for all oneof fields in a message.
+type oneofMarshaler func(Message, *Buffer) error
+
+// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
+type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
+
 // tagMap is an optimization over map[int]int for typical protocol buffer
 // use-cases. Encoded protocol buffers are often in tag order with small tag
 // numbers.
@@ -137,6 +144,21 @@ type StructProperties struct {
 	order            []int          // list of struct field numbers in tag order
 	unrecField       field          // field id of the XXX_unrecognized []byte field
 	extendable       bool           // is this an extendable proto
+
+	oneofMarshaler   oneofMarshaler
+	oneofUnmarshaler oneofUnmarshaler
+	stype            reflect.Type
+
+	// OneofTypes contains information about the oneof fields in this message.
+	// It is keyed by the original name of a field.
+	OneofTypes map[string]*OneofProperties
+}
+
+// OneofProperties represents information about a specific field in a oneof.
+type OneofProperties struct {
+	Type  reflect.Type // pointer to generated struct type for this oneof field
+	Field int          // struct field number of the containing oneof in the message
+	Prop  *Properties
 }
 
 // Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
@@ -161,6 +183,7 @@ type Properties struct {
 	Packed   bool   // relevant for repeated primitives only
 	Enum     string // set for enum types only
 	proto3   bool   // whether this is known to be a proto3 field; set for []byte only
+	oneof    bool   // whether this is a oneof field
 
 	Default    string // default value
 	HasDefault bool   // whether an explicit default was provided
@@ -216,6 +239,9 @@ func (p *Properties) String() string {
 	if p.proto3 {
 		s += ",proto3"
 	}
+	if p.oneof {
+		s += ",oneof"
+	}
 	if len(p.Enum) > 0 {
 		s += ",enum=" + p.Enum
 	}
@@ -292,6 +318,8 @@ func (p *Properties) Parse(s string) {
 			p.Enum = f[5:]
 		case f == "proto3":
 			p.proto3 = true
+		case f == "oneof":
+			p.oneof = true
 		case strings.HasPrefix(f, "def="):
 			p.HasDefault = true
 			p.Default = f[4:] // rest of string
@@ -713,6 +741,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	prop.Prop = make([]*Properties, t.NumField())
 	prop.order = make([]int, t.NumField())
 
+	isOneofMessage := false
 	for i := 0; i < t.NumField(); i++ {
 		f := t.Field(i)
 		p := new(Properties)
@@ -733,6 +762,10 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 		if f.Name == "XXX_unrecognized" { // special case
 			prop.unrecField = toField(&f)
 		}
+		oneof := f.Tag.Get("protobuf_oneof") != "" // special case
+		if oneof {
+			isOneofMessage = true
+		}
 		prop.Prop[i] = p
 		prop.order[i] = i
 		if debug {
@@ -742,7 +775,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 			}
 			print("\n")
 		}
-		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
+		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof {
 			fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
 		}
 	}
@@ -750,6 +783,41 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	// Re-order prop.order.
 	sort.Sort(prop)
 
+	type oneofMessage interface {
+		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), []interface{})
+	}
+	if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); isOneofMessage && ok {
+		var oots []interface{}
+		prop.oneofMarshaler, prop.oneofUnmarshaler, oots = om.XXX_OneofFuncs()
+		prop.stype = t
+
+		// Interpret oneof metadata.
+		prop.OneofTypes = make(map[string]*OneofProperties)
+		for _, oot := range oots {
+			oop := &OneofProperties{
+				Type: reflect.ValueOf(oot).Type(), // *T
+				Prop: new(Properties),
+			}
+			sft := oop.Type.Elem().Field(0)
+			oop.Prop.Name = sft.Name
+			oop.Prop.Parse(sft.Tag.Get("protobuf"))
+			// There will be exactly one interface field that
+			// this new value is assignable to.
+			for i := 0; i < t.NumField(); i++ {
+				f := t.Field(i)
+				if f.Type.Kind() != reflect.Interface {
+					continue
+				}
+				if !oop.Type.AssignableTo(f.Type) {
+					continue
+				}
+				oop.Field = i
+				break
+			}
+			prop.OneofTypes[oop.Prop.OrigName] = oop
+		}
+	}
+
 	// build required counts
 	// build tags
 	reqCount := 0
@@ -813,3 +881,35 @@ func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[
 	}
 	enumStringMaps[typeName] = unusedNameMap
 }
+
+// EnumValueMap returns the mapping from names to integers of the
+// enum type enumType, or a nil if not found.
+func EnumValueMap(enumType string) map[string]int32 {
+	return enumValueMaps[enumType]
+}
+
+// A registry of all linked message types.
+// The string is a fully-qualified proto name ("pkg.Message").
+var (
+	protoTypes    = make(map[string]reflect.Type)
+	revProtoTypes = make(map[reflect.Type]string)
+)
+
+// RegisterType is called from generated code and maps from the fully qualified
+// proto name to the type (pointer to struct) of the protocol buffer.
+func RegisterType(x Message, name string) {
+	if _, ok := protoTypes[name]; ok {
+		// TODO: Some day, make this a panic.
+		log.Printf("proto: duplicate proto type registered: %s", name)
+		return
+	}
+	t := reflect.TypeOf(x)
+	protoTypes[name] = t
+	revProtoTypes[t] = name
+}
+
+// MessageName returns the fully-qualified proto name for the given message type.
+func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
+
+// MessageType returns the message type (pointer to struct) for a named message.
+func MessageType(name string) reflect.Type { return protoTypes[name] }

+ 7 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go

@@ -16,10 +16,14 @@ It has these top-level messages:
 package proto3_proto
 
 import proto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
 import testdata "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
 
 type Message_Humour int32
 
@@ -118,5 +122,8 @@ func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
 }
 
 func init() {
+	proto.RegisterType((*Message)(nil), "proto3_proto.Message")
+	proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
+	proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
 	proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
 }

+ 5 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/proto/size_test.go

@@ -124,6 +124,11 @@ var SizeTests = []struct {
 	{"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}},
 	{"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}},
 	{"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}},
+
+	{"oneof not set", &pb.Communique{}},
+	{"oneof zero int32", &pb.Communique{Union: &pb.Communique_Number{Number: 0}}},
+	{"oneof int32", &pb.Communique{Union: &pb.Communique_Number{Number: 3}}},
+	{"oneof string", &pb.Communique{Union: &pb.Communique_Name{Name: "Rhythmic Fman"}}},
 }
 
 func TestSize(t *testing.T) {

+ 1 - 1
Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/Makefile

@@ -32,6 +32,6 @@
 all:	regenerate
 
 regenerate:
-	go install github.com/gogo/protobuf/protoc-gen-gogo/version/protoc-min-version
+	go install github.com/gogo/protobuf/protoc-min-version
 	protoc-min-version --version="3.0.0" --gogo_out=. test.proto
 	

+ 620 - 32
Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go

@@ -22,6 +22,7 @@ It has these top-level messages:
 	OtherMessage
 	MyMessage
 	Ext
+	DefaultsMessage
 	MyMessageSet
 	Empty
 	MessageList
@@ -34,14 +35,17 @@ It has these top-level messages:
 	GroupNew
 	FloatingPoint
 	MessageWithMap
+	Communique
 */
 package testdata
 
-import proto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
 import math "math"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
+var _ = fmt.Errorf
 var _ = math.Inf
 
 type FOO int32
@@ -181,6 +185,42 @@ func (x *MyMessage_Color) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
+type DefaultsMessage_DefaultsEnum int32
+
+const (
+	DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0
+	DefaultsMessage_ONE  DefaultsMessage_DefaultsEnum = 1
+	DefaultsMessage_TWO  DefaultsMessage_DefaultsEnum = 2
+)
+
+var DefaultsMessage_DefaultsEnum_name = map[int32]string{
+	0: "ZERO",
+	1: "ONE",
+	2: "TWO",
+}
+var DefaultsMessage_DefaultsEnum_value = map[string]int32{
+	"ZERO": 0,
+	"ONE":  1,
+	"TWO":  2,
+}
+
+func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum {
+	p := new(DefaultsMessage_DefaultsEnum)
+	*p = x
+	return p
+}
+func (x DefaultsMessage_DefaultsEnum) String() string {
+	return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x))
+}
+func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum")
+	if err != nil {
+		return err
+	}
+	*x = DefaultsMessage_DefaultsEnum(value)
+	return nil
+}
+
 type Defaults_Color int32
 
 const (
@@ -264,8 +304,8 @@ func (m *GoEnum) GetFoo() FOO {
 }
 
 type GoTestField struct {
-	Label            *string `protobuf:"bytes,1,req" json:"Label,omitempty"`
-	Type             *string `protobuf:"bytes,2,req" json:"Type,omitempty"`
+	Label            *string `protobuf:"bytes,1,req,name=Label" json:"Label,omitempty"`
+	Type             *string `protobuf:"bytes,2,req,name=Type" json:"Type,omitempty"`
 	XXX_unrecognized []byte  `json:"-"`
 }
 
@@ -289,13 +329,13 @@ func (m *GoTestField) GetType() string {
 
 type GoTest struct {
 	// Some typical parameters
-	Kind  *GoTest_KIND `protobuf:"varint,1,req,enum=testdata.GoTest_KIND" json:"Kind,omitempty"`
-	Table *string      `protobuf:"bytes,2,opt" json:"Table,omitempty"`
-	Param *int32       `protobuf:"varint,3,opt" json:"Param,omitempty"`
+	Kind  *GoTest_KIND `protobuf:"varint,1,req,name=Kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"`
+	Table *string      `protobuf:"bytes,2,opt,name=Table" json:"Table,omitempty"`
+	Param *int32       `protobuf:"varint,3,opt,name=Param" json:"Param,omitempty"`
 	// Required, repeated and optional foreign fields.
-	RequiredField *GoTestField   `protobuf:"bytes,4,req" json:"RequiredField,omitempty"`
-	RepeatedField []*GoTestField `protobuf:"bytes,5,rep" json:"RepeatedField,omitempty"`
-	OptionalField *GoTestField   `protobuf:"bytes,6,opt" json:"OptionalField,omitempty"`
+	RequiredField *GoTestField   `protobuf:"bytes,4,req,name=RequiredField" json:"RequiredField,omitempty"`
+	RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField" json:"RepeatedField,omitempty"`
+	OptionalField *GoTestField   `protobuf:"bytes,6,opt,name=OptionalField" json:"OptionalField,omitempty"`
 	// Required fields of all basic types
 	F_BoolRequired    *bool    `protobuf:"varint,10,req,name=F_Bool_required" json:"F_Bool_required,omitempty"`
 	F_Int32Required   *int32   `protobuf:"varint,11,req,name=F_Int32_required" json:"F_Int32_required,omitempty"`
@@ -896,7 +936,7 @@ func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup {
 
 // Required, repeated, and optional groups.
 type GoTest_RequiredGroup struct {
-	RequiredField    *string `protobuf:"bytes,71,req" json:"RequiredField,omitempty"`
+	RequiredField    *string `protobuf:"bytes,71,req,name=RequiredField" json:"RequiredField,omitempty"`
 	XXX_unrecognized []byte  `json:"-"`
 }
 
@@ -912,7 +952,7 @@ func (m *GoTest_RequiredGroup) GetRequiredField() string {
 }
 
 type GoTest_RepeatedGroup struct {
-	RequiredField    *string `protobuf:"bytes,81,req" json:"RequiredField,omitempty"`
+	RequiredField    *string `protobuf:"bytes,81,req,name=RequiredField" json:"RequiredField,omitempty"`
 	XXX_unrecognized []byte  `json:"-"`
 }
 
@@ -928,7 +968,7 @@ func (m *GoTest_RepeatedGroup) GetRequiredField() string {
 }
 
 type GoTest_OptionalGroup struct {
-	RequiredField    *string `protobuf:"bytes,91,req" json:"RequiredField,omitempty"`
+	RequiredField    *string `protobuf:"bytes,91,req,name=RequiredField" json:"RequiredField,omitempty"`
 	XXX_unrecognized []byte  `json:"-"`
 }
 
@@ -1402,6 +1442,29 @@ var E_Ext_Number = &proto.ExtensionDesc{
 	Tag:           "varint,105,opt,name=number",
 }
 
+type DefaultsMessage struct {
+	XXX_extensions   map[int32]proto.Extension `json:"-"`
+	XXX_unrecognized []byte                    `json:"-"`
+}
+
+func (m *DefaultsMessage) Reset()         { *m = DefaultsMessage{} }
+func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) }
+func (*DefaultsMessage) ProtoMessage()    {}
+
+var extRange_DefaultsMessage = []proto.ExtensionRange{
+	{100, 536870911},
+}
+
+func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange {
+	return extRange_DefaultsMessage
+}
+func (m *DefaultsMessage) ExtensionMap() map[int32]proto.Extension {
+	if m.XXX_extensions == nil {
+		m.XXX_extensions = make(map[int32]proto.Extension)
+	}
+	return m.XXX_extensions
+}
+
 type MyMessageSet struct {
 	XXX_extensions   map[int32]proto.Extension `json:"-"`
 	XXX_unrecognized []byte                    `json:"-"`
@@ -1451,7 +1514,7 @@ func (m *Empty) String() string { return proto.CompactTextString(m) }
 func (*Empty) ProtoMessage()    {}
 
 type MessageList struct {
-	Message          []*MessageList_Message `protobuf:"group,1,rep" json:"message,omitempty"`
+	Message          []*MessageList_Message `protobuf:"group,1,rep,name=Message" json:"message,omitempty"`
 	XXX_unrecognized []byte                 `json:"-"`
 }
 
@@ -1517,24 +1580,24 @@ func (m *Strings) GetBytesField() []byte {
 type Defaults struct {
 	// Default-valued fields of all basic types.
 	// Same as GoTest, but copied here to make testing easier.
-	F_Bool    *bool           `protobuf:"varint,1,opt,def=1" json:"F_Bool,omitempty"`
-	F_Int32   *int32          `protobuf:"varint,2,opt,def=32" json:"F_Int32,omitempty"`
-	F_Int64   *int64          `protobuf:"varint,3,opt,def=64" json:"F_Int64,omitempty"`
-	F_Fixed32 *uint32         `protobuf:"fixed32,4,opt,def=320" json:"F_Fixed32,omitempty"`
-	F_Fixed64 *uint64         `protobuf:"fixed64,5,opt,def=640" json:"F_Fixed64,omitempty"`
-	F_Uint32  *uint32         `protobuf:"varint,6,opt,def=3200" json:"F_Uint32,omitempty"`
-	F_Uint64  *uint64         `protobuf:"varint,7,opt,def=6400" json:"F_Uint64,omitempty"`
-	F_Float   *float32        `protobuf:"fixed32,8,opt,def=314159" json:"F_Float,omitempty"`
-	F_Double  *float64        `protobuf:"fixed64,9,opt,def=271828" json:"F_Double,omitempty"`
-	F_String  *string         `protobuf:"bytes,10,opt,def=hello, \"world!\"\n" json:"F_String,omitempty"`
-	F_Bytes   []byte          `protobuf:"bytes,11,opt,def=Bignose" json:"F_Bytes,omitempty"`
-	F_Sint32  *int32          `protobuf:"zigzag32,12,opt,def=-32" json:"F_Sint32,omitempty"`
-	F_Sint64  *int64          `protobuf:"zigzag64,13,opt,def=-64" json:"F_Sint64,omitempty"`
-	F_Enum    *Defaults_Color `protobuf:"varint,14,opt,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"`
+	F_Bool    *bool           `protobuf:"varint,1,opt,name=F_Bool,def=1" json:"F_Bool,omitempty"`
+	F_Int32   *int32          `protobuf:"varint,2,opt,name=F_Int32,def=32" json:"F_Int32,omitempty"`
+	F_Int64   *int64          `protobuf:"varint,3,opt,name=F_Int64,def=64" json:"F_Int64,omitempty"`
+	F_Fixed32 *uint32         `protobuf:"fixed32,4,opt,name=F_Fixed32,def=320" json:"F_Fixed32,omitempty"`
+	F_Fixed64 *uint64         `protobuf:"fixed64,5,opt,name=F_Fixed64,def=640" json:"F_Fixed64,omitempty"`
+	F_Uint32  *uint32         `protobuf:"varint,6,opt,name=F_Uint32,def=3200" json:"F_Uint32,omitempty"`
+	F_Uint64  *uint64         `protobuf:"varint,7,opt,name=F_Uint64,def=6400" json:"F_Uint64,omitempty"`
+	F_Float   *float32        `protobuf:"fixed32,8,opt,name=F_Float,def=314159" json:"F_Float,omitempty"`
+	F_Double  *float64        `protobuf:"fixed64,9,opt,name=F_Double,def=271828" json:"F_Double,omitempty"`
+	F_String  *string         `protobuf:"bytes,10,opt,name=F_String,def=hello, \"world!\"\n" json:"F_String,omitempty"`
+	F_Bytes   []byte          `protobuf:"bytes,11,opt,name=F_Bytes,def=Bignose" json:"F_Bytes,omitempty"`
+	F_Sint32  *int32          `protobuf:"zigzag32,12,opt,name=F_Sint32,def=-32" json:"F_Sint32,omitempty"`
+	F_Sint64  *int64          `protobuf:"zigzag64,13,opt,name=F_Sint64,def=-64" json:"F_Sint64,omitempty"`
+	F_Enum    *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"`
 	// More fields with crazy defaults.
-	F_Pinf *float32 `protobuf:"fixed32,15,opt,def=inf" json:"F_Pinf,omitempty"`
-	F_Ninf *float32 `protobuf:"fixed32,16,opt,def=-inf" json:"F_Ninf,omitempty"`
-	F_Nan  *float32 `protobuf:"fixed32,17,opt,def=nan" json:"F_Nan,omitempty"`
+	F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,def=inf" json:"F_Pinf,omitempty"`
+	F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,def=-inf" json:"F_Ninf,omitempty"`
+	F_Nan  *float32 `protobuf:"fixed32,17,opt,name=F_Nan,def=nan" json:"F_Nan,omitempty"`
 	// Sub-message.
 	Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"`
 	// Redundant but explicit defaults.
@@ -1799,7 +1862,7 @@ func (m *MoreRepeated) GetFixeds() []uint32 {
 }
 
 type GroupOld struct {
-	G                *GroupOld_G `protobuf:"group,101,opt" json:"g,omitempty"`
+	G                *GroupOld_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"`
 	XXX_unrecognized []byte      `json:"-"`
 }
 
@@ -1831,7 +1894,7 @@ func (m *GroupOld_G) GetX() int32 {
 }
 
 type GroupNew struct {
-	G                *GroupNew_G `protobuf:"group,101,opt" json:"g,omitempty"`
+	G                *GroupNew_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"`
 	XXX_unrecognized []byte      `json:"-"`
 }
 
@@ -1926,6 +1989,205 @@ func (m *MessageWithMap) GetStrToStr() map[string]string {
 	return nil
 }
 
+type Communique struct {
+	MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry" json:"make_me_cry,omitempty"`
+	// This is a oneof, called "union".
+	//
+	// Types that are valid to be assigned to Union:
+	//	*Communique_Number
+	//	*Communique_Name
+	//	*Communique_Data
+	//	*Communique_TempC
+	//	*Communique_Col
+	//	*Communique_Msg
+	Union            isCommunique_Union `protobuf_oneof:"union"`
+	XXX_unrecognized []byte             `json:"-"`
+}
+
+func (m *Communique) Reset()         { *m = Communique{} }
+func (m *Communique) String() string { return proto.CompactTextString(m) }
+func (*Communique) ProtoMessage()    {}
+
+type isCommunique_Union interface {
+	isCommunique_Union()
+}
+
+type Communique_Number struct {
+	Number int32 `protobuf:"varint,5,opt,name=number,oneof"`
+}
+type Communique_Name struct {
+	Name string `protobuf:"bytes,6,opt,name=name,oneof"`
+}
+type Communique_Data struct {
+	Data []byte `protobuf:"bytes,7,opt,name=data,oneof"`
+}
+type Communique_TempC struct {
+	TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,oneof"`
+}
+type Communique_Col struct {
+	Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"`
+}
+type Communique_Msg struct {
+	Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"`
+}
+
+func (*Communique_Number) isCommunique_Union() {}
+func (*Communique_Name) isCommunique_Union()   {}
+func (*Communique_Data) isCommunique_Union()   {}
+func (*Communique_TempC) isCommunique_Union()  {}
+func (*Communique_Col) isCommunique_Union()    {}
+func (*Communique_Msg) isCommunique_Union()    {}
+
+func (m *Communique) GetUnion() isCommunique_Union {
+	if m != nil {
+		return m.Union
+	}
+	return nil
+}
+
+func (m *Communique) GetMakeMeCry() bool {
+	if m != nil && m.MakeMeCry != nil {
+		return *m.MakeMeCry
+	}
+	return false
+}
+
+func (m *Communique) GetNumber() int32 {
+	if x, ok := m.GetUnion().(*Communique_Number); ok {
+		return x.Number
+	}
+	return 0
+}
+
+func (m *Communique) GetName() string {
+	if x, ok := m.GetUnion().(*Communique_Name); ok {
+		return x.Name
+	}
+	return ""
+}
+
+func (m *Communique) GetData() []byte {
+	if x, ok := m.GetUnion().(*Communique_Data); ok {
+		return x.Data
+	}
+	return nil
+}
+
+func (m *Communique) GetTempC() float64 {
+	if x, ok := m.GetUnion().(*Communique_TempC); ok {
+		return x.TempC
+	}
+	return 0
+}
+
+func (m *Communique) GetCol() MyMessage_Color {
+	if x, ok := m.GetUnion().(*Communique_Col); ok {
+		return x.Col
+	}
+	return MyMessage_RED
+}
+
+func (m *Communique) GetMsg() *Strings {
+	if x, ok := m.GetUnion().(*Communique_Msg); ok {
+		return x.Msg
+	}
+	return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), []interface{}) {
+	return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, []interface{}{
+		(*Communique_Number)(nil),
+		(*Communique_Name)(nil),
+		(*Communique_Data)(nil),
+		(*Communique_TempC)(nil),
+		(*Communique_Col)(nil),
+		(*Communique_Msg)(nil),
+	}
+}
+
+func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+	m := msg.(*Communique)
+	// union
+	switch x := m.Union.(type) {
+	case *Communique_Number:
+		_ = b.EncodeVarint(5<<3 | proto.WireVarint)
+		_ = b.EncodeVarint(uint64(x.Number))
+	case *Communique_Name:
+		_ = b.EncodeVarint(6<<3 | proto.WireBytes)
+		_ = b.EncodeStringBytes(x.Name)
+	case *Communique_Data:
+		_ = b.EncodeVarint(7<<3 | proto.WireBytes)
+		_ = b.EncodeRawBytes(x.Data)
+	case *Communique_TempC:
+		_ = b.EncodeVarint(8<<3 | proto.WireFixed64)
+		_ = b.EncodeFixed64(math.Float64bits(x.TempC))
+	case *Communique_Col:
+		_ = b.EncodeVarint(9<<3 | proto.WireVarint)
+		_ = b.EncodeVarint(uint64(x.Col))
+	case *Communique_Msg:
+		_ = b.EncodeVarint(10<<3 | proto.WireBytes)
+		if err := b.EncodeMessage(x.Msg); err != nil {
+			return err
+		}
+	case nil:
+	default:
+		return fmt.Errorf("Communique.Union has unexpected type %T", x)
+	}
+	return nil
+}
+
+func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+	m := msg.(*Communique)
+	switch tag {
+	case 5: // union.number
+		if wire != proto.WireVarint {
+			return true, proto.ErrInternalBadWireType
+		}
+		x, err := b.DecodeVarint()
+		m.Union = &Communique_Number{int32(x)}
+		return true, err
+	case 6: // union.name
+		if wire != proto.WireBytes {
+			return true, proto.ErrInternalBadWireType
+		}
+		x, err := b.DecodeStringBytes()
+		m.Union = &Communique_Name{x}
+		return true, err
+	case 7: // union.data
+		if wire != proto.WireBytes {
+			return true, proto.ErrInternalBadWireType
+		}
+		x, err := b.DecodeRawBytes(true)
+		m.Union = &Communique_Data{x}
+		return true, err
+	case 8: // union.temp_c
+		if wire != proto.WireFixed64 {
+			return true, proto.ErrInternalBadWireType
+		}
+		x, err := b.DecodeFixed64()
+		m.Union = &Communique_TempC{math.Float64frombits(x)}
+		return true, err
+	case 9: // union.col
+		if wire != proto.WireVarint {
+			return true, proto.ErrInternalBadWireType
+		}
+		x, err := b.DecodeVarint()
+		m.Union = &Communique_Col{MyMessage_Color(x)}
+		return true, err
+	case 10: // union.msg
+		if wire != proto.WireBytes {
+			return true, proto.ErrInternalBadWireType
+		}
+		msg := new(Strings)
+		err := b.DecodeMessage(msg)
+		m.Union = &Communique_Msg{msg}
+		return true, err
+	default:
+		return false, nil
+	}
+}
+
 var E_Greeting = &proto.ExtensionDesc{
 	ExtendedType:  (*MyMessage)(nil),
 	ExtensionType: ([]string)(nil),
@@ -1934,6 +2196,262 @@ var E_Greeting = &proto.ExtensionDesc{
 	Tag:           "bytes,106,rep,name=greeting",
 }
 
+var E_NoDefaultDouble = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*float64)(nil),
+	Field:         101,
+	Name:          "testdata.no_default_double",
+	Tag:           "fixed64,101,opt,name=no_default_double",
+}
+
+var E_NoDefaultFloat = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*float32)(nil),
+	Field:         102,
+	Name:          "testdata.no_default_float",
+	Tag:           "fixed32,102,opt,name=no_default_float",
+}
+
+var E_NoDefaultInt32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         103,
+	Name:          "testdata.no_default_int32",
+	Tag:           "varint,103,opt,name=no_default_int32",
+}
+
+var E_NoDefaultInt64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         104,
+	Name:          "testdata.no_default_int64",
+	Tag:           "varint,104,opt,name=no_default_int64",
+}
+
+var E_NoDefaultUint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         105,
+	Name:          "testdata.no_default_uint32",
+	Tag:           "varint,105,opt,name=no_default_uint32",
+}
+
+var E_NoDefaultUint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         106,
+	Name:          "testdata.no_default_uint64",
+	Tag:           "varint,106,opt,name=no_default_uint64",
+}
+
+var E_NoDefaultSint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         107,
+	Name:          "testdata.no_default_sint32",
+	Tag:           "zigzag32,107,opt,name=no_default_sint32",
+}
+
+var E_NoDefaultSint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         108,
+	Name:          "testdata.no_default_sint64",
+	Tag:           "zigzag64,108,opt,name=no_default_sint64",
+}
+
+var E_NoDefaultFixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         109,
+	Name:          "testdata.no_default_fixed32",
+	Tag:           "fixed32,109,opt,name=no_default_fixed32",
+}
+
+var E_NoDefaultFixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         110,
+	Name:          "testdata.no_default_fixed64",
+	Tag:           "fixed64,110,opt,name=no_default_fixed64",
+}
+
+var E_NoDefaultSfixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         111,
+	Name:          "testdata.no_default_sfixed32",
+	Tag:           "fixed32,111,opt,name=no_default_sfixed32",
+}
+
+var E_NoDefaultSfixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         112,
+	Name:          "testdata.no_default_sfixed64",
+	Tag:           "fixed64,112,opt,name=no_default_sfixed64",
+}
+
+var E_NoDefaultBool = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         113,
+	Name:          "testdata.no_default_bool",
+	Tag:           "varint,113,opt,name=no_default_bool",
+}
+
+var E_NoDefaultString = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         114,
+	Name:          "testdata.no_default_string",
+	Tag:           "bytes,114,opt,name=no_default_string",
+}
+
+var E_NoDefaultBytes = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: ([]byte)(nil),
+	Field:         115,
+	Name:          "testdata.no_default_bytes",
+	Tag:           "bytes,115,opt,name=no_default_bytes",
+}
+
+var E_NoDefaultEnum = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil),
+	Field:         116,
+	Name:          "testdata.no_default_enum",
+	Tag:           "varint,116,opt,name=no_default_enum,enum=testdata.DefaultsMessage_DefaultsEnum",
+}
+
+var E_DefaultDouble = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*float64)(nil),
+	Field:         201,
+	Name:          "testdata.default_double",
+	Tag:           "fixed64,201,opt,name=default_double,def=3.1415",
+}
+
+var E_DefaultFloat = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*float32)(nil),
+	Field:         202,
+	Name:          "testdata.default_float",
+	Tag:           "fixed32,202,opt,name=default_float,def=3.14",
+}
+
+var E_DefaultInt32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         203,
+	Name:          "testdata.default_int32",
+	Tag:           "varint,203,opt,name=default_int32,def=42",
+}
+
+var E_DefaultInt64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         204,
+	Name:          "testdata.default_int64",
+	Tag:           "varint,204,opt,name=default_int64,def=43",
+}
+
+var E_DefaultUint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         205,
+	Name:          "testdata.default_uint32",
+	Tag:           "varint,205,opt,name=default_uint32,def=44",
+}
+
+var E_DefaultUint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         206,
+	Name:          "testdata.default_uint64",
+	Tag:           "varint,206,opt,name=default_uint64,def=45",
+}
+
+var E_DefaultSint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         207,
+	Name:          "testdata.default_sint32",
+	Tag:           "zigzag32,207,opt,name=default_sint32,def=46",
+}
+
+var E_DefaultSint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         208,
+	Name:          "testdata.default_sint64",
+	Tag:           "zigzag64,208,opt,name=default_sint64,def=47",
+}
+
+var E_DefaultFixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         209,
+	Name:          "testdata.default_fixed32",
+	Tag:           "fixed32,209,opt,name=default_fixed32,def=48",
+}
+
+var E_DefaultFixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         210,
+	Name:          "testdata.default_fixed64",
+	Tag:           "fixed64,210,opt,name=default_fixed64,def=49",
+}
+
+var E_DefaultSfixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         211,
+	Name:          "testdata.default_sfixed32",
+	Tag:           "fixed32,211,opt,name=default_sfixed32,def=50",
+}
+
+var E_DefaultSfixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         212,
+	Name:          "testdata.default_sfixed64",
+	Tag:           "fixed64,212,opt,name=default_sfixed64,def=51",
+}
+
+var E_DefaultBool = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         213,
+	Name:          "testdata.default_bool",
+	Tag:           "varint,213,opt,name=default_bool,def=1",
+}
+
+var E_DefaultString = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         214,
+	Name:          "testdata.default_string",
+	Tag:           "bytes,214,opt,name=default_string,def=Hello, string",
+}
+
+var E_DefaultBytes = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: ([]byte)(nil),
+	Field:         215,
+	Name:          "testdata.default_bytes",
+	Tag:           "bytes,215,opt,name=default_bytes,def=Hello, bytes",
+}
+
+var E_DefaultEnum = &proto.ExtensionDesc{
+	ExtendedType:  (*DefaultsMessage)(nil),
+	ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil),
+	Field:         216,
+	Name:          "testdata.default_enum",
+	Tag:           "varint,216,opt,name=default_enum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1",
+}
+
 var E_X201 = &proto.ExtensionDesc{
 	ExtendedType:  (*MyMessageSet)(nil),
 	ExtensionType: (*Empty)(nil),
@@ -2335,15 +2853,85 @@ var E_X250 = &proto.ExtensionDesc{
 }
 
 func init() {
+	proto.RegisterType((*GoEnum)(nil), "testdata.GoEnum")
+	proto.RegisterType((*GoTestField)(nil), "testdata.GoTestField")
+	proto.RegisterType((*GoTest)(nil), "testdata.GoTest")
+	proto.RegisterType((*GoTest_RequiredGroup)(nil), "testdata.GoTest.RequiredGroup")
+	proto.RegisterType((*GoTest_RepeatedGroup)(nil), "testdata.GoTest.RepeatedGroup")
+	proto.RegisterType((*GoTest_OptionalGroup)(nil), "testdata.GoTest.OptionalGroup")
+	proto.RegisterType((*GoSkipTest)(nil), "testdata.GoSkipTest")
+	proto.RegisterType((*GoSkipTest_SkipGroup)(nil), "testdata.GoSkipTest.SkipGroup")
+	proto.RegisterType((*NonPackedTest)(nil), "testdata.NonPackedTest")
+	proto.RegisterType((*PackedTest)(nil), "testdata.PackedTest")
+	proto.RegisterType((*MaxTag)(nil), "testdata.MaxTag")
+	proto.RegisterType((*OldMessage)(nil), "testdata.OldMessage")
+	proto.RegisterType((*OldMessage_Nested)(nil), "testdata.OldMessage.Nested")
+	proto.RegisterType((*NewMessage)(nil), "testdata.NewMessage")
+	proto.RegisterType((*NewMessage_Nested)(nil), "testdata.NewMessage.Nested")
+	proto.RegisterType((*InnerMessage)(nil), "testdata.InnerMessage")
+	proto.RegisterType((*OtherMessage)(nil), "testdata.OtherMessage")
+	proto.RegisterType((*MyMessage)(nil), "testdata.MyMessage")
+	proto.RegisterType((*MyMessage_SomeGroup)(nil), "testdata.MyMessage.SomeGroup")
+	proto.RegisterType((*Ext)(nil), "testdata.Ext")
+	proto.RegisterType((*DefaultsMessage)(nil), "testdata.DefaultsMessage")
+	proto.RegisterType((*MyMessageSet)(nil), "testdata.MyMessageSet")
+	proto.RegisterType((*Empty)(nil), "testdata.Empty")
+	proto.RegisterType((*MessageList)(nil), "testdata.MessageList")
+	proto.RegisterType((*MessageList_Message)(nil), "testdata.MessageList.Message")
+	proto.RegisterType((*Strings)(nil), "testdata.Strings")
+	proto.RegisterType((*Defaults)(nil), "testdata.Defaults")
+	proto.RegisterType((*SubDefaults)(nil), "testdata.SubDefaults")
+	proto.RegisterType((*RepeatedEnum)(nil), "testdata.RepeatedEnum")
+	proto.RegisterType((*MoreRepeated)(nil), "testdata.MoreRepeated")
+	proto.RegisterType((*GroupOld)(nil), "testdata.GroupOld")
+	proto.RegisterType((*GroupOld_G)(nil), "testdata.GroupOld.G")
+	proto.RegisterType((*GroupNew)(nil), "testdata.GroupNew")
+	proto.RegisterType((*GroupNew_G)(nil), "testdata.GroupNew.G")
+	proto.RegisterType((*FloatingPoint)(nil), "testdata.FloatingPoint")
+	proto.RegisterType((*MessageWithMap)(nil), "testdata.MessageWithMap")
+	proto.RegisterType((*Communique)(nil), "testdata.Communique")
 	proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value)
 	proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value)
 	proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value)
+	proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value)
 	proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value)
 	proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value)
 	proto.RegisterExtension(E_Ext_More)
 	proto.RegisterExtension(E_Ext_Text)
 	proto.RegisterExtension(E_Ext_Number)
 	proto.RegisterExtension(E_Greeting)
+	proto.RegisterExtension(E_NoDefaultDouble)
+	proto.RegisterExtension(E_NoDefaultFloat)
+	proto.RegisterExtension(E_NoDefaultInt32)
+	proto.RegisterExtension(E_NoDefaultInt64)
+	proto.RegisterExtension(E_NoDefaultUint32)
+	proto.RegisterExtension(E_NoDefaultUint64)
+	proto.RegisterExtension(E_NoDefaultSint32)
+	proto.RegisterExtension(E_NoDefaultSint64)
+	proto.RegisterExtension(E_NoDefaultFixed32)
+	proto.RegisterExtension(E_NoDefaultFixed64)
+	proto.RegisterExtension(E_NoDefaultSfixed32)
+	proto.RegisterExtension(E_NoDefaultSfixed64)
+	proto.RegisterExtension(E_NoDefaultBool)
+	proto.RegisterExtension(E_NoDefaultString)
+	proto.RegisterExtension(E_NoDefaultBytes)
+	proto.RegisterExtension(E_NoDefaultEnum)
+	proto.RegisterExtension(E_DefaultDouble)
+	proto.RegisterExtension(E_DefaultFloat)
+	proto.RegisterExtension(E_DefaultInt32)
+	proto.RegisterExtension(E_DefaultInt64)
+	proto.RegisterExtension(E_DefaultUint32)
+	proto.RegisterExtension(E_DefaultUint64)
+	proto.RegisterExtension(E_DefaultSint32)
+	proto.RegisterExtension(E_DefaultSint64)
+	proto.RegisterExtension(E_DefaultFixed32)
+	proto.RegisterExtension(E_DefaultFixed64)
+	proto.RegisterExtension(E_DefaultSfixed32)
+	proto.RegisterExtension(E_DefaultSfixed64)
+	proto.RegisterExtension(E_DefaultBool)
+	proto.RegisterExtension(E_DefaultString)
+	proto.RegisterExtension(E_DefaultBytes)
+	proto.RegisterExtension(E_DefaultEnum)
 	proto.RegisterExtension(E_X201)
 	proto.RegisterExtension(E_X202)
 	proto.RegisterExtension(E_X203)

+ 59 - 0
Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.proto

@@ -277,6 +277,51 @@ extend MyMessage {
   repeated string greeting = 106;
 }
 
+message DefaultsMessage {
+  enum DefaultsEnum {
+    ZERO = 0;
+    ONE = 1;
+    TWO = 2;
+  };
+  extensions 100 to max;
+}
+
+extend DefaultsMessage {
+  optional double no_default_double = 101;
+  optional float no_default_float = 102;
+  optional int32 no_default_int32 = 103;
+  optional int64 no_default_int64 = 104;
+  optional uint32 no_default_uint32 = 105;
+  optional uint64 no_default_uint64 = 106;
+  optional sint32 no_default_sint32 = 107;
+  optional sint64 no_default_sint64 = 108;
+  optional fixed32 no_default_fixed32 = 109;
+  optional fixed64 no_default_fixed64 = 110;
+  optional sfixed32 no_default_sfixed32 = 111;
+  optional sfixed64 no_default_sfixed64 = 112;
+  optional bool no_default_bool = 113;
+  optional string no_default_string = 114;
+  optional bytes no_default_bytes = 115;
+  optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
+
+  optional double default_double = 201 [default = 3.1415];
+  optional float default_float = 202 [default = 3.14];
+  optional int32 default_int32 = 203 [default = 42];
+  optional int64 default_int64 = 204 [default = 43];
+  optional uint32 default_uint32 = 205 [default = 44];
+  optional uint64 default_uint64 = 206 [default = 45];
+  optional sint32 default_sint32 = 207 [default = 46];
+  optional sint64 default_sint64 = 208 [default = 47];
+  optional fixed32 default_fixed32 = 209 [default = 48];
+  optional fixed64 default_fixed64 = 210 [default = 49];
+  optional sfixed32 default_sfixed32 = 211 [default = 50];
+  optional sfixed64 default_sfixed64 = 212 [default = 51];
+  optional bool default_bool = 213 [default = true];
+  optional string default_string = 214 [default = "Hello, string"];
+  optional bytes default_bytes = 215 [default = "Hello, bytes"];
+  optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
+}
+
 message MyMessageSet {
   option message_set_wire_format = true;
   extensions 100 to max;
@@ -433,3 +478,17 @@ message MessageWithMap {
   map<bool, bytes> byte_mapping = 3;
   map<string, string> str_to_str = 4;
 }
+
+message Communique {
+  optional bool make_me_cry = 1;
+
+  // This is a oneof, called "union".
+  oneof union {
+    int32 number = 5;
+    string name = 6;
+    bytes data = 7;
+    double temp_c = 8;
+    MyMessage.Color col = 9;
+    Strings msg = 10;
+  }
+}

+ 67 - 98
Godeps/_workspace/src/github.com/gogo/protobuf/proto/text.go

@@ -42,11 +42,11 @@ import (
 	"bufio"
 	"bytes"
 	"encoding"
+	"errors"
 	"fmt"
 	"io"
 	"log"
 	"math"
-	"os"
 	"reflect"
 	"sort"
 	"strings"
@@ -175,20 +175,12 @@ func writeName(w *textWriter, props *Properties) error {
 	return nil
 }
 
-var (
-	messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem()
-)
-
 // raw is the interface satisfied by RawMessage.
 type raw interface {
 	Bytes() []byte
 }
 
 func writeStruct(w *textWriter, sv reflect.Value) error {
-	if sv.Type() == messageSetType {
-		return writeMessageSet(w, sv.Addr().Interface().(*MessageSet))
-	}
-
 	st := sv.Type()
 	sprops := GetProperties(st)
 	for i := 0; i < sv.NumField(); i++ {
@@ -255,7 +247,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 		}
 		if fv.Kind() == reflect.Map {
 			// Map fields are rendered as a repeated struct with key/value fields.
-			keys := fv.MapKeys() // TODO: should we sort these for deterministic output?
+			keys := fv.MapKeys()
 			sort.Sort(mapKeys(keys))
 			for _, key := range keys {
 				val := fv.MapIndex(key)
@@ -292,20 +284,23 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 				if err := w.WriteByte('\n'); err != nil {
 					return err
 				}
-				// value
-				if _, err := w.WriteString("value:"); err != nil {
-					return err
-				}
-				if !w.compact {
-					if err := w.WriteByte(' '); err != nil {
+				// nil values aren't legal, but we can avoid panicking because of them.
+				if val.Kind() != reflect.Ptr || !val.IsNil() {
+					// value
+					if _, err := w.WriteString("value:"); err != nil {
+						return err
+					}
+					if !w.compact {
+						if err := w.WriteByte(' '); err != nil {
+							return err
+						}
+					}
+					if err := writeAny(w, val, props.mvalprop); err != nil {
+						return err
+					}
+					if err := w.WriteByte('\n'); err != nil {
 						return err
 					}
-				}
-				if err := writeAny(w, val, props.mvalprop); err != nil {
-					return err
-				}
-				if err := w.WriteByte('\n'); err != nil {
-					return err
 				}
 				// close struct
 				w.unindent()
@@ -324,26 +319,33 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 		}
 		if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
 			// proto3 non-repeated scalar field; skip if zero value
-			switch fv.Kind() {
-			case reflect.Bool:
-				if !fv.Bool() {
-					continue
-				}
-			case reflect.Int32, reflect.Int64:
-				if fv.Int() == 0 {
-					continue
-				}
-			case reflect.Uint32, reflect.Uint64:
-				if fv.Uint() == 0 {
-					continue
-				}
-			case reflect.Float32, reflect.Float64:
-				if fv.Float() == 0 {
+			if isProto3Zero(fv) {
+				continue
+			}
+		}
+
+		if fv.Kind() == reflect.Interface {
+			// Check if it is a oneof.
+			if st.Field(i).Tag.Get("protobuf_oneof") != "" {
+				// fv is nil, or holds a pointer to generated struct.
+				// That generated struct has exactly one field,
+				// which has a protobuf struct tag.
+				if fv.IsNil() {
 					continue
 				}
-			case reflect.String:
-				if fv.String() == "" {
-					continue
+				inner := fv.Elem().Elem() // interface -> *T -> T
+				tag := inner.Type().Field(0).Tag.Get("protobuf")
+				props.Parse(tag) // Overwrite the outer props.
+				// Write the value in the oneof, not the oneof itself.
+				fv = inner.Field(0)
+
+				// Special case to cope with malformed messages gracefully:
+				// If the value in the oneof is a nil pointer, don't panic
+				// in writeAny.
+				if fv.Kind() == reflect.Ptr && fv.IsNil() {
+					// Use errors.New so writeAny won't render quotes.
+					msg := errors.New("/* nil */")
+					fv = reflect.ValueOf(&msg).Elem()
 				}
 			}
 		}
@@ -377,7 +379,13 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 	}
 
 	// Extensions (the XXX_extensions field).
-	pv := sv.Addr()
+	pv := sv
+	if pv.CanAddr() {
+		pv = sv.Addr()
+	} else {
+		pv = reflect.New(sv.Type())
+		pv.Elem().Set(sv)
+	}
 	if pv.Type().Implements(extendableProtoType) {
 		if err := writeExtensions(w, pv); err != nil {
 			return err
@@ -413,15 +421,17 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
 	v = reflect.Indirect(v)
 
 	if props != nil && len(props.CustomType) > 0 {
-		var custom Marshaler = v.Interface().(Marshaler)
-		data, err := custom.Marshal()
-		if err != nil {
-			return err
-		}
-		if err := writeString(w, string(data)); err != nil {
-			return err
+		custom, ok := v.Interface().(Marshaler)
+		if ok {
+			data, err := custom.Marshal()
+			if err != nil {
+				return err
+			}
+			if err := writeString(w, string(data)); err != nil {
+				return err
+			}
+			return nil
 		}
-		return nil
 	}
 
 	// Floats have special cases.
@@ -538,44 +548,6 @@ func writeString(w *textWriter, s string) error {
 	return w.WriteByte('"')
 }
 
-func writeMessageSet(w *textWriter, ms *MessageSet) error {
-	for _, item := range ms.Item {
-		id := *item.TypeId
-		if msd, ok := messageSetMap[id]; ok {
-			// Known message set type.
-			if _, err := fmt.Fprintf(w, "[%s]: <\n", msd.name); err != nil {
-				return err
-			}
-			w.indent()
-
-			pb := reflect.New(msd.t.Elem())
-			if err := Unmarshal(item.Message, pb.Interface().(Message)); err != nil {
-				if _, err := fmt.Fprintf(w, "/* bad message: %v */\n", err); err != nil {
-					return err
-				}
-			} else {
-				if err := writeStruct(w, pb.Elem()); err != nil {
-					return err
-				}
-			}
-		} else {
-			// Unknown type.
-			if _, err := fmt.Fprintf(w, "[%d]: <\n", id); err != nil {
-				return err
-			}
-			w.indent()
-			if err := writeUnknownStruct(w, item.Message); err != nil {
-				return err
-			}
-		}
-		w.unindent()
-		if _, err := w.Write(gtNewline); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
 func writeUnknownStruct(w *textWriter, data []byte) (err error) {
 	if !w.compact {
 		if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
@@ -586,19 +558,19 @@ func writeUnknownStruct(w *textWriter, data []byte) (err error) {
 	for b.index < len(b.buf) {
 		x, err := b.DecodeVarint()
 		if err != nil {
-			_, err := fmt.Fprintf(w, "/* %v */\n", err)
-			return err
+			_, ferr := fmt.Fprintf(w, "/* %v */\n", err)
+			return ferr
 		}
 		wire, tag := x&7, x>>3
 		if wire == WireEndGroup {
 			w.unindent()
-			if _, err := w.Write(endBraceNewline); err != nil {
-				return err
+			if _, werr := w.Write(endBraceNewline); werr != nil {
+				return werr
 			}
 			continue
 		}
-		if _, err := fmt.Fprint(w, tag); err != nil {
-			return err
+		if _, ferr := fmt.Fprint(w, tag); ferr != nil {
+			return ferr
 		}
 		if wire != WireStartGroup {
 			if err := w.WriteByte(':'); err != nil {
@@ -636,7 +608,7 @@ func writeUnknownStruct(w *textWriter, data []byte) (err error) {
 		if err != nil {
 			return err
 		}
-		if err = w.WriteByte('\n'); err != nil {
+		if err := w.WriteByte('\n'); err != nil {
 			return err
 		}
 	}
@@ -701,10 +673,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
 
 		pb, err := GetExtension(ep, desc)
 		if err != nil {
-			if _, err := fmt.Fprintln(os.Stderr, "proto: failed getting extension: ", err); err != nil {
-				return err
-			}
-			continue
+			return fmt.Errorf("failed getting extension: %v", err)
 		}
 
 		// Repeated extensions will appear as a slice.

+ 135 - 94
Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser.go

@@ -179,7 +179,7 @@ func (p *textParser) advance() {
 		}
 		unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
 		if err != nil {
-			p.errorf("invalid quoted string %v", p.s[0:i+1])
+			p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
 			return
 		}
 		p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
@@ -390,8 +390,7 @@ func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSet
 }
 
 // Returns the index in the struct for the named field, as well as the parsed tag properties.
-func structFieldByName(st reflect.Type, name string) (int, *Properties, bool) {
-	sprops := GetProperties(st)
+func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
 	i, ok := sprops.decoderOrigNames[name]
 	if ok {
 		return i, sprops.Prop[i], true
@@ -443,7 +442,8 @@ func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseEr
 
 func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 	st := sv.Type()
-	reqCount := GetProperties(st).reqCount
+	sprops := GetProperties(st)
+	reqCount := sprops.reqCount
 	var reqFieldErr error
 	fieldSet := make(map[string]bool)
 	// A struct is a sequence of "name: value", terminated by one of
@@ -525,99 +525,113 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 				sl = reflect.Append(sl, ext)
 				SetExtension(ep, desc, sl.Interface())
 			}
-		} else {
-			// This is a normal, non-extension field.
-			name := tok.value
-			fi, props, ok := structFieldByName(st, name)
-			if !ok {
-				return p.errorf("unknown field name %q in %v", name, st)
+			if err := p.consumeOptionalSeparator(); err != nil {
+				return err
 			}
+			continue
+		}
 
-			dst := sv.Field(fi)
-
-			if dst.Kind() == reflect.Map {
-				// Consume any colon.
-				if err := p.checkForColon(props, dst.Type()); err != nil {
-					return err
-				}
-
-				// Construct the map if it doesn't already exist.
-				if dst.IsNil() {
-					dst.Set(reflect.MakeMap(dst.Type()))
-				}
-				key := reflect.New(dst.Type().Key()).Elem()
-				val := reflect.New(dst.Type().Elem()).Elem()
-
-				// The map entry should be this sequence of tokens:
-				//	< key : KEY value : VALUE >
-				// Technically the "key" and "value" could come in any order,
-				// but in practice they won't.
-
-				tok := p.next()
-				var terminator string
-				switch tok.value {
-				case "<":
-					terminator = ">"
-				case "{":
-					terminator = "}"
-				default:
-					return p.errorf("expected '{' or '<', found %q", tok.value)
-				}
-				if err := p.consumeToken("key"); err != nil {
-					return err
-				}
-				if err := p.consumeToken(":"); err != nil {
-					return err
-				}
-				if err := p.readAny(key, props.mkeyprop); err != nil {
-					return err
-				}
-				if err := p.consumeToken("value"); err != nil {
-					return err
-				}
-				if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
-					return err
-				}
-				if err := p.readAny(val, props.mvalprop); err != nil {
-					return err
-				}
-				if err := p.consumeToken(terminator); err != nil {
-					return err
-				}
+		// This is a normal, non-extension field.
+		name := tok.value
+		var dst reflect.Value
+		fi, props, ok := structFieldByName(sprops, name)
+		if ok {
+			dst = sv.Field(fi)
+		} else if oop, ok := sprops.OneofTypes[name]; ok {
+			// It is a oneof.
+			props = oop.Prop
+			nv := reflect.New(oop.Type.Elem())
+			dst = nv.Elem().Field(0)
+			sv.Field(oop.Field).Set(nv)
+		}
+		if !dst.IsValid() {
+			return p.errorf("unknown field name %q in %v", name, st)
+		}
 
-				dst.SetMapIndex(key, val)
-				continue
+		if dst.Kind() == reflect.Map {
+			// Consume any colon.
+			if err := p.checkForColon(props, dst.Type()); err != nil {
+				return err
 			}
 
-			// Check that it's not already set if it's not a repeated field.
-			if !props.Repeated && fieldSet[name] {
-				return p.errorf("non-repeated field %q was repeated", name)
+			// Construct the map if it doesn't already exist.
+			if dst.IsNil() {
+				dst.Set(reflect.MakeMap(dst.Type()))
 			}
-
-			if err := p.checkForColon(props, st.Field(fi).Type); err != nil {
+			key := reflect.New(dst.Type().Key()).Elem()
+			val := reflect.New(dst.Type().Elem()).Elem()
+
+			// The map entry should be this sequence of tokens:
+			//	< key : KEY value : VALUE >
+			// Technically the "key" and "value" could come in any order,
+			// but in practice they won't.
+
+			tok := p.next()
+			var terminator string
+			switch tok.value {
+			case "<":
+				terminator = ">"
+			case "{":
+				terminator = "}"
+			default:
+				return p.errorf("expected '{' or '<', found %q", tok.value)
+			}
+			if err := p.consumeToken("key"); err != nil {
 				return err
 			}
-
-			// Parse into the field.
-			fieldSet[name] = true
-			if err := p.readAny(dst, props); err != nil {
-				if _, ok := err.(*RequiredNotSetError); !ok {
-					return err
-				}
-				reqFieldErr = err
-			} else if props.Required {
-				reqCount--
+			if err := p.consumeToken(":"); err != nil {
+				return err
+			}
+			if err := p.readAny(key, props.mkeyprop); err != nil {
+				return err
+			}
+			if err := p.consumeOptionalSeparator(); err != nil {
+				return err
+			}
+			if err := p.consumeToken("value"); err != nil {
+				return err
+			}
+			if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+				return err
+			}
+			if err := p.readAny(val, props.mvalprop); err != nil {
+				return err
+			}
+			if err := p.consumeOptionalSeparator(); err != nil {
+				return err
+			}
+			if err := p.consumeToken(terminator); err != nil {
+				return err
 			}
+
+			dst.SetMapIndex(key, val)
+			continue
 		}
 
-		// For backward compatibility, permit a semicolon or comma after a field.
-		tok = p.next()
-		if tok.err != nil {
-			return tok.err
+		// Check that it's not already set if it's not a repeated field.
+		if !props.Repeated && fieldSet[name] {
+			return p.errorf("non-repeated field %q was repeated", name)
+		}
+
+		if err := p.checkForColon(props, dst.Type()); err != nil {
+			return err
 		}
-		if tok.value != ";" && tok.value != "," {
-			p.back()
+
+		// Parse into the field.
+		fieldSet[name] = true
+		if err := p.readAny(dst, props); err != nil {
+			if _, ok := err.(*RequiredNotSetError); !ok {
+				return err
+			}
+			reqFieldErr = err
+		} else if props.Required {
+			reqCount--
+		}
+
+		if err := p.consumeOptionalSeparator(); err != nil {
+			return err
 		}
+
 	}
 
 	if reqCount > 0 {
@@ -626,6 +640,19 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 	return reqFieldErr
 }
 
+// consumeOptionalSeparator consumes an optional semicolon or comma.
+// It is used in readStruct to provide backward compatibility.
+func (p *textParser) consumeOptionalSeparator() error {
+	tok := p.next()
+	if tok.err != nil {
+		return tok.err
+	}
+	if tok.value != ";" && tok.value != "," {
+		p.back()
+	}
+	return nil
+}
+
 func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 	tok := p.next()
 	if tok.err != nil {
@@ -688,18 +715,32 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 			fv.Set(reflect.ValueOf(bytes))
 			return nil
 		}
-		// Repeated field. May already exist.
-		flen := fv.Len()
-		if flen == fv.Cap() {
-			nav := reflect.MakeSlice(at, flen, 2*flen+1)
-			reflect.Copy(nav, fv)
-			fv.Set(nav)
+		// Repeated field.
+		if tok.value == "[" {
+			// Repeated field with list notation, like [1,2,3].
+			for {
+				fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+				err := p.readAny(fv.Index(fv.Len()-1), props)
+				if err != nil {
+					return err
+				}
+				tok := p.next()
+				if tok.err != nil {
+					return tok.err
+				}
+				if tok.value == "]" {
+					break
+				}
+				if tok.value != "," {
+					return p.errorf("Expected ']' or ',' found %q", tok.value)
+				}
+			}
+			return nil
 		}
-		fv.SetLen(flen + 1)
-
-		// Read one.
+		// One value of the repeated field.
 		p.back()
-		return p.readAny(fv.Index(flen), props)
+		fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+		return p.readAny(fv.Index(fv.Len()-1), props)
 	case reflect.Bool:
 		// Either "true", "false", 1 or 0.
 		switch tok.value {

+ 23 - 2
Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser_test.go

@@ -152,7 +152,7 @@ var unMarshalTextTests = []UnmarshalTextTest{
 	// Bad quoted string
 	{
 		in:  `inner: < host: "\0" >` + "\n",
-		err: `line 1.15: invalid quoted string "\0"`,
+		err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`,
 	},
 
 	// Number too large for int64
@@ -256,6 +256,15 @@ var unMarshalTextTests = []UnmarshalTextTest{
 		},
 	},
 
+	// Repeated field with list notation
+	{
+		in: `count:42 pet: ["horsey", "bunny"]`,
+		out: &MyMessage{
+			Count: Int32(42),
+			Pet:   []string{"horsey", "bunny"},
+		},
+	},
+
 	// Repeated message with/without colon and <>/{}
 	{
 		in: `count:42 others:{} others{} others:<> others:{}`,
@@ -462,7 +471,7 @@ func TestProto3TextParsing(t *testing.T) {
 func TestMapParsing(t *testing.T) {
 	m := new(MessageWithMap)
 	const in = `name_mapping:<key:1234 value:"Feist"> name_mapping:<key:1 value:"Beatles">` +
-		`msg_mapping:<key:-4 value:<f: 2.0>>` +
+		`msg_mapping:<key:-4, value:<f: 2.0>,>` + // separating commas are okay
 		`msg_mapping<key:-2 value<f: 4.0>>` + // no colon after "value"
 		`byte_mapping:<key:true value:"so be it">`
 	want := &MessageWithMap{
@@ -486,6 +495,18 @@ func TestMapParsing(t *testing.T) {
 	}
 }
 
+func TestOneofParsing(t *testing.T) {
+	const in = `name:"Shrek"`
+	m := new(Communique)
+	want := &Communique{Union: &Communique_Name{"Shrek"}}
+	if err := UnmarshalText(in, m); err != nil {
+		t.Fatal(err)
+	}
+	if !Equal(m, want) {
+		t.Errorf("\n got %v\nwant %v", m, want)
+	}
+}
+
 var benchInput string
 
 func init() {

+ 42 - 3
Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_test.go

@@ -40,6 +40,7 @@ import (
 	"testing"
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
+
 	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto"
 	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata"
 )
@@ -207,6 +208,30 @@ func TestMarshalTextUnknownEnum(t *testing.T) {
 	}
 }
 
+func TestTextOneof(t *testing.T) {
+	tests := []struct {
+		m    proto.Message
+		want string
+	}{
+		// zero message
+		{&pb.Communique{}, ``},
+		// scalar field
+		{&pb.Communique{Union: &pb.Communique_Number{Number: 4}}, `number:4`},
+		// message field
+		{&pb.Communique{Union: &pb.Communique_Msg{
+			Msg: &pb.Strings{StringField: proto.String("why hello!")},
+		}}, `msg:<string_field:"why hello!" >`},
+		// bad oneof (should not panic)
+		{&pb.Communique{Union: &pb.Communique_Msg{Msg: nil}}, `msg:/* nil */`},
+	}
+	for _, test := range tests {
+		got := strings.TrimSpace(test.m.String())
+		if got != test.want {
+			t.Errorf("\n got %s\nwant %s", got, test.want)
+		}
+	}
+}
+
 func BenchmarkMarshalTextBuffered(b *testing.B) {
 	buf := new(bytes.Buffer)
 	m := newTestMessage()
@@ -420,10 +445,24 @@ func TestProto3Text(t *testing.T) {
 		{&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`},
 		// empty map
 		{&pb.MessageWithMap{}, ``},
-		// non-empty map; current map format is the same as a repeated struct
+		// non-empty map; map format is the same as a repeated struct,
+		// and they are sorted by key (numerically for numeric keys).
+		{
+			&pb.MessageWithMap{NameMapping: map[int32]string{
+				-1:      "Negatory",
+				7:       "Lucky",
+				1234:    "Feist",
+				6345789: "Otis",
+			}},
+			`name_mapping:<key:-1 value:"Negatory" > ` +
+				`name_mapping:<key:7 value:"Lucky" > ` +
+				`name_mapping:<key:1234 value:"Feist" > ` +
+				`name_mapping:<key:6345789 value:"Otis" >`,
+		},
+		// map with nil value; not well-defined, but we shouldn't crash
 		{
-			&pb.MessageWithMap{NameMapping: map[int32]string{1234: "Feist"}},
-			`name_mapping:<key:1234 value:"Feist" >`,
+			&pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}},
+			`msg_mapping:<key:7 >`,
 		},
 	}
 	for _, test := range tests {

+ 31 - 0
Godeps/_workspace/src/github.com/golang/protobuf/LICENSE

@@ -0,0 +1,31 @@
+Go support for Protocol Buffers - Google's data interchange format
+
+Copyright 2010 The Go Authors.  All rights reserved.
+https://github.com/golang/protobuf
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+

+ 1 - 1
Godeps/_workspace/src/github.com/golang/protobuf/proto/Makefile

@@ -39,5 +39,5 @@ test: install generate-test-pbs
 generate-test-pbs:
 	make install
 	make -C testdata
-	make -C proto3_proto
+	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata:. proto3_proto/proto3.proto
 	make

+ 122 - 12
Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go

@@ -44,8 +44,8 @@ import (
 	"testing"
 	"time"
 
-	. "./testdata"
 	. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 var globalO *Buffer
@@ -401,17 +401,18 @@ type fakeMarshaler struct {
 	err error
 }
 
-func (f fakeMarshaler) Marshal() ([]byte, error) {
-	return f.b, f.err
-}
+func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err }
+func (f *fakeMarshaler) String() string           { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) }
+func (f *fakeMarshaler) ProtoMessage()            {}
+func (f *fakeMarshaler) Reset()                   {}
 
-func (f fakeMarshaler) String() string {
-	return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err)
+type msgWithFakeMarshaler struct {
+	M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"`
 }
 
-func (f fakeMarshaler) ProtoMessage() {}
-
-func (f fakeMarshaler) Reset() {}
+func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) }
+func (m *msgWithFakeMarshaler) ProtoMessage()  {}
+func (m *msgWithFakeMarshaler) Reset()         {}
 
 // Simple tests for proto messages that implement the Marshaler interface.
 func TestMarshalerEncoding(t *testing.T) {
@@ -423,7 +424,7 @@ func TestMarshalerEncoding(t *testing.T) {
 	}{
 		{
 			name: "Marshaler that fails",
-			m: fakeMarshaler{
+			m: &fakeMarshaler{
 				err: errors.New("some marshal err"),
 				b:   []byte{5, 6, 7},
 			},
@@ -431,9 +432,25 @@ func TestMarshalerEncoding(t *testing.T) {
 			want:    nil,
 			wantErr: errors.New("some marshal err"),
 		},
+		{
+			name: "Marshaler that fails with RequiredNotSetError",
+			m: &msgWithFakeMarshaler{
+				M: &fakeMarshaler{
+					err: &RequiredNotSetError{},
+					b:   []byte{5, 6, 7},
+				},
+			},
+			// Since there's an error that can be continued after,
+			// the buffer should be written.
+			want: []byte{
+				10, 3, // for &msgWithFakeMarshaler
+				5, 6, 7, // for &fakeMarshaler
+			},
+			wantErr: &RequiredNotSetError{},
+		},
 		{
 			name: "Marshaler that succeeds",
-			m: fakeMarshaler{
+			m: &fakeMarshaler{
 				b: []byte{0, 1, 2, 3, 4, 127, 255},
 			},
 			want:    []byte{0, 1, 2, 3, 4, 127, 255},
@@ -443,6 +460,10 @@ func TestMarshalerEncoding(t *testing.T) {
 	for _, test := range tests {
 		b := NewBuffer(nil)
 		err := b.Marshal(test.m)
+		if _, ok := err.(*RequiredNotSetError); ok {
+			// We're not in package proto, so we can only assert the type in this case.
+			err = &RequiredNotSetError{}
+		}
 		if !reflect.DeepEqual(test.wantErr, err) {
 			t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr)
 		}
@@ -1252,7 +1273,8 @@ func TestProto1RepeatedGroup(t *testing.T) {
 	}
 
 	o := old()
-	if err := o.Marshal(pb); err != ErrRepeatedHasNil {
+	err := o.Marshal(pb)
+	if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") {
 		t.Fatalf("unexpected or no error when marshaling: %v", err)
 	}
 }
@@ -1441,6 +1463,17 @@ func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) {
 	}
 }
 
+func TestSetDefaultWithRepeatedNonMessage(t *testing.T) {
+	m := &MyMessage{
+		Pet: []string{"turtle", "wombat"},
+	}
+	expected := Clone(m)
+	SetDefaults(m)
+	if !Equal(m, expected) {
+		t.Errorf("\n got %v\nwant %v", m, expected)
+	}
+}
+
 func TestMaximumTagNumber(t *testing.T) {
 	m := &MaxTag{
 		LastField: String("natural goat essence"),
@@ -1913,6 +1946,83 @@ func TestMapFieldRoundTrips(t *testing.T) {
 	}
 }
 
+func TestMapFieldWithNil(t *testing.T) {
+	m := &MessageWithMap{
+		MsgMapping: map[int64]*FloatingPoint{
+			1: nil,
+		},
+	}
+	b, err := Marshal(m)
+	if err == nil {
+		t.Fatalf("Marshal of bad map should have failed, got these bytes: %v", b)
+	}
+}
+
+func TestOneof(t *testing.T) {
+	m := &Communique{}
+	b, err := Marshal(m)
+	if err != nil {
+		t.Fatalf("Marshal of empty message with oneof: %v", err)
+	}
+	if len(b) != 0 {
+		t.Errorf("Marshal of empty message yielded too many bytes: %v", b)
+	}
+
+	m = &Communique{
+		Union: &Communique_Name{"Barry"},
+	}
+
+	// Round-trip.
+	b, err = Marshal(m)
+	if err != nil {
+		t.Fatalf("Marshal of message with oneof: %v", err)
+	}
+	if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5)
+		t.Errorf("Incorrect marshal of message with oneof: %v", b)
+	}
+	m.Reset()
+	if err := Unmarshal(b, m); err != nil {
+		t.Fatalf("Unmarshal of message with oneof: %v", err)
+	}
+	if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" {
+		t.Errorf("After round trip, Union = %+v", m.Union)
+	}
+	if name := m.GetName(); name != "Barry" {
+		t.Errorf("After round trip, GetName = %q, want %q", name, "Barry")
+	}
+
+	// Let's try with a message in the oneof.
+	m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}}
+	b, err = Marshal(m)
+	if err != nil {
+		t.Fatalf("Marshal of message with oneof set to message: %v", err)
+	}
+	if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16)
+		t.Errorf("Incorrect marshal of message with oneof set to message: %v", b)
+	}
+	m.Reset()
+	if err := Unmarshal(b, m); err != nil {
+		t.Fatalf("Unmarshal of message with oneof set to message: %v", err)
+	}
+	ss, ok := m.Union.(*Communique_Msg)
+	if !ok || ss.Msg.GetStringField() != "deep deep string" {
+		t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union)
+	}
+}
+
+func TestInefficientPackedBool(t *testing.T) {
+	// https://github.com/golang/protobuf/issues/76
+	inp := []byte{
+		0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes
+		// Usually a bool should take a single byte,
+		// but it is permitted to be any varint.
+		0xb9, 0x30,
+	}
+	if err := Unmarshal(inp, new(MoreRepeated)); err != nil {
+		t.Error(err)
+	}
+}
+
 // Benchmarks
 
 func testMsg() *GoTest {

+ 33 - 7
Godeps/_workspace/src/github.com/golang/protobuf/proto/clone.go

@@ -30,7 +30,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Protocol buffer deep copy and merge.
-// TODO: MessageSet and RawMessage.
+// TODO: RawMessage.
 
 package proto
 
@@ -75,12 +75,13 @@ func Merge(dst, src Message) {
 }
 
 func mergeStruct(out, in reflect.Value) {
+	sprop := GetProperties(in.Type())
 	for i := 0; i < in.NumField(); i++ {
 		f := in.Type().Field(i)
 		if strings.HasPrefix(f.Name, "XXX_") {
 			continue
 		}
-		mergeAny(out.Field(i), in.Field(i))
+		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
 	}
 
 	if emIn, ok := in.Addr().Interface().(extendableProto); ok {
@@ -98,7 +99,10 @@ func mergeStruct(out, in reflect.Value) {
 	}
 }
 
-func mergeAny(out, in reflect.Value) {
+// mergeAny performs a merge between two values of the same type.
+// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
+// prop is set if this is a struct field (it may be nil).
+func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
 	if in.Type() == protoMessageType {
 		if !in.IsNil() {
 			if out.IsNil() {
@@ -112,7 +116,21 @@ func mergeAny(out, in reflect.Value) {
 	switch in.Kind() {
 	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
 		reflect.String, reflect.Uint32, reflect.Uint64:
+		if !viaPtr && isProto3Zero(in) {
+			return
+		}
 		out.Set(in)
+	case reflect.Interface:
+		// Probably a oneof field; copy non-nil values.
+		if in.IsNil() {
+			return
+		}
+		// Allocate destination if it is not set, or set to a different type.
+		// Otherwise we will merge as normal.
+		if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
+			out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
+		}
+		mergeAny(out.Elem(), in.Elem(), false, nil)
 	case reflect.Map:
 		if in.Len() == 0 {
 			return
@@ -127,7 +145,7 @@ func mergeAny(out, in reflect.Value) {
 			switch elemKind {
 			case reflect.Ptr:
 				val = reflect.New(in.Type().Elem().Elem())
-				mergeAny(val, in.MapIndex(key))
+				mergeAny(val, in.MapIndex(key), false, nil)
 			case reflect.Slice:
 				val = in.MapIndex(key)
 				val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
@@ -143,13 +161,21 @@ func mergeAny(out, in reflect.Value) {
 		if out.IsNil() {
 			out.Set(reflect.New(in.Elem().Type()))
 		}
-		mergeAny(out.Elem(), in.Elem())
+		mergeAny(out.Elem(), in.Elem(), true, nil)
 	case reflect.Slice:
 		if in.IsNil() {
 			return
 		}
 		if in.Type().Elem().Kind() == reflect.Uint8 {
 			// []byte is a scalar bytes field, not a repeated field.
+
+			// Edge case: if this is in a proto3 message, a zero length
+			// bytes field is considered the zero value, and should not
+			// be merged.
+			if prop != nil && prop.proto3 && in.Len() == 0 {
+				return
+			}
+
 			// Make a deep copy.
 			// Append to []byte{} instead of []byte(nil) so that we never end up
 			// with a nil result.
@@ -167,7 +193,7 @@ func mergeAny(out, in reflect.Value) {
 		default:
 			for i := 0; i < n; i++ {
 				x := reflect.Indirect(reflect.New(in.Type().Elem()))
-				mergeAny(x, in.Index(i))
+				mergeAny(x, in.Index(i), false, nil)
 				out.Set(reflect.Append(out, x))
 			}
 		}
@@ -184,7 +210,7 @@ func mergeExtension(out, in map[int32]Extension) {
 		eOut := Extension{desc: eIn.desc}
 		if eIn.value != nil {
 			v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
-			mergeAny(v, reflect.ValueOf(eIn.value))
+			mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
 			eOut.value = v.Interface()
 		}
 		if eIn.enc != nil {

+ 41 - 1
Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go

@@ -36,7 +36,8 @@ import (
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
 
-	pb "./testdata"
+	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
+	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 var cloneTestMessage = &pb.MyMessage{
@@ -214,6 +215,45 @@ var mergeTests = []struct {
 			ByteMapping: map[bool][]byte{true: []byte("wowsa")},
 		},
 	},
+	// proto3 shouldn't merge zero values,
+	// in the same way that proto2 shouldn't merge nils.
+	{
+		src: &proto3pb.Message{
+			Name: "Aaron",
+			Data: []byte(""), // zero value, but not nil
+		},
+		dst: &proto3pb.Message{
+			HeightInCm: 176,
+			Data:       []byte("texas!"),
+		},
+		want: &proto3pb.Message{
+			Name:       "Aaron",
+			HeightInCm: 176,
+			Data:       []byte("texas!"),
+		},
+	},
+	// Oneof fields should merge by assignment.
+	{
+		src: &pb.Communique{
+			Union: &pb.Communique_Number{41},
+		},
+		dst: &pb.Communique{
+			Union: &pb.Communique_Name{"Bobby Tables"},
+		},
+		want: &pb.Communique{
+			Union: &pb.Communique_Number{41},
+		},
+	},
+	// Oneof nil is the same as not set.
+	{
+		src: &pb.Communique{},
+		dst: &pb.Communique{
+			Union: &pb.Communique_Name{"Bobby Tables"},
+		},
+		want: &pb.Communique{
+			Union: &pb.Communique_Name{"Bobby Tables"},
+		},
+	},
 }
 
 func TestMerge(t *testing.T) {

+ 49 - 3
Godeps/_workspace/src/github.com/golang/protobuf/proto/decode.go

@@ -46,6 +46,10 @@ import (
 // errOverflow is returned when an integer is too large to be represented.
 var errOverflow = errors.New("proto: integer overflow")
 
+// ErrInternalBadWireType is returned by generated code when an incorrect
+// wire type is encountered. It does not get returned to user code.
+var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
+
 // The fundamental decoders that interpret bytes on the wire.
 // Those that take integer types all return uint64 and are
 // therefore of type valueDecoder.
@@ -314,6 +318,24 @@ func UnmarshalMerge(buf []byte, pb Message) error {
 	return NewBuffer(buf).Unmarshal(pb)
 }
 
+// DecodeMessage reads a count-delimited message from the Buffer.
+func (p *Buffer) DecodeMessage(pb Message) error {
+	enc, err := p.DecodeRawBytes(false)
+	if err != nil {
+		return err
+	}
+	return NewBuffer(enc).Unmarshal(pb)
+}
+
+// DecodeGroup reads a tag-delimited group from the Buffer.
+func (p *Buffer) DecodeGroup(pb Message) error {
+	typ, base, err := getbase(pb)
+	if err != nil {
+		return err
+	}
+	return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+}
+
 // Unmarshal parses the protocol buffer representation in the
 // Buffer and places the decoded result in pb.  If the struct
 // underlying pb does not match the data in the buffer, the results can be
@@ -377,6 +399,20 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group
 					continue
 				}
 			}
+			// Maybe it's a oneof?
+			if prop.oneofUnmarshaler != nil {
+				m := structPointer_Interface(base, st).(Message)
+				// First return value indicates whether tag is a oneof field.
+				ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
+				if err == ErrInternalBadWireType {
+					// Map the error to something more descriptive.
+					// Do the formatting here to save generated code space.
+					err = fmt.Errorf("bad wiretype for oneof field in %T", m)
+				}
+				if ok {
+					continue
+				}
+			}
 			err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
 			continue
 		}
@@ -561,9 +597,13 @@ func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error
 		return err
 	}
 	nb := int(nn) // number of bytes of encoded bools
+	fin := o.index + nb
+	if fin < o.index {
+		return errOverflow
+	}
 
 	y := *v
-	for i := 0; i < nb; i++ {
+	for o.index < fin {
 		u, err := p.valDec(o)
 		if err != nil {
 			return err
@@ -675,7 +715,7 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
 	oi := o.index       // index at the end of this map entry
 	o.index -= len(raw) // move buffer back to start of map entry
 
-	mptr := structPointer_Map(base, p.field, p.mtype) // *map[K]V
+	mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
 	if mptr.Elem().IsNil() {
 		mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
 	}
@@ -727,8 +767,14 @@ func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
 			return fmt.Errorf("proto: bad map data tag %d", raw[0])
 		}
 	}
+	keyelem, valelem := keyptr.Elem(), valptr.Elem()
+	if !keyelem.IsValid() || !valelem.IsValid() {
+		// We did not decode the key or the value in the map entry.
+		// Either way, it's an invalid map entry.
+		return fmt.Errorf("proto: bad map data: missing key/val")
+	}
 
-	v.SetMapIndex(keyptr.Elem(), valptr.Elem())
+	v.SetMapIndex(keyelem, valelem)
 	return nil
 }
 

+ 65 - 23
Godeps/_workspace/src/github.com/golang/protobuf/proto/encode.go

@@ -60,9 +60,9 @@ func (e *RequiredNotSetError) Error() string {
 }
 
 var (
-	// ErrRepeatedHasNil is the error returned if Marshal is called with
+	// errRepeatedHasNil is the error returned if Marshal is called with
 	// a struct with a repeated field containing a nil element.
-	ErrRepeatedHasNil = errors.New("proto: repeated field has nil element")
+	errRepeatedHasNil = errors.New("proto: repeated field has nil element")
 
 	// ErrNil is the error returned if Marshal is called with nil.
 	ErrNil = errors.New("proto: Marshal called with nil")
@@ -105,6 +105,11 @@ func (p *Buffer) EncodeVarint(x uint64) error {
 	return nil
 }
 
+// SizeVarint returns the varint encoding size of an integer.
+func SizeVarint(x uint64) int {
+	return sizeVarint(x)
+}
+
 func sizeVarint(x uint64) (n int) {
 	for {
 		n++
@@ -228,6 +233,20 @@ func Marshal(pb Message) ([]byte, error) {
 	return p.buf, err
 }
 
+// EncodeMessage writes the protocol buffer to the Buffer,
+// prefixed by a varint-encoded length.
+func (p *Buffer) EncodeMessage(pb Message) error {
+	t, base, err := getbase(pb)
+	if structPointer_IsNil(base) {
+		return ErrNil
+	}
+	if err == nil {
+		var state errorState
+		err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
+	}
+	return err
+}
+
 // Marshal takes the protocol buffer
 // and encodes it into the wire format, writing the result to the
 // Buffer.
@@ -318,7 +337,7 @@ func size_bool(p *Properties, base structPointer) int {
 
 func size_proto3_bool(p *Properties, base structPointer) int {
 	v := *structPointer_BoolVal(base, p.field)
-	if !v {
+	if !v && !p.oneof {
 		return 0
 	}
 	return len(p.tagcode) + 1 // each bool takes exactly one byte
@@ -361,7 +380,7 @@ func size_int32(p *Properties, base structPointer) (n int) {
 func size_proto3_int32(p *Properties, base structPointer) (n int) {
 	v := structPointer_Word32Val(base, p.field)
 	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
-	if x == 0 {
+	if x == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -407,7 +426,7 @@ func size_uint32(p *Properties, base structPointer) (n int) {
 func size_proto3_uint32(p *Properties, base structPointer) (n int) {
 	v := structPointer_Word32Val(base, p.field)
 	x := word32Val_Get(v)
-	if x == 0 {
+	if x == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -452,7 +471,7 @@ func size_int64(p *Properties, base structPointer) (n int) {
 func size_proto3_int64(p *Properties, base structPointer) (n int) {
 	v := structPointer_Word64Val(base, p.field)
 	x := word64Val_Get(v)
-	if x == 0 {
+	if x == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -495,7 +514,7 @@ func size_string(p *Properties, base structPointer) (n int) {
 
 func size_proto3_string(p *Properties, base structPointer) (n int) {
 	v := *structPointer_StringVal(base, p.field)
-	if v == "" {
+	if v == "" && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -529,7 +548,7 @@ func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
 		}
 		o.buf = append(o.buf, p.tagcode...)
 		o.EncodeRawBytes(data)
-		return nil
+		return state.err
 	}
 
 	o.buf = append(o.buf, p.tagcode...)
@@ -667,7 +686,7 @@ func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error
 
 func size_slice_byte(p *Properties, base structPointer) (n int) {
 	s := *structPointer_Bytes(base, p.field)
-	if s == nil {
+	if s == nil && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -677,7 +696,7 @@ func size_slice_byte(p *Properties, base structPointer) (n int) {
 
 func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
 	s := *structPointer_Bytes(base, p.field)
-	if len(s) == 0 {
+	if len(s) == 0 && !p.oneof {
 		return 0
 	}
 	n += len(p.tagcode)
@@ -939,7 +958,7 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
 	for i := 0; i < l; i++ {
 		structp := s.Index(i)
 		if structPointer_IsNil(structp) {
-			return ErrRepeatedHasNil
+			return errRepeatedHasNil
 		}
 
 		// Can the object marshal itself?
@@ -958,7 +977,7 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
 		err := o.enc_len_struct(p.sprop, structp, &state)
 		if err != nil && !state.shouldContinue(err, nil) {
 			if err == ErrNil {
-				return ErrRepeatedHasNil
+				return errRepeatedHasNil
 			}
 			return err
 		}
@@ -1001,7 +1020,7 @@ func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error
 	for i := 0; i < l; i++ {
 		b := s.Index(i)
 		if structPointer_IsNil(b) {
-			return ErrRepeatedHasNil
+			return errRepeatedHasNil
 		}
 
 		o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
@@ -1010,7 +1029,7 @@ func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error
 
 		if err != nil && !state.shouldContinue(err, nil) {
 			if err == ErrNil {
-				return ErrRepeatedHasNil
+				return errRepeatedHasNil
 			}
 			return err
 		}
@@ -1084,7 +1103,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
 			repeated MapFieldEntry map_field = N;
 	*/
 
-	v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
+	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
 	if v.Len() == 0 {
 		return nil
 	}
@@ -1101,11 +1120,15 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
 		return nil
 	}
 
-	keys := v.MapKeys()
-	sort.Sort(mapKeys(keys))
-	for _, key := range keys {
+	// Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
+	for _, key := range v.MapKeys() {
 		val := v.MapIndex(key)
 
+		// The only illegal map entry values are nil message pointers.
+		if val.Kind() == reflect.Ptr && val.IsNil() {
+			return errors.New("proto: map has nil element")
+		}
+
 		keycopy.Set(key)
 		valcopy.Set(val)
 
@@ -1118,7 +1141,7 @@ func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
 }
 
 func size_new_map(p *Properties, base structPointer) int {
-	v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V
+	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
 
 	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
 
@@ -1128,10 +1151,12 @@ func size_new_map(p *Properties, base structPointer) int {
 		keycopy.Set(key)
 		valcopy.Set(val)
 
-		// Tag codes are two bytes per map entry.
-		n += 2
-		n += p.mkeyprop.size(p.mkeyprop, keybase)
-		n += p.mvalprop.size(p.mvalprop, valbase)
+		// Tag codes for key and val are the responsibility of the sub-sizer.
+		keysize := p.mkeyprop.size(p.mkeyprop, keybase)
+		valsize := p.mvalprop.size(p.mvalprop, valbase)
+		entry := keysize + valsize
+		// Add on tag code and length of map entry itself.
+		n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
 	}
 	return n
 }
@@ -1184,6 +1209,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
 					if p.Required && state.err == nil {
 						state.err = &RequiredNotSetError{p.Name}
 					}
+				} else if err == errRepeatedHasNil {
+					// Give more context to nil values in repeated fields.
+					return errors.New("repeated field " + p.OrigName + " has nil element")
 				} else if !state.shouldContinue(err, p) {
 					return err
 				}
@@ -1191,6 +1219,14 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
 		}
 	}
 
+	// Do oneof fields.
+	if prop.oneofMarshaler != nil {
+		m := structPointer_Interface(base, prop.stype).(Message)
+		if err := prop.oneofMarshaler(m, o); err != nil {
+			return err
+		}
+	}
+
 	// Add unrecognized fields at the end.
 	if prop.unrecField.IsValid() {
 		v := *structPointer_Bytes(base, prop.unrecField)
@@ -1216,6 +1252,12 @@ func size_struct(prop *StructProperties, base structPointer) (n int) {
 		n += len(v)
 	}
 
+	// Factor in any oneof fields.
+	if prop.oneofSizer != nil {
+		m := structPointer_Interface(base, prop.stype).(Message)
+		n += prop.oneofSizer(m)
+	}
+
 	return
 }
 

+ 29 - 9
Godeps/_workspace/src/github.com/golang/protobuf/proto/equal.go

@@ -30,7 +30,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Protocol buffer comparison.
-// TODO: MessageSet.
 
 package proto
 
@@ -51,7 +50,9 @@ Equality is defined in this way:
     are equal, and extensions sets are equal.
   - Two set scalar fields are equal iff their values are equal.
     If the fields are of a floating-point type, remember that
-    NaN != x for all x, including NaN.
+    NaN != x for all x, including NaN. If the message is defined
+    in a proto3 .proto file, fields are not "set"; specifically,
+    zero length proto3 "bytes" fields are equal (nil == {}).
   - Two repeated fields are equal iff their lengths are the same,
     and their corresponding elements are equal (a "bytes" field,
     although represented by []byte, is not a repeated field)
@@ -89,6 +90,7 @@ func Equal(a, b Message) bool {
 
 // v1 and v2 are known to have the same type.
 func equalStruct(v1, v2 reflect.Value) bool {
+	sprop := GetProperties(v1.Type())
 	for i := 0; i < v1.NumField(); i++ {
 		f := v1.Type().Field(i)
 		if strings.HasPrefix(f.Name, "XXX_") {
@@ -114,7 +116,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
 			}
 			f1, f2 = f1.Elem(), f2.Elem()
 		}
-		if !equalAny(f1, f2) {
+		if !equalAny(f1, f2, sprop.Prop[i]) {
 			return false
 		}
 	}
@@ -141,7 +143,8 @@ func equalStruct(v1, v2 reflect.Value) bool {
 }
 
 // v1 and v2 are known to have the same type.
-func equalAny(v1, v2 reflect.Value) bool {
+// prop may be nil.
+func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
 	if v1.Type() == protoMessageType {
 		m1, _ := v1.Interface().(Message)
 		m2, _ := v2.Interface().(Message)
@@ -154,6 +157,17 @@ func equalAny(v1, v2 reflect.Value) bool {
 		return v1.Float() == v2.Float()
 	case reflect.Int32, reflect.Int64:
 		return v1.Int() == v2.Int()
+	case reflect.Interface:
+		// Probably a oneof field; compare the inner values.
+		n1, n2 := v1.IsNil(), v2.IsNil()
+		if n1 || n2 {
+			return n1 == n2
+		}
+		e1, e2 := v1.Elem(), v2.Elem()
+		if e1.Type() != e2.Type() {
+			return false
+		}
+		return equalAny(e1, e2, nil)
 	case reflect.Map:
 		if v1.Len() != v2.Len() {
 			return false
@@ -164,16 +178,22 @@ func equalAny(v1, v2 reflect.Value) bool {
 				// This key was not found in the second map.
 				return false
 			}
-			if !equalAny(v1.MapIndex(key), val2) {
+			if !equalAny(v1.MapIndex(key), val2, nil) {
 				return false
 			}
 		}
 		return true
 	case reflect.Ptr:
-		return equalAny(v1.Elem(), v2.Elem())
+		return equalAny(v1.Elem(), v2.Elem(), prop)
 	case reflect.Slice:
 		if v1.Type().Elem().Kind() == reflect.Uint8 {
 			// short circuit: []byte
+
+			// Edge case: if this is in a proto3 message, a zero length
+			// bytes field is considered the zero value.
+			if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
+				return true
+			}
 			if v1.IsNil() != v2.IsNil() {
 				return false
 			}
@@ -184,7 +204,7 @@ func equalAny(v1, v2 reflect.Value) bool {
 			return false
 		}
 		for i := 0; i < v1.Len(); i++ {
-			if !equalAny(v1.Index(i), v2.Index(i)) {
+			if !equalAny(v1.Index(i), v2.Index(i), prop) {
 				return false
 			}
 		}
@@ -219,7 +239,7 @@ func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
 
 		if m1 != nil && m2 != nil {
 			// Both are unencoded.
-			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) {
+			if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
 				return false
 			}
 			continue
@@ -247,7 +267,7 @@ func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bool {
 			log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
 			return false
 		}
-		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2)) {
+		if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
 			return false
 		}
 	}

+ 22 - 1
Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go

@@ -34,8 +34,9 @@ package proto_test
 import (
 	"testing"
 
-	pb "./testdata"
 	. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
+	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 // Four identical base messages.
@@ -131,6 +132,8 @@ var EqualTests = []struct {
 		&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
 		true,
 	},
+	// In proto3, []byte{} and []byte(nil) are equal.
+	{"proto3 bytes, empty vs nil", &proto3pb.Message{Data: []byte{}}, &proto3pb.Message{Data: nil}, true},
 
 	{"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false},
 	{"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true},
@@ -180,6 +183,24 @@ var EqualTests = []struct {
 		&pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}},
 		false,
 	},
+	{
+		"oneof same",
+		&pb.Communique{Union: &pb.Communique_Number{41}},
+		&pb.Communique{Union: &pb.Communique_Number{41}},
+		true,
+	},
+	{
+		"oneof one nil",
+		&pb.Communique{Union: &pb.Communique_Number{41}},
+		&pb.Communique{},
+		false,
+	},
+	{
+		"oneof different",
+		&pb.Communique{Union: &pb.Communique_Number{41}},
+		&pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}},
+		false,
+	},
 }
 
 func TestEqual(t *testing.T) {

+ 50 - 4
Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions.go

@@ -37,6 +37,7 @@ package proto
 
 import (
 	"errors"
+	"fmt"
 	"reflect"
 	"strconv"
 	"sync"
@@ -221,7 +222,7 @@ func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
 }
 
 // GetExtension parses and returns the given extension of pb.
-// If the extension is not present it returns ErrMissingExtension.
+// If the extension is not present and has no default value it returns ErrMissingExtension.
 func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
 	if err := checkExtensionTypes(pb, extension); err != nil {
 		return nil, err
@@ -230,8 +231,11 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
 	emap := pb.ExtensionMap()
 	e, ok := emap[extension.Field]
 	if !ok {
-		return nil, ErrMissingExtension
+		// defaultExtensionValue returns the default value or
+		// ErrMissingExtension if there is no default.
+		return defaultExtensionValue(extension)
 	}
+
 	if e.value != nil {
 		// Already decoded. Check the descriptor, though.
 		if e.desc != extension {
@@ -257,12 +261,46 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
 	return e.value, nil
 }
 
+// defaultExtensionValue returns the default value for extension.
+// If no default for an extension is defined ErrMissingExtension is returned.
+func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+	t := reflect.TypeOf(extension.ExtensionType)
+	props := extensionProperties(extension)
+
+	sf, _, err := fieldDefault(t, props)
+	if err != nil {
+		return nil, err
+	}
+
+	if sf == nil || sf.value == nil {
+		// There is no default value.
+		return nil, ErrMissingExtension
+	}
+
+	if t.Kind() != reflect.Ptr {
+		// We do not need to return a Ptr, we can directly return sf.value.
+		return sf.value, nil
+	}
+
+	// We need to return an interface{} that is a pointer to sf.value.
+	value := reflect.New(t).Elem()
+	value.Set(reflect.New(value.Type().Elem()))
+	if sf.kind == reflect.Int32 {
+		// We may have an int32 or an enum, but the underlying data is int32.
+		// Since we can't set an int32 into a non int32 reflect.value directly
+		// set it as a int32.
+		value.Elem().SetInt(int64(sf.value.(int32)))
+	} else {
+		value.Elem().Set(reflect.ValueOf(sf.value))
+	}
+	return value.Interface(), nil
+}
+
 // decodeExtension decodes an extension encoded in b.
 func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 	o := NewBuffer(b)
 
 	t := reflect.TypeOf(extension.ExtensionType)
-	rep := extension.repeated()
 
 	props := extensionProperties(extension)
 
@@ -284,7 +322,7 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 			return nil, err
 		}
 
-		if !rep || o.index >= len(o.buf) {
+		if o.index >= len(o.buf) {
 			break
 		}
 	}
@@ -321,6 +359,14 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
 	if typ != reflect.TypeOf(value) {
 		return errors.New("proto: bad extension value type")
 	}
+	// nil extension values need to be caught early, because the
+	// encoder can't distinguish an ErrNil due to a nil extension
+	// from an ErrNil due to a missing field. Extensions are
+	// always optional, so the encoder would just swallow the error
+	// and drop all the extensions from the encoded message.
+	if reflect.ValueOf(value).IsNil() {
+		return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
+	}
 
 	pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
 	return nil

+ 294 - 1
Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go

@@ -32,10 +32,13 @@
 package proto_test
 
 import (
+	"bytes"
+	"fmt"
+	"reflect"
 	"testing"
 
-	pb "./testdata"
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 func TestGetExtensionsWithMissingExtensions(t *testing.T) {
@@ -93,6 +96,143 @@ func TestGetExtensionStability(t *testing.T) {
 	}
 }
 
+func TestGetExtensionDefaults(t *testing.T) {
+	var setFloat64 float64 = 1
+	var setFloat32 float32 = 2
+	var setInt32 int32 = 3
+	var setInt64 int64 = 4
+	var setUint32 uint32 = 5
+	var setUint64 uint64 = 6
+	var setBool = true
+	var setBool2 = false
+	var setString = "Goodnight string"
+	var setBytes = []byte("Goodnight bytes")
+	var setEnum = pb.DefaultsMessage_TWO
+
+	type testcase struct {
+		ext  *proto.ExtensionDesc // Extension we are testing.
+		want interface{}          // Expected value of extension, or nil (meaning that GetExtension will fail).
+		def  interface{}          // Expected value of extension after ClearExtension().
+	}
+	tests := []testcase{
+		{pb.E_NoDefaultDouble, setFloat64, nil},
+		{pb.E_NoDefaultFloat, setFloat32, nil},
+		{pb.E_NoDefaultInt32, setInt32, nil},
+		{pb.E_NoDefaultInt64, setInt64, nil},
+		{pb.E_NoDefaultUint32, setUint32, nil},
+		{pb.E_NoDefaultUint64, setUint64, nil},
+		{pb.E_NoDefaultSint32, setInt32, nil},
+		{pb.E_NoDefaultSint64, setInt64, nil},
+		{pb.E_NoDefaultFixed32, setUint32, nil},
+		{pb.E_NoDefaultFixed64, setUint64, nil},
+		{pb.E_NoDefaultSfixed32, setInt32, nil},
+		{pb.E_NoDefaultSfixed64, setInt64, nil},
+		{pb.E_NoDefaultBool, setBool, nil},
+		{pb.E_NoDefaultBool, setBool2, nil},
+		{pb.E_NoDefaultString, setString, nil},
+		{pb.E_NoDefaultBytes, setBytes, nil},
+		{pb.E_NoDefaultEnum, setEnum, nil},
+		{pb.E_DefaultDouble, setFloat64, float64(3.1415)},
+		{pb.E_DefaultFloat, setFloat32, float32(3.14)},
+		{pb.E_DefaultInt32, setInt32, int32(42)},
+		{pb.E_DefaultInt64, setInt64, int64(43)},
+		{pb.E_DefaultUint32, setUint32, uint32(44)},
+		{pb.E_DefaultUint64, setUint64, uint64(45)},
+		{pb.E_DefaultSint32, setInt32, int32(46)},
+		{pb.E_DefaultSint64, setInt64, int64(47)},
+		{pb.E_DefaultFixed32, setUint32, uint32(48)},
+		{pb.E_DefaultFixed64, setUint64, uint64(49)},
+		{pb.E_DefaultSfixed32, setInt32, int32(50)},
+		{pb.E_DefaultSfixed64, setInt64, int64(51)},
+		{pb.E_DefaultBool, setBool, true},
+		{pb.E_DefaultBool, setBool2, true},
+		{pb.E_DefaultString, setString, "Hello, string"},
+		{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
+		{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
+	}
+
+	checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error {
+		val, err := proto.GetExtension(msg, test.ext)
+		if err != nil {
+			if valWant != nil {
+				return fmt.Errorf("GetExtension(): %s", err)
+			}
+			if want := proto.ErrMissingExtension; err != want {
+				return fmt.Errorf("Unexpected error: got %v, want %v", err, want)
+			}
+			return nil
+		}
+
+		// All proto2 extension values are either a pointer to a value or a slice of values.
+		ty := reflect.TypeOf(val)
+		tyWant := reflect.TypeOf(test.ext.ExtensionType)
+		if got, want := ty, tyWant; got != want {
+			return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want)
+		}
+		tye := ty.Elem()
+		tyeWant := tyWant.Elem()
+		if got, want := tye, tyeWant; got != want {
+			return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want)
+		}
+
+		// Check the name of the type of the value.
+		// If it is an enum it will be type int32 with the name of the enum.
+		if got, want := tye.Name(), tye.Name(); got != want {
+			return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want)
+		}
+
+		// Check that value is what we expect.
+		// If we have a pointer in val, get the value it points to.
+		valExp := val
+		if ty.Kind() == reflect.Ptr {
+			valExp = reflect.ValueOf(val).Elem().Interface()
+		}
+		if got, want := valExp, valWant; !reflect.DeepEqual(got, want) {
+			return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want)
+		}
+
+		return nil
+	}
+
+	setTo := func(test testcase) interface{} {
+		setTo := reflect.ValueOf(test.want)
+		if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr {
+			setTo = reflect.New(typ).Elem()
+			setTo.Set(reflect.New(setTo.Type().Elem()))
+			setTo.Elem().Set(reflect.ValueOf(test.want))
+		}
+		return setTo.Interface()
+	}
+
+	for _, test := range tests {
+		msg := &pb.DefaultsMessage{}
+		name := test.ext.Name
+
+		// Check the initial value.
+		if err := checkVal(test, msg, test.def); err != nil {
+			t.Errorf("%s: %v", name, err)
+		}
+
+		// Set the per-type value and check value.
+		name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want)
+		if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil {
+			t.Errorf("%s: SetExtension(): %v", name, err)
+			continue
+		}
+		if err := checkVal(test, msg, test.want); err != nil {
+			t.Errorf("%s: %v", name, err)
+			continue
+		}
+
+		// Set and check the value.
+		name += " (cleared)"
+		proto.ClearExtension(msg, test.ext)
+		if err := checkVal(test, msg, test.def); err != nil {
+			t.Errorf("%s: %v", name, err)
+		}
+	}
+}
+
 func TestExtensionsRoundTrip(t *testing.T) {
 	msg := &pb.MyMessage{}
 	ext1 := &pb.Ext{
@@ -135,3 +275,156 @@ func TestExtensionsRoundTrip(t *testing.T) {
 		t.Error("expected some sort of type mismatch error, got nil")
 	}
 }
+
+func TestNilExtension(t *testing.T) {
+	msg := &pb.MyMessage{
+		Count: proto.Int32(1),
+	}
+	if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil {
+		t.Fatal(err)
+	}
+	if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil {
+		t.Error("expected SetExtension to fail due to a nil extension")
+	} else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want {
+		t.Errorf("expected error %v, got %v", want, err)
+	}
+	// Note: if the behavior of Marshal is ever changed to ignore nil extensions, update
+	// this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal.
+}
+
+func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
+	// Add a repeated extension to the result.
+	tests := []struct {
+		name string
+		ext  []*pb.ComplexExtension
+	}{
+		{
+			"two fields",
+			[]*pb.ComplexExtension{
+				{First: proto.Int32(7)},
+				{Second: proto.Int32(11)},
+			},
+		},
+		{
+			"repeated field",
+			[]*pb.ComplexExtension{
+				{Third: []int32{1000}},
+				{Third: []int32{2000}},
+			},
+		},
+		{
+			"two fields and repeated field",
+			[]*pb.ComplexExtension{
+				{Third: []int32{1000}},
+				{First: proto.Int32(9)},
+				{Second: proto.Int32(21)},
+				{Third: []int32{2000}},
+			},
+		},
+	}
+	for _, test := range tests {
+		// Marshal message with a repeated extension.
+		msg1 := new(pb.OtherMessage)
+		err := proto.SetExtension(msg1, pb.E_RComplex, test.ext)
+		if err != nil {
+			t.Fatalf("[%s] Error setting extension: %v", test.name, err)
+		}
+		b, err := proto.Marshal(msg1)
+		if err != nil {
+			t.Fatalf("[%s] Error marshaling message: %v", test.name, err)
+		}
+
+		// Unmarshal and read the merged proto.
+		msg2 := new(pb.OtherMessage)
+		err = proto.Unmarshal(b, msg2)
+		if err != nil {
+			t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
+		}
+		e, err := proto.GetExtension(msg2, pb.E_RComplex)
+		if err != nil {
+			t.Fatalf("[%s] Error getting extension: %v", test.name, err)
+		}
+		ext := e.([]*pb.ComplexExtension)
+		if ext == nil {
+			t.Fatalf("[%s] Invalid extension", test.name)
+		}
+		if !reflect.DeepEqual(ext, test.ext) {
+			t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext)
+		}
+	}
+}
+
+func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
+	// We may see multiple instances of the same extension in the wire
+	// format. For example, the proto compiler may encode custom options in
+	// this way. Here, we verify that we merge the extensions together.
+	tests := []struct {
+		name string
+		ext  []*pb.ComplexExtension
+	}{
+		{
+			"two fields",
+			[]*pb.ComplexExtension{
+				{First: proto.Int32(7)},
+				{Second: proto.Int32(11)},
+			},
+		},
+		{
+			"repeated field",
+			[]*pb.ComplexExtension{
+				{Third: []int32{1000}},
+				{Third: []int32{2000}},
+			},
+		},
+		{
+			"two fields and repeated field",
+			[]*pb.ComplexExtension{
+				{Third: []int32{1000}},
+				{First: proto.Int32(9)},
+				{Second: proto.Int32(21)},
+				{Third: []int32{2000}},
+			},
+		},
+	}
+	for _, test := range tests {
+		var buf bytes.Buffer
+		var want pb.ComplexExtension
+
+		// Generate a serialized representation of a repeated extension
+		// by catenating bytes together.
+		for i, e := range test.ext {
+			// Merge to create the wanted proto.
+			proto.Merge(&want, e)
+
+			// serialize the message
+			msg := new(pb.OtherMessage)
+			err := proto.SetExtension(msg, pb.E_Complex, e)
+			if err != nil {
+				t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err)
+			}
+			b, err := proto.Marshal(msg)
+			if err != nil {
+				t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err)
+			}
+			buf.Write(b)
+		}
+
+		// Unmarshal and read the merged proto.
+		msg2 := new(pb.OtherMessage)
+		err := proto.Unmarshal(buf.Bytes(), msg2)
+		if err != nil {
+			t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
+		}
+		e, err := proto.GetExtension(msg2, pb.E_Complex)
+		if err != nil {
+			t.Fatalf("[%s] Error getting extension: %v", test.name, err)
+		}
+		ext := e.(*pb.ComplexExtension)
+		if ext == nil {
+			t.Fatalf("[%s] Invalid extension", test.name)
+		}
+		if !reflect.DeepEqual(*ext, want) {
+			t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want)
+		}
+	}
+}

+ 396 - 261
Godeps/_workspace/src/github.com/golang/protobuf/proto/lib.go

@@ -30,179 +30,237 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /*
-	Package proto converts data structures to and from the wire format of
-	protocol buffers.  It works in concert with the Go source code generated
-	for .proto files by the protocol compiler.
-
-	A summary of the properties of the protocol buffer interface
-	for a protocol buffer variable v:
-
-	  - Names are turned from camel_case to CamelCase for export.
-	  - There are no methods on v to set fields; just treat
-		them as structure fields.
-	  - There are getters that return a field's value if set,
-		and return the field's default value if unset.
-		The getters work even if the receiver is a nil message.
-	  - The zero value for a struct is its correct initialization state.
-		All desired fields must be set before marshaling.
-	  - A Reset() method will restore a protobuf struct to its zero state.
-	  - Non-repeated fields are pointers to the values; nil means unset.
-		That is, optional or required field int32 f becomes F *int32.
-	  - Repeated fields are slices.
-	  - Helper functions are available to aid the setting of fields.
-		msg.Foo = proto.String("hello") // set field
-	  - Constants are defined to hold the default values of all fields that
-		have them.  They have the form Default_StructName_FieldName.
-		Because the getter methods handle defaulted values,
-		direct use of these constants should be rare.
-	  - Enums are given type names and maps from names to values.
-		Enum values are prefixed by the enclosing message's name, or by the
-		enum's type name if it is a top-level enum. Enum types have a String
-		method, and a Enum method to assist in message construction.
-	  - Nested messages, groups and enums have type names prefixed with the name of
-	  	the surrounding message type.
-	  - Extensions are given descriptor names that start with E_,
-		followed by an underscore-delimited list of the nested messages
-		that contain it (if any) followed by the CamelCased name of the
-		extension field itself.  HasExtension, ClearExtension, GetExtension
-		and SetExtension are functions for manipulating extensions.
-	  - Marshal and Unmarshal are functions to encode and decode the wire format.
-
-	The simplest way to describe this is to see an example.
-	Given file test.proto, containing
-
-		package example;
-
-		enum FOO { X = 17; }
-
-		message Test {
-		  required string label = 1;
-		  optional int32 type = 2 [default=77];
-		  repeated int64 reps = 3;
-		  optional group OptionalGroup = 4 {
-		    required string RequiredField = 5;
-		  }
-		}
-
-	The resulting file, test.pb.go, is:
-
-		package example
-
-		import proto "github.com/golang/protobuf/proto"
-		import math "math"
-
-		type FOO int32
-		const (
-			FOO_X FOO = 17
-		)
-		var FOO_name = map[int32]string{
-			17: "X",
-		}
-		var FOO_value = map[string]int32{
-			"X": 17,
-		}
-
-		func (x FOO) Enum() *FOO {
-			p := new(FOO)
-			*p = x
-			return p
-		}
-		func (x FOO) String() string {
-			return proto.EnumName(FOO_name, int32(x))
-		}
-		func (x *FOO) UnmarshalJSON(data []byte) error {
-			value, err := proto.UnmarshalJSONEnum(FOO_value, data)
-			if err != nil {
-				return err
-			}
-			*x = FOO(value)
-			return nil
+Package proto converts data structures to and from the wire format of
+protocol buffers.  It works in concert with the Go source code generated
+for .proto files by the protocol compiler.
+
+A summary of the properties of the protocol buffer interface
+for a protocol buffer variable v:
+
+  - Names are turned from camel_case to CamelCase for export.
+  - There are no methods on v to set fields; just treat
+	them as structure fields.
+  - There are getters that return a field's value if set,
+	and return the field's default value if unset.
+	The getters work even if the receiver is a nil message.
+  - The zero value for a struct is its correct initialization state.
+	All desired fields must be set before marshaling.
+  - A Reset() method will restore a protobuf struct to its zero state.
+  - Non-repeated fields are pointers to the values; nil means unset.
+	That is, optional or required field int32 f becomes F *int32.
+  - Repeated fields are slices.
+  - Helper functions are available to aid the setting of fields.
+	msg.Foo = proto.String("hello") // set field
+  - Constants are defined to hold the default values of all fields that
+	have them.  They have the form Default_StructName_FieldName.
+	Because the getter methods handle defaulted values,
+	direct use of these constants should be rare.
+  - Enums are given type names and maps from names to values.
+	Enum values are prefixed by the enclosing message's name, or by the
+	enum's type name if it is a top-level enum. Enum types have a String
+	method, and a Enum method to assist in message construction.
+  - Nested messages, groups and enums have type names prefixed with the name of
+	the surrounding message type.
+  - Extensions are given descriptor names that start with E_,
+	followed by an underscore-delimited list of the nested messages
+	that contain it (if any) followed by the CamelCased name of the
+	extension field itself.  HasExtension, ClearExtension, GetExtension
+	and SetExtension are functions for manipulating extensions.
+  - Oneof field sets are given a single field in their message,
+	with distinguished wrapper types for each possible field value.
+  - Marshal and Unmarshal are functions to encode and decode the wire format.
+
+When the .proto file specifies `syntax="proto3"`, there are some differences:
+
+  - Non-repeated fields of non-message type are values instead of pointers.
+  - Getters are only generated for message and oneof fields.
+  - Enum types do not get an Enum method.
+
+The simplest way to describe this is to see an example.
+Given file test.proto, containing
+
+	package example;
+
+	enum FOO { X = 17; }
+
+	message Test {
+	  required string label = 1;
+	  optional int32 type = 2 [default=77];
+	  repeated int64 reps = 3;
+	  optional group OptionalGroup = 4 {
+	    required string RequiredField = 5;
+	  }
+	  oneof union {
+	    int32 number = 6;
+	    string name = 7;
+	  }
+	}
+
+The resulting file, test.pb.go, is:
+
+	package example
+
+	import proto "github.com/golang/protobuf/proto"
+	import math "math"
+
+	type FOO int32
+	const (
+		FOO_X FOO = 17
+	)
+	var FOO_name = map[int32]string{
+		17: "X",
+	}
+	var FOO_value = map[string]int32{
+		"X": 17,
+	}
+
+	func (x FOO) Enum() *FOO {
+		p := new(FOO)
+		*p = x
+		return p
+	}
+	func (x FOO) String() string {
+		return proto.EnumName(FOO_name, int32(x))
+	}
+	func (x *FOO) UnmarshalJSON(data []byte) error {
+		value, err := proto.UnmarshalJSONEnum(FOO_value, data)
+		if err != nil {
+			return err
 		}
+		*x = FOO(value)
+		return nil
+	}
 
-		type Test struct {
-			Label            *string             `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
-			Type             *int32              `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
-			Reps             []int64             `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
-			Optionalgroup    *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
-			XXX_unrecognized []byte              `json:"-"`
+	type Test struct {
+		Label         *string             `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
+		Type          *int32              `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
+		Reps          []int64             `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
+		Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
+		// Types that are valid to be assigned to Union:
+		//	*Test_Number
+		//	*Test_Name
+		Union            isTest_Union `protobuf_oneof:"union"`
+		XXX_unrecognized []byte       `json:"-"`
+	}
+	func (m *Test) Reset()         { *m = Test{} }
+	func (m *Test) String() string { return proto.CompactTextString(m) }
+	func (*Test) ProtoMessage() {}
+
+	type isTest_Union interface {
+		isTest_Union()
+	}
+
+	type Test_Number struct {
+		Number int32 `protobuf:"varint,6,opt,name=number"`
+	}
+	type Test_Name struct {
+		Name string `protobuf:"bytes,7,opt,name=name"`
+	}
+
+	func (*Test_Number) isTest_Union() {}
+	func (*Test_Name) isTest_Union()   {}
+
+	func (m *Test) GetUnion() isTest_Union {
+		if m != nil {
+			return m.Union
 		}
-		func (m *Test) Reset()         { *m = Test{} }
-		func (m *Test) String() string { return proto.CompactTextString(m) }
-		func (*Test) ProtoMessage()    {}
-		const Default_Test_Type int32 = 77
+		return nil
+	}
+	const Default_Test_Type int32 = 77
 
-		func (m *Test) GetLabel() string {
-			if m != nil && m.Label != nil {
-				return *m.Label
-			}
-			return ""
+	func (m *Test) GetLabel() string {
+		if m != nil && m.Label != nil {
+			return *m.Label
 		}
+		return ""
+	}
 
-		func (m *Test) GetType() int32 {
-			if m != nil && m.Type != nil {
-				return *m.Type
-			}
-			return Default_Test_Type
+	func (m *Test) GetType() int32 {
+		if m != nil && m.Type != nil {
+			return *m.Type
 		}
+		return Default_Test_Type
+	}
 
-		func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
-			if m != nil {
-				return m.Optionalgroup
-			}
-			return nil
+	func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
+		if m != nil {
+			return m.Optionalgroup
 		}
+		return nil
+	}
+
+	type Test_OptionalGroup struct {
+		RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+	}
+	func (m *Test_OptionalGroup) Reset()         { *m = Test_OptionalGroup{} }
+	func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
 
-		type Test_OptionalGroup struct {
-			RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
+	func (m *Test_OptionalGroup) GetRequiredField() string {
+		if m != nil && m.RequiredField != nil {
+			return *m.RequiredField
 		}
-		func (m *Test_OptionalGroup) Reset()         { *m = Test_OptionalGroup{} }
-		func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
+		return ""
+	}
 
-		func (m *Test_OptionalGroup) GetRequiredField() string {
-			if m != nil && m.RequiredField != nil {
-				return *m.RequiredField
-			}
-			return ""
+	func (m *Test) GetNumber() int32 {
+		if x, ok := m.GetUnion().(*Test_Number); ok {
+			return x.Number
 		}
+		return 0
+	}
 
-		func init() {
-			proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+	func (m *Test) GetName() string {
+		if x, ok := m.GetUnion().(*Test_Name); ok {
+			return x.Name
 		}
+		return ""
+	}
 
-	To create and play with a Test object:
+	func init() {
+		proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
+	}
 
-		package main
+To create and play with a Test object:
 
-		import (
-			"log"
+	package main
 
-			"github.com/golang/protobuf/proto"
-			pb "./example.pb"
-		)
+	import (
+		"log"
 
-		func main() {
-			test := &pb.Test{
-				Label: proto.String("hello"),
-				Type:  proto.Int32(17),
-				Optionalgroup: &pb.Test_OptionalGroup{
-					RequiredField: proto.String("good bye"),
-				},
-			}
-			data, err := proto.Marshal(test)
-			if err != nil {
-				log.Fatal("marshaling error: ", err)
-			}
-			newTest := &pb.Test{}
-			err = proto.Unmarshal(data, newTest)
-			if err != nil {
-				log.Fatal("unmarshaling error: ", err)
-			}
-			// Now test and newTest contain the same data.
-			if test.GetLabel() != newTest.GetLabel() {
-				log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
-			}
-			// etc.
+		"github.com/golang/protobuf/proto"
+		pb "./example.pb"
+	)
+
+	func main() {
+		test := &pb.Test{
+			Label: proto.String("hello"),
+			Type:  proto.Int32(17),
+			Reps:  []int64{1, 2, 3},
+			Optionalgroup: &pb.Test_OptionalGroup{
+				RequiredField: proto.String("good bye"),
+			},
+			Union: &pb.Test_Name{"fred"},
+		}
+		data, err := proto.Marshal(test)
+		if err != nil {
+			log.Fatal("marshaling error: ", err)
+		}
+		newTest := &pb.Test{}
+		err = proto.Unmarshal(data, newTest)
+		if err != nil {
+			log.Fatal("unmarshaling error: ", err)
 		}
+		// Now test and newTest contain the same data.
+		if test.GetLabel() != newTest.GetLabel() {
+			log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
+		}
+		// Use a type switch to determine which oneof was set.
+		switch u := test.Union.(type) {
+		case *pb.Test_Number: // u.Number contains the number.
+		case *pb.Test_Name: // u.Name contains the string.
+		}
+		// etc.
+	}
 */
 package proto
 
@@ -211,6 +269,7 @@ import (
 	"fmt"
 	"log"
 	"reflect"
+	"sort"
 	"strconv"
 	"sync"
 )
@@ -385,13 +444,13 @@ func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32,
 
 // DebugPrint dumps the encoded data in b in a debugging format with a header
 // including the string s. Used in testing but made available for general debugging.
-func (o *Buffer) DebugPrint(s string, b []byte) {
+func (p *Buffer) DebugPrint(s string, b []byte) {
 	var u uint64
 
-	obuf := o.buf
-	index := o.index
-	o.buf = b
-	o.index = 0
+	obuf := p.buf
+	index := p.index
+	p.buf = b
+	p.index = 0
 	depth := 0
 
 	fmt.Printf("\n--- %s ---\n", s)
@@ -402,12 +461,12 @@ out:
 			fmt.Print("  ")
 		}
 
-		index := o.index
-		if index == len(o.buf) {
+		index := p.index
+		if index == len(p.buf) {
 			break
 		}
 
-		op, err := o.DecodeVarint()
+		op, err := p.DecodeVarint()
 		if err != nil {
 			fmt.Printf("%3d: fetching op err %v\n", index, err)
 			break out
@@ -424,7 +483,7 @@ out:
 		case WireBytes:
 			var r []byte
 
-			r, err = o.DecodeRawBytes(false)
+			r, err = p.DecodeRawBytes(false)
 			if err != nil {
 				break out
 			}
@@ -445,7 +504,7 @@ out:
 			fmt.Printf("\n")
 
 		case WireFixed32:
-			u, err = o.DecodeFixed32()
+			u, err = p.DecodeFixed32()
 			if err != nil {
 				fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
 				break out
@@ -453,16 +512,15 @@ out:
 			fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
 
 		case WireFixed64:
-			u, err = o.DecodeFixed64()
+			u, err = p.DecodeFixed64()
 			if err != nil {
 				fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
 				break out
 			}
 			fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
-			break
 
 		case WireVarint:
-			u, err = o.DecodeVarint()
+			u, err = p.DecodeVarint()
 			if err != nil {
 				fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
 				break out
@@ -470,30 +528,22 @@ out:
 			fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
 
 		case WireStartGroup:
-			if err != nil {
-				fmt.Printf("%3d: t=%3d start err %v\n", index, tag, err)
-				break out
-			}
 			fmt.Printf("%3d: t=%3d start\n", index, tag)
 			depth++
 
 		case WireEndGroup:
 			depth--
-			if err != nil {
-				fmt.Printf("%3d: t=%3d end err %v\n", index, tag, err)
-				break out
-			}
 			fmt.Printf("%3d: t=%3d end\n", index, tag)
 		}
 	}
 
 	if depth != 0 {
-		fmt.Printf("%3d: start-end not balanced %d\n", o.index, depth)
+		fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
 	}
 	fmt.Printf("\n")
 
-	o.buf = obuf
-	o.index = index
+	p.buf = obuf
+	p.index = index
 }
 
 // SetDefaults sets unset protocol buffer fields to their default values.
@@ -607,13 +657,15 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
 
 	for _, ni := range dm.nested {
 		f := v.Field(ni)
-		if f.IsNil() {
-			continue
-		}
-		// f is *T or []*T
-		if f.Kind() == reflect.Ptr {
+		// f is *T or []*T or map[T]*T
+		switch f.Kind() {
+		case reflect.Ptr:
+			if f.IsNil() {
+				continue
+			}
 			setDefaults(f, recur, zeros)
-		} else {
+
+		case reflect.Slice:
 			for i := 0; i < f.Len(); i++ {
 				e := f.Index(i)
 				if e.IsNil() {
@@ -621,6 +673,15 @@ func setDefaults(v reflect.Value, recur, zeros bool) {
 				}
 				setDefaults(e, recur, zeros)
 			}
+
+		case reflect.Map:
+			for _, k := range f.MapKeys() {
+				e := f.MapIndex(k)
+				if e.IsNil() {
+					continue
+				}
+				setDefaults(e, recur, zeros)
+			}
 		}
 	}
 }
@@ -646,10 +707,6 @@ type scalarField struct {
 	value interface{}  // the proto-declared default value, or nil
 }
 
-func ptrToStruct(t reflect.Type) bool {
-	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
-}
-
 // t is a struct type.
 func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 	sprop := GetProperties(t)
@@ -661,88 +718,118 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 		}
 		ft := t.Field(fi).Type
 
-		// nested messages
-		if ptrToStruct(ft) || (ft.Kind() == reflect.Slice && ptrToStruct(ft.Elem())) {
+		sf, nested, err := fieldDefault(ft, prop)
+		switch {
+		case err != nil:
+			log.Print(err)
+		case nested:
 			dm.nested = append(dm.nested, fi)
-			continue
+		case sf != nil:
+			sf.index = fi
+			dm.scalars = append(dm.scalars, *sf)
 		}
+	}
 
-		sf := scalarField{
-			index: fi,
-			kind:  ft.Elem().Kind(),
-		}
+	return dm
+}
 
-		// scalar fields without defaults
-		if !prop.HasDefault {
-			dm.scalars = append(dm.scalars, sf)
-			continue
+// fieldDefault returns the scalarField for field type ft.
+// sf will be nil if the field can not have a default.
+// nestedMessage will be true if this is a nested message.
+// Note that sf.index is not set on return.
+func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
+	var canHaveDefault bool
+	switch ft.Kind() {
+	case reflect.Ptr:
+		if ft.Elem().Kind() == reflect.Struct {
+			nestedMessage = true
+		} else {
+			canHaveDefault = true // proto2 scalar field
 		}
 
-		// a scalar field: either *T or []byte
+	case reflect.Slice:
 		switch ft.Elem().Kind() {
-		case reflect.Bool:
-			x, err := strconv.ParseBool(prop.Default)
-			if err != nil {
-				log.Printf("proto: bad default bool %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		case reflect.Float32:
-			x, err := strconv.ParseFloat(prop.Default, 32)
-			if err != nil {
-				log.Printf("proto: bad default float32 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = float32(x)
-		case reflect.Float64:
-			x, err := strconv.ParseFloat(prop.Default, 64)
-			if err != nil {
-				log.Printf("proto: bad default float64 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		case reflect.Int32:
-			x, err := strconv.ParseInt(prop.Default, 10, 32)
-			if err != nil {
-				log.Printf("proto: bad default int32 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = int32(x)
-		case reflect.Int64:
-			x, err := strconv.ParseInt(prop.Default, 10, 64)
-			if err != nil {
-				log.Printf("proto: bad default int64 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		case reflect.String:
-			sf.value = prop.Default
+		case reflect.Ptr:
+			nestedMessage = true // repeated message
 		case reflect.Uint8:
-			// []byte (not *uint8)
-			sf.value = []byte(prop.Default)
-		case reflect.Uint32:
-			x, err := strconv.ParseUint(prop.Default, 10, 32)
-			if err != nil {
-				log.Printf("proto: bad default uint32 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = uint32(x)
-		case reflect.Uint64:
-			x, err := strconv.ParseUint(prop.Default, 10, 64)
-			if err != nil {
-				log.Printf("proto: bad default uint64 %q: %v", prop.Default, err)
-				continue
-			}
-			sf.value = x
-		default:
-			log.Printf("proto: unhandled def kind %v", ft.Elem().Kind())
-			continue
+			canHaveDefault = true // bytes field
 		}
 
-		dm.scalars = append(dm.scalars, sf)
+	case reflect.Map:
+		if ft.Elem().Kind() == reflect.Ptr {
+			nestedMessage = true // map with message values
+		}
 	}
 
-	return dm
+	if !canHaveDefault {
+		if nestedMessage {
+			return nil, true, nil
+		}
+		return nil, false, nil
+	}
+
+	// We now know that ft is a pointer or slice.
+	sf = &scalarField{kind: ft.Elem().Kind()}
+
+	// scalar fields without defaults
+	if !prop.HasDefault {
+		return sf, false, nil
+	}
+
+	// a scalar field: either *T or []byte
+	switch ft.Elem().Kind() {
+	case reflect.Bool:
+		x, err := strconv.ParseBool(prop.Default)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	case reflect.Float32:
+		x, err := strconv.ParseFloat(prop.Default, 32)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
+		}
+		sf.value = float32(x)
+	case reflect.Float64:
+		x, err := strconv.ParseFloat(prop.Default, 64)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	case reflect.Int32:
+		x, err := strconv.ParseInt(prop.Default, 10, 32)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
+		}
+		sf.value = int32(x)
+	case reflect.Int64:
+		x, err := strconv.ParseInt(prop.Default, 10, 64)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	case reflect.String:
+		sf.value = prop.Default
+	case reflect.Uint8:
+		// []byte (not *uint8)
+		sf.value = []byte(prop.Default)
+	case reflect.Uint32:
+		x, err := strconv.ParseUint(prop.Default, 10, 32)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
+		}
+		sf.value = uint32(x)
+	case reflect.Uint64:
+		x, err := strconv.ParseUint(prop.Default, 10, 64)
+		if err != nil {
+			return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
+		}
+		sf.value = x
+	default:
+		return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
+	}
+
+	return sf, false, nil
 }
 
 // Map fields may have key types of non-float scalars, strings and enums.
@@ -750,10 +837,58 @@ func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
 // If this turns out to be inefficient we can always consider other options,
 // such as doing a Schwartzian transform.
 
-type mapKeys []reflect.Value
+func mapKeys(vs []reflect.Value) sort.Interface {
+	s := mapKeySorter{
+		vs: vs,
+		// default Less function: textual comparison
+		less: func(a, b reflect.Value) bool {
+			return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
+		},
+	}
+
+	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
+	// numeric keys are sorted numerically.
+	if len(vs) == 0 {
+		return s
+	}
+	switch vs[0].Kind() {
+	case reflect.Int32, reflect.Int64:
+		s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
+	case reflect.Uint32, reflect.Uint64:
+		s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+	}
+
+	return s
+}
+
+type mapKeySorter struct {
+	vs   []reflect.Value
+	less func(a, b reflect.Value) bool
+}
 
-func (s mapKeys) Len() int      { return len(s) }
-func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s mapKeys) Less(i, j int) bool {
-	return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
+func (s mapKeySorter) Len() int      { return len(s.vs) }
+func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
+func (s mapKeySorter) Less(i, j int) bool {
+	return s.less(s.vs[i], s.vs[j])
 }
+
+// isProto3Zero reports whether v is a zero proto3 value.
+func isProto3Zero(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint32, reflect.Uint64:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.String:
+		return v.String() == ""
+	}
+	return false
+}
+
+// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
+// to assert that that code is compatible with this version of the proto package.
+const ProtoPackageIsVersion1 = true

+ 17 - 24
Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set.go

@@ -44,11 +44,11 @@ import (
 	"sort"
 )
 
-// ErrNoMessageTypeId occurs when a protocol buffer does not have a message type ID.
+// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
 // A message type ID is required for storing a protocol buffer in a message set.
-var ErrNoMessageTypeId = errors.New("proto does not have a message type ID")
+var errNoMessageTypeID = errors.New("proto does not have a message type ID")
 
-// The first two types (_MessageSet_Item and MessageSet)
+// The first two types (_MessageSet_Item and messageSet)
 // model what the protocol compiler produces for the following protocol message:
 //   message MessageSet {
 //     repeated group Item = 1 {
@@ -58,27 +58,20 @@ var ErrNoMessageTypeId = errors.New("proto does not have a message type ID")
 //   }
 // That is the MessageSet wire format. We can't use a proto to generate these
 // because that would introduce a circular dependency between it and this package.
-//
-// When a proto1 proto has a field that looks like:
-//   optional message<MessageSet> info = 3;
-// the protocol compiler produces a field in the generated struct that looks like:
-//   Info *_proto_.MessageSet  `protobuf:"bytes,3,opt,name=info"`
-// The package is automatically inserted so there is no need for that proto file to
-// import this package.
 
 type _MessageSet_Item struct {
 	TypeId  *int32 `protobuf:"varint,2,req,name=type_id"`
 	Message []byte `protobuf:"bytes,3,req,name=message"`
 }
 
-type MessageSet struct {
+type messageSet struct {
 	Item             []*_MessageSet_Item `protobuf:"group,1,rep"`
 	XXX_unrecognized []byte
 	// TODO: caching?
 }
 
-// Make sure MessageSet is a Message.
-var _ Message = (*MessageSet)(nil)
+// Make sure messageSet is a Message.
+var _ Message = (*messageSet)(nil)
 
 // messageTypeIder is an interface satisfied by a protocol buffer type
 // that may be stored in a MessageSet.
@@ -86,7 +79,7 @@ type messageTypeIder interface {
 	MessageTypeId() int32
 }
 
-func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
+func (ms *messageSet) find(pb Message) *_MessageSet_Item {
 	mti, ok := pb.(messageTypeIder)
 	if !ok {
 		return nil
@@ -100,24 +93,24 @@ func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
 	return nil
 }
 
-func (ms *MessageSet) Has(pb Message) bool {
+func (ms *messageSet) Has(pb Message) bool {
 	if ms.find(pb) != nil {
 		return true
 	}
 	return false
 }
 
-func (ms *MessageSet) Unmarshal(pb Message) error {
+func (ms *messageSet) Unmarshal(pb Message) error {
 	if item := ms.find(pb); item != nil {
 		return Unmarshal(item.Message, pb)
 	}
 	if _, ok := pb.(messageTypeIder); !ok {
-		return ErrNoMessageTypeId
+		return errNoMessageTypeID
 	}
 	return nil // TODO: return error instead?
 }
 
-func (ms *MessageSet) Marshal(pb Message) error {
+func (ms *messageSet) Marshal(pb Message) error {
 	msg, err := Marshal(pb)
 	if err != nil {
 		return err
@@ -130,7 +123,7 @@ func (ms *MessageSet) Marshal(pb Message) error {
 
 	mti, ok := pb.(messageTypeIder)
 	if !ok {
-		return ErrNoMessageTypeId
+		return errNoMessageTypeID
 	}
 
 	mtid := mti.MessageTypeId()
@@ -141,9 +134,9 @@ func (ms *MessageSet) Marshal(pb Message) error {
 	return nil
 }
 
-func (ms *MessageSet) Reset()         { *ms = MessageSet{} }
-func (ms *MessageSet) String() string { return CompactTextString(ms) }
-func (*MessageSet) ProtoMessage()     {}
+func (ms *messageSet) Reset()         { *ms = messageSet{} }
+func (ms *messageSet) String() string { return CompactTextString(ms) }
+func (*messageSet) ProtoMessage()     {}
 
 // Support for the message_set_wire_format message option.
 
@@ -169,7 +162,7 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
 	}
 	sort.Ints(ids)
 
-	ms := &MessageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
+	ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
 	for _, id := range ids {
 		e := m[int32(id)]
 		// Remove the wire type and field number varint, as well as the length varint.
@@ -186,7 +179,7 @@ func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
 // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
 func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
-	ms := new(MessageSet)
+	ms := new(messageSet)
 	if err := Unmarshal(buf, ms); err != nil {
 		return err
 	}

+ 1 - 1
Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go

@@ -38,7 +38,7 @@ import (
 
 func TestUnmarshalMessageSetWithDuplicate(t *testing.T) {
 	// Check that a repeated message set entry will be concatenated.
-	in := &MessageSet{
+	in := &messageSet{
 		Item: []*_MessageSet_Item{
 			{TypeId: Int32(12345), Message: []byte("hoo")},
 			{TypeId: Int32(12345), Message: []byte("hah")},

+ 2 - 2
Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_reflect.go

@@ -144,8 +144,8 @@ func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
 	return structPointer_ifield(p, f).(*map[int32]Extension)
 }
 
-// Map returns the reflect.Value for the address of a map field in the struct.
-func structPointer_Map(p structPointer, f field, typ reflect.Type) reflect.Value {
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
 	return structPointer_field(p, f).Addr()
 }
 

+ 2 - 2
Godeps/_workspace/src/github.com/golang/protobuf/proto/pointer_unsafe.go

@@ -130,8 +130,8 @@ func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
 	return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
 }
 
-// Map returns the reflect.Value for the address of a map field in the struct.
-func structPointer_Map(p structPointer, f field, typ reflect.Type) reflect.Value {
+// NewAt returns the reflect.Value for a pointer to a field in the struct.
+func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
 	return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
 }
 

+ 125 - 7
Godeps/_workspace/src/github.com/golang/protobuf/proto/properties.go

@@ -37,6 +37,7 @@ package proto
 
 import (
 	"fmt"
+	"log"
 	"os"
 	"reflect"
 	"sort"
@@ -84,6 +85,15 @@ type decoder func(p *Buffer, prop *Properties, base structPointer) error
 // A valueDecoder decodes a single integer in a particular encoding.
 type valueDecoder func(o *Buffer) (x uint64, err error)
 
+// A oneofMarshaler does the marshaling for all oneof fields in a message.
+type oneofMarshaler func(Message, *Buffer) error
+
+// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
+type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
+
+// A oneofSizer does the sizing for all oneof fields in a message.
+type oneofSizer func(Message) int
+
 // tagMap is an optimization over map[int]int for typical protocol buffer
 // use-cases. Encoded protocol buffers are often in tag order with small tag
 // numbers.
@@ -132,6 +142,22 @@ type StructProperties struct {
 	order            []int          // list of struct field numbers in tag order
 	unrecField       field          // field id of the XXX_unrecognized []byte field
 	extendable       bool           // is this an extendable proto
+
+	oneofMarshaler   oneofMarshaler
+	oneofUnmarshaler oneofUnmarshaler
+	oneofSizer       oneofSizer
+	stype            reflect.Type
+
+	// OneofTypes contains information about the oneof fields in this message.
+	// It is keyed by the original name of a field.
+	OneofTypes map[string]*OneofProperties
+}
+
+// OneofProperties represents information about a specific field in a oneof.
+type OneofProperties struct {
+	Type  reflect.Type // pointer to generated struct type for this oneof field
+	Field int          // struct field number of the containing oneof in the message
+	Prop  *Properties
 }
 
 // Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
@@ -156,6 +182,7 @@ type Properties struct {
 	Packed   bool   // relevant for repeated primitives only
 	Enum     string // set for enum types only
 	proto3   bool   // whether this is known to be a proto3 field; set for []byte only
+	oneof    bool   // whether this is a oneof field
 
 	Default    string // default value
 	HasDefault bool   // whether an explicit default was provided
@@ -208,6 +235,9 @@ func (p *Properties) String() string {
 	if p.proto3 {
 		s += ",proto3"
 	}
+	if p.oneof {
+		s += ",oneof"
+	}
 	if len(p.Enum) > 0 {
 		s += ",enum=" + p.Enum
 	}
@@ -284,6 +314,8 @@ func (p *Properties) Parse(s string) {
 			p.Enum = f[5:]
 		case f == "proto3":
 			p.proto3 = true
+		case f == "oneof":
+			p.oneof = true
 		case strings.HasPrefix(f, "def="):
 			p.HasDefault = true
 			p.Default = f[4:] // rest of string
@@ -440,7 +472,12 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
 			p.enc = (*Buffer).enc_slice_byte
 			p.dec = (*Buffer).dec_slice_byte
 			p.size = size_slice_byte
-			if p.proto3 {
+			// This is a []byte, which is either a bytes field,
+			// or the value of a map field. In the latter case,
+			// we always encode an empty []byte, so we should not
+			// use the proto3 enc/size funcs.
+			// f == nil iff this is the key/value of a map field.
+			if p.proto3 && f != nil {
 				p.enc = (*Buffer).enc_proto3_slice_byte
 				p.size = size_proto3_slice_byte
 			}
@@ -595,7 +632,7 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
 }
 
 var (
-	mutex         sync.Mutex
+	propertiesMu  sync.RWMutex
 	propertiesMap = make(map[reflect.Type]*StructProperties)
 )
 
@@ -605,13 +642,26 @@ func GetProperties(t reflect.Type) *StructProperties {
 	if t.Kind() != reflect.Struct {
 		panic("proto: type must have kind struct")
 	}
-	mutex.Lock()
-	sprop := getPropertiesLocked(t)
-	mutex.Unlock()
+
+	// Most calls to GetProperties in a long-running program will be
+	// retrieving details for types we have seen before.
+	propertiesMu.RLock()
+	sprop, ok := propertiesMap[t]
+	propertiesMu.RUnlock()
+	if ok {
+		if collectStats {
+			stats.Chit++
+		}
+		return sprop
+	}
+
+	propertiesMu.Lock()
+	sprop = getPropertiesLocked(t)
+	propertiesMu.Unlock()
 	return sprop
 }
 
-// getPropertiesLocked requires that mutex is held.
+// getPropertiesLocked requires that propertiesMu is held.
 func getPropertiesLocked(t reflect.Type) *StructProperties {
 	if prop, ok := propertiesMap[t]; ok {
 		if collectStats {
@@ -647,6 +697,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 		if f.Name == "XXX_unrecognized" { // special case
 			prop.unrecField = toField(&f)
 		}
+		oneof := f.Tag.Get("protobuf_oneof") != "" // special case
 		prop.Prop[i] = p
 		prop.order[i] = i
 		if debug {
@@ -656,7 +707,7 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 			}
 			print("\n")
 		}
-		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
+		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && !oneof {
 			fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
 		}
 	}
@@ -664,6 +715,41 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	// Re-order prop.order.
 	sort.Sort(prop)
 
+	type oneofMessage interface {
+		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+	}
+	if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
+		var oots []interface{}
+		prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
+		prop.stype = t
+
+		// Interpret oneof metadata.
+		prop.OneofTypes = make(map[string]*OneofProperties)
+		for _, oot := range oots {
+			oop := &OneofProperties{
+				Type: reflect.ValueOf(oot).Type(), // *T
+				Prop: new(Properties),
+			}
+			sft := oop.Type.Elem().Field(0)
+			oop.Prop.Name = sft.Name
+			oop.Prop.Parse(sft.Tag.Get("protobuf"))
+			// There will be exactly one interface field that
+			// this new value is assignable to.
+			for i := 0; i < t.NumField(); i++ {
+				f := t.Field(i)
+				if f.Type.Kind() != reflect.Interface {
+					continue
+				}
+				if !oop.Type.AssignableTo(f.Type) {
+					continue
+				}
+				oop.Field = i
+				break
+			}
+			prop.OneofTypes[oop.Prop.OrigName] = oop
+		}
+	}
+
 	// build required counts
 	// build tags
 	reqCount := 0
@@ -722,3 +808,35 @@ func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[
 	}
 	enumValueMaps[typeName] = valueMap
 }
+
+// EnumValueMap returns the mapping from names to integers of the
+// enum type enumType, or a nil if not found.
+func EnumValueMap(enumType string) map[string]int32 {
+	return enumValueMaps[enumType]
+}
+
+// A registry of all linked message types.
+// The string is a fully-qualified proto name ("pkg.Message").
+var (
+	protoTypes    = make(map[string]reflect.Type)
+	revProtoTypes = make(map[reflect.Type]string)
+)
+
+// RegisterType is called from generated code and maps from the fully qualified
+// proto name to the type (pointer to struct) of the protocol buffer.
+func RegisterType(x Message, name string) {
+	if _, ok := protoTypes[name]; ok {
+		// TODO: Some day, make this a panic.
+		log.Printf("proto: duplicate proto type registered: %s", name)
+		return
+	}
+	t := reflect.TypeOf(x)
+	protoTypes[name] = t
+	revProtoTypes[t] = name
+}
+
+// MessageName returns the fully-qualified proto name for the given message type.
+func MessageName(x Message) string { return revProtoTypes[reflect.TypeOf(x)] }
+
+// MessageType returns the message type (pointer to struct) for a named message.
+func MessageType(name string) reflect.Type { return protoTypes[name] }

+ 0 - 44
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/Makefile

@@ -1,44 +0,0 @@
-# Go support for Protocol Buffers - Google's data interchange format
-#
-# Copyright 2014 The Go Authors.  All rights reserved.
-# https://github.com/golang/protobuf
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-include ../../Make.protobuf
-
-all:	regenerate
-
-regenerate:
-	rm -f proto3.pb.go
-	make proto3.pb.go
-
-# The following rules are just aids to development. Not needed for typical testing.
-
-diff:	regenerate
-	git diff proto3.pb.go

+ 122 - 0
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go

@@ -0,0 +1,122 @@
+// Code generated by protoc-gen-go.
+// source: proto3_proto/proto3.proto
+// DO NOT EDIT!
+
+/*
+Package proto3_proto is a generated protocol buffer package.
+
+It is generated from these files:
+	proto3_proto/proto3.proto
+
+It has these top-level messages:
+	Message
+	Nested
+	MessageWithMap
+*/
+package proto3_proto
+
+import proto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+import testdata "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+
+type Message_Humour int32
+
+const (
+	Message_UNKNOWN     Message_Humour = 0
+	Message_PUNS        Message_Humour = 1
+	Message_SLAPSTICK   Message_Humour = 2
+	Message_BILL_BAILEY Message_Humour = 3
+)
+
+var Message_Humour_name = map[int32]string{
+	0: "UNKNOWN",
+	1: "PUNS",
+	2: "SLAPSTICK",
+	3: "BILL_BAILEY",
+}
+var Message_Humour_value = map[string]int32{
+	"UNKNOWN":     0,
+	"PUNS":        1,
+	"SLAPSTICK":   2,
+	"BILL_BAILEY": 3,
+}
+
+func (x Message_Humour) String() string {
+	return proto.EnumName(Message_Humour_name, int32(x))
+}
+
+type Message struct {
+	Name         string                           `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+	Hilarity     Message_Humour                   `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
+	HeightInCm   uint32                           `protobuf:"varint,3,opt,name=height_in_cm" json:"height_in_cm,omitempty"`
+	Data         []byte                           `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
+	ResultCount  int64                            `protobuf:"varint,7,opt,name=result_count" json:"result_count,omitempty"`
+	TrueScotsman bool                             `protobuf:"varint,8,opt,name=true_scotsman" json:"true_scotsman,omitempty"`
+	Score        float32                          `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"`
+	Key          []uint64                         `protobuf:"varint,5,rep,name=key" json:"key,omitempty"`
+	Nested       *Nested                          `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
+	Terrain      map[string]*Nested               `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+	Proto2Field  *testdata.SubDefaults            `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"`
+	Proto2Value  map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+}
+
+func (m *Message) Reset()         { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage()    {}
+
+func (m *Message) GetNested() *Nested {
+	if m != nil {
+		return m.Nested
+	}
+	return nil
+}
+
+func (m *Message) GetTerrain() map[string]*Nested {
+	if m != nil {
+		return m.Terrain
+	}
+	return nil
+}
+
+func (m *Message) GetProto2Field() *testdata.SubDefaults {
+	if m != nil {
+		return m.Proto2Field
+	}
+	return nil
+}
+
+func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
+	if m != nil {
+		return m.Proto2Value
+	}
+	return nil
+}
+
+type Nested struct {
+	Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
+}
+
+func (m *Nested) Reset()         { *m = Nested{} }
+func (m *Nested) String() string { return proto.CompactTextString(m) }
+func (*Nested) ProtoMessage()    {}
+
+type MessageWithMap struct {
+	ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"`
+}
+
+func (m *MessageWithMap) Reset()         { *m = MessageWithMap{} }
+func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
+func (*MessageWithMap) ProtoMessage()    {}
+
+func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
+	if m != nil {
+		return m.ByteMapping
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
+}

+ 10 - 0
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto

@@ -31,6 +31,8 @@
 
 syntax = "proto3";
 
+import "testdata/test.proto";
+
 package proto3_proto;
 
 message Message {
@@ -51,8 +53,16 @@ message Message {
 
   repeated uint64 key = 5;
   Nested nested = 6;
+
+  map<string, Nested> terrain = 10;
+  testdata.SubDefaults proto2_field = 11;
+  map<string, testdata.SubDefaults> proto2_value = 13;
 }
 
 message Nested {
   string bunny = 1;
 }
+
+message MessageWithMap {
+  map<bool, bytes> byte_mapping = 1;
+}

+ 33 - 1
Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go

@@ -34,8 +34,9 @@ package proto_test
 import (
 	"testing"
 
-	pb "./proto3_proto"
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
+	tpb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 func TestProto3ZeroValues(t *testing.T) {
@@ -91,3 +92,34 @@ func TestRoundTripProto3(t *testing.T) {
 		t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2)
 	}
 }
+
+func TestProto3SetDefaults(t *testing.T) {
+	in := &pb.Message{
+		Terrain: map[string]*pb.Nested{
+			"meadow": new(pb.Nested),
+		},
+		Proto2Field: new(tpb.SubDefaults),
+		Proto2Value: map[string]*tpb.SubDefaults{
+			"badlands": new(tpb.SubDefaults),
+		},
+	}
+
+	got := proto.Clone(in).(*pb.Message)
+	proto.SetDefaults(got)
+
+	// There are no defaults in proto3.  Everything should be the zero value, but
+	// we need to remember to set defaults for nested proto2 messages.
+	want := &pb.Message{
+		Terrain: map[string]*pb.Nested{
+			"meadow": new(pb.Nested),
+		},
+		Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)},
+		Proto2Value: map[string]*tpb.SubDefaults{
+			"badlands": &tpb.SubDefaults{N: proto.Int64(7)},
+		},
+	}
+
+	if !proto.Equal(got, want) {
+		t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want)
+	}
+}

+ 31 - 2
Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go

@@ -33,11 +33,12 @@ package proto_test
 
 import (
 	"log"
+	"strings"
 	"testing"
 
-	proto3pb "./proto3_proto"
-	pb "./testdata"
 	. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
+	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)}
@@ -113,10 +114,38 @@ var SizeTests = []struct {
 	{"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}},
 	{"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}},
 	{"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
+	{"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}},
 
 	{"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}},
 	{"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}},
 	{"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}},
+	{"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}},
+
+	{"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}},
+	{"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}},
+	{"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}},
+
+	{"oneof not set", &pb.Oneof{}},
+	{"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}},
+	{"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}},
+	{"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}},
+	{"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}},
+	{"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}},
+	{"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}},
+	{"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}},
+	{"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}},
+	{"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}},
+	{"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}},
+	{"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}},
+	{"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}},
+	{"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}},
+	{"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}},
+	{"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}},
+	{"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}},
+	{"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}},
+	{"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}},
+	{"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}},
+	{"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}},
 }
 
 func TestSize(t *testing.T) {

Diff do ficheiro suprimidas por serem muito extensas
+ 1095 - 118
Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go


+ 101 - 0
Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto

@@ -233,6 +233,8 @@ message OtherMessage {
   optional bytes value = 2;
   optional float weight = 3;
   optional InnerMessage inner = 4;
+
+  extensions 100 to max;
 }
 
 message MyMessage {
@@ -277,6 +279,62 @@ extend MyMessage {
   repeated string greeting = 106;
 }
 
+message ComplexExtension {
+  optional int32 first = 1;
+  optional int32 second = 2;
+  repeated int32 third = 3;
+}
+
+extend OtherMessage {
+  optional ComplexExtension complex = 200;
+  repeated ComplexExtension r_complex = 201;
+}
+
+message DefaultsMessage {
+  enum DefaultsEnum {
+    ZERO = 0;
+    ONE = 1;
+    TWO = 2;
+  };
+  extensions 100 to max;
+}
+
+extend DefaultsMessage {
+  optional double no_default_double = 101;
+  optional float no_default_float = 102;
+  optional int32 no_default_int32 = 103;
+  optional int64 no_default_int64 = 104;
+  optional uint32 no_default_uint32 = 105;
+  optional uint64 no_default_uint64 = 106;
+  optional sint32 no_default_sint32 = 107;
+  optional sint64 no_default_sint64 = 108;
+  optional fixed32 no_default_fixed32 = 109;
+  optional fixed64 no_default_fixed64 = 110;
+  optional sfixed32 no_default_sfixed32 = 111;
+  optional sfixed64 no_default_sfixed64 = 112;
+  optional bool no_default_bool = 113;
+  optional string no_default_string = 114;
+  optional bytes no_default_bytes = 115;
+  optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
+
+  optional double default_double = 201 [default = 3.1415];
+  optional float default_float = 202 [default = 3.14];
+  optional int32 default_int32 = 203 [default = 42];
+  optional int64 default_int64 = 204 [default = 43];
+  optional uint32 default_uint32 = 205 [default = 44];
+  optional uint64 default_uint64 = 206 [default = 45];
+  optional sint32 default_sint32 = 207 [default = 46];
+  optional sint64 default_sint64 = 208 [default = 47];
+  optional fixed32 default_fixed32 = 209 [default = 48];
+  optional fixed64 default_fixed64 = 210 [default = 49];
+  optional sfixed32 default_sfixed32 = 211 [default = 50];
+  optional sfixed64 default_sfixed64 = 212 [default = 51];
+  optional bool default_bool = 213 [default = true];
+  optional string default_string = 214 [default = "Hello, string"];
+  optional bytes default_bytes = 215 [default = "Hello, bytes"];
+  optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
+}
+
 message MyMessageSet {
   option message_set_wire_format = true;
   extensions 100 to max;
@@ -431,4 +489,47 @@ message MessageWithMap {
   map<int32, string> name_mapping = 1;
   map<sint64, FloatingPoint> msg_mapping = 2;
   map<bool, bytes> byte_mapping = 3;
+  map<string, string> str_to_str = 4;
+}
+
+message Oneof {
+  oneof union {
+    bool F_Bool = 1;
+    int32 F_Int32 = 2;
+    int64 F_Int64 = 3;
+    fixed32 F_Fixed32 = 4;
+    fixed64 F_Fixed64 = 5;
+    uint32 F_Uint32 = 6;
+    uint64 F_Uint64 = 7;
+    float F_Float = 8;
+    double F_Double = 9;
+    string F_String = 10;
+    bytes F_Bytes = 11;
+    sint32 F_Sint32 = 12;
+    sint64 F_Sint64 = 13;
+    MyMessage.Color F_Enum = 14;
+    GoTestField F_Message = 15;
+    group F_Group = 16 {
+      optional int32 x = 17;
+    }
+    int32 F_Largest_Tag = 536870911;
+  }
+
+  oneof tormato {
+    int32 value = 100;
+  }
+}
+
+message Communique {
+  optional bool make_me_cry = 1;
+
+  // This is a oneof, called "union".
+  oneof union {
+    int32 number = 5;
+    string name = 6;
+    bytes data = 7;
+    double temp_c = 8;
+    MyMessage.Color col = 9;
+    Strings msg = 10;
+  }
 }

+ 44 - 82
Godeps/_workspace/src/github.com/golang/protobuf/proto/text.go

@@ -37,11 +37,11 @@ import (
 	"bufio"
 	"bytes"
 	"encoding"
+	"errors"
 	"fmt"
 	"io"
 	"log"
 	"math"
-	"os"
 	"reflect"
 	"sort"
 	"strings"
@@ -170,20 +170,12 @@ func writeName(w *textWriter, props *Properties) error {
 	return nil
 }
 
-var (
-	messageSetType = reflect.TypeOf((*MessageSet)(nil)).Elem()
-)
-
 // raw is the interface satisfied by RawMessage.
 type raw interface {
 	Bytes() []byte
 }
 
 func writeStruct(w *textWriter, sv reflect.Value) error {
-	if sv.Type() == messageSetType {
-		return writeMessageSet(w, sv.Addr().Interface().(*MessageSet))
-	}
-
 	st := sv.Type()
 	sprops := GetProperties(st)
 	for i := 0; i < sv.NumField(); i++ {
@@ -246,7 +238,7 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 		}
 		if fv.Kind() == reflect.Map {
 			// Map fields are rendered as a repeated struct with key/value fields.
-			keys := fv.MapKeys() // TODO: should we sort these for deterministic output?
+			keys := fv.MapKeys()
 			sort.Sort(mapKeys(keys))
 			for _, key := range keys {
 				val := fv.MapIndex(key)
@@ -283,20 +275,23 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 				if err := w.WriteByte('\n'); err != nil {
 					return err
 				}
-				// value
-				if _, err := w.WriteString("value:"); err != nil {
-					return err
-				}
-				if !w.compact {
-					if err := w.WriteByte(' '); err != nil {
+				// nil values aren't legal, but we can avoid panicking because of them.
+				if val.Kind() != reflect.Ptr || !val.IsNil() {
+					// value
+					if _, err := w.WriteString("value:"); err != nil {
+						return err
+					}
+					if !w.compact {
+						if err := w.WriteByte(' '); err != nil {
+							return err
+						}
+					}
+					if err := writeAny(w, val, props.mvalprop); err != nil {
+						return err
+					}
+					if err := w.WriteByte('\n'); err != nil {
 						return err
 					}
-				}
-				if err := writeAny(w, val, props.mvalprop); err != nil {
-					return err
-				}
-				if err := w.WriteByte('\n'); err != nil {
-					return err
 				}
 				// close struct
 				w.unindent()
@@ -315,26 +310,34 @@ func writeStruct(w *textWriter, sv reflect.Value) error {
 		}
 		if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
 			// proto3 non-repeated scalar field; skip if zero value
-			switch fv.Kind() {
-			case reflect.Bool:
-				if !fv.Bool() {
-					continue
-				}
-			case reflect.Int32, reflect.Int64:
-				if fv.Int() == 0 {
-					continue
-				}
-			case reflect.Uint32, reflect.Uint64:
-				if fv.Uint() == 0 {
+			if isProto3Zero(fv) {
+				continue
+			}
+		}
+
+		if fv.Kind() == reflect.Interface {
+			// Check if it is a oneof.
+			if st.Field(i).Tag.Get("protobuf_oneof") != "" {
+				// fv is nil, or holds a pointer to generated struct.
+				// That generated struct has exactly one field,
+				// which has a protobuf struct tag.
+				if fv.IsNil() {
 					continue
 				}
-			case reflect.Float32, reflect.Float64:
-				if fv.Float() == 0 {
-					continue
-				}
-			case reflect.String:
-				if fv.String() == "" {
-					continue
+				inner := fv.Elem().Elem() // interface -> *T -> T
+				tag := inner.Type().Field(0).Tag.Get("protobuf")
+				props = new(Properties) // Overwrite the outer props var, but not its pointee.
+				props.Parse(tag)
+				// Write the value in the oneof, not the oneof itself.
+				fv = inner.Field(0)
+
+				// Special case to cope with malformed messages gracefully:
+				// If the value in the oneof is a nil pointer, don't panic
+				// in writeAny.
+				if fv.Kind() == reflect.Ptr && fv.IsNil() {
+					// Use errors.New so writeAny won't render quotes.
+					msg := errors.New("/* nil */")
+					fv = reflect.ValueOf(&msg).Elem()
 				}
 			}
 		}
@@ -514,44 +517,6 @@ func writeString(w *textWriter, s string) error {
 	return w.WriteByte('"')
 }
 
-func writeMessageSet(w *textWriter, ms *MessageSet) error {
-	for _, item := range ms.Item {
-		id := *item.TypeId
-		if msd, ok := messageSetMap[id]; ok {
-			// Known message set type.
-			if _, err := fmt.Fprintf(w, "[%s]: <\n", msd.name); err != nil {
-				return err
-			}
-			w.indent()
-
-			pb := reflect.New(msd.t.Elem())
-			if err := Unmarshal(item.Message, pb.Interface().(Message)); err != nil {
-				if _, err := fmt.Fprintf(w, "/* bad message: %v */\n", err); err != nil {
-					return err
-				}
-			} else {
-				if err := writeStruct(w, pb.Elem()); err != nil {
-					return err
-				}
-			}
-		} else {
-			// Unknown type.
-			if _, err := fmt.Fprintf(w, "[%d]: <\n", id); err != nil {
-				return err
-			}
-			w.indent()
-			if err := writeUnknownStruct(w, item.Message); err != nil {
-				return err
-			}
-		}
-		w.unindent()
-		if _, err := w.Write(gtNewline); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
 func writeUnknownStruct(w *textWriter, data []byte) (err error) {
 	if !w.compact {
 		if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
@@ -666,10 +631,7 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
 
 		pb, err := GetExtension(ep, desc)
 		if err != nil {
-			if _, err := fmt.Fprintln(os.Stderr, "proto: failed getting extension: ", err); err != nil {
-				return err
-			}
-			continue
+			return fmt.Errorf("failed getting extension: %v", err)
 		}
 
 		// Repeated extensions will appear as a slice.

+ 135 - 94
Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser.go

@@ -174,7 +174,7 @@ func (p *textParser) advance() {
 		}
 		unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
 		if err != nil {
-			p.errorf("invalid quoted string %v", p.s[0:i+1])
+			p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
 			return
 		}
 		p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
@@ -385,8 +385,7 @@ func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSet
 }
 
 // Returns the index in the struct for the named field, as well as the parsed tag properties.
-func structFieldByName(st reflect.Type, name string) (int, *Properties, bool) {
-	sprops := GetProperties(st)
+func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
 	i, ok := sprops.decoderOrigNames[name]
 	if ok {
 		return i, sprops.Prop[i], true
@@ -438,7 +437,8 @@ func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseEr
 
 func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 	st := sv.Type()
-	reqCount := GetProperties(st).reqCount
+	sprops := GetProperties(st)
+	reqCount := sprops.reqCount
 	var reqFieldErr error
 	fieldSet := make(map[string]bool)
 	// A struct is a sequence of "name: value", terminated by one of
@@ -520,99 +520,113 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 				sl = reflect.Append(sl, ext)
 				SetExtension(ep, desc, sl.Interface())
 			}
-		} else {
-			// This is a normal, non-extension field.
-			name := tok.value
-			fi, props, ok := structFieldByName(st, name)
-			if !ok {
-				return p.errorf("unknown field name %q in %v", name, st)
+			if err := p.consumeOptionalSeparator(); err != nil {
+				return err
 			}
+			continue
+		}
 
-			dst := sv.Field(fi)
-
-			if dst.Kind() == reflect.Map {
-				// Consume any colon.
-				if err := p.checkForColon(props, dst.Type()); err != nil {
-					return err
-				}
-
-				// Construct the map if it doesn't already exist.
-				if dst.IsNil() {
-					dst.Set(reflect.MakeMap(dst.Type()))
-				}
-				key := reflect.New(dst.Type().Key()).Elem()
-				val := reflect.New(dst.Type().Elem()).Elem()
-
-				// The map entry should be this sequence of tokens:
-				//	< key : KEY value : VALUE >
-				// Technically the "key" and "value" could come in any order,
-				// but in practice they won't.
-
-				tok := p.next()
-				var terminator string
-				switch tok.value {
-				case "<":
-					terminator = ">"
-				case "{":
-					terminator = "}"
-				default:
-					return p.errorf("expected '{' or '<', found %q", tok.value)
-				}
-				if err := p.consumeToken("key"); err != nil {
-					return err
-				}
-				if err := p.consumeToken(":"); err != nil {
-					return err
-				}
-				if err := p.readAny(key, props.mkeyprop); err != nil {
-					return err
-				}
-				if err := p.consumeToken("value"); err != nil {
-					return err
-				}
-				if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
-					return err
-				}
-				if err := p.readAny(val, props.mvalprop); err != nil {
-					return err
-				}
-				if err := p.consumeToken(terminator); err != nil {
-					return err
-				}
+		// This is a normal, non-extension field.
+		name := tok.value
+		var dst reflect.Value
+		fi, props, ok := structFieldByName(sprops, name)
+		if ok {
+			dst = sv.Field(fi)
+		} else if oop, ok := sprops.OneofTypes[name]; ok {
+			// It is a oneof.
+			props = oop.Prop
+			nv := reflect.New(oop.Type.Elem())
+			dst = nv.Elem().Field(0)
+			sv.Field(oop.Field).Set(nv)
+		}
+		if !dst.IsValid() {
+			return p.errorf("unknown field name %q in %v", name, st)
+		}
 
-				dst.SetMapIndex(key, val)
-				continue
+		if dst.Kind() == reflect.Map {
+			// Consume any colon.
+			if err := p.checkForColon(props, dst.Type()); err != nil {
+				return err
 			}
 
-			// Check that it's not already set if it's not a repeated field.
-			if !props.Repeated && fieldSet[name] {
-				return p.errorf("non-repeated field %q was repeated", name)
+			// Construct the map if it doesn't already exist.
+			if dst.IsNil() {
+				dst.Set(reflect.MakeMap(dst.Type()))
 			}
-
-			if err := p.checkForColon(props, st.Field(fi).Type); err != nil {
+			key := reflect.New(dst.Type().Key()).Elem()
+			val := reflect.New(dst.Type().Elem()).Elem()
+
+			// The map entry should be this sequence of tokens:
+			//	< key : KEY value : VALUE >
+			// Technically the "key" and "value" could come in any order,
+			// but in practice they won't.
+
+			tok := p.next()
+			var terminator string
+			switch tok.value {
+			case "<":
+				terminator = ">"
+			case "{":
+				terminator = "}"
+			default:
+				return p.errorf("expected '{' or '<', found %q", tok.value)
+			}
+			if err := p.consumeToken("key"); err != nil {
 				return err
 			}
-
-			// Parse into the field.
-			fieldSet[name] = true
-			if err := p.readAny(dst, props); err != nil {
-				if _, ok := err.(*RequiredNotSetError); !ok {
-					return err
-				}
-				reqFieldErr = err
-			} else if props.Required {
-				reqCount--
+			if err := p.consumeToken(":"); err != nil {
+				return err
+			}
+			if err := p.readAny(key, props.mkeyprop); err != nil {
+				return err
+			}
+			if err := p.consumeOptionalSeparator(); err != nil {
+				return err
+			}
+			if err := p.consumeToken("value"); err != nil {
+				return err
+			}
+			if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+				return err
+			}
+			if err := p.readAny(val, props.mvalprop); err != nil {
+				return err
+			}
+			if err := p.consumeOptionalSeparator(); err != nil {
+				return err
+			}
+			if err := p.consumeToken(terminator); err != nil {
+				return err
 			}
+
+			dst.SetMapIndex(key, val)
+			continue
 		}
 
-		// For backward compatibility, permit a semicolon or comma after a field.
-		tok = p.next()
-		if tok.err != nil {
-			return tok.err
+		// Check that it's not already set if it's not a repeated field.
+		if !props.Repeated && fieldSet[name] {
+			return p.errorf("non-repeated field %q was repeated", name)
+		}
+
+		if err := p.checkForColon(props, dst.Type()); err != nil {
+			return err
 		}
-		if tok.value != ";" && tok.value != "," {
-			p.back()
+
+		// Parse into the field.
+		fieldSet[name] = true
+		if err := p.readAny(dst, props); err != nil {
+			if _, ok := err.(*RequiredNotSetError); !ok {
+				return err
+			}
+			reqFieldErr = err
+		} else if props.Required {
+			reqCount--
+		}
+
+		if err := p.consumeOptionalSeparator(); err != nil {
+			return err
 		}
+
 	}
 
 	if reqCount > 0 {
@@ -621,6 +635,19 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 	return reqFieldErr
 }
 
+// consumeOptionalSeparator consumes an optional semicolon or comma.
+// It is used in readStruct to provide backward compatibility.
+func (p *textParser) consumeOptionalSeparator() error {
+	tok := p.next()
+	if tok.err != nil {
+		return tok.err
+	}
+	if tok.value != ";" && tok.value != "," {
+		p.back()
+	}
+	return nil
+}
+
 func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 	tok := p.next()
 	if tok.err != nil {
@@ -645,18 +672,32 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 			fv.Set(reflect.ValueOf(bytes))
 			return nil
 		}
-		// Repeated field. May already exist.
-		flen := fv.Len()
-		if flen == fv.Cap() {
-			nav := reflect.MakeSlice(at, flen, 2*flen+1)
-			reflect.Copy(nav, fv)
-			fv.Set(nav)
+		// Repeated field.
+		if tok.value == "[" {
+			// Repeated field with list notation, like [1,2,3].
+			for {
+				fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+				err := p.readAny(fv.Index(fv.Len()-1), props)
+				if err != nil {
+					return err
+				}
+				tok := p.next()
+				if tok.err != nil {
+					return tok.err
+				}
+				if tok.value == "]" {
+					break
+				}
+				if tok.value != "," {
+					return p.errorf("Expected ']' or ',' found %q", tok.value)
+				}
+			}
+			return nil
 		}
-		fv.SetLen(flen + 1)
-
-		// Read one.
+		// One value of the repeated field.
 		p.back()
-		return p.readAny(fv.Index(flen), props)
+		fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
+		return p.readAny(fv.Index(fv.Len()-1), props)
 	case reflect.Bool:
 		// Either "true", "false", 1 or 0.
 		switch tok.value {

+ 25 - 4
Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go

@@ -36,9 +36,9 @@ import (
 	"reflect"
 	"testing"
 
-	proto3pb "./proto3_proto"
-	. "./testdata"
 	. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
+	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
+	. "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 type UnmarshalTextTest struct {
@@ -152,7 +152,7 @@ var unMarshalTextTests = []UnmarshalTextTest{
 	// Bad quoted string
 	{
 		in:  `inner: < host: "\0" >` + "\n",
-		err: `line 1.15: invalid quoted string "\0"`,
+		err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`,
 	},
 
 	// Number too large for int64
@@ -256,6 +256,15 @@ var unMarshalTextTests = []UnmarshalTextTest{
 		},
 	},
 
+	// Repeated field with list notation
+	{
+		in: `count:42 pet: ["horsey", "bunny"]`,
+		out: &MyMessage{
+			Count: Int32(42),
+			Pet:   []string{"horsey", "bunny"},
+		},
+	},
+
 	// Repeated message with/without colon and <>/{}
 	{
 		in: `count:42 others:{} others{} others:<> others:{}`,
@@ -462,7 +471,7 @@ func TestProto3TextParsing(t *testing.T) {
 func TestMapParsing(t *testing.T) {
 	m := new(MessageWithMap)
 	const in = `name_mapping:<key:1234 value:"Feist"> name_mapping:<key:1 value:"Beatles">` +
-		`msg_mapping:<key:-4 value:<f: 2.0>>` +
+		`msg_mapping:<key:-4, value:<f: 2.0>,>` + // separating commas are okay
 		`msg_mapping<key:-2 value<f: 4.0>>` + // no colon after "value"
 		`byte_mapping:<key:true value:"so be it">`
 	want := &MessageWithMap{
@@ -486,6 +495,18 @@ func TestMapParsing(t *testing.T) {
 	}
 }
 
+func TestOneofParsing(t *testing.T) {
+	const in = `name:"Shrek"`
+	m := new(Communique)
+	want := &Communique{Union: &Communique_Name{"Shrek"}}
+	if err := UnmarshalText(in, m); err != nil {
+		t.Fatal(err)
+	}
+	if !Equal(m, want) {
+		t.Errorf("\n got %v\nwant %v", m, want)
+	}
+}
+
 var benchInput string
 
 func init() {

+ 43 - 5
Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go

@@ -41,8 +41,8 @@ import (
 
 	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto"
 
-	proto3pb "./proto3_proto"
-	pb "./testdata"
+	proto3pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto"
+	pb "github.com/coreos/etcd/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata"
 )
 
 // textMessage implements the methods that allow it to marshal and unmarshal
@@ -208,6 +208,30 @@ func TestMarshalTextUnknownEnum(t *testing.T) {
 	}
 }
 
+func TestTextOneof(t *testing.T) {
+	tests := []struct {
+		m    proto.Message
+		want string
+	}{
+		// zero message
+		{&pb.Communique{}, ``},
+		// scalar field
+		{&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`},
+		// message field
+		{&pb.Communique{Union: &pb.Communique_Msg{
+			&pb.Strings{StringField: proto.String("why hello!")},
+		}}, `msg:<string_field:"why hello!" >`},
+		// bad oneof (should not panic)
+		{&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`},
+	}
+	for _, test := range tests {
+		got := strings.TrimSpace(test.m.String())
+		if got != test.want {
+			t.Errorf("\n got %s\nwant %s", got, test.want)
+		}
+	}
+}
+
 func BenchmarkMarshalTextBuffered(b *testing.B) {
 	buf := new(bytes.Buffer)
 	m := newTestMessage()
@@ -421,10 +445,24 @@ func TestProto3Text(t *testing.T) {
 		{&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`},
 		// empty map
 		{&pb.MessageWithMap{}, ``},
-		// non-empty map; current map format is the same as a repeated struct
+		// non-empty map; map format is the same as a repeated struct,
+		// and they are sorted by key (numerically for numeric keys).
+		{
+			&pb.MessageWithMap{NameMapping: map[int32]string{
+				-1:      "Negatory",
+				7:       "Lucky",
+				1234:    "Feist",
+				6345789: "Otis",
+			}},
+			`name_mapping:<key:-1 value:"Negatory" > ` +
+				`name_mapping:<key:7 value:"Lucky" > ` +
+				`name_mapping:<key:1234 value:"Feist" > ` +
+				`name_mapping:<key:6345789 value:"Otis" >`,
+		},
+		// map with nil value; not well-defined, but we shouldn't crash
 		{
-			&pb.MessageWithMap{NameMapping: map[int32]string{1234: "Feist"}},
-			`name_mapping:<key:1234 value:"Feist" >`,
+			&pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}},
+			`msg_mapping:<key:7 >`,
 		},
 	}
 	for _, test := range tests {

+ 1 - 1
Godeps/_workspace/src/golang.org/x/oauth2/LICENSE → Godeps/_workspace/src/golang.org/x/net/LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) 2009 The oauth2 Authors. All rights reserved.
+Copyright (c) 2009 The Go Authors. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are

+ 22 - 0
Godeps/_workspace/src/golang.org/x/net/PATENTS

@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.

+ 1 - 1
Godeps/_workspace/src/golang.org/x/net/context/context.go

@@ -189,7 +189,7 @@ func Background() Context {
 }
 
 // TODO returns a non-nil, empty Context.  Code should use context.TODO when
-// it's unclear which Context to use or it's is not yet available (because the
+// it's unclear which Context to use or it is not yet available (because the
 // surrounding function has not yet been extended to accept a Context
 // parameter).  TODO is recognized by static analysis tools that determine
 // whether Contexts are propagated correctly in a program.

+ 2 - 2
Godeps/_workspace/src/golang.org/x/net/context/context_test.go

@@ -375,7 +375,7 @@ func TestAllocs(t *testing.T) {
 				<-c.Done()
 			},
 			limit:      8,
-			gccgoLimit: 13,
+			gccgoLimit: 15,
 		},
 		{
 			desc: "WithCancel(bg)",
@@ -536,7 +536,7 @@ func testLayers(t *testing.T, seed int64, testTimeout bool) {
 	if testTimeout {
 		select {
 		case <-ctx.Done():
-		case <-time.After(timeout + timeout/10):
+		case <-time.After(timeout + 100*time.Millisecond):
 			errorf("ctx should have timed out")
 		}
 		checkValues("after timeout")

+ 19 - 0
Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq.go

@@ -0,0 +1,19 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.5
+
+package ctxhttp
+
+import "net/http"
+
+func canceler(client *http.Client, req *http.Request) func() {
+	// TODO(djd): Respect any existing value of req.Cancel.
+	ch := make(chan struct{})
+	req.Cancel = ch
+
+	return func() {
+		close(ch)
+	}
+}

+ 23 - 0
Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/cancelreq_go14.go

@@ -0,0 +1,23 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.5
+
+package ctxhttp
+
+import "net/http"
+
+type requestCanceler interface {
+	CancelRequest(*http.Request)
+}
+
+func canceler(client *http.Client, req *http.Request) func() {
+	rc, ok := client.Transport.(requestCanceler)
+	if !ok {
+		return func() {}
+	}
+	return func() {
+		rc.CancelRequest(req)
+	}
+}

+ 140 - 0
Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp.go

@@ -0,0 +1,140 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+package ctxhttp
+
+import (
+	"io"
+	"net/http"
+	"net/url"
+	"strings"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
+)
+
+func nop() {}
+
+var (
+	testHookContextDoneBeforeHeaders = nop
+	testHookDoReturned               = nop
+	testHookDidBodyClose             = nop
+)
+
+// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
+// If the client is nil, http.DefaultClient is used.
+// If the context is canceled or times out, ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+	if client == nil {
+		client = http.DefaultClient
+	}
+
+	// Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
+	cancel := canceler(client, req)
+
+	type responseAndError struct {
+		resp *http.Response
+		err  error
+	}
+	result := make(chan responseAndError, 1)
+
+	go func() {
+		resp, err := client.Do(req)
+		testHookDoReturned()
+		result <- responseAndError{resp, err}
+	}()
+
+	var resp *http.Response
+
+	select {
+	case <-ctx.Done():
+		testHookContextDoneBeforeHeaders()
+		cancel()
+		// Clean up after the goroutine calling client.Do:
+		go func() {
+			if r := <-result; r.resp != nil {
+				testHookDidBodyClose()
+				r.resp.Body.Close()
+			}
+		}()
+		return nil, ctx.Err()
+	case r := <-result:
+		var err error
+		resp, err = r.resp, r.err
+		if err != nil {
+			return resp, err
+		}
+	}
+
+	c := make(chan struct{})
+	go func() {
+		select {
+		case <-ctx.Done():
+			cancel()
+		case <-c:
+			// The response's Body is closed.
+		}
+	}()
+	resp.Body = &notifyingReader{resp.Body, c}
+
+	return resp, nil
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+	req, err := http.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+	req, err := http.NewRequest("HEAD", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+	req, err := http.NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", bodyType)
+	return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+	return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
+
+// notifyingReader is an io.ReadCloser that closes the notify channel after
+// Close is called or a Read fails on the underlying ReadCloser.
+type notifyingReader struct {
+	io.ReadCloser
+	notify chan<- struct{}
+}
+
+func (r *notifyingReader) Read(p []byte) (int, error) {
+	n, err := r.ReadCloser.Read(p)
+	if err != nil && r.notify != nil {
+		close(r.notify)
+		r.notify = nil
+	}
+	return n, err
+}
+
+func (r *notifyingReader) Close() error {
+	err := r.ReadCloser.Close()
+	if r.notify != nil {
+		close(r.notify)
+		r.notify = nil
+	}
+	return err
+}

+ 176 - 0
Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp_test.go

@@ -0,0 +1,176 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !plan9
+
+package ctxhttp
+
+import (
+	"io/ioutil"
+	"net"
+	"net/http"
+	"net/http/httptest"
+	"sync"
+	"testing"
+	"time"
+
+	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
+)
+
+const (
+	requestDuration = 100 * time.Millisecond
+	requestBody     = "ok"
+)
+
+func TestNoTimeout(t *testing.T) {
+	ctx := context.Background()
+	resp, err := doRequest(ctx)
+
+	if resp == nil || err != nil {
+		t.Fatalf("error received from client: %v %v", err, resp)
+	}
+}
+
+func TestCancel(t *testing.T) {
+	ctx, cancel := context.WithCancel(context.Background())
+	go func() {
+		time.Sleep(requestDuration / 2)
+		cancel()
+	}()
+
+	resp, err := doRequest(ctx)
+
+	if resp != nil || err == nil {
+		t.Fatalf("expected error, didn't get one. resp: %v", resp)
+	}
+	if err != ctx.Err() {
+		t.Fatalf("expected error from context but got: %v", err)
+	}
+}
+
+func TestCancelAfterRequest(t *testing.T) {
+	ctx, cancel := context.WithCancel(context.Background())
+
+	resp, err := doRequest(ctx)
+
+	// Cancel before reading the body.
+	// Request.Body should still be readable after the context is canceled.
+	cancel()
+
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil || string(b) != requestBody {
+		t.Fatalf("could not read body: %q %v", b, err)
+	}
+}
+
+func TestCancelAfterHangingRequest(t *testing.T) {
+	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusOK)
+		w.(http.Flusher).Flush()
+		<-w.(http.CloseNotifier).CloseNotify()
+	})
+
+	serv := httptest.NewServer(handler)
+	defer serv.Close()
+
+	ctx, cancel := context.WithCancel(context.Background())
+	resp, err := Get(ctx, nil, serv.URL)
+	if err != nil {
+		t.Fatalf("unexpected error in Get: %v", err)
+	}
+
+	// Cancel befer reading the body.
+	// Reading Request.Body should fail, since the request was
+	// canceled before anything was written.
+	cancel()
+
+	done := make(chan struct{})
+
+	go func() {
+		b, err := ioutil.ReadAll(resp.Body)
+		if len(b) != 0 || err == nil {
+			t.Errorf(`Read got (%q, %v); want ("", error)`, b, err)
+		}
+		close(done)
+	}()
+
+	select {
+	case <-time.After(1 * time.Second):
+		t.Errorf("Test timed out")
+	case <-done:
+	}
+}
+
+func doRequest(ctx context.Context) (*http.Response, error) {
+	var okHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		time.Sleep(requestDuration)
+		w.Write([]byte(requestBody))
+	})
+
+	serv := httptest.NewServer(okHandler)
+	defer serv.Close()
+
+	return Get(ctx, nil, serv.URL)
+}
+
+// golang.org/issue/14065
+func TestClosesResponseBodyOnCancel(t *testing.T) {
+	defer func() { testHookContextDoneBeforeHeaders = nop }()
+	defer func() { testHookDoReturned = nop }()
+	defer func() { testHookDidBodyClose = nop }()
+
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+	defer ts.Close()
+
+	ctx, cancel := context.WithCancel(context.Background())
+
+	// closed when Do enters select case <-ctx.Done()
+	enteredDonePath := make(chan struct{})
+
+	testHookContextDoneBeforeHeaders = func() {
+		close(enteredDonePath)
+	}
+
+	testHookDoReturned = func() {
+		// We now have the result (the Flush'd headers) at least,
+		// so we can cancel the request.
+		cancel()
+
+		// But block the client.Do goroutine from sending
+		// until Do enters into the <-ctx.Done() path, since
+		// otherwise if both channels are readable, select
+		// picks a random one.
+		<-enteredDonePath
+	}
+
+	sawBodyClose := make(chan struct{})
+	testHookDidBodyClose = func() { close(sawBodyClose) }
+
+	tr := &http.Transport{}
+	defer tr.CloseIdleConnections()
+	c := &http.Client{Transport: tr}
+	req, _ := http.NewRequest("GET", ts.URL, nil)
+	_, doErr := Do(ctx, c, req)
+
+	select {
+	case <-sawBodyClose:
+	case <-time.After(5 * time.Second):
+		t.Fatal("timeout waiting for body to close")
+	}
+
+	if doErr != ctx.Err() {
+		t.Errorf("Do error = %v; want %v", doErr, ctx.Err())
+	}
+}
+
+type noteCloseConn struct {
+	net.Conn
+	onceClose sync.Once
+	closefn   func()
+}
+
+func (c *noteCloseConn) Close() error {
+	c.onceClose.Do(c.closefn)
+	return c.Conn.Close()
+}

+ 2 - 0
Godeps/_workspace/src/golang.org/x/net/http2/.gitignore

@@ -0,0 +1,2 @@
+*~
+h2i/h2i

+ 11 - 4
Godeps/_workspace/src/github.com/bradfitz/http2/Dockerfile → Godeps/_workspace/src/golang.org/x/net/http2/Dockerfile

@@ -17,8 +17,15 @@ RUN apt-get install -y --no-install-recommends \
        libcunit1-dev libssl-dev libxml2-dev libevent-dev \
        automake autoconf
 
+# The list of packages nghttp2 recommends for h2load:
+RUN apt-get install -y --no-install-recommends make binutils \
+        autoconf automake autotools-dev \
+        libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \
+        libev-dev libevent-dev libjansson-dev libjemalloc-dev \
+        cython python3.4-dev python-setuptools
+
 # Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
-ENV NGHTTP2_VER af24f8394e43f4
+ENV NGHTTP2_VER 895da9a
 RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git
 
 WORKDIR /root/nghttp2
@@ -31,9 +38,9 @@ RUN make
 RUN make install
 
 WORKDIR /root
-RUN wget http://curl.haxx.se/download/curl-7.40.0.tar.gz
-RUN tar -zxvf curl-7.40.0.tar.gz
-WORKDIR /root/curl-7.40.0
+RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz
+RUN tar -zxvf curl-7.45.0.tar.gz
+WORKDIR /root/curl-7.45.0
 RUN ./configure --with-ssl --with-nghttp2=/usr/local
 RUN make
 RUN make install

+ 0 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/Makefile → Godeps/_workspace/src/golang.org/x/net/http2/Makefile


+ 5 - 2
Godeps/_workspace/src/github.com/bradfitz/http2/README → Godeps/_workspace/src/golang.org/x/net/http2/README

@@ -10,8 +10,11 @@ Status:
 * The client work has just started but shares a lot of code
   is coming along much quicker.
 
-Docs are at https://godoc.org/github.com/bradfitz/http2
+Docs are at https://godoc.org/golang.org/x/net/http2
 
 Demo test server at https://http2.golang.org/
 
-Help & bug reports welcome.
+Help & bug reports welcome!
+
+Contributing: https://golang.org/doc/contribute.html
+Bugs:         https://golang.org/issue/new?title=x/net/http2:+

+ 225 - 0
Godeps/_workspace/src/golang.org/x/net/http2/client_conn_pool.go

@@ -0,0 +1,225 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Transport code's client connection pooling.
+
+package http2
+
+import (
+	"crypto/tls"
+	"net/http"
+	"sync"
+)
+
+// ClientConnPool manages a pool of HTTP/2 client connections.
+type ClientConnPool interface {
+	GetClientConn(req *http.Request, addr string) (*ClientConn, error)
+	MarkDead(*ClientConn)
+}
+
+// TODO: use singleflight for dialing and addConnCalls?
+type clientConnPool struct {
+	t *Transport
+
+	mu sync.Mutex // TODO: maybe switch to RWMutex
+	// TODO: add support for sharing conns based on cert names
+	// (e.g. share conn for googleapis.com and appspot.com)
+	conns        map[string][]*ClientConn // key is host:port
+	dialing      map[string]*dialCall     // currently in-flight dials
+	keys         map[*ClientConn][]string
+	addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
+}
+
+func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+	return p.getClientConn(req, addr, dialOnMiss)
+}
+
+const (
+	dialOnMiss   = true
+	noDialOnMiss = false
+)
+
+func (p *clientConnPool) getClientConn(_ *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
+	p.mu.Lock()
+	for _, cc := range p.conns[addr] {
+		if cc.CanTakeNewRequest() {
+			p.mu.Unlock()
+			return cc, nil
+		}
+	}
+	if !dialOnMiss {
+		p.mu.Unlock()
+		return nil, ErrNoCachedConn
+	}
+	call := p.getStartDialLocked(addr)
+	p.mu.Unlock()
+	<-call.done
+	return call.res, call.err
+}
+
+// dialCall is an in-flight Transport dial call to a host.
+type dialCall struct {
+	p    *clientConnPool
+	done chan struct{} // closed when done
+	res  *ClientConn   // valid after done is closed
+	err  error         // valid after done is closed
+}
+
+// requires p.mu is held.
+func (p *clientConnPool) getStartDialLocked(addr string) *dialCall {
+	if call, ok := p.dialing[addr]; ok {
+		// A dial is already in-flight. Don't start another.
+		return call
+	}
+	call := &dialCall{p: p, done: make(chan struct{})}
+	if p.dialing == nil {
+		p.dialing = make(map[string]*dialCall)
+	}
+	p.dialing[addr] = call
+	go call.dial(addr)
+	return call
+}
+
+// run in its own goroutine.
+func (c *dialCall) dial(addr string) {
+	c.res, c.err = c.p.t.dialClientConn(addr)
+	close(c.done)
+
+	c.p.mu.Lock()
+	delete(c.p.dialing, addr)
+	if c.err == nil {
+		c.p.addConnLocked(addr, c.res)
+	}
+	c.p.mu.Unlock()
+}
+
+// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
+// already exist. It coalesces concurrent calls with the same key.
+// This is used by the http1 Transport code when it creates a new connection. Because
+// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
+// the protocol), it can get into a situation where it has multiple TLS connections.
+// This code decides which ones live or die.
+// The return value used is whether c was used.
+// c is never closed.
+func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
+	p.mu.Lock()
+	for _, cc := range p.conns[key] {
+		if cc.CanTakeNewRequest() {
+			p.mu.Unlock()
+			return false, nil
+		}
+	}
+	call, dup := p.addConnCalls[key]
+	if !dup {
+		if p.addConnCalls == nil {
+			p.addConnCalls = make(map[string]*addConnCall)
+		}
+		call = &addConnCall{
+			p:    p,
+			done: make(chan struct{}),
+		}
+		p.addConnCalls[key] = call
+		go call.run(t, key, c)
+	}
+	p.mu.Unlock()
+
+	<-call.done
+	if call.err != nil {
+		return false, call.err
+	}
+	return !dup, nil
+}
+
+type addConnCall struct {
+	p    *clientConnPool
+	done chan struct{} // closed when done
+	err  error
+}
+
+func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
+	cc, err := t.NewClientConn(tc)
+
+	p := c.p
+	p.mu.Lock()
+	if err != nil {
+		c.err = err
+	} else {
+		p.addConnLocked(key, cc)
+	}
+	delete(p.addConnCalls, key)
+	p.mu.Unlock()
+	close(c.done)
+}
+
+func (p *clientConnPool) addConn(key string, cc *ClientConn) {
+	p.mu.Lock()
+	p.addConnLocked(key, cc)
+	p.mu.Unlock()
+}
+
+// p.mu must be held
+func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
+	for _, v := range p.conns[key] {
+		if v == cc {
+			return
+		}
+	}
+	if p.conns == nil {
+		p.conns = make(map[string][]*ClientConn)
+	}
+	if p.keys == nil {
+		p.keys = make(map[*ClientConn][]string)
+	}
+	p.conns[key] = append(p.conns[key], cc)
+	p.keys[cc] = append(p.keys[cc], key)
+}
+
+func (p *clientConnPool) MarkDead(cc *ClientConn) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	for _, key := range p.keys[cc] {
+		vv, ok := p.conns[key]
+		if !ok {
+			continue
+		}
+		newList := filterOutClientConn(vv, cc)
+		if len(newList) > 0 {
+			p.conns[key] = newList
+		} else {
+			delete(p.conns, key)
+		}
+	}
+	delete(p.keys, cc)
+}
+
+func (p *clientConnPool) closeIdleConnections() {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	// TODO: don't close a cc if it was just added to the pool
+	// milliseconds ago and has never been used. There's currently
+	// a small race window with the HTTP/1 Transport's integration
+	// where it can add an idle conn just before using it, and
+	// somebody else can concurrently call CloseIdleConns and
+	// break some caller's RoundTrip.
+	for _, vv := range p.conns {
+		for _, cc := range vv {
+			cc.closeIfIdle()
+		}
+	}
+}
+
+func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
+	out := in[:0]
+	for _, v := range in {
+		if v != exclude {
+			out = append(out, v)
+		}
+	}
+	// If we filtered it out, zero out the last item to prevent
+	// the GC from seeing it.
+	if len(in) != len(out) {
+		in[len(in)-1] = nil
+	}
+	return out
+}

+ 89 - 0
Godeps/_workspace/src/golang.org/x/net/http2/configure_transport.go

@@ -0,0 +1,89 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.6
+
+package http2
+
+import (
+	"crypto/tls"
+	"fmt"
+	"net/http"
+)
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+	connPool := new(clientConnPool)
+	t2 := &Transport{
+		ConnPool: noDialClientConnPool{connPool},
+		t1:       t1,
+	}
+	connPool.t = t2
+	if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
+		return nil, err
+	}
+	if t1.TLSClientConfig == nil {
+		t1.TLSClientConfig = new(tls.Config)
+	}
+	if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
+		t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
+	}
+	if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
+		t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
+	}
+	upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
+		addr := authorityAddr(authority)
+		if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
+			go c.Close()
+			return erringRoundTripper{err}
+		} else if !used {
+			// Turns out we don't need this c.
+			// For example, two goroutines made requests to the same host
+			// at the same time, both kicking off TCP dials. (since protocol
+			// was unknown)
+			go c.Close()
+		}
+		return t2
+	}
+	if m := t1.TLSNextProto; len(m) == 0 {
+		t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
+			"h2": upgradeFn,
+		}
+	} else {
+		m["h2"] = upgradeFn
+	}
+	return t2, nil
+}
+
+// registerHTTPSProtocol calls Transport.RegisterProtocol but
+// convering panics into errors.
+func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
+	defer func() {
+		if e := recover(); e != nil {
+			err = fmt.Errorf("%v", e)
+		}
+	}()
+	t.RegisterProtocol("https", rt)
+	return nil
+}
+
+// noDialClientConnPool is an implementation of http2.ClientConnPool
+// which never dials.  We let the HTTP/1.1 client dial and use its TLS
+// connection instead.
+type noDialClientConnPool struct{ *clientConnPool }
+
+func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+	return p.getClientConn(req, addr, noDialOnMiss)
+}
+
+// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
+// if there's already has a cached connection to the host.
+type noDialH2RoundTripper struct{ t *Transport }
+
+func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+	res, err := rt.t.RoundTrip(req)
+	if err == ErrNoCachedConn {
+		return nil, http.ErrSkipAltProtocol
+	}
+	return res, err
+}

+ 16 - 4
Godeps/_workspace/src/github.com/bradfitz/http2/errors.go → Godeps/_workspace/src/golang.org/x/net/http2/errors.go

@@ -1,7 +1,6 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 
 package http2
 
@@ -76,3 +75,16 @@ func (e StreamError) Error() string {
 type goAwayFlowError struct{}
 
 func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
+
+// connErrorReason wraps a ConnectionError with an informative error about why it occurs.
+
+// Errors of this type are only returned by the frame parser functions
+// and converted into ConnectionError(ErrCodeProtocol).
+type connError struct {
+	Code   ErrCode
+	Reason string
+}
+
+func (e connError) Error() string {
+	return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
+}

+ 0 - 3
Godeps/_workspace/src/github.com/bradfitz/http2/errors_test.go → Godeps/_workspace/src/golang.org/x/net/http2/errors_test.go

@@ -1,9 +1,6 @@
 // Copyright 2014 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
 
 package http2
 

+ 60 - 0
Godeps/_workspace/src/golang.org/x/net/http2/fixed_buffer.go

@@ -0,0 +1,60 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+	"errors"
+)
+
+// fixedBuffer is an io.ReadWriter backed by a fixed size buffer.
+// It never allocates, but moves old data as new data is written.
+type fixedBuffer struct {
+	buf  []byte
+	r, w int
+}
+
+var (
+	errReadEmpty = errors.New("read from empty fixedBuffer")
+	errWriteFull = errors.New("write on full fixedBuffer")
+)
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *fixedBuffer) Read(p []byte) (n int, err error) {
+	if b.r == b.w {
+		return 0, errReadEmpty
+	}
+	n = copy(p, b.buf[b.r:b.w])
+	b.r += n
+	if b.r == b.w {
+		b.r = 0
+		b.w = 0
+	}
+	return n, nil
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *fixedBuffer) Len() int {
+	return b.w - b.r
+}
+
+// Write copies bytes from p into the buffer.
+// It is an error to write more data than the buffer can hold.
+func (b *fixedBuffer) Write(p []byte) (n int, err error) {
+	// Slide existing data to beginning.
+	if b.r > 0 && len(p) > len(b.buf)-b.w {
+		copy(b.buf, b.buf[b.r:b.w])
+		b.w -= b.r
+		b.r = 0
+	}
+
+	// Write new data.
+	n = copy(b.buf[b.w:], p)
+	b.w += n
+	if n < len(p) {
+		err = errWriteFull
+	}
+	return n, err
+}

+ 128 - 0
Godeps/_workspace/src/golang.org/x/net/http2/fixed_buffer_test.go

@@ -0,0 +1,128 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+	"reflect"
+	"testing"
+)
+
+var bufferReadTests = []struct {
+	buf      fixedBuffer
+	read, wn int
+	werr     error
+	wp       []byte
+	wbuf     fixedBuffer
+}{
+	{
+		fixedBuffer{[]byte{'a', 0}, 0, 1},
+		5, 1, nil, []byte{'a'},
+		fixedBuffer{[]byte{'a', 0}, 0, 0},
+	},
+	{
+		fixedBuffer{[]byte{0, 'a'}, 1, 2},
+		5, 1, nil, []byte{'a'},
+		fixedBuffer{[]byte{0, 'a'}, 0, 0},
+	},
+	{
+		fixedBuffer{[]byte{'a', 'b'}, 0, 2},
+		1, 1, nil, []byte{'a'},
+		fixedBuffer{[]byte{'a', 'b'}, 1, 2},
+	},
+	{
+		fixedBuffer{[]byte{}, 0, 0},
+		5, 0, errReadEmpty, []byte{},
+		fixedBuffer{[]byte{}, 0, 0},
+	},
+}
+
+func TestBufferRead(t *testing.T) {
+	for i, tt := range bufferReadTests {
+		read := make([]byte, tt.read)
+		n, err := tt.buf.Read(read)
+		if n != tt.wn {
+			t.Errorf("#%d: wn = %d want %d", i, n, tt.wn)
+			continue
+		}
+		if err != tt.werr {
+			t.Errorf("#%d: werr = %v want %v", i, err, tt.werr)
+			continue
+		}
+		read = read[:n]
+		if !reflect.DeepEqual(read, tt.wp) {
+			t.Errorf("#%d: read = %+v want %+v", i, read, tt.wp)
+		}
+		if !reflect.DeepEqual(tt.buf, tt.wbuf) {
+			t.Errorf("#%d: buf = %+v want %+v", i, tt.buf, tt.wbuf)
+		}
+	}
+}
+
+var bufferWriteTests = []struct {
+	buf       fixedBuffer
+	write, wn int
+	werr      error
+	wbuf      fixedBuffer
+}{
+	{
+		buf: fixedBuffer{
+			buf: []byte{},
+		},
+		wbuf: fixedBuffer{
+			buf: []byte{},
+		},
+	},
+	{
+		buf: fixedBuffer{
+			buf: []byte{1, 'a'},
+		},
+		write: 1,
+		wn:    1,
+		wbuf: fixedBuffer{
+			buf: []byte{0, 'a'},
+			w:   1,
+		},
+	},
+	{
+		buf: fixedBuffer{
+			buf: []byte{'a', 1},
+			r:   1,
+			w:   1,
+		},
+		write: 2,
+		wn:    2,
+		wbuf: fixedBuffer{
+			buf: []byte{0, 0},
+			w:   2,
+		},
+	},
+	{
+		buf: fixedBuffer{
+			buf: []byte{},
+		},
+		write: 5,
+		werr:  errWriteFull,
+		wbuf: fixedBuffer{
+			buf: []byte{},
+		},
+	},
+}
+
+func TestBufferWrite(t *testing.T) {
+	for i, tt := range bufferWriteTests {
+		n, err := tt.buf.Write(make([]byte, tt.write))
+		if n != tt.wn {
+			t.Errorf("#%d: wrote %d bytes; want %d", i, n, tt.wn)
+			continue
+		}
+		if err != tt.werr {
+			t.Errorf("#%d: error = %v; want %v", i, err, tt.werr)
+			continue
+		}
+		if !reflect.DeepEqual(tt.buf, tt.wbuf) {
+			t.Errorf("#%d: buf = %+v; want %+v", i, tt.buf, tt.wbuf)
+		}
+	}
+}

+ 3 - 4
Godeps/_workspace/src/github.com/bradfitz/http2/flow.go → Godeps/_workspace/src/golang.org/x/net/http2/flow.go

@@ -1,7 +1,6 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 
 // Flow control
 

+ 3 - 4
Godeps/_workspace/src/github.com/bradfitz/http2/flow_test.go → Godeps/_workspace/src/golang.org/x/net/http2/flow_test.go

@@ -1,7 +1,6 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 
 package http2
 

+ 182 - 26
Godeps/_workspace/src/github.com/bradfitz/http2/frame.go → Godeps/_workspace/src/golang.org/x/net/http2/frame.go

@@ -1,7 +1,6 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 
 package http2
 
@@ -11,6 +10,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"log"
 	"sync"
 )
 
@@ -85,8 +85,8 @@ const (
 	// Continuation Frame
 	FlagContinuationEndHeaders Flags = 0x4
 
-	FlagPushPromiseEndHeaders = 0x4
-	FlagPushPromisePadded     = 0x8
+	FlagPushPromiseEndHeaders Flags = 0x4
+	FlagPushPromisePadded     Flags = 0x8
 )
 
 var flagName = map[FrameType]map[Flags]string{
@@ -172,6 +172,12 @@ func (h FrameHeader) Header() FrameHeader { return h }
 func (h FrameHeader) String() string {
 	var buf bytes.Buffer
 	buf.WriteString("[FrameHeader ")
+	h.writeDebug(&buf)
+	buf.WriteByte(']')
+	return buf.String()
+}
+
+func (h FrameHeader) writeDebug(buf *bytes.Buffer) {
 	buf.WriteString(h.Type.String())
 	if h.Flags != 0 {
 		buf.WriteString(" flags=")
@@ -188,15 +194,14 @@ func (h FrameHeader) String() string {
 			if name != "" {
 				buf.WriteString(name)
 			} else {
-				fmt.Fprintf(&buf, "0x%x", 1<<i)
+				fmt.Fprintf(buf, "0x%x", 1<<i)
 			}
 		}
 	}
 	if h.StreamID != 0 {
-		fmt.Fprintf(&buf, " stream=%d", h.StreamID)
+		fmt.Fprintf(buf, " stream=%d", h.StreamID)
 	}
-	fmt.Fprintf(&buf, " len=%d]", h.Length)
-	return buf.String()
+	fmt.Fprintf(buf, " len=%d", h.Length)
 }
 
 func (h *FrameHeader) checkValid() {
@@ -256,6 +261,11 @@ type Frame interface {
 type Framer struct {
 	r         io.Reader
 	lastFrame Frame
+	errReason string
+
+	// lastHeaderStream is non-zero if the last frame was an
+	// unfinished HEADERS/CONTINUATION.
+	lastHeaderStream uint32
 
 	maxReadSize uint32
 	headerBuf   [frameHeaderLen]byte
@@ -272,18 +282,29 @@ type Framer struct {
 	wbuf []byte
 
 	// AllowIllegalWrites permits the Framer's Write methods to
-	// write frames that do not conform to the HTTP/2 spec.  This
+	// write frames that do not conform to the HTTP/2 spec. This
 	// permits using the Framer to test other HTTP/2
 	// implementations' conformance to the spec.
 	// If false, the Write methods will prefer to return an error
 	// rather than comply.
 	AllowIllegalWrites bool
 
+	// AllowIllegalReads permits the Framer's ReadFrame method
+	// to return non-compliant frames or frame orders.
+	// This is for testing and permits using the Framer to test
+	// other HTTP/2 implementations' conformance to the spec.
+	AllowIllegalReads bool
+
 	// TODO: track which type of frame & with which flags was sent
 	// last.  Then return an error (unless AllowIllegalWrites) if
 	// we're in the middle of a header block and a
 	// non-Continuation or Continuation on a different stream is
 	// attempted to be written.
+
+	logReads bool
+
+	debugFramer    *Framer // only use for logging written writes
+	debugFramerBuf *bytes.Buffer
 }
 
 func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
@@ -311,6 +332,10 @@ func (f *Framer) endWrite() error {
 		byte(length>>16),
 		byte(length>>8),
 		byte(length))
+	if logFrameWrites {
+		f.logWrite()
+	}
+
 	n, err := f.w.Write(f.wbuf)
 	if err == nil && n != len(f.wbuf) {
 		err = io.ErrShortWrite
@@ -318,6 +343,24 @@ func (f *Framer) endWrite() error {
 	return err
 }
 
+func (f *Framer) logWrite() {
+	if f.debugFramer == nil {
+		f.debugFramerBuf = new(bytes.Buffer)
+		f.debugFramer = NewFramer(nil, f.debugFramerBuf)
+		f.debugFramer.logReads = false // we log it ourselves, saying "wrote" below
+		// Let us read anything, even if we accidentally wrote it
+		// in the wrong order:
+		f.debugFramer.AllowIllegalReads = true
+	}
+	f.debugFramerBuf.Write(f.wbuf)
+	fr, err := f.debugFramer.ReadFrame()
+	if err != nil {
+		log.Printf("http2: Framer %p: failed to decode just-written frame", f)
+		return
+	}
+	log.Printf("http2: Framer %p: wrote %v", f, summarizeFrame(fr))
+}
+
 func (f *Framer) writeByte(v byte)     { f.wbuf = append(f.wbuf, v) }
 func (f *Framer) writeBytes(v []byte)  { f.wbuf = append(f.wbuf, v...) }
 func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
@@ -333,8 +376,9 @@ const (
 // NewFramer returns a Framer that writes frames to w and reads them from r.
 func NewFramer(w io.Writer, r io.Reader) *Framer {
 	fr := &Framer{
-		w: w,
-		r: r,
+		w:        w,
+		r:        r,
+		logReads: logFrameReads,
 	}
 	fr.getReadBuf = func(size uint32) []byte {
 		if cap(fr.readBuf) >= int(size) {
@@ -362,10 +406,22 @@ func (fr *Framer) SetMaxReadFrameSize(v uint32) {
 // sends a frame that is larger than declared with SetMaxReadFrameSize.
 var ErrFrameTooLarge = errors.New("http2: frame too large")
 
+// terminalReadFrameError reports whether err is an unrecoverable
+// error from ReadFrame and no other frames should be read.
+func terminalReadFrameError(err error) bool {
+	if _, ok := err.(StreamError); ok {
+		return false
+	}
+	return err != nil
+}
+
 // ReadFrame reads a single frame. The returned Frame is only valid
 // until the next call to ReadFrame.
-// If the frame is larger than previously set with SetMaxReadFrameSize,
-// the returned error is ErrFrameTooLarge.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from from the underlying
+// reader.
 func (fr *Framer) ReadFrame() (Frame, error) {
 	if fr.lastFrame != nil {
 		fr.lastFrame.invalidate()
@@ -383,12 +439,68 @@ func (fr *Framer) ReadFrame() (Frame, error) {
 	}
 	f, err := typeFrameParser(fh.Type)(fh, payload)
 	if err != nil {
+		if ce, ok := err.(connError); ok {
+			return nil, fr.connError(ce.Code, ce.Reason)
+		}
 		return nil, err
 	}
-	fr.lastFrame = f
+	if err := fr.checkFrameOrder(f); err != nil {
+		return nil, err
+	}
+	if fr.logReads {
+		log.Printf("http2: Framer %p: read %v", fr, summarizeFrame(f))
+	}
 	return f, nil
 }
 
+// connError returns ConnectionError(code) but first
+// stashes away a public reason to the caller can optionally relay it
+// to the peer before hanging up on them. This might help others debug
+// their implementations.
+func (fr *Framer) connError(code ErrCode, reason string) error {
+	fr.errReason = reason
+	return ConnectionError(code)
+}
+
+// checkFrameOrder reports an error if f is an invalid frame to return
+// next from ReadFrame. Mostly it checks whether HEADERS and
+// CONTINUATION frames are contiguous.
+func (fr *Framer) checkFrameOrder(f Frame) error {
+	last := fr.lastFrame
+	fr.lastFrame = f
+	if fr.AllowIllegalReads {
+		return nil
+	}
+
+	fh := f.Header()
+	if fr.lastHeaderStream != 0 {
+		if fh.Type != FrameContinuation {
+			return fr.connError(ErrCodeProtocol,
+				fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
+					fh.Type, fh.StreamID,
+					last.Header().Type, fr.lastHeaderStream))
+		}
+		if fh.StreamID != fr.lastHeaderStream {
+			return fr.connError(ErrCodeProtocol,
+				fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
+					fh.StreamID, fr.lastHeaderStream))
+		}
+	} else if fh.Type == FrameContinuation {
+		return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
+	}
+
+	switch fh.Type {
+	case FrameHeaders, FrameContinuation:
+		if fh.Flags.Has(FlagHeadersEndHeaders) {
+			fr.lastHeaderStream = 0
+		} else {
+			fr.lastHeaderStream = fh.StreamID
+		}
+	}
+
+	return nil
+}
+
 // A DataFrame conveys arbitrary, variable-length sequences of octets
 // associated with a stream.
 // See http://http2.github.io/http2-spec/#rfc.section.6.1
@@ -417,7 +529,7 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
 		// field is 0x0, the recipient MUST respond with a
 		// connection error (Section 5.4.1) of type
 		// PROTOCOL_ERROR.
-		return nil, ConnectionError(ErrCodeProtocol)
+		return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
 	}
 	f := &DataFrame{
 		FrameHeader: fh,
@@ -435,7 +547,7 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
 		// length of the frame payload, the recipient MUST
 		// treat this as a connection error.
 		// Filed: https://github.com/http2/http2-spec/issues/610
-		return nil, ConnectionError(ErrCodeProtocol)
+		return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
 	}
 	f.data = payload[:len(payload)-int(padSize)]
 	return f, nil
@@ -575,6 +687,8 @@ type PingFrame struct {
 	Data [8]byte
 }
 
+func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
+
 func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
 	if len(payload) != 8 {
 		return nil, ConnectionError(ErrCodeFrameSize)
@@ -663,7 +777,7 @@ func parseUnknownFrame(fh FrameHeader, p []byte) (Frame, error) {
 // See http://http2.github.io/http2-spec/#rfc.section.6.9
 type WindowUpdateFrame struct {
 	FrameHeader
-	Increment uint32
+	Increment uint32 // never read with high bit set
 }
 
 func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
@@ -740,7 +854,7 @@ func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
 		// is received whose stream identifier field is 0x0, the recipient MUST
 		// respond with a connection error (Section 5.4.1) of type
 		// PROTOCOL_ERROR.
-		return nil, ConnectionError(ErrCodeProtocol)
+		return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
 	}
 	var padLength uint8
 	if fh.Flags.Has(FlagHeadersPadded) {
@@ -870,10 +984,10 @@ func (p PriorityParam) IsZero() bool {
 
 func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) {
 	if fh.StreamID == 0 {
-		return nil, ConnectionError(ErrCodeProtocol)
+		return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
 	}
 	if len(payload) != 5 {
-		return nil, ConnectionError(ErrCodeFrameSize)
+		return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
 	}
 	v := binary.BigEndian.Uint32(payload[:4])
 	streamID := v & 0x7fffffff // mask off high bit
@@ -943,13 +1057,12 @@ type ContinuationFrame struct {
 }
 
 func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) {
+	if fh.StreamID == 0 {
+		return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
+	}
 	return &ContinuationFrame{fh, p}, nil
 }
 
-func (f *ContinuationFrame) StreamEnded() bool {
-	return f.FrameHeader.Flags.Has(FlagDataEndStream)
-}
-
 func (f *ContinuationFrame) HeaderBlockFragment() []byte {
 	f.checkValid()
 	return f.headerFragBuf
@@ -1111,3 +1224,46 @@ type streamEnder interface {
 type headersEnder interface {
 	HeadersEnded() bool
 }
+
+func summarizeFrame(f Frame) string {
+	var buf bytes.Buffer
+	f.Header().writeDebug(&buf)
+	switch f := f.(type) {
+	case *SettingsFrame:
+		n := 0
+		f.ForeachSetting(func(s Setting) error {
+			n++
+			if n == 1 {
+				buf.WriteString(", settings:")
+			}
+			fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
+			return nil
+		})
+		if n > 0 {
+			buf.Truncate(buf.Len() - 1) // remove trailing comma
+		}
+	case *DataFrame:
+		data := f.Data()
+		const max = 256
+		if len(data) > max {
+			data = data[:max]
+		}
+		fmt.Fprintf(&buf, " data=%q", data)
+		if len(f.Data()) > max {
+			fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
+		}
+	case *WindowUpdateFrame:
+		if f.StreamID == 0 {
+			buf.WriteString(" (conn)")
+		}
+		fmt.Fprintf(&buf, " incr=%v", f.Increment)
+	case *PingFrame:
+		fmt.Fprintf(&buf, " ping=%q", f.Data[:])
+	case *GoAwayFrame:
+		fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
+			f.LastStreamID, f.ErrCode, f.debugData)
+	case *RSTStreamFrame:
+		fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
+	}
+	return buf.String()
+}

+ 157 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/frame_test.go → Godeps/_workspace/src/golang.org/x/net/http2/frame_test.go

@@ -6,6 +6,8 @@ package http2
 
 import (
 	"bytes"
+	"fmt"
+	"io"
 	"reflect"
 	"strings"
 	"testing"
@@ -24,6 +26,25 @@ func TestFrameSizes(t *testing.T) {
 	}
 }
 
+func TestFrameTypeString(t *testing.T) {
+	tests := []struct {
+		ft   FrameType
+		want string
+	}{
+		{FrameData, "DATA"},
+		{FramePing, "PING"},
+		{FrameGoAway, "GOAWAY"},
+		{0xf, "UNKNOWN_FRAME_TYPE_15"},
+	}
+
+	for i, tt := range tests {
+		got := tt.ft.String()
+		if got != tt.want {
+			t.Errorf("%d. String(FrameType %d) = %q; want %q", i, int(tt.ft), got, tt.want)
+		}
+	}
+}
+
 func TestWriteRST(t *testing.T) {
 	fr, buf := testFramer()
 	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
@@ -245,6 +266,7 @@ func TestWriteContinuation(t *testing.T) {
 			t.Errorf("test %q: %v", tt.name, err)
 			continue
 		}
+		fr.AllowIllegalReads = true
 		f, err := fr.ReadFrame()
 		if err != nil {
 			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
@@ -576,3 +598,138 @@ func TestWritePushPromise(t *testing.T) {
 		t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
 	}
 }
+
+// test checkFrameOrder and that HEADERS and CONTINUATION frames can't be intermingled.
+func TestReadFrameOrder(t *testing.T) {
+	head := func(f *Framer, id uint32, end bool) {
+		f.WriteHeaders(HeadersFrameParam{
+			StreamID:      id,
+			BlockFragment: []byte("foo"), // unused, but non-empty
+			EndHeaders:    end,
+		})
+	}
+	cont := func(f *Framer, id uint32, end bool) {
+		f.WriteContinuation(id, end, []byte("foo"))
+	}
+
+	tests := [...]struct {
+		name    string
+		w       func(*Framer)
+		atLeast int
+		wantErr string
+	}{
+		0: {
+			w: func(f *Framer) {
+				head(f, 1, true)
+			},
+		},
+		1: {
+			w: func(f *Framer) {
+				head(f, 1, true)
+				head(f, 2, true)
+			},
+		},
+		2: {
+			wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
+			w: func(f *Framer) {
+				head(f, 1, false)
+				head(f, 2, true)
+			},
+		},
+		3: {
+			wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
+			w: func(f *Framer) {
+				head(f, 1, false)
+			},
+		},
+		4: {
+			w: func(f *Framer) {
+				head(f, 1, false)
+				cont(f, 1, true)
+				head(f, 2, true)
+			},
+		},
+		5: {
+			wantErr: "got CONTINUATION for stream 2; expected stream 1",
+			w: func(f *Framer) {
+				head(f, 1, false)
+				cont(f, 2, true)
+				head(f, 2, true)
+			},
+		},
+		6: {
+			wantErr: "unexpected CONTINUATION for stream 1",
+			w: func(f *Framer) {
+				cont(f, 1, true)
+			},
+		},
+		7: {
+			wantErr: "unexpected CONTINUATION for stream 1",
+			w: func(f *Framer) {
+				cont(f, 1, false)
+			},
+		},
+		8: {
+			wantErr: "HEADERS frame with stream ID 0",
+			w: func(f *Framer) {
+				head(f, 0, true)
+			},
+		},
+		9: {
+			wantErr: "CONTINUATION frame with stream ID 0",
+			w: func(f *Framer) {
+				cont(f, 0, true)
+			},
+		},
+		10: {
+			wantErr: "unexpected CONTINUATION for stream 1",
+			atLeast: 5,
+			w: func(f *Framer) {
+				head(f, 1, false)
+				cont(f, 1, false)
+				cont(f, 1, false)
+				cont(f, 1, false)
+				cont(f, 1, true)
+				cont(f, 1, false)
+			},
+		},
+	}
+	for i, tt := range tests {
+		buf := new(bytes.Buffer)
+		f := NewFramer(buf, buf)
+		f.AllowIllegalWrites = true
+		tt.w(f)
+		f.WriteData(1, true, nil) // to test transition away from last step
+
+		var err error
+		n := 0
+		var log bytes.Buffer
+		for {
+			var got Frame
+			got, err = f.ReadFrame()
+			fmt.Fprintf(&log, "  read %v, %v\n", got, err)
+			if err != nil {
+				break
+			}
+			n++
+		}
+		if err == io.EOF {
+			err = nil
+		}
+		ok := tt.wantErr == ""
+		if ok && err != nil {
+			t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
+			continue
+		}
+		if !ok && err != ConnectionError(ErrCodeProtocol) {
+			t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
+			continue
+		}
+		if f.errReason != tt.wantErr {
+			t.Errorf("%d. framer eror = %q; want %q\n%s", i, f.errReason, tt.wantErr, log.Bytes())
+		}
+		if n < tt.atLeast {
+			t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
+		}
+	}
+}

+ 11 - 0
Godeps/_workspace/src/golang.org/x/net/http2/go15.go

@@ -0,0 +1,11 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.5
+
+package http2
+
+import "net/http"
+
+func requestCancel(req *http.Request) <-chan struct{} { return req.Cancel }

+ 5 - 4
Godeps/_workspace/src/github.com/bradfitz/http2/gotrack.go → Godeps/_workspace/src/golang.org/x/net/http2/gotrack.go

@@ -1,9 +1,6 @@
 // Copyright 2014 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
 
 // Defensive debug-only utility to track that functions run on the
 // goroutine that they're supposed to.
@@ -14,16 +11,20 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
+	"os"
 	"runtime"
 	"strconv"
 	"sync"
 )
 
-var DebugGoroutines = false
+var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
 
 type goroutineLock uint64
 
 func newGoroutineLock() goroutineLock {
+	if !DebugGoroutines {
+		return 0
+	}
 	return goroutineLock(curGoroutineID())
 }
 

+ 3 - 3
Godeps/_workspace/src/github.com/bradfitz/http2/gotrack_test.go → Godeps/_workspace/src/golang.org/x/net/http2/gotrack_test.go

@@ -1,9 +1,6 @@
 // Copyright 2014 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
 
 package http2
 
@@ -14,7 +11,10 @@ import (
 )
 
 func TestGoroutineLock(t *testing.T) {
+	oldDebug := DebugGoroutines
 	DebugGoroutines = true
+	defer func() { DebugGoroutines = oldDebug }()
+
 	g := newGoroutineLock()
 	g.check()
 

+ 0 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/.gitignore → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/.gitignore


+ 8 - 0
Godeps/_workspace/src/golang.org/x/net/http2/h2demo/Makefile

@@ -0,0 +1,8 @@
+h2demo.linux: h2demo.go
+	GOOS=linux go build --tags=h2demo -o h2demo.linux .
+
+FORCE:
+
+upload: FORCE
+	go install golang.org/x/build/cmd/upload
+	upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo

+ 0 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/README → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/README


+ 78 - 32
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/h2demo.go → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/h2demo.go

@@ -1,7 +1,6 @@
-// Copyright 2014 The Go Authors.
-// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
-// Licensed under the same terms as Go itself:
-// https://code.google.com/p/go/source/browse/LICENSE
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
 
 // +build h2demo
 
@@ -20,7 +19,6 @@ import (
 	"log"
 	"net"
 	"net/http"
-	"os/exec"
 	"path"
 	"regexp"
 	"runtime"
@@ -31,14 +29,17 @@ import (
 
 	"camlistore.org/pkg/googlestorage"
 	"camlistore.org/pkg/singleflight"
-	"github.com/coreos/etcd/Godeps/_workspace/src/github.com/bradfitz/http2"
+	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/http2"
 )
 
 var (
-	openFirefox = flag.Bool("openff", false, "Open Firefox")
-	addr        = flag.String("addr", "localhost:4430", "TLS address to listen on")
-	httpAddr    = flag.String("httpaddr", "", "If non-empty, address to listen for regular HTTP on")
-	prod        = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
+	prod = flag.Bool("prod", false, "Whether to configure itself to be the production http2.golang.org server.")
+
+	httpsAddr = flag.String("https_addr", "localhost:4430", "TLS address to listen on ('host:port' or ':port'). Required.")
+	httpAddr  = flag.String("http_addr", "", "Plain HTTP address to listen on ('host:port', or ':port'). Empty means no HTTP.")
+
+	hostHTTP  = flag.String("http_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -http_addr.")
+	hostHTTPS = flag.String("https_host", "", "Optional host or host:port to use for http:// links to this service. By default, this is implied from -https_addr.")
 )
 
 func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
@@ -51,7 +52,7 @@ func homeOldHTTP(w http.ResponseWriter, r *http.Request) {
    <li>Use Firefox Nightly or go to <b>about:config</b> and enable "network.http.spdy.enabled.http2draft"</li>
    <li>Use Google Chrome Canary and/or go to <b>chrome://flags/#enable-spdy4</b> to <i>Enable SPDY/4</i> (Chrome's name for HTTP/2)</li>
 </ul>
-<p>See code & instructions for connecting at <a href="https://github.com/bradfitz/http2">https://github.com/bradfitz/http2</a>.</p>
+<p>See code & instructions for connecting at <a href="https://github.com/golang/net/tree/master/http2">https://github.com/golang/net/tree/master/http2</a>.</p>
 
 </body></html>`)
 }
@@ -72,13 +73,13 @@ href="https://http2.github.io/">HTTP/2</a> demo & interop server.</p>
 
 <p>This server exists for others in the HTTP/2 community to test their HTTP/2 client implementations and point out flaws in our server.</p>
 
-<p> The code is currently at <a
-href="https://github.com/bradfitz/http2">github.com/bradfitz/http2</a>
-but will move to the Go standard library at some point in the future
-(enabled by default, without users needing to change their code).</p>
+<p>
+The code is at <a href="https://golang.org/x/net/http2">golang.org/x/net/http2</a> and
+is used transparently by the Go standard library from Go 1.6 and later.
+</p>
 
 <p>Contact info: <i>bradfitz@golang.org</i>, or <a
-href="https://github.com/bradfitz/http2/issues">file a bug</a>.</p>
+href="https://golang.org/issues">file a bug</a>.</p>
 
 <h2>Handlers for testing</h2>
 <ul>
@@ -90,6 +91,7 @@ href="https://github.com/bradfitz/http2/issues">file a bug</a>.</p>
   <li>GET <a href="/redirect">/redirect</a> to redirect back to / (this page)</li>
   <li>GET <a href="/goroutines">/goroutines</a> to see all active goroutines in this server</li>
   <li>PUT something to <a href="/crc32">/crc32</a> to get a count of number of bytes and its CRC-32</li>
+  <li>PUT something to <a href="/ECHO">/ECHO</a> and it will be streamed back to you capitalized</li>
 </ul>
 
 </body></html>`)
@@ -123,6 +125,40 @@ func crcHandler(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+type capitalizeReader struct {
+	r io.Reader
+}
+
+func (cr capitalizeReader) Read(p []byte) (n int, err error) {
+	n, err = cr.r.Read(p)
+	for i, b := range p[:n] {
+		if b >= 'a' && b <= 'z' {
+			p[i] = b - ('a' - 'A')
+		}
+	}
+	return
+}
+
+type flushWriter struct {
+	w io.Writer
+}
+
+func (fw flushWriter) Write(p []byte) (n int, err error) {
+	n, err = fw.w.Write(p)
+	if f, ok := fw.w.(http.Flusher); ok {
+		f.Flush()
+	}
+	return
+}
+
+func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "PUT" {
+		http.Error(w, "PUT required.", 400)
+		return
+	}
+	io.Copy(flushWriter{w}, capitalizeReader{r.Body})
+}
+
 var (
 	fsGrp   singleflight.Group
 	fsMu    sync.Mutex // guards fsCache
@@ -198,7 +234,7 @@ func registerHandlers() {
 				tiles.ServeHTTP(w, r)
 				return
 			}
-			http.Redirect(w, r, "https://http2.golang.org/", http.StatusFound)
+			http.Redirect(w, r, "https://"+httpsHost()+"/", http.StatusFound)
 			return
 		}
 		if r.ProtoMajor == 1 {
@@ -216,6 +252,7 @@ func registerHandlers() {
 	mux2.Handle("/file/go.src.tar.gz", fileServer("https://storage.googleapis.com/golang/go1.4.1.src.tar.gz"))
 	mux2.HandleFunc("/reqinfo", reqInfoHandler)
 	mux2.HandleFunc("/crc32", crcHandler)
+	mux2.HandleFunc("/ECHO", echoCapitalHandler)
 	mux2.HandleFunc("/clockstream", clockStreamHandler)
 	mux2.Handle("/gophertiles", tiles)
 	mux2.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
@@ -287,7 +324,7 @@ func newGopherTilesHandler() http.Handler {
 				return
 			}
 		}
-		io.WriteString(w, "<html><body>")
+		io.WriteString(w, "<html><body onload='showtimes()'>")
 		fmt.Fprintf(w, "A grid of %d tiled images is below. Compare:<p>", xt*yt)
 		for _, ms := range []int{0, 30, 200, 1000} {
 			d := time.Duration(ms) * nanosPerMilli
@@ -305,15 +342,24 @@ func newGopherTilesHandler() http.Handler {
 			}
 			io.WriteString(w, "<br/>\n")
 		}
-		io.WriteString(w, "<hr><a href='/'>&lt;&lt Back to Go HTTP/2 demo server</a></body></html>")
+		io.WriteString(w, `<p><div id='loadtimes'></div></p>
+<script>
+function showtimes() {
+	var times = 'Times from connection start:<br>'
+	times += 'DOM loaded: ' + (window.performance.timing.domContentLoadedEventEnd - window.performance.timing.connectStart) + 'ms<br>'
+	times += 'DOM complete (images loaded): ' + (window.performance.timing.domComplete - window.performance.timing.connectStart) + 'ms<br>'
+	document.getElementById('loadtimes').innerHTML = times
+}
+</script>
+<hr><a href='/'>&lt;&lt Back to Go HTTP/2 demo server</a></body></html>`)
 	})
 }
 
 func httpsHost() string {
-	if *prod {
-		return "http2.golang.org"
+	if *hostHTTPS != "" {
+		return *hostHTTPS
 	}
-	if v := *addr; strings.HasPrefix(v, ":") {
+	if v := *httpsAddr; strings.HasPrefix(v, ":") {
 		return "localhost" + v
 	} else {
 		return v
@@ -321,8 +367,8 @@ func httpsHost() string {
 }
 
 func httpHost() string {
-	if *prod {
-		return "http2.golang.org"
+	if *hostHTTP != "" {
+		return *hostHTTP
 	}
 	if v := *httpAddr; strings.HasPrefix(v, ":") {
 		return "localhost" + v
@@ -398,29 +444,29 @@ func main() {
 	var srv http.Server
 	flag.BoolVar(&http2.VerboseLogs, "verbose", false, "Verbose HTTP/2 debugging.")
 	flag.Parse()
-	srv.Addr = *addr
+	srv.Addr = *httpsAddr
 
 	registerHandlers()
 
 	if *prod {
-		*httpAddr = "http2.golang.org"
+		*hostHTTP = "http2.golang.org"
+		*hostHTTPS = "http2.golang.org"
 		log.Fatal(serveProd())
 	}
 
-	url := "https://" + *addr + "/"
+	url := "https://" + httpsHost() + "/"
 	log.Printf("Listening on " + url)
 	http2.ConfigureServer(&srv, &http2.Server{})
 
 	if *httpAddr != "" {
-		go func() { log.Fatal(http.ListenAndServe(*httpAddr, nil)) }()
+		go func() {
+			log.Printf("Listening on http://" + httpHost() + "/ (for unencrypted HTTP/1)")
+			log.Fatal(http.ListenAndServe(*httpAddr, nil))
+		}()
 	}
 
 	go func() {
 		log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
 	}()
-	if *openFirefox && runtime.GOOS == "darwin" {
-		time.Sleep(250 * time.Millisecond)
-		exec.Command("open", "-b", "org.mozilla.nightly", "https://localhost:4430/").Run()
-	}
 	select {}
 }

+ 45 - 22
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/launch.go → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/launch.go

@@ -20,8 +20,9 @@ import (
 	"strings"
 	"time"
 
-	"code.google.com/p/goauth2/oauth"
-	compute "code.google.com/p/google-api-go-client/compute/v1"
+	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/google"
+	compute "google.golang.org/api/compute/v1"
 )
 
 var (
@@ -44,19 +45,18 @@ func readFile(v string) string {
 	return strings.TrimSpace(string(slurp))
 }
 
-var config = &oauth.Config{
+var config = &oauth2.Config{
 	// The client-id and secret should be for an "Installed Application" when using
 	// the CLI. Later we'll use a web application with a callback.
-	ClientId:     readFile("client-id.dat"),
+	ClientID:     readFile("client-id.dat"),
 	ClientSecret: readFile("client-secret.dat"),
-	Scope: strings.Join([]string{
-		compute.DevstorageFull_controlScope,
+	Endpoint:     google.Endpoint,
+	Scopes: []string{
+		compute.DevstorageFullControlScope,
 		compute.ComputeScope,
 		"https://www.googleapis.com/auth/sqlservice",
 		"https://www.googleapis.com/auth/sqlservice.admin",
-	}, " "),
-	AuthURL:     "https://accounts.google.com/o/oauth2/auth",
-	TokenURL:    "https://accounts.google.com/o/oauth2/token",
+	},
 	RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
 }
 
@@ -88,31 +88,32 @@ func main() {
 	prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
 	machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
 
-	tr := &oauth.Transport{
-		Config: config,
-	}
-
-	tokenCache := oauth.CacheFile("token.dat")
-	token, err := tokenCache.Token()
+	const tokenFileName = "token.dat"
+	tokenFile := tokenCacheFile(tokenFileName)
+	tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
+	token, err := tokenSource.Token()
 	if err != nil {
 		if *writeObject != "" {
 			log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
 		}
-		log.Printf("Error getting token from %s: %v", string(tokenCache), err)
+		log.Printf("Error getting token from %s: %v", tokenFileName, err)
 		log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
 		fmt.Print("\nEnter auth code: ")
 		sc := bufio.NewScanner(os.Stdin)
 		sc.Scan()
 		authCode := strings.TrimSpace(sc.Text())
-		token, err = tr.Exchange(authCode)
+		token, err = config.Exchange(oauth2.NoContext, authCode)
 		if err != nil {
 			log.Fatalf("Error exchanging auth code for a token: %v", err)
 		}
-		tokenCache.PutToken(token)
+		if err := tokenFile.WriteToken(token); err != nil {
+			log.Fatalf("Error writing to %s: %v", tokenFileName, err)
+		}
+		tokenSource = oauth2.ReuseTokenSource(token, nil)
 	}
 
-	tr.Token = token
-	oauthClient := &http.Client{Transport: tr}
+	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
+
 	if *writeObject != "" {
 		writeCloudStorageObject(oauthClient)
 		return
@@ -164,7 +165,7 @@ func main() {
 			Items: []*compute.MetadataItems{
 				{
 					Key:   "user-data",
-					Value: cloudConfig,
+					Value: &cloudConfig,
 				},
 			},
 		},
@@ -184,7 +185,7 @@ func main() {
 			{
 				Email: "default",
 				Scopes: []string{
-					compute.DevstorageFull_controlScope,
+					compute.DevstorageFullControlScope,
 					compute.ComputeScope,
 				},
 			},
@@ -277,3 +278,25 @@ func writeCloudStorageObject(httpClient *http.Client) {
 	log.Printf("Success.")
 	os.Exit(0)
 }
+
+type tokenCacheFile string
+
+func (f tokenCacheFile) Token() (*oauth2.Token, error) {
+	slurp, err := ioutil.ReadFile(string(f))
+	if err != nil {
+		return nil, err
+	}
+	t := new(oauth2.Token)
+	if err := json.Unmarshal(slurp, t); err != nil {
+		return nil, err
+	}
+	return t, nil
+}
+
+func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
+	jt, err := json.Marshal(t)
+	if err != nil {
+		return err
+	}
+	return ioutil.WriteFile(string(f), jt, 0600)
+}

+ 0 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/rootCA.key → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/rootCA.key


+ 0 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/rootCA.pem → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/rootCA.pem


+ 0 - 0
Godeps/_workspace/src/github.com/bradfitz/http2/h2demo/rootCA.srl → Godeps/_workspace/src/golang.org/x/net/http2/h2demo/rootCA.srl


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff