blob: 3952dc485984bc3a6d515474f118d6fbaaefc567 [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
David Symonds4fee3b12010-11-11 10:00:13 +110094var emptyBytes [maxVarintBytes]byte
95
Rob Pikeaaa3a622010-03-20 22:32:34 -070096// EncodeVarint writes a varint-encoded integer to the Buffer.
97// This is the format for the
98// int32, int64, uint32, uint64, bool, and enum
99// protocol buffer types.
100func (p *Buffer) EncodeVarint(x uint64) os.Error {
101 l := len(p.buf)
David Symondse37856c2011-06-22 12:52:53 +1000102 p.buf = append(p.buf, emptyBytes[:]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700103
David Symonds4fee3b12010-11-11 10:00:13 +1100104 for x >= 1<<7 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700105 p.buf[l] = uint8(x&0x7f | 0x80)
106 l++
107 x >>= 7
108 }
109 p.buf[l] = uint8(x)
David Symonds4fee3b12010-11-11 10:00:13 +1100110 p.buf = p.buf[:l+1]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700111 return nil
112}
113
114// EncodeFixed64 writes a 64-bit integer to the Buffer.
115// This is the format for the
116// fixed64, sfixed64, and double protocol buffer types.
117func (p *Buffer) EncodeFixed64(x uint64) os.Error {
David Symonds4fee3b12010-11-11 10:00:13 +1100118 const fixed64Bytes = 8
Rob Pikeaaa3a622010-03-20 22:32:34 -0700119 l := len(p.buf)
David Symondse37856c2011-06-22 12:52:53 +1000120 p.buf = append(p.buf, emptyBytes[:fixed64Bytes]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700121
122 p.buf[l] = uint8(x)
123 p.buf[l+1] = uint8(x >> 8)
124 p.buf[l+2] = uint8(x >> 16)
125 p.buf[l+3] = uint8(x >> 24)
126 p.buf[l+4] = uint8(x >> 32)
127 p.buf[l+5] = uint8(x >> 40)
128 p.buf[l+6] = uint8(x >> 48)
129 p.buf[l+7] = uint8(x >> 56)
130 return nil
131}
132
133// EncodeFixed32 writes a 32-bit integer to the Buffer.
134// This is the format for the
135// fixed32, sfixed32, and float protocol buffer types.
136func (p *Buffer) EncodeFixed32(x uint64) os.Error {
David Symonds4fee3b12010-11-11 10:00:13 +1100137 const fixed32Bytes = 4
Rob Pikeaaa3a622010-03-20 22:32:34 -0700138 l := len(p.buf)
David Symondse37856c2011-06-22 12:52:53 +1000139 p.buf = append(p.buf, emptyBytes[:fixed32Bytes]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700140
141 p.buf[l] = uint8(x)
142 p.buf[l+1] = uint8(x >> 8)
143 p.buf[l+2] = uint8(x >> 16)
144 p.buf[l+3] = uint8(x >> 24)
145 return nil
146}
147
148// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
149// to the Buffer.
150// This is the format used for the sint64 protocol buffer type.
151func (p *Buffer) EncodeZigzag64(x uint64) os.Error {
152 // use signed number to get arithmetic right shift.
153 return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
154}
155
156// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
157// to the Buffer.
158// This is the format used for the sint32 protocol buffer type.
159func (p *Buffer) EncodeZigzag32(x uint64) os.Error {
160 // use signed number to get arithmetic right shift.
161 return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
162}
163
164// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
165// This is the format used for the bytes protocol buffer
166// type and for embedded messages.
167func (p *Buffer) EncodeRawBytes(b []byte) os.Error {
168 lb := len(b)
169 p.EncodeVarint(uint64(lb))
Rob Pike99fa2b62010-12-02 10:39:42 -0800170 p.buf = append(p.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700171 return nil
172}
173
174// EncodeStringBytes writes an encoded string to the Buffer.
175// This is the format used for the proto2 string type.
176func (p *Buffer) EncodeStringBytes(s string) os.Error {
177
178 // this works because strings and slices are the same.
179 y := *(*[]byte)(unsafe.Pointer(&s))
180 p.EncodeRawBytes(y)
181 return nil
182}
183
184// Marshaler is the interface representing objects that can marshal themselves.
185type Marshaler interface {
186 Marshal() ([]byte, os.Error)
187}
188
189// Marshal takes the protocol buffer struct represented by pb
190// and encodes it into the wire format, returning the data.
191func Marshal(pb interface{}) ([]byte, os.Error) {
192 // Can the object marshal itself?
193 if m, ok := pb.(Marshaler); ok {
194 return m.Marshal()
195 }
196 p := NewBuffer(nil)
197 err := p.Marshal(pb)
198 if err != nil {
199 return nil, err
200 }
201 return p.buf, err
202}
203
204// Marshal takes the protocol buffer struct represented by pb
205// and encodes it into the wire format, writing the result to the
206// Buffer.
207func (p *Buffer) Marshal(pb interface{}) os.Error {
208 // Can the object marshal itself?
209 if m, ok := pb.(Marshaler); ok {
210 data, err := m.Marshal()
211 if err != nil {
212 return err
213 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800214 p.buf = append(p.buf, data...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700215 return nil
216 }
217
218 mstat := runtime.MemStats.Mallocs
219
220 t, b, err := getbase(pb)
David Symonds7656e742011-07-22 14:54:17 +1000221 if t.Kind() != reflect.Ptr {
222 return ErrNotPtr
223 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700224 if err == nil {
Rob Pike97e934d2011-04-11 12:52:49 -0700225 err = p.enc_struct(t.Elem(), b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700226 }
227
228 mstat = runtime.MemStats.Mallocs - mstat
229 stats.Emalloc += mstat
230 stats.Encode++
231
232 return err
233}
234
235// Individual type encoders.
236
237// Encode a bool.
238func (o *Buffer) enc_bool(p *Properties, base uintptr) os.Error {
239 v := *(**uint8)(unsafe.Pointer(base + p.offset))
240 if v == nil {
241 return ErrNil
242 }
243 x := *v
244 if x != 0 {
245 x = 1
246 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800247 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700248 p.valEnc(o, uint64(x))
249 return nil
250}
251
252// Encode an int32.
253func (o *Buffer) enc_int32(p *Properties, base uintptr) os.Error {
254 v := *(**uint32)(unsafe.Pointer(base + p.offset))
255 if v == nil {
256 return ErrNil
257 }
258 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800259 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700260 p.valEnc(o, uint64(x))
261 return nil
262}
263
264// Encode an int64.
265func (o *Buffer) enc_int64(p *Properties, base uintptr) os.Error {
266 v := *(**uint64)(unsafe.Pointer(base + p.offset))
267 if v == nil {
268 return ErrNil
269 }
270 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800271 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700272 p.valEnc(o, uint64(x))
273 return nil
274}
275
276// Encode a string.
277func (o *Buffer) enc_string(p *Properties, base uintptr) os.Error {
278 v := *(**string)(unsafe.Pointer(base + p.offset))
279 if v == nil {
280 return ErrNil
281 }
282 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800283 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700284 o.EncodeStringBytes(x)
285 return nil
286}
287
Rob Pike97e934d2011-04-11 12:52:49 -0700288// All protocol buffer fields are nillable, but be careful.
289func isNil(v reflect.Value) bool {
290 switch v.Kind() {
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700291 case reflect.Map, reflect.Ptr, reflect.Slice:
Rob Pike97e934d2011-04-11 12:52:49 -0700292 return v.IsNil()
293 }
294 return false
295}
296
Rob Pikeaaa3a622010-03-20 22:32:34 -0700297// Encode a message struct.
298func (o *Buffer) enc_struct_message(p *Properties, base uintptr) os.Error {
299 // Can the object marshal itself?
300 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(base+p.offset))
301 if m, ok := iv.(Marshaler); ok {
Nigel Tao4ede8452011-04-28 11:27:25 +1000302 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000303 return ErrNil
304 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700305 data, err := m.Marshal()
306 if err != nil {
307 return err
308 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800309 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700310 o.EncodeRawBytes(data)
311 return nil
312 }
313 v := *(**struct{})(unsafe.Pointer(base + p.offset))
314 if v == nil {
315 return ErrNil
316 }
317
318 // need the length before we can write out the message itself,
319 // so marshal into a separate byte buffer first.
320 obuf := o.buf
321 o.buf = o.bufalloc()
322
323 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700324 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700325 err := o.enc_struct(typ, b)
326
327 nbuf := o.buf
328 o.buf = obuf
329 if err != nil {
330 o.buffree(nbuf)
331 return err
332 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800333 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700334 o.EncodeRawBytes(nbuf)
335 o.buffree(nbuf)
336 return nil
337}
338
339// Encode a group struct.
340func (o *Buffer) enc_struct_group(p *Properties, base uintptr) os.Error {
341 v := *(**struct{})(unsafe.Pointer(base + p.offset))
342 if v == nil {
343 return ErrNil
344 }
345
346 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
347 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700348 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700349 err := o.enc_struct(typ, b)
350 if err != nil {
351 return err
352 }
353 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
354 return nil
355}
356
357// Encode a slice of bools ([]bool).
358func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) os.Error {
359 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
360 l := len(s)
361 if l == 0 {
362 return ErrNil
363 }
364 for _, x := range s {
Rob Pike99fa2b62010-12-02 10:39:42 -0800365 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700366 if x != 0 {
367 x = 1
368 }
369 p.valEnc(o, uint64(x))
370 }
371 return nil
372}
373
David Symonds5b7775e2010-12-01 10:09:04 +1100374// Encode a slice of bools ([]bool) in packed format.
375func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) os.Error {
376 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
377 l := len(s)
378 if l == 0 {
379 return ErrNil
380 }
381 o.buf = append(o.buf, p.tagcode...)
382 o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
383 for _, x := range s {
384 if x != 0 {
385 x = 1
386 }
387 p.valEnc(o, uint64(x))
388 }
389 return nil
390}
391
Rob Pikeaaa3a622010-03-20 22:32:34 -0700392// Encode a slice of bytes ([]byte).
393func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) os.Error {
394 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800395 if s == nil {
396 return ErrNil
397 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800398 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700399 o.EncodeRawBytes(s)
400 return nil
401}
402
403// Encode a slice of int32s ([]int32).
404func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) os.Error {
405 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
406 l := len(s)
407 if l == 0 {
408 return ErrNil
409 }
410 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800411 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700412 x := s[i]
413 p.valEnc(o, uint64(x))
414 }
415 return nil
416}
417
David Symonds5b7775e2010-12-01 10:09:04 +1100418// Encode a slice of int32s ([]int32) in packed format.
419func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) os.Error {
420 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
421 l := len(s)
422 if l == 0 {
423 return ErrNil
424 }
425 // TODO: Reuse a Buffer.
426 buf := NewBuffer(nil)
427 for i := 0; i < l; i++ {
428 p.valEnc(buf, uint64(s[i]))
429 }
430
431 o.buf = append(o.buf, p.tagcode...)
432 o.EncodeVarint(uint64(len(buf.buf)))
433 o.buf = append(o.buf, buf.buf...)
434 return nil
435}
436
Rob Pikeaaa3a622010-03-20 22:32:34 -0700437// Encode a slice of int64s ([]int64).
438func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) os.Error {
439 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
440 l := len(s)
441 if l == 0 {
442 return ErrNil
443 }
444 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800445 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700446 x := s[i]
447 p.valEnc(o, uint64(x))
448 }
449 return nil
450}
451
David Symonds5b7775e2010-12-01 10:09:04 +1100452// Encode a slice of int64s ([]int64) in packed format.
453func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) os.Error {
454 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
455 l := len(s)
456 if l == 0 {
457 return ErrNil
458 }
459 // TODO: Reuse a Buffer.
460 buf := NewBuffer(nil)
461 for i := 0; i < l; i++ {
462 p.valEnc(buf, s[i])
463 }
464
465 o.buf = append(o.buf, p.tagcode...)
466 o.EncodeVarint(uint64(len(buf.buf)))
467 o.buf = append(o.buf, buf.buf...)
468 return nil
469}
470
Rob Pikeaaa3a622010-03-20 22:32:34 -0700471// Encode a slice of slice of bytes ([][]byte).
472func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) os.Error {
473 ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
474 l := len(ss)
475 if l == 0 {
476 return ErrNil
477 }
478 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800479 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700480 s := ss[i]
481 o.EncodeRawBytes(s)
482 }
483 return nil
484}
485
486// Encode a slice of strings ([]string).
487func (o *Buffer) enc_slice_string(p *Properties, base uintptr) os.Error {
488 ss := *(*[]string)(unsafe.Pointer(base + p.offset))
489 l := len(ss)
490 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800491 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700492 s := ss[i]
493 o.EncodeStringBytes(s)
494 }
495 return nil
496}
497
498// Encode a slice of message structs ([]*struct).
499func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) os.Error {
500 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
501 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700502 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700503
504 for i := 0; i < l; i++ {
505 v := s[i]
506 if v == nil {
507 return ErrRepeatedHasNil
508 }
509
510 // Can the object marshal itself?
511 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&s[i]))
512 if m, ok := iv.(Marshaler); ok {
David Symonds3fa055f2011-05-05 15:19:04 -0700513 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000514 return ErrNil
515 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700516 data, err := m.Marshal()
517 if err != nil {
518 return err
519 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800520 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700521 o.EncodeRawBytes(data)
522 continue
523 }
524
525 obuf := o.buf
526 o.buf = o.bufalloc()
527
528 b := uintptr(unsafe.Pointer(v))
529 err := o.enc_struct(typ, b)
530
531 nbuf := o.buf
532 o.buf = obuf
533 if err != nil {
534 o.buffree(nbuf)
535 if err == ErrNil {
536 return ErrRepeatedHasNil
537 }
538 return err
539 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800540 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700541 o.EncodeRawBytes(nbuf)
542
543 o.buffree(nbuf)
544 }
545 return nil
546}
547
548// Encode a slice of group structs ([]*struct).
549func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) os.Error {
550 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
551 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700552 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700553
554 for i := 0; i < l; i++ {
555 v := s[i]
556 if v == nil {
557 return ErrRepeatedHasNil
558 }
559
560 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
561
562 b := uintptr(unsafe.Pointer(v))
563 err := o.enc_struct(typ, b)
564
565 if err != nil {
566 if err == ErrNil {
567 return ErrRepeatedHasNil
568 }
569 return err
570 }
571
572 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
573 }
574 return nil
575}
576
577// Encode an extension map.
578func (o *Buffer) enc_map(p *Properties, base uintptr) os.Error {
579 v := *(*map[int32][]byte)(unsafe.Pointer(base + p.offset))
580 for _, b := range v {
Rob Pike99fa2b62010-12-02 10:39:42 -0800581 o.buf = append(o.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700582 }
583 return nil
584}
585
586// Encode a struct.
Rob Pike97e934d2011-04-11 12:52:49 -0700587func (o *Buffer) enc_struct(t reflect.Type, base uintptr) os.Error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700588 prop := GetProperties(t)
589 required := prop.reqCount
590 for _, p := range prop.Prop {
591 if p.enc != nil {
592 err := p.enc(o, p, base)
593 if err != nil {
594 if err != ErrNil {
595 return err
596 }
597 } else if p.Required {
598 required--
599 }
600 }
601 }
602 // See if we encoded all required fields.
603 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100604 return &ErrRequiredNotSet{t}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700605 }
606
607 return nil
608}