blob: 7f242e151979596df3ec8388aa4fd931aea31216 [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 {
55 return "required fields not set in " + e.t.String()
56}
Rob Pikeaaa3a622010-03-20 22:32:34 -070057
58// ErrRepeatedHasNil is the error returned if Marshal is called with
59// a protocol buffer struct with a repeated field containing a nil element.
60var ErrRepeatedHasNil = os.NewError("repeated field has nil")
61
62// ErrNil is the error returned if Marshal is called with nil.
63var ErrNil = os.NewError("marshal called with nil")
64
65// The fundamental encoders that put bytes on the wire.
66// Those that take integer types all accept uint64 and are
67// therefore of type valueEncoder.
68
David Symonds4fee3b12010-11-11 10:00:13 +110069const maxVarintBytes = 10 // maximum length of a varint
70
Rob Pikeaaa3a622010-03-20 22:32:34 -070071// EncodeVarint returns the varint encoding of x.
72// This is the format for the
73// int32, int64, uint32, uint64, bool, and enum
74// protocol buffer types.
75// Not used by the package itself, but helpful to clients
76// wishing to use the same encoding.
77func EncodeVarint(x uint64) []byte {
David Symonds4fee3b12010-11-11 10:00:13 +110078 var buf [maxVarintBytes]byte
Rob Pikeaaa3a622010-03-20 22:32:34 -070079 var n int
80 for n = 0; x > 127; n++ {
81 buf[n] = 0x80 | uint8(x&0x7F)
82 x >>= 7
83 }
84 buf[n] = uint8(x)
85 n++
86 return buf[0:n]
87}
88
David Symonds4fee3b12010-11-11 10:00:13 +110089var emptyBytes [maxVarintBytes]byte
90
Rob Pikeaaa3a622010-03-20 22:32:34 -070091// EncodeVarint writes a varint-encoded integer to the Buffer.
92// This is the format for the
93// int32, int64, uint32, uint64, bool, and enum
94// protocol buffer types.
95func (p *Buffer) EncodeVarint(x uint64) os.Error {
96 l := len(p.buf)
David Symondse37856c2011-06-22 12:52:53 +100097 p.buf = append(p.buf, emptyBytes[:]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -070098
David Symonds4fee3b12010-11-11 10:00:13 +110099 for x >= 1<<7 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700100 p.buf[l] = uint8(x&0x7f | 0x80)
101 l++
102 x >>= 7
103 }
104 p.buf[l] = uint8(x)
David Symonds4fee3b12010-11-11 10:00:13 +1100105 p.buf = p.buf[:l+1]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700106 return nil
107}
108
109// EncodeFixed64 writes a 64-bit integer to the Buffer.
110// This is the format for the
111// fixed64, sfixed64, and double protocol buffer types.
112func (p *Buffer) EncodeFixed64(x uint64) os.Error {
David Symonds4fee3b12010-11-11 10:00:13 +1100113 const fixed64Bytes = 8
Rob Pikeaaa3a622010-03-20 22:32:34 -0700114 l := len(p.buf)
David Symondse37856c2011-06-22 12:52:53 +1000115 p.buf = append(p.buf, emptyBytes[:fixed64Bytes]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700116
117 p.buf[l] = uint8(x)
118 p.buf[l+1] = uint8(x >> 8)
119 p.buf[l+2] = uint8(x >> 16)
120 p.buf[l+3] = uint8(x >> 24)
121 p.buf[l+4] = uint8(x >> 32)
122 p.buf[l+5] = uint8(x >> 40)
123 p.buf[l+6] = uint8(x >> 48)
124 p.buf[l+7] = uint8(x >> 56)
125 return nil
126}
127
128// EncodeFixed32 writes a 32-bit integer to the Buffer.
129// This is the format for the
130// fixed32, sfixed32, and float protocol buffer types.
131func (p *Buffer) EncodeFixed32(x uint64) os.Error {
David Symonds4fee3b12010-11-11 10:00:13 +1100132 const fixed32Bytes = 4
Rob Pikeaaa3a622010-03-20 22:32:34 -0700133 l := len(p.buf)
David Symondse37856c2011-06-22 12:52:53 +1000134 p.buf = append(p.buf, emptyBytes[:fixed32Bytes]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700135
136 p.buf[l] = uint8(x)
137 p.buf[l+1] = uint8(x >> 8)
138 p.buf[l+2] = uint8(x >> 16)
139 p.buf[l+3] = uint8(x >> 24)
140 return nil
141}
142
143// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
144// to the Buffer.
145// This is the format used for the sint64 protocol buffer type.
146func (p *Buffer) EncodeZigzag64(x uint64) os.Error {
147 // use signed number to get arithmetic right shift.
148 return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
149}
150
151// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
152// to the Buffer.
153// This is the format used for the sint32 protocol buffer type.
154func (p *Buffer) EncodeZigzag32(x uint64) os.Error {
155 // use signed number to get arithmetic right shift.
156 return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
157}
158
159// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
160// This is the format used for the bytes protocol buffer
161// type and for embedded messages.
162func (p *Buffer) EncodeRawBytes(b []byte) os.Error {
163 lb := len(b)
164 p.EncodeVarint(uint64(lb))
Rob Pike99fa2b62010-12-02 10:39:42 -0800165 p.buf = append(p.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700166 return nil
167}
168
169// EncodeStringBytes writes an encoded string to the Buffer.
170// This is the format used for the proto2 string type.
171func (p *Buffer) EncodeStringBytes(s string) os.Error {
172
173 // this works because strings and slices are the same.
174 y := *(*[]byte)(unsafe.Pointer(&s))
175 p.EncodeRawBytes(y)
176 return nil
177}
178
179// Marshaler is the interface representing objects that can marshal themselves.
180type Marshaler interface {
181 Marshal() ([]byte, os.Error)
182}
183
184// Marshal takes the protocol buffer struct represented by pb
185// and encodes it into the wire format, returning the data.
186func Marshal(pb interface{}) ([]byte, os.Error) {
187 // Can the object marshal itself?
188 if m, ok := pb.(Marshaler); ok {
189 return m.Marshal()
190 }
191 p := NewBuffer(nil)
192 err := p.Marshal(pb)
193 if err != nil {
194 return nil, err
195 }
196 return p.buf, err
197}
198
199// Marshal takes the protocol buffer struct represented by pb
200// and encodes it into the wire format, writing the result to the
201// Buffer.
202func (p *Buffer) Marshal(pb interface{}) os.Error {
203 // Can the object marshal itself?
204 if m, ok := pb.(Marshaler); ok {
205 data, err := m.Marshal()
206 if err != nil {
207 return err
208 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800209 p.buf = append(p.buf, data...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700210 return nil
211 }
212
213 mstat := runtime.MemStats.Mallocs
214
215 t, b, err := getbase(pb)
216 if err == nil {
Rob Pike97e934d2011-04-11 12:52:49 -0700217 err = p.enc_struct(t.Elem(), b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700218 }
219
220 mstat = runtime.MemStats.Mallocs - mstat
221 stats.Emalloc += mstat
222 stats.Encode++
223
224 return err
225}
226
227// Individual type encoders.
228
229// Encode a bool.
230func (o *Buffer) enc_bool(p *Properties, base uintptr) os.Error {
231 v := *(**uint8)(unsafe.Pointer(base + p.offset))
232 if v == nil {
233 return ErrNil
234 }
235 x := *v
236 if x != 0 {
237 x = 1
238 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800239 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700240 p.valEnc(o, uint64(x))
241 return nil
242}
243
244// Encode an int32.
245func (o *Buffer) enc_int32(p *Properties, base uintptr) os.Error {
246 v := *(**uint32)(unsafe.Pointer(base + p.offset))
247 if v == nil {
248 return ErrNil
249 }
250 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800251 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700252 p.valEnc(o, uint64(x))
253 return nil
254}
255
256// Encode an int64.
257func (o *Buffer) enc_int64(p *Properties, base uintptr) os.Error {
258 v := *(**uint64)(unsafe.Pointer(base + p.offset))
259 if v == nil {
260 return ErrNil
261 }
262 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800263 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700264 p.valEnc(o, uint64(x))
265 return nil
266}
267
268// Encode a string.
269func (o *Buffer) enc_string(p *Properties, base uintptr) os.Error {
270 v := *(**string)(unsafe.Pointer(base + p.offset))
271 if v == nil {
272 return ErrNil
273 }
274 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800275 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700276 o.EncodeStringBytes(x)
277 return nil
278}
279
Rob Pike97e934d2011-04-11 12:52:49 -0700280// All protocol buffer fields are nillable, but be careful.
281func isNil(v reflect.Value) bool {
282 switch v.Kind() {
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700283 case reflect.Map, reflect.Ptr, reflect.Slice:
Rob Pike97e934d2011-04-11 12:52:49 -0700284 return v.IsNil()
285 }
286 return false
287}
288
Rob Pikeaaa3a622010-03-20 22:32:34 -0700289// Encode a message struct.
290func (o *Buffer) enc_struct_message(p *Properties, base uintptr) os.Error {
291 // Can the object marshal itself?
292 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(base+p.offset))
293 if m, ok := iv.(Marshaler); ok {
Nigel Tao4ede8452011-04-28 11:27:25 +1000294 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000295 return ErrNil
296 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700297 data, err := m.Marshal()
298 if err != nil {
299 return err
300 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800301 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700302 o.EncodeRawBytes(data)
303 return nil
304 }
305 v := *(**struct{})(unsafe.Pointer(base + p.offset))
306 if v == nil {
307 return ErrNil
308 }
309
310 // need the length before we can write out the message itself,
311 // so marshal into a separate byte buffer first.
312 obuf := o.buf
313 o.buf = o.bufalloc()
314
315 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700316 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700317 err := o.enc_struct(typ, b)
318
319 nbuf := o.buf
320 o.buf = obuf
321 if err != nil {
322 o.buffree(nbuf)
323 return err
324 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800325 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700326 o.EncodeRawBytes(nbuf)
327 o.buffree(nbuf)
328 return nil
329}
330
331// Encode a group struct.
332func (o *Buffer) enc_struct_group(p *Properties, base uintptr) os.Error {
333 v := *(**struct{})(unsafe.Pointer(base + p.offset))
334 if v == nil {
335 return ErrNil
336 }
337
338 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
339 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700340 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700341 err := o.enc_struct(typ, b)
342 if err != nil {
343 return err
344 }
345 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
346 return nil
347}
348
349// Encode a slice of bools ([]bool).
350func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) os.Error {
351 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
352 l := len(s)
353 if l == 0 {
354 return ErrNil
355 }
356 for _, x := range s {
Rob Pike99fa2b62010-12-02 10:39:42 -0800357 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700358 if x != 0 {
359 x = 1
360 }
361 p.valEnc(o, uint64(x))
362 }
363 return nil
364}
365
David Symonds5b7775e2010-12-01 10:09:04 +1100366// Encode a slice of bools ([]bool) in packed format.
367func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) os.Error {
368 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
369 l := len(s)
370 if l == 0 {
371 return ErrNil
372 }
373 o.buf = append(o.buf, p.tagcode...)
374 o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
375 for _, x := range s {
376 if x != 0 {
377 x = 1
378 }
379 p.valEnc(o, uint64(x))
380 }
381 return nil
382}
383
Rob Pikeaaa3a622010-03-20 22:32:34 -0700384// Encode a slice of bytes ([]byte).
385func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) os.Error {
386 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800387 if s == nil {
388 return ErrNil
389 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800390 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700391 o.EncodeRawBytes(s)
392 return nil
393}
394
395// Encode a slice of int32s ([]int32).
396func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) os.Error {
397 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
398 l := len(s)
399 if l == 0 {
400 return ErrNil
401 }
402 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800403 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700404 x := s[i]
405 p.valEnc(o, uint64(x))
406 }
407 return nil
408}
409
David Symonds5b7775e2010-12-01 10:09:04 +1100410// Encode a slice of int32s ([]int32) in packed format.
411func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) os.Error {
412 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
413 l := len(s)
414 if l == 0 {
415 return ErrNil
416 }
417 // TODO: Reuse a Buffer.
418 buf := NewBuffer(nil)
419 for i := 0; i < l; i++ {
420 p.valEnc(buf, uint64(s[i]))
421 }
422
423 o.buf = append(o.buf, p.tagcode...)
424 o.EncodeVarint(uint64(len(buf.buf)))
425 o.buf = append(o.buf, buf.buf...)
426 return nil
427}
428
Rob Pikeaaa3a622010-03-20 22:32:34 -0700429// Encode a slice of int64s ([]int64).
430func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) os.Error {
431 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
432 l := len(s)
433 if l == 0 {
434 return ErrNil
435 }
436 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800437 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700438 x := s[i]
439 p.valEnc(o, uint64(x))
440 }
441 return nil
442}
443
David Symonds5b7775e2010-12-01 10:09:04 +1100444// Encode a slice of int64s ([]int64) in packed format.
445func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) os.Error {
446 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
447 l := len(s)
448 if l == 0 {
449 return ErrNil
450 }
451 // TODO: Reuse a Buffer.
452 buf := NewBuffer(nil)
453 for i := 0; i < l; i++ {
454 p.valEnc(buf, s[i])
455 }
456
457 o.buf = append(o.buf, p.tagcode...)
458 o.EncodeVarint(uint64(len(buf.buf)))
459 o.buf = append(o.buf, buf.buf...)
460 return nil
461}
462
Rob Pikeaaa3a622010-03-20 22:32:34 -0700463// Encode a slice of slice of bytes ([][]byte).
464func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) os.Error {
465 ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
466 l := len(ss)
467 if l == 0 {
468 return ErrNil
469 }
470 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800471 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700472 s := ss[i]
473 o.EncodeRawBytes(s)
474 }
475 return nil
476}
477
478// Encode a slice of strings ([]string).
479func (o *Buffer) enc_slice_string(p *Properties, base uintptr) os.Error {
480 ss := *(*[]string)(unsafe.Pointer(base + p.offset))
481 l := len(ss)
482 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800483 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700484 s := ss[i]
485 o.EncodeStringBytes(s)
486 }
487 return nil
488}
489
490// Encode a slice of message structs ([]*struct).
491func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) os.Error {
492 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
493 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700494 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700495
496 for i := 0; i < l; i++ {
497 v := s[i]
498 if v == nil {
499 return ErrRepeatedHasNil
500 }
501
502 // Can the object marshal itself?
503 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&s[i]))
504 if m, ok := iv.(Marshaler); ok {
David Symonds3fa055f2011-05-05 15:19:04 -0700505 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000506 return ErrNil
507 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700508 data, err := m.Marshal()
509 if err != nil {
510 return err
511 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800512 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700513 o.EncodeRawBytes(data)
514 continue
515 }
516
517 obuf := o.buf
518 o.buf = o.bufalloc()
519
520 b := uintptr(unsafe.Pointer(v))
521 err := o.enc_struct(typ, b)
522
523 nbuf := o.buf
524 o.buf = obuf
525 if err != nil {
526 o.buffree(nbuf)
527 if err == ErrNil {
528 return ErrRepeatedHasNil
529 }
530 return err
531 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800532 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700533 o.EncodeRawBytes(nbuf)
534
535 o.buffree(nbuf)
536 }
537 return nil
538}
539
540// Encode a slice of group structs ([]*struct).
541func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) os.Error {
542 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
543 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700544 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700545
546 for i := 0; i < l; i++ {
547 v := s[i]
548 if v == nil {
549 return ErrRepeatedHasNil
550 }
551
552 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
553
554 b := uintptr(unsafe.Pointer(v))
555 err := o.enc_struct(typ, b)
556
557 if err != nil {
558 if err == ErrNil {
559 return ErrRepeatedHasNil
560 }
561 return err
562 }
563
564 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
565 }
566 return nil
567}
568
569// Encode an extension map.
570func (o *Buffer) enc_map(p *Properties, base uintptr) os.Error {
571 v := *(*map[int32][]byte)(unsafe.Pointer(base + p.offset))
572 for _, b := range v {
Rob Pike99fa2b62010-12-02 10:39:42 -0800573 o.buf = append(o.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700574 }
575 return nil
576}
577
578// Encode a struct.
Rob Pike97e934d2011-04-11 12:52:49 -0700579func (o *Buffer) enc_struct(t reflect.Type, base uintptr) os.Error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700580 prop := GetProperties(t)
581 required := prop.reqCount
582 for _, p := range prop.Prop {
583 if p.enc != nil {
584 err := p.enc(o, p, base)
585 if err != nil {
586 if err != ErrNil {
587 return err
588 }
589 } else if p.Required {
590 required--
591 }
592 }
593 }
594 // See if we encoded all required fields.
595 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100596 return &ErrRequiredNotSet{t}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700597 }
598
599 return nil
600}