blob: ae3820bb398bb69b9a1a7e507d278ef90abf624c [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
3// Copyright 2010 Google Inc. All rights reserved.
4// http://code.google.com/p/goprotobuf/
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32package proto
33
34/*
35 * Routines for encoding data into the wire format for protocol buffers.
36 */
37
38import (
Rob Pikeaaa3a622010-03-20 22:32:34 -070039 "os"
40 "reflect"
41 "runtime"
42 "unsafe"
43)
44
45// ErrRequiredNotSet is the error returned if Marshal is called with
46// a protocol buffer struct whose required fields have not
Rob Pikec6d8e4a2010-07-28 15:34:32 -070047// all been initialized. It is also the error returned if Unmarshal is
48// called with an encoded protocol buffer that does not include all the
49// required fields.
David Symonds5b7775e2010-12-01 10:09:04 +110050type ErrRequiredNotSet struct {
51 t reflect.Type
52}
53
54func (e *ErrRequiredNotSet) String() string {
David Symonds7656e742011-07-22 14:54:17 +100055 return "proto: required fields not set in " + e.t.String()
David Symonds5b7775e2010-12-01 10:09:04 +110056}
Rob Pikeaaa3a622010-03-20 22:32:34 -070057
David Symonds7656e742011-07-22 14:54:17 +100058var (
59 // ErrRepeatedHasNil is the error returned if Marshal is called with
60 // a struct with a repeated field containing a nil element.
61 ErrRepeatedHasNil = os.NewError("proto: repeated field has nil")
Rob Pikeaaa3a622010-03-20 22:32:34 -070062
David Symonds7656e742011-07-22 14:54:17 +100063 // ErrNil is the error returned if Marshal is called with nil.
64 ErrNil = os.NewError("proto: Marshal called with nil")
65
66 // ErrNotPtr is the error returned if Marshal is called with a non-pointer.
67 ErrNotPtr = os.NewError("proto: Marshal called with a non-pointer")
68)
Rob Pikeaaa3a622010-03-20 22:32:34 -070069
70// The fundamental encoders that put bytes on the wire.
71// Those that take integer types all accept uint64 and are
72// therefore of type valueEncoder.
73
David Symonds4fee3b12010-11-11 10:00:13 +110074const maxVarintBytes = 10 // maximum length of a varint
75
Rob Pikeaaa3a622010-03-20 22:32:34 -070076// EncodeVarint returns the varint encoding of x.
77// This is the format for the
78// int32, int64, uint32, uint64, bool, and enum
79// protocol buffer types.
80// Not used by the package itself, but helpful to clients
81// wishing to use the same encoding.
82func EncodeVarint(x uint64) []byte {
David Symonds4fee3b12010-11-11 10:00:13 +110083 var buf [maxVarintBytes]byte
Rob Pikeaaa3a622010-03-20 22:32:34 -070084 var n int
85 for n = 0; x > 127; n++ {
86 buf[n] = 0x80 | uint8(x&0x7F)
87 x >>= 7
88 }
89 buf[n] = uint8(x)
90 n++
91 return buf[0:n]
92}
93
94// EncodeVarint writes a varint-encoded integer to the Buffer.
95// This is the format for the
96// int32, int64, uint32, uint64, bool, and enum
97// protocol buffer types.
98func (p *Buffer) EncodeVarint(x uint64) os.Error {
David Symonds4fee3b12010-11-11 10:00:13 +110099 for x >= 1<<7 {
David Symondsd9da6ba2011-08-30 14:41:30 +1000100 p.buf = append(p.buf, uint8(x&0x7f|0x80))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700101 x >>= 7
102 }
David Symondsd9da6ba2011-08-30 14:41:30 +1000103 p.buf = append(p.buf, uint8(x))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700104 return nil
105}
106
107// EncodeFixed64 writes a 64-bit integer to the Buffer.
108// This is the format for the
109// fixed64, sfixed64, and double protocol buffer types.
110func (p *Buffer) EncodeFixed64(x uint64) os.Error {
David Symondsd9da6ba2011-08-30 14:41:30 +1000111 p.buf = append(p.buf,
112 uint8(x),
113 uint8(x>>8),
114 uint8(x>>16),
115 uint8(x>>24),
116 uint8(x>>32),
117 uint8(x>>40),
118 uint8(x>>48),
119 uint8(x>>56))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700120 return nil
121}
122
123// EncodeFixed32 writes a 32-bit integer to the Buffer.
124// This is the format for the
125// fixed32, sfixed32, and float protocol buffer types.
126func (p *Buffer) EncodeFixed32(x uint64) os.Error {
David Symondsd9da6ba2011-08-30 14:41:30 +1000127 p.buf = append(p.buf,
128 uint8(x),
129 uint8(x>>8),
130 uint8(x>>16),
131 uint8(x>>24))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700132 return nil
133}
134
135// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
136// to the Buffer.
137// This is the format used for the sint64 protocol buffer type.
138func (p *Buffer) EncodeZigzag64(x uint64) os.Error {
139 // use signed number to get arithmetic right shift.
140 return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
141}
142
143// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
144// to the Buffer.
145// This is the format used for the sint32 protocol buffer type.
146func (p *Buffer) EncodeZigzag32(x uint64) os.Error {
147 // use signed number to get arithmetic right shift.
148 return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
149}
150
151// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
152// This is the format used for the bytes protocol buffer
153// type and for embedded messages.
154func (p *Buffer) EncodeRawBytes(b []byte) os.Error {
Rob Pike76f6ee52011-10-20 12:58:28 -0700155 p.EncodeVarint(uint64(len(b)))
Rob Pike99fa2b62010-12-02 10:39:42 -0800156 p.buf = append(p.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700157 return nil
158}
159
160// EncodeStringBytes writes an encoded string to the Buffer.
161// This is the format used for the proto2 string type.
162func (p *Buffer) EncodeStringBytes(s string) os.Error {
Rob Pike76f6ee52011-10-20 12:58:28 -0700163 p.EncodeVarint(uint64(len(s)))
164 p.buf = append(p.buf, s...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700165 return nil
166}
167
168// Marshaler is the interface representing objects that can marshal themselves.
169type Marshaler interface {
170 Marshal() ([]byte, os.Error)
171}
172
173// Marshal takes the protocol buffer struct represented by pb
174// and encodes it into the wire format, returning the data.
175func Marshal(pb interface{}) ([]byte, os.Error) {
176 // Can the object marshal itself?
177 if m, ok := pb.(Marshaler); ok {
178 return m.Marshal()
179 }
180 p := NewBuffer(nil)
181 err := p.Marshal(pb)
182 if err != nil {
183 return nil, err
184 }
185 return p.buf, err
186}
187
188// Marshal takes the protocol buffer struct represented by pb
189// and encodes it into the wire format, writing the result to the
190// Buffer.
191func (p *Buffer) Marshal(pb interface{}) os.Error {
192 // Can the object marshal itself?
193 if m, ok := pb.(Marshaler); ok {
194 data, err := m.Marshal()
195 if err != nil {
196 return err
197 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800198 p.buf = append(p.buf, data...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700199 return nil
200 }
201
202 mstat := runtime.MemStats.Mallocs
203
204 t, b, err := getbase(pb)
205 if err == nil {
Rob Pike97e934d2011-04-11 12:52:49 -0700206 err = p.enc_struct(t.Elem(), b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700207 }
208
209 mstat = runtime.MemStats.Mallocs - mstat
210 stats.Emalloc += mstat
211 stats.Encode++
212
213 return err
214}
215
216// Individual type encoders.
217
218// Encode a bool.
219func (o *Buffer) enc_bool(p *Properties, base uintptr) os.Error {
Rob Pike0f42a272011-10-20 16:03:11 -0700220 v := *(**bool)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700221 if v == nil {
222 return ErrNil
223 }
Rob Pike0f42a272011-10-20 16:03:11 -0700224 x := 0
225 if *v {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700226 x = 1
227 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800228 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700229 p.valEnc(o, uint64(x))
230 return nil
231}
232
233// Encode an int32.
234func (o *Buffer) enc_int32(p *Properties, base uintptr) os.Error {
Rob Pike0f42a272011-10-20 16:03:11 -0700235 v := *(**int32)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700236 if v == nil {
237 return ErrNil
238 }
239 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800240 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700241 p.valEnc(o, uint64(x))
242 return nil
243}
244
245// Encode an int64.
246func (o *Buffer) enc_int64(p *Properties, base uintptr) os.Error {
Rob Pike0f42a272011-10-20 16:03:11 -0700247 v := *(**int64)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700248 if v == nil {
249 return ErrNil
250 }
251 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800252 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700253 p.valEnc(o, uint64(x))
254 return nil
255}
256
257// Encode a string.
258func (o *Buffer) enc_string(p *Properties, base uintptr) os.Error {
259 v := *(**string)(unsafe.Pointer(base + p.offset))
260 if v == nil {
261 return ErrNil
262 }
263 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800264 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700265 o.EncodeStringBytes(x)
266 return nil
267}
268
Rob Pike97e934d2011-04-11 12:52:49 -0700269// All protocol buffer fields are nillable, but be careful.
270func isNil(v reflect.Value) bool {
271 switch v.Kind() {
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700272 case reflect.Map, reflect.Ptr, reflect.Slice:
Rob Pike97e934d2011-04-11 12:52:49 -0700273 return v.IsNil()
274 }
275 return false
276}
277
Rob Pikeaaa3a622010-03-20 22:32:34 -0700278// Encode a message struct.
279func (o *Buffer) enc_struct_message(p *Properties, base uintptr) os.Error {
280 // Can the object marshal itself?
281 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(base+p.offset))
282 if m, ok := iv.(Marshaler); ok {
Nigel Tao4ede8452011-04-28 11:27:25 +1000283 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000284 return ErrNil
285 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700286 data, err := m.Marshal()
287 if err != nil {
288 return err
289 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800290 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700291 o.EncodeRawBytes(data)
292 return nil
293 }
294 v := *(**struct{})(unsafe.Pointer(base + p.offset))
295 if v == nil {
296 return ErrNil
297 }
298
299 // need the length before we can write out the message itself,
300 // so marshal into a separate byte buffer first.
301 obuf := o.buf
302 o.buf = o.bufalloc()
303
304 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700305 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700306 err := o.enc_struct(typ, b)
307
308 nbuf := o.buf
309 o.buf = obuf
310 if err != nil {
311 o.buffree(nbuf)
312 return err
313 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800314 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700315 o.EncodeRawBytes(nbuf)
316 o.buffree(nbuf)
317 return nil
318}
319
320// Encode a group struct.
321func (o *Buffer) enc_struct_group(p *Properties, base uintptr) os.Error {
322 v := *(**struct{})(unsafe.Pointer(base + p.offset))
323 if v == nil {
324 return ErrNil
325 }
326
327 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
328 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700329 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700330 err := o.enc_struct(typ, b)
331 if err != nil {
332 return err
333 }
334 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
335 return nil
336}
337
338// Encode a slice of bools ([]bool).
339func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) os.Error {
340 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
341 l := len(s)
342 if l == 0 {
343 return ErrNil
344 }
345 for _, x := range s {
Rob Pike99fa2b62010-12-02 10:39:42 -0800346 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700347 if x != 0 {
348 x = 1
349 }
350 p.valEnc(o, uint64(x))
351 }
352 return nil
353}
354
David Symonds5b7775e2010-12-01 10:09:04 +1100355// Encode a slice of bools ([]bool) in packed format.
356func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) os.Error {
357 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
358 l := len(s)
359 if l == 0 {
360 return ErrNil
361 }
362 o.buf = append(o.buf, p.tagcode...)
363 o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
364 for _, x := range s {
365 if x != 0 {
366 x = 1
367 }
368 p.valEnc(o, uint64(x))
369 }
370 return nil
371}
372
Rob Pikeaaa3a622010-03-20 22:32:34 -0700373// Encode a slice of bytes ([]byte).
374func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) os.Error {
375 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800376 if s == nil {
377 return ErrNil
378 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800379 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700380 o.EncodeRawBytes(s)
381 return nil
382}
383
384// Encode a slice of int32s ([]int32).
385func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) os.Error {
386 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
387 l := len(s)
388 if l == 0 {
389 return ErrNil
390 }
391 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800392 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700393 x := s[i]
394 p.valEnc(o, uint64(x))
395 }
396 return nil
397}
398
David Symonds5b7775e2010-12-01 10:09:04 +1100399// Encode a slice of int32s ([]int32) in packed format.
400func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) os.Error {
401 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
402 l := len(s)
403 if l == 0 {
404 return ErrNil
405 }
406 // TODO: Reuse a Buffer.
407 buf := NewBuffer(nil)
408 for i := 0; i < l; i++ {
409 p.valEnc(buf, uint64(s[i]))
410 }
411
412 o.buf = append(o.buf, p.tagcode...)
413 o.EncodeVarint(uint64(len(buf.buf)))
414 o.buf = append(o.buf, buf.buf...)
415 return nil
416}
417
Rob Pikeaaa3a622010-03-20 22:32:34 -0700418// Encode a slice of int64s ([]int64).
419func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) os.Error {
420 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
421 l := len(s)
422 if l == 0 {
423 return ErrNil
424 }
425 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800426 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700427 x := s[i]
428 p.valEnc(o, uint64(x))
429 }
430 return nil
431}
432
David Symonds5b7775e2010-12-01 10:09:04 +1100433// Encode a slice of int64s ([]int64) in packed format.
434func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) os.Error {
435 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
436 l := len(s)
437 if l == 0 {
438 return ErrNil
439 }
440 // TODO: Reuse a Buffer.
441 buf := NewBuffer(nil)
442 for i := 0; i < l; i++ {
443 p.valEnc(buf, s[i])
444 }
445
446 o.buf = append(o.buf, p.tagcode...)
447 o.EncodeVarint(uint64(len(buf.buf)))
448 o.buf = append(o.buf, buf.buf...)
449 return nil
450}
451
Rob Pikeaaa3a622010-03-20 22:32:34 -0700452// Encode a slice of slice of bytes ([][]byte).
453func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) os.Error {
454 ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
455 l := len(ss)
456 if l == 0 {
457 return ErrNil
458 }
459 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800460 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700461 s := ss[i]
462 o.EncodeRawBytes(s)
463 }
464 return nil
465}
466
467// Encode a slice of strings ([]string).
468func (o *Buffer) enc_slice_string(p *Properties, base uintptr) os.Error {
469 ss := *(*[]string)(unsafe.Pointer(base + p.offset))
470 l := len(ss)
471 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800472 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700473 s := ss[i]
474 o.EncodeStringBytes(s)
475 }
476 return nil
477}
478
479// Encode a slice of message structs ([]*struct).
480func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) os.Error {
481 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
482 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700483 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700484
485 for i := 0; i < l; i++ {
486 v := s[i]
487 if v == nil {
488 return ErrRepeatedHasNil
489 }
490
491 // Can the object marshal itself?
492 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&s[i]))
493 if m, ok := iv.(Marshaler); ok {
David Symonds3fa055f2011-05-05 15:19:04 -0700494 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000495 return ErrNil
496 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700497 data, err := m.Marshal()
498 if err != nil {
499 return err
500 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800501 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700502 o.EncodeRawBytes(data)
503 continue
504 }
505
506 obuf := o.buf
507 o.buf = o.bufalloc()
508
509 b := uintptr(unsafe.Pointer(v))
510 err := o.enc_struct(typ, b)
511
512 nbuf := o.buf
513 o.buf = obuf
514 if err != nil {
515 o.buffree(nbuf)
516 if err == ErrNil {
517 return ErrRepeatedHasNil
518 }
519 return err
520 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800521 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700522 o.EncodeRawBytes(nbuf)
523
524 o.buffree(nbuf)
525 }
526 return nil
527}
528
529// Encode a slice of group structs ([]*struct).
530func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) os.Error {
531 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
532 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700533 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700534
535 for i := 0; i < l; i++ {
536 v := s[i]
537 if v == nil {
538 return ErrRepeatedHasNil
539 }
540
541 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
542
543 b := uintptr(unsafe.Pointer(v))
544 err := o.enc_struct(typ, b)
545
546 if err != nil {
547 if err == ErrNil {
548 return ErrRepeatedHasNil
549 }
550 return err
551 }
552
553 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
554 }
555 return nil
556}
557
558// Encode an extension map.
559func (o *Buffer) enc_map(p *Properties, base uintptr) os.Error {
David Symonds1d72f7a2011-08-19 18:28:52 +1000560 v := *(*map[int32]Extension)(unsafe.Pointer(base + p.offset))
561 if err := encodeExtensionMap(v); err != nil {
562 return err
563 }
564 for _, e := range v {
565 o.buf = append(o.buf, e.enc...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700566 }
567 return nil
568}
569
570// Encode a struct.
Rob Pike97e934d2011-04-11 12:52:49 -0700571func (o *Buffer) enc_struct(t reflect.Type, base uintptr) os.Error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700572 prop := GetProperties(t)
573 required := prop.reqCount
David Symondsd15e81b2011-10-03 14:31:12 -0700574 // Encode fields in tag order so that decoders may use optimizations
575 // that depend on the ordering.
576 // http://code.google.com/apis/protocolbuffers/docs/encoding.html#order
577 for _, i := range prop.order {
578 p := prop.Prop[i]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700579 if p.enc != nil {
580 err := p.enc(o, p, base)
581 if err != nil {
582 if err != ErrNil {
583 return err
584 }
585 } else if p.Required {
586 required--
587 }
588 }
589 }
590 // See if we encoded all required fields.
591 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100592 return &ErrRequiredNotSet{t}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700593 }
594
595 return nil
596}