blob: a1a9f1da6b7d8b3e9b1dd47f950fdf559140230a [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 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700275 // Can the object marshal itself?
Rob Pike7a788132012-02-14 08:14:14 +1100276 iv := reflect.NewAt(p.stype, unsafe.Pointer(base+p.offset)).Elem().Interface()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700277 if m, ok := iv.(Marshaler); ok {
Nigel Tao4ede8452011-04-28 11:27:25 +1000278 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000279 return ErrNil
280 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700281 data, err := m.Marshal()
282 if err != nil {
283 return err
284 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800285 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700286 o.EncodeRawBytes(data)
287 return nil
288 }
289 v := *(**struct{})(unsafe.Pointer(base + p.offset))
290 if v == nil {
291 return ErrNil
292 }
293
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
299 b := uintptr(unsafe.Pointer(v))
Rob Pike97e934d2011-04-11 12:52:49 -0700300 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700301 err := o.enc_struct(typ, b)
302
303 nbuf := o.buf
304 o.buf = obuf
305 if err != nil {
306 o.buffree(nbuf)
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(nbuf)
311 o.buffree(nbuf)
312 return nil
313}
314
315// Encode a group struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700316func (o *Buffer) enc_struct_group(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700317 v := *(**struct{})(unsafe.Pointer(base + p.offset))
318 if v == nil {
319 return ErrNil
320 }
321
322 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
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 if err != nil {
327 return err
328 }
329 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
330 return nil
331}
332
333// Encode a slice of bools ([]bool).
Rob Pikea17fdd92011-11-02 12:43:05 -0700334func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700335 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
336 l := len(s)
337 if l == 0 {
338 return ErrNil
339 }
340 for _, x := range s {
Rob Pike99fa2b62010-12-02 10:39:42 -0800341 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700342 if x != 0 {
343 x = 1
344 }
345 p.valEnc(o, uint64(x))
346 }
347 return nil
348}
349
David Symonds5b7775e2010-12-01 10:09:04 +1100350// Encode a slice of bools ([]bool) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700351func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100352 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
353 l := len(s)
354 if l == 0 {
355 return ErrNil
356 }
357 o.buf = append(o.buf, p.tagcode...)
358 o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
359 for _, x := range s {
360 if x != 0 {
361 x = 1
362 }
363 p.valEnc(o, uint64(x))
364 }
365 return nil
366}
367
Rob Pikeaaa3a622010-03-20 22:32:34 -0700368// Encode a slice of bytes ([]byte).
Rob Pikea17fdd92011-11-02 12:43:05 -0700369func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700370 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800371 if s == nil {
372 return ErrNil
373 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800374 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700375 o.EncodeRawBytes(s)
376 return nil
377}
378
379// Encode a slice of int32s ([]int32).
Rob Pikea17fdd92011-11-02 12:43:05 -0700380func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700381 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
382 l := len(s)
383 if l == 0 {
384 return ErrNil
385 }
386 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800387 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700388 x := s[i]
389 p.valEnc(o, uint64(x))
390 }
391 return nil
392}
393
David Symonds5b7775e2010-12-01 10:09:04 +1100394// Encode a slice of int32s ([]int32) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700395func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100396 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
397 l := len(s)
398 if l == 0 {
399 return ErrNil
400 }
401 // TODO: Reuse a Buffer.
402 buf := NewBuffer(nil)
403 for i := 0; i < l; i++ {
404 p.valEnc(buf, uint64(s[i]))
405 }
406
407 o.buf = append(o.buf, p.tagcode...)
408 o.EncodeVarint(uint64(len(buf.buf)))
409 o.buf = append(o.buf, buf.buf...)
410 return nil
411}
412
Rob Pikeaaa3a622010-03-20 22:32:34 -0700413// Encode a slice of int64s ([]int64).
Rob Pikea17fdd92011-11-02 12:43:05 -0700414func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700415 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
416 l := len(s)
417 if l == 0 {
418 return ErrNil
419 }
420 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800421 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700422 x := s[i]
423 p.valEnc(o, uint64(x))
424 }
425 return nil
426}
427
David Symonds5b7775e2010-12-01 10:09:04 +1100428// Encode a slice of int64s ([]int64) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700429func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100430 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
431 l := len(s)
432 if l == 0 {
433 return ErrNil
434 }
435 // TODO: Reuse a Buffer.
436 buf := NewBuffer(nil)
437 for i := 0; i < l; i++ {
438 p.valEnc(buf, s[i])
439 }
440
441 o.buf = append(o.buf, p.tagcode...)
442 o.EncodeVarint(uint64(len(buf.buf)))
443 o.buf = append(o.buf, buf.buf...)
444 return nil
445}
446
Rob Pikeaaa3a622010-03-20 22:32:34 -0700447// Encode a slice of slice of bytes ([][]byte).
Rob Pikea17fdd92011-11-02 12:43:05 -0700448func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700449 ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
450 l := len(ss)
451 if l == 0 {
452 return ErrNil
453 }
454 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800455 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700456 s := ss[i]
457 o.EncodeRawBytes(s)
458 }
459 return nil
460}
461
462// Encode a slice of strings ([]string).
Rob Pikea17fdd92011-11-02 12:43:05 -0700463func (o *Buffer) enc_slice_string(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700464 ss := *(*[]string)(unsafe.Pointer(base + p.offset))
465 l := len(ss)
466 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800467 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700468 s := ss[i]
469 o.EncodeStringBytes(s)
470 }
471 return nil
472}
473
474// Encode a slice of message structs ([]*struct).
Rob Pikea17fdd92011-11-02 12:43:05 -0700475func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700476 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
477 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700478 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700479
480 for i := 0; i < l; i++ {
481 v := s[i]
482 if v == nil {
483 return ErrRepeatedHasNil
484 }
485
486 // Can the object marshal itself?
Rob Pike7a788132012-02-14 08:14:14 +1100487 iv := reflect.NewAt(p.stype, unsafe.Pointer(&s[i])).Elem().Interface()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700488 if m, ok := iv.(Marshaler); ok {
David Symonds3fa055f2011-05-05 15:19:04 -0700489 if isNil(reflect.ValueOf(iv)) {
David Symonds03c9d412010-08-26 14:23:18 +1000490 return ErrNil
491 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700492 data, err := m.Marshal()
493 if err != nil {
494 return err
495 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800496 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700497 o.EncodeRawBytes(data)
498 continue
499 }
500
501 obuf := o.buf
502 o.buf = o.bufalloc()
503
504 b := uintptr(unsafe.Pointer(v))
505 err := o.enc_struct(typ, b)
506
507 nbuf := o.buf
508 o.buf = obuf
509 if err != nil {
510 o.buffree(nbuf)
511 if err == ErrNil {
512 return ErrRepeatedHasNil
513 }
514 return err
515 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800516 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700517 o.EncodeRawBytes(nbuf)
518
519 o.buffree(nbuf)
520 }
521 return nil
522}
523
524// Encode a slice of group structs ([]*struct).
Rob Pikea17fdd92011-11-02 12:43:05 -0700525func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700526 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
527 l := len(s)
Rob Pike97e934d2011-04-11 12:52:49 -0700528 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700529
530 for i := 0; i < l; i++ {
531 v := s[i]
532 if v == nil {
533 return ErrRepeatedHasNil
534 }
535
536 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
537
538 b := uintptr(unsafe.Pointer(v))
539 err := o.enc_struct(typ, b)
540
541 if err != nil {
542 if err == ErrNil {
543 return ErrRepeatedHasNil
544 }
545 return err
546 }
547
548 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
549 }
550 return nil
551}
552
553// Encode an extension map.
Rob Pikea17fdd92011-11-02 12:43:05 -0700554func (o *Buffer) enc_map(p *Properties, base uintptr) error {
David Symonds1d72f7a2011-08-19 18:28:52 +1000555 v := *(*map[int32]Extension)(unsafe.Pointer(base + p.offset))
556 if err := encodeExtensionMap(v); err != nil {
557 return err
558 }
559 for _, e := range v {
560 o.buf = append(o.buf, e.enc...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700561 }
562 return nil
563}
564
565// Encode a struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700566func (o *Buffer) enc_struct(t reflect.Type, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700567 prop := GetProperties(t)
568 required := prop.reqCount
David Symondsd15e81b2011-10-03 14:31:12 -0700569 // Encode fields in tag order so that decoders may use optimizations
570 // that depend on the ordering.
571 // http://code.google.com/apis/protocolbuffers/docs/encoding.html#order
572 for _, i := range prop.order {
573 p := prop.Prop[i]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700574 if p.enc != nil {
575 err := p.enc(o, p, base)
576 if err != nil {
577 if err != ErrNil {
578 return err
579 }
580 } else if p.Required {
581 required--
582 }
583 }
584 }
585 // See if we encoded all required fields.
586 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100587 return &ErrRequiredNotSet{t}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700588 }
589
590 return nil
591}