blob: a64de1ff7d4a077029a5569c99e8038b8a61c012 [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 Pikea17fdd92011-11-02 12:43:05 -070039 "errors"
Rob Pikeaaa3a622010-03-20 22:32:34 -070040 "reflect"
Rob Pikeaaa3a622010-03-20 22:32:34 -070041 "unsafe"
42)
43
44// ErrRequiredNotSet is the error returned if Marshal is called with
45// a protocol buffer struct whose required fields have not
Rob Pikec6d8e4a2010-07-28 15:34:32 -070046// all been initialized. It is also the error returned if Unmarshal is
47// called with an encoded protocol buffer that does not include all the
48// required fields.
David Symonds5b7775e2010-12-01 10:09:04 +110049type ErrRequiredNotSet struct {
50 t reflect.Type
51}
52
Rob Pikea17fdd92011-11-02 12:43:05 -070053func (e *ErrRequiredNotSet) Error() string {
David Symonds7656e742011-07-22 14:54:17 +100054 return "proto: required fields not set in " + e.t.String()
David Symonds5b7775e2010-12-01 10:09:04 +110055}
Rob Pikeaaa3a622010-03-20 22:32:34 -070056
David Symonds7656e742011-07-22 14:54:17 +100057var (
58 // ErrRepeatedHasNil is the error returned if Marshal is called with
59 // a struct with a repeated field containing a nil element.
Rob Pikea17fdd92011-11-02 12:43:05 -070060 ErrRepeatedHasNil = errors.New("proto: repeated field has nil")
Rob Pikeaaa3a622010-03-20 22:32:34 -070061
David Symonds7656e742011-07-22 14:54:17 +100062 // ErrNil is the error returned if Marshal is called with nil.
Rob Pikea17fdd92011-11-02 12:43:05 -070063 ErrNil = errors.New("proto: Marshal called with nil")
David Symonds7656e742011-07-22 14:54:17 +100064
65 // ErrNotPtr is the error returned if Marshal is called with a non-pointer.
Rob Pikea17fdd92011-11-02 12:43:05 -070066 ErrNotPtr = errors.New("proto: Marshal called with a non-pointer")
David Symonds7656e742011-07-22 14:54:17 +100067)
Rob Pikeaaa3a622010-03-20 22:32:34 -070068
69// The fundamental encoders that put bytes on the wire.
70// Those that take integer types all accept uint64 and are
71// therefore of type valueEncoder.
72
David Symonds4fee3b12010-11-11 10:00:13 +110073const maxVarintBytes = 10 // maximum length of a varint
74
Rob Pikeaaa3a622010-03-20 22:32:34 -070075// EncodeVarint returns the varint encoding of x.
76// This is the format for the
77// int32, int64, uint32, uint64, bool, and enum
78// protocol buffer types.
79// Not used by the package itself, but helpful to clients
80// wishing to use the same encoding.
81func EncodeVarint(x uint64) []byte {
David Symonds4fee3b12010-11-11 10:00:13 +110082 var buf [maxVarintBytes]byte
Rob Pikeaaa3a622010-03-20 22:32:34 -070083 var n int
84 for n = 0; x > 127; n++ {
85 buf[n] = 0x80 | uint8(x&0x7F)
86 x >>= 7
87 }
88 buf[n] = uint8(x)
89 n++
90 return buf[0:n]
91}
92
93// EncodeVarint writes a varint-encoded integer to the Buffer.
94// This is the format for the
95// int32, int64, uint32, uint64, bool, and enum
96// protocol buffer types.
Rob Pikea17fdd92011-11-02 12:43:05 -070097func (p *Buffer) EncodeVarint(x uint64) error {
David Symonds4fee3b12010-11-11 10:00:13 +110098 for x >= 1<<7 {
David Symondsd9da6ba2011-08-30 14:41:30 +100099 p.buf = append(p.buf, uint8(x&0x7f|0x80))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700100 x >>= 7
101 }
David Symondsd9da6ba2011-08-30 14:41:30 +1000102 p.buf = append(p.buf, uint8(x))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700103 return nil
104}
105
106// EncodeFixed64 writes a 64-bit integer to the Buffer.
107// This is the format for the
108// fixed64, sfixed64, and double protocol buffer types.
Rob Pikea17fdd92011-11-02 12:43:05 -0700109func (p *Buffer) EncodeFixed64(x uint64) error {
David Symondsd9da6ba2011-08-30 14:41:30 +1000110 p.buf = append(p.buf,
111 uint8(x),
112 uint8(x>>8),
113 uint8(x>>16),
114 uint8(x>>24),
115 uint8(x>>32),
116 uint8(x>>40),
117 uint8(x>>48),
118 uint8(x>>56))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700119 return nil
120}
121
122// EncodeFixed32 writes a 32-bit integer to the Buffer.
123// This is the format for the
124// fixed32, sfixed32, and float protocol buffer types.
Rob Pikea17fdd92011-11-02 12:43:05 -0700125func (p *Buffer) EncodeFixed32(x uint64) error {
David Symondsd9da6ba2011-08-30 14:41:30 +1000126 p.buf = append(p.buf,
127 uint8(x),
128 uint8(x>>8),
129 uint8(x>>16),
130 uint8(x>>24))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700131 return nil
132}
133
134// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
135// to the Buffer.
136// This is the format used for the sint64 protocol buffer type.
Rob Pikea17fdd92011-11-02 12:43:05 -0700137func (p *Buffer) EncodeZigzag64(x uint64) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700138 // use signed number to get arithmetic right shift.
139 return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
140}
141
142// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
143// to the Buffer.
144// This is the format used for the sint32 protocol buffer type.
Rob Pikea17fdd92011-11-02 12:43:05 -0700145func (p *Buffer) EncodeZigzag32(x uint64) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700146 // use signed number to get arithmetic right shift.
147 return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
148}
149
150// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
151// This is the format used for the bytes protocol buffer
152// type and for embedded messages.
Rob Pikea17fdd92011-11-02 12:43:05 -0700153func (p *Buffer) EncodeRawBytes(b []byte) error {
Rob Pike76f6ee52011-10-20 12:58:28 -0700154 p.EncodeVarint(uint64(len(b)))
Rob Pike99fa2b62010-12-02 10:39:42 -0800155 p.buf = append(p.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700156 return nil
157}
158
159// EncodeStringBytes writes an encoded string to the Buffer.
160// This is the format used for the proto2 string type.
Rob Pikea17fdd92011-11-02 12:43:05 -0700161func (p *Buffer) EncodeStringBytes(s string) error {
Rob Pike76f6ee52011-10-20 12:58:28 -0700162 p.EncodeVarint(uint64(len(s)))
163 p.buf = append(p.buf, s...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700164 return nil
165}
166
167// Marshaler is the interface representing objects that can marshal themselves.
168type Marshaler interface {
Rob Pikea17fdd92011-11-02 12:43:05 -0700169 Marshal() ([]byte, error)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700170}
171
172// Marshal takes the protocol buffer struct represented by pb
173// and encodes it into the wire format, returning the data.
Rob Pikea17fdd92011-11-02 12:43:05 -0700174func Marshal(pb interface{}) ([]byte, error) {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700175 // Can the object marshal itself?
176 if m, ok := pb.(Marshaler); ok {
177 return m.Marshal()
178 }
179 p := NewBuffer(nil)
180 err := p.Marshal(pb)
181 if err != nil {
182 return nil, err
183 }
184 return p.buf, err
185}
186
187// Marshal takes the protocol buffer struct represented by pb
188// and encodes it into the wire format, writing the result to the
189// Buffer.
Rob Pikea17fdd92011-11-02 12:43:05 -0700190func (p *Buffer) Marshal(pb interface{}) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700191 // Can the object marshal itself?
192 if m, ok := pb.(Marshaler); ok {
193 data, err := m.Marshal()
194 if err != nil {
195 return err
196 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800197 p.buf = append(p.buf, data...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700198 return nil
199 }
200
Rob Pikeaaa3a622010-03-20 22:32:34 -0700201 t, b, err := getbase(pb)
202 if err == nil {
Rob Pike97e934d2011-04-11 12:52:49 -0700203 err = p.enc_struct(t.Elem(), b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700204 }
205
Rob Pikeaaa3a622010-03-20 22:32:34 -0700206 stats.Encode++
207
208 return err
209}
210
211// Individual type encoders.
212
213// Encode a bool.
Rob Pikea17fdd92011-11-02 12:43:05 -0700214func (o *Buffer) enc_bool(p *Properties, base uintptr) error {
Rob Pike0f42a272011-10-20 16:03:11 -0700215 v := *(**bool)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700216 if v == nil {
217 return ErrNil
218 }
Rob Pike0f42a272011-10-20 16:03:11 -0700219 x := 0
220 if *v {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700221 x = 1
222 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800223 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700224 p.valEnc(o, uint64(x))
225 return nil
226}
227
228// Encode an int32.
Rob Pikea17fdd92011-11-02 12:43:05 -0700229func (o *Buffer) enc_int32(p *Properties, base uintptr) error {
Rob Pike0f42a272011-10-20 16:03:11 -0700230 v := *(**int32)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700231 if v == nil {
232 return ErrNil
233 }
234 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800235 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700236 p.valEnc(o, uint64(x))
237 return nil
238}
239
240// Encode an int64.
Rob Pikea17fdd92011-11-02 12:43:05 -0700241func (o *Buffer) enc_int64(p *Properties, base uintptr) error {
Rob Pike0f42a272011-10-20 16:03:11 -0700242 v := *(**int64)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700243 if v == nil {
244 return ErrNil
245 }
246 x := *v
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 a string.
Rob Pikea17fdd92011-11-02 12:43:05 -0700253func (o *Buffer) enc_string(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700254 v := *(**string)(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 o.EncodeStringBytes(x)
261 return nil
262}
263
Rob Pike97e934d2011-04-11 12:52:49 -0700264// All protocol buffer fields are nillable, but be careful.
265func isNil(v reflect.Value) bool {
266 switch v.Kind() {
Rob Pikeac8b1ce2011-04-11 16:14:54 -0700267 case reflect.Map, reflect.Ptr, reflect.Slice:
Rob Pike97e934d2011-04-11 12:52:49 -0700268 return v.IsNil()
269 }
270 return false
271}
272
Rob Pikeaaa3a622010-03-20 22:32:34 -0700273// Encode a message struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700274func (o *Buffer) enc_struct_message(p *Properties, base uintptr) error {
David Symondsa80b2822012-03-14 14:31:25 +1100275 structp := *(*unsafe.Pointer)(unsafe.Pointer(base + p.offset))
276 if structp == nil {
277 return ErrNil
278 }
279
280 typ := p.stype.Elem()
281
Rob Pikeaaa3a622010-03-20 22:32:34 -0700282 // Can the object marshal itself?
David Symondsa80b2822012-03-14 14:31:25 +1100283 if p.isMarshaler {
284 m := reflect.NewAt(typ, structp).Interface().(Marshaler)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700285 data, err := m.Marshal()
286 if err != nil {
287 return err
288 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800289 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700290 o.EncodeRawBytes(data)
291 return nil
292 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700293
294 // need the length before we can write out the message itself,
295 // so marshal into a separate byte buffer first.
296 obuf := o.buf
297 o.buf = o.bufalloc()
298
David Symondsa80b2822012-03-14 14:31:25 +1100299 err := o.enc_struct(typ, uintptr(structp))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700300
301 nbuf := o.buf
302 o.buf = obuf
303 if err != nil {
304 o.buffree(nbuf)
305 return err
306 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800307 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700308 o.EncodeRawBytes(nbuf)
309 o.buffree(nbuf)
310 return nil
311}
312
313// Encode a group struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700314func (o *Buffer) enc_struct_group(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700315 v := *(**struct{})(unsafe.Pointer(base + p.offset))
316 if v == nil {
317 return ErrNil
318 }
319
320 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
321 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700322 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700323 err := o.enc_struct(typ, b)
324 if err != nil {
325 return err
326 }
327 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
328 return nil
329}
330
331// Encode a slice of bools ([]bool).
Rob Pikea17fdd92011-11-02 12:43:05 -0700332func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700333 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
334 l := len(s)
335 if l == 0 {
336 return ErrNil
337 }
338 for _, x := range s {
Rob Pike99fa2b62010-12-02 10:39:42 -0800339 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700340 if x != 0 {
341 x = 1
342 }
343 p.valEnc(o, uint64(x))
344 }
345 return nil
346}
347
David Symonds5b7775e2010-12-01 10:09:04 +1100348// Encode a slice of bools ([]bool) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700349func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100350 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
351 l := len(s)
352 if l == 0 {
353 return ErrNil
354 }
355 o.buf = append(o.buf, p.tagcode...)
356 o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
357 for _, x := range s {
358 if x != 0 {
359 x = 1
360 }
361 p.valEnc(o, uint64(x))
362 }
363 return nil
364}
365
Rob Pikeaaa3a622010-03-20 22:32:34 -0700366// Encode a slice of bytes ([]byte).
Rob Pikea17fdd92011-11-02 12:43:05 -0700367func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700368 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800369 if s == nil {
370 return ErrNil
371 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800372 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700373 o.EncodeRawBytes(s)
374 return nil
375}
376
377// Encode a slice of int32s ([]int32).
Rob Pikea17fdd92011-11-02 12:43:05 -0700378func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700379 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
380 l := len(s)
381 if l == 0 {
382 return ErrNil
383 }
384 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800385 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700386 x := s[i]
387 p.valEnc(o, uint64(x))
388 }
389 return nil
390}
391
David Symonds5b7775e2010-12-01 10:09:04 +1100392// Encode a slice of int32s ([]int32) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700393func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100394 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
395 l := len(s)
396 if l == 0 {
397 return ErrNil
398 }
399 // TODO: Reuse a Buffer.
400 buf := NewBuffer(nil)
401 for i := 0; i < l; i++ {
402 p.valEnc(buf, uint64(s[i]))
403 }
404
405 o.buf = append(o.buf, p.tagcode...)
406 o.EncodeVarint(uint64(len(buf.buf)))
407 o.buf = append(o.buf, buf.buf...)
408 return nil
409}
410
Rob Pikeaaa3a622010-03-20 22:32:34 -0700411// Encode a slice of int64s ([]int64).
Rob Pikea17fdd92011-11-02 12:43:05 -0700412func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700413 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
414 l := len(s)
415 if l == 0 {
416 return ErrNil
417 }
418 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800419 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700420 x := s[i]
421 p.valEnc(o, uint64(x))
422 }
423 return nil
424}
425
David Symonds5b7775e2010-12-01 10:09:04 +1100426// Encode a slice of int64s ([]int64) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700427func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100428 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
429 l := len(s)
430 if l == 0 {
431 return ErrNil
432 }
433 // TODO: Reuse a Buffer.
434 buf := NewBuffer(nil)
435 for i := 0; i < l; i++ {
436 p.valEnc(buf, s[i])
437 }
438
439 o.buf = append(o.buf, p.tagcode...)
440 o.EncodeVarint(uint64(len(buf.buf)))
441 o.buf = append(o.buf, buf.buf...)
442 return nil
443}
444
Rob Pikeaaa3a622010-03-20 22:32:34 -0700445// Encode a slice of slice of bytes ([][]byte).
Rob Pikea17fdd92011-11-02 12:43:05 -0700446func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700447 ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
448 l := len(ss)
449 if l == 0 {
450 return ErrNil
451 }
452 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800453 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700454 s := ss[i]
455 o.EncodeRawBytes(s)
456 }
457 return nil
458}
459
460// Encode a slice of strings ([]string).
Rob Pikea17fdd92011-11-02 12:43:05 -0700461func (o *Buffer) enc_slice_string(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700462 ss := *(*[]string)(unsafe.Pointer(base + p.offset))
463 l := len(ss)
464 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800465 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700466 s := ss[i]
467 o.EncodeStringBytes(s)
468 }
469 return nil
470}
471
472// Encode a slice of message structs ([]*struct).
Rob Pikea17fdd92011-11-02 12:43:05 -0700473func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) error {
David Symondsa80b2822012-03-14 14:31:25 +1100474 s := *(*[]unsafe.Pointer)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700475 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700476 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700477
478 for i := 0; i < l; i++ {
David Symondsa80b2822012-03-14 14:31:25 +1100479 structp := s[i]
480 if structp == nil {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700481 return ErrRepeatedHasNil
482 }
483
484 // Can the object marshal itself?
David Symondsa80b2822012-03-14 14:31:25 +1100485 if p.isMarshaler {
486 m := reflect.NewAt(typ, structp).Interface().(Marshaler)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700487 data, err := m.Marshal()
488 if err != nil {
489 return err
490 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800491 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700492 o.EncodeRawBytes(data)
493 continue
494 }
495
496 obuf := o.buf
497 o.buf = o.bufalloc()
498
David Symondsa80b2822012-03-14 14:31:25 +1100499 err := o.enc_struct(typ, uintptr(structp))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700500
501 nbuf := o.buf
502 o.buf = obuf
503 if err != nil {
504 o.buffree(nbuf)
505 if err == ErrNil {
506 return ErrRepeatedHasNil
507 }
508 return err
509 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800510 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700511 o.EncodeRawBytes(nbuf)
512
513 o.buffree(nbuf)
514 }
515 return nil
516}
517
518// Encode a slice of group structs ([]*struct).
Rob Pikea17fdd92011-11-02 12:43:05 -0700519func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700520 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
521 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700522 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700523
524 for i := 0; i < l; i++ {
525 v := s[i]
526 if v == nil {
527 return ErrRepeatedHasNil
528 }
529
530 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
531
532 b := uintptr(unsafe.Pointer(v))
533 err := o.enc_struct(typ, b)
534
535 if err != nil {
536 if err == ErrNil {
537 return ErrRepeatedHasNil
538 }
539 return err
540 }
541
542 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
543 }
544 return nil
545}
546
547// Encode an extension map.
Rob Pikea17fdd92011-11-02 12:43:05 -0700548func (o *Buffer) enc_map(p *Properties, base uintptr) error {
David Symonds1d72f7a2011-08-19 18:28:52 +1000549 v := *(*map[int32]Extension)(unsafe.Pointer(base + p.offset))
550 if err := encodeExtensionMap(v); err != nil {
551 return err
552 }
553 for _, e := range v {
554 o.buf = append(o.buf, e.enc...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700555 }
556 return nil
557}
558
559// Encode a struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700560func (o *Buffer) enc_struct(t reflect.Type, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700561 prop := GetProperties(t)
562 required := prop.reqCount
David Symondsd15e81b2011-10-03 14:31:12 -0700563 // Encode fields in tag order so that decoders may use optimizations
564 // that depend on the ordering.
565 // http://code.google.com/apis/protocolbuffers/docs/encoding.html#order
566 for _, i := range prop.order {
567 p := prop.Prop[i]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700568 if p.enc != nil {
569 err := p.enc(o, p, base)
570 if err != nil {
571 if err != ErrNil {
572 return err
573 }
574 } else if p.Required {
575 required--
576 }
577 }
578 }
579 // See if we encoded all required fields.
580 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100581 return &ErrRequiredNotSet{t}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700582 }
583
584 return nil
585}