blob: 2eec125573ab61be1305d0ec3c9b0af9c13fd410 [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)
Rob Pikeaaa3a622010-03-20 22:32:34 -070065
66// The fundamental encoders that put bytes on the wire.
67// Those that take integer types all accept uint64 and are
68// therefore of type valueEncoder.
69
David Symonds4fee3b12010-11-11 10:00:13 +110070const maxVarintBytes = 10 // maximum length of a varint
71
Rob Pikeaaa3a622010-03-20 22:32:34 -070072// EncodeVarint returns the varint encoding of x.
73// This is the format for the
74// int32, int64, uint32, uint64, bool, and enum
75// protocol buffer types.
76// Not used by the package itself, but helpful to clients
77// wishing to use the same encoding.
78func EncodeVarint(x uint64) []byte {
David Symonds4fee3b12010-11-11 10:00:13 +110079 var buf [maxVarintBytes]byte
Rob Pikeaaa3a622010-03-20 22:32:34 -070080 var n int
81 for n = 0; x > 127; n++ {
82 buf[n] = 0x80 | uint8(x&0x7F)
83 x >>= 7
84 }
85 buf[n] = uint8(x)
86 n++
87 return buf[0:n]
88}
89
90// EncodeVarint writes a varint-encoded integer to the Buffer.
91// This is the format for the
92// int32, int64, uint32, uint64, bool, and enum
93// protocol buffer types.
Rob Pikea17fdd92011-11-02 12:43:05 -070094func (p *Buffer) EncodeVarint(x uint64) error {
David Symonds4fee3b12010-11-11 10:00:13 +110095 for x >= 1<<7 {
David Symondsd9da6ba2011-08-30 14:41:30 +100096 p.buf = append(p.buf, uint8(x&0x7f|0x80))
Rob Pikeaaa3a622010-03-20 22:32:34 -070097 x >>= 7
98 }
David Symondsd9da6ba2011-08-30 14:41:30 +100099 p.buf = append(p.buf, uint8(x))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700100 return nil
101}
102
103// EncodeFixed64 writes a 64-bit integer to the Buffer.
104// This is the format for the
105// fixed64, sfixed64, and double protocol buffer types.
Rob Pikea17fdd92011-11-02 12:43:05 -0700106func (p *Buffer) EncodeFixed64(x uint64) error {
David Symondsd9da6ba2011-08-30 14:41:30 +1000107 p.buf = append(p.buf,
108 uint8(x),
109 uint8(x>>8),
110 uint8(x>>16),
111 uint8(x>>24),
112 uint8(x>>32),
113 uint8(x>>40),
114 uint8(x>>48),
115 uint8(x>>56))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700116 return nil
117}
118
119// EncodeFixed32 writes a 32-bit integer to the Buffer.
120// This is the format for the
121// fixed32, sfixed32, and float protocol buffer types.
Rob Pikea17fdd92011-11-02 12:43:05 -0700122func (p *Buffer) EncodeFixed32(x uint64) error {
David Symondsd9da6ba2011-08-30 14:41:30 +1000123 p.buf = append(p.buf,
124 uint8(x),
125 uint8(x>>8),
126 uint8(x>>16),
127 uint8(x>>24))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700128 return nil
129}
130
131// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
132// to the Buffer.
133// This is the format used for the sint64 protocol buffer type.
Rob Pikea17fdd92011-11-02 12:43:05 -0700134func (p *Buffer) EncodeZigzag64(x uint64) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700135 // use signed number to get arithmetic right shift.
136 return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
137}
138
139// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
140// to the Buffer.
141// This is the format used for the sint32 protocol buffer type.
Rob Pikea17fdd92011-11-02 12:43:05 -0700142func (p *Buffer) EncodeZigzag32(x uint64) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700143 // use signed number to get arithmetic right shift.
144 return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
145}
146
147// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
148// This is the format used for the bytes protocol buffer
149// type and for embedded messages.
Rob Pikea17fdd92011-11-02 12:43:05 -0700150func (p *Buffer) EncodeRawBytes(b []byte) error {
Rob Pike76f6ee52011-10-20 12:58:28 -0700151 p.EncodeVarint(uint64(len(b)))
Rob Pike99fa2b62010-12-02 10:39:42 -0800152 p.buf = append(p.buf, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700153 return nil
154}
155
156// EncodeStringBytes writes an encoded string to the Buffer.
157// This is the format used for the proto2 string type.
Rob Pikea17fdd92011-11-02 12:43:05 -0700158func (p *Buffer) EncodeStringBytes(s string) error {
Rob Pike76f6ee52011-10-20 12:58:28 -0700159 p.EncodeVarint(uint64(len(s)))
160 p.buf = append(p.buf, s...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700161 return nil
162}
163
164// Marshaler is the interface representing objects that can marshal themselves.
165type Marshaler interface {
Rob Pikea17fdd92011-11-02 12:43:05 -0700166 Marshal() ([]byte, error)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700167}
168
David Symonds9f60f432012-06-14 09:45:25 +1000169// Marshal takes the protocol buffer
Rob Pikeaaa3a622010-03-20 22:32:34 -0700170// and encodes it into the wire format, returning the data.
David Symonds9f60f432012-06-14 09:45:25 +1000171func Marshal(pb Message) ([]byte, error) {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700172 // Can the object marshal itself?
173 if m, ok := pb.(Marshaler); ok {
174 return m.Marshal()
175 }
176 p := NewBuffer(nil)
177 err := p.Marshal(pb)
178 if err != nil {
179 return nil, err
180 }
181 return p.buf, err
182}
183
David Symonds9f60f432012-06-14 09:45:25 +1000184// Marshal takes the protocol buffer
Rob Pikeaaa3a622010-03-20 22:32:34 -0700185// and encodes it into the wire format, writing the result to the
186// Buffer.
David Symonds9f60f432012-06-14 09:45:25 +1000187func (p *Buffer) Marshal(pb Message) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700188 // Can the object marshal itself?
189 if m, ok := pb.(Marshaler); ok {
190 data, err := m.Marshal()
191 if err != nil {
192 return err
193 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800194 p.buf = append(p.buf, data...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700195 return nil
196 }
197
Rob Pikeaaa3a622010-03-20 22:32:34 -0700198 t, b, err := getbase(pb)
199 if err == nil {
David Symondsc0287172012-08-15 11:10:30 +1000200 err = p.enc_struct(t.Elem(), GetProperties(t.Elem()), b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700201 }
202
David Symonds9f60f432012-06-14 09:45:25 +1000203 if collectStats {
204 stats.Encode++
205 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700206
207 return err
208}
209
210// Individual type encoders.
211
212// Encode a bool.
Rob Pikea17fdd92011-11-02 12:43:05 -0700213func (o *Buffer) enc_bool(p *Properties, base uintptr) error {
Rob Pike0f42a272011-10-20 16:03:11 -0700214 v := *(**bool)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700215 if v == nil {
216 return ErrNil
217 }
Rob Pike0f42a272011-10-20 16:03:11 -0700218 x := 0
219 if *v {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700220 x = 1
221 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800222 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700223 p.valEnc(o, uint64(x))
224 return nil
225}
226
227// Encode an int32.
Rob Pikea17fdd92011-11-02 12:43:05 -0700228func (o *Buffer) enc_int32(p *Properties, base uintptr) error {
Rob Pike0f42a272011-10-20 16:03:11 -0700229 v := *(**int32)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700230 if v == nil {
231 return ErrNil
232 }
233 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800234 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700235 p.valEnc(o, uint64(x))
236 return nil
237}
238
239// Encode an int64.
Rob Pikea17fdd92011-11-02 12:43:05 -0700240func (o *Buffer) enc_int64(p *Properties, base uintptr) error {
Rob Pike0f42a272011-10-20 16:03:11 -0700241 v := *(**int64)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700242 if v == nil {
243 return ErrNil
244 }
245 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800246 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700247 p.valEnc(o, uint64(x))
248 return nil
249}
250
251// Encode a string.
Rob Pikea17fdd92011-11-02 12:43:05 -0700252func (o *Buffer) enc_string(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700253 v := *(**string)(unsafe.Pointer(base + p.offset))
254 if v == nil {
255 return ErrNil
256 }
257 x := *v
Rob Pike99fa2b62010-12-02 10:39:42 -0800258 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700259 o.EncodeStringBytes(x)
260 return nil
261}
262
Rob Pike97e934d2011-04-11 12:52:49 -0700263// All protocol buffer fields are nillable, but be careful.
264func isNil(v reflect.Value) bool {
265 switch v.Kind() {
David Symonds007ed9d2012-07-24 10:59:36 +1000266 case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
Rob Pike97e934d2011-04-11 12:52:49 -0700267 return v.IsNil()
268 }
269 return false
270}
271
Rob Pikeaaa3a622010-03-20 22:32:34 -0700272// Encode a message struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700273func (o *Buffer) enc_struct_message(p *Properties, base uintptr) error {
David Symondsa80b2822012-03-14 14:31:25 +1100274 structp := *(*unsafe.Pointer)(unsafe.Pointer(base + p.offset))
275 if structp == nil {
276 return ErrNil
277 }
278
Rob Pikeaaa3a622010-03-20 22:32:34 -0700279 // Can the object marshal itself?
David Symondsa80b2822012-03-14 14:31:25 +1100280 if p.isMarshaler {
David Symonds6a6f82c2012-08-22 09:18:54 +1000281 m := reflect.NewAt(p.stype, structp).Interface().(Marshaler)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700282 data, err := m.Marshal()
283 if err != nil {
284 return err
285 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800286 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700287 o.EncodeRawBytes(data)
288 return nil
289 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700290
291 // need the length before we can write out the message itself,
292 // so marshal into a separate byte buffer first.
293 obuf := o.buf
294 o.buf = o.bufalloc()
295
David Symonds6a6f82c2012-08-22 09:18:54 +1000296 err := o.enc_struct(p.stype, p.sprop, uintptr(structp))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700297
298 nbuf := o.buf
299 o.buf = obuf
300 if err != nil {
301 o.buffree(nbuf)
302 return err
303 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800304 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700305 o.EncodeRawBytes(nbuf)
306 o.buffree(nbuf)
307 return nil
308}
309
310// Encode a group struct.
Rob Pikea17fdd92011-11-02 12:43:05 -0700311func (o *Buffer) enc_struct_group(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700312 v := *(**struct{})(unsafe.Pointer(base + p.offset))
313 if v == nil {
314 return ErrNil
315 }
316
317 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
318 b := uintptr(unsafe.Pointer(v))
David Symonds6a6f82c2012-08-22 09:18:54 +1000319 err := o.enc_struct(p.stype, p.sprop, b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700320 if err != nil {
321 return err
322 }
323 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
324 return nil
325}
326
327// Encode a slice of bools ([]bool).
Rob Pikea17fdd92011-11-02 12:43:05 -0700328func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700329 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
330 l := len(s)
331 if l == 0 {
332 return ErrNil
333 }
334 for _, x := range s {
Rob Pike99fa2b62010-12-02 10:39:42 -0800335 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700336 if x != 0 {
337 x = 1
338 }
339 p.valEnc(o, uint64(x))
340 }
341 return nil
342}
343
David Symonds5b7775e2010-12-01 10:09:04 +1100344// Encode a slice of bools ([]bool) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700345func (o *Buffer) enc_slice_packed_bool(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100346 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
347 l := len(s)
348 if l == 0 {
349 return ErrNil
350 }
351 o.buf = append(o.buf, p.tagcode...)
352 o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
353 for _, x := range s {
354 if x != 0 {
355 x = 1
356 }
357 p.valEnc(o, uint64(x))
358 }
359 return nil
360}
361
Rob Pikeaaa3a622010-03-20 22:32:34 -0700362// Encode a slice of bytes ([]byte).
Rob Pikea17fdd92011-11-02 12:43:05 -0700363func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700364 s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800365 if s == nil {
366 return ErrNil
367 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800368 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700369 o.EncodeRawBytes(s)
370 return nil
371}
372
373// Encode a slice of int32s ([]int32).
Rob Pikea17fdd92011-11-02 12:43:05 -0700374func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700375 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
376 l := len(s)
377 if l == 0 {
378 return ErrNil
379 }
380 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800381 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700382 x := s[i]
383 p.valEnc(o, uint64(x))
384 }
385 return nil
386}
387
David Symonds5b7775e2010-12-01 10:09:04 +1100388// Encode a slice of int32s ([]int32) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700389func (o *Buffer) enc_slice_packed_int32(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100390 s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
391 l := len(s)
392 if l == 0 {
393 return ErrNil
394 }
395 // TODO: Reuse a Buffer.
396 buf := NewBuffer(nil)
397 for i := 0; i < l; i++ {
398 p.valEnc(buf, uint64(s[i]))
399 }
400
401 o.buf = append(o.buf, p.tagcode...)
402 o.EncodeVarint(uint64(len(buf.buf)))
403 o.buf = append(o.buf, buf.buf...)
404 return nil
405}
406
Rob Pikeaaa3a622010-03-20 22:32:34 -0700407// Encode a slice of int64s ([]int64).
Rob Pikea17fdd92011-11-02 12:43:05 -0700408func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700409 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
410 l := len(s)
411 if l == 0 {
412 return ErrNil
413 }
414 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800415 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700416 x := s[i]
417 p.valEnc(o, uint64(x))
418 }
419 return nil
420}
421
David Symonds5b7775e2010-12-01 10:09:04 +1100422// Encode a slice of int64s ([]int64) in packed format.
Rob Pikea17fdd92011-11-02 12:43:05 -0700423func (o *Buffer) enc_slice_packed_int64(p *Properties, base uintptr) error {
David Symonds5b7775e2010-12-01 10:09:04 +1100424 s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
425 l := len(s)
426 if l == 0 {
427 return ErrNil
428 }
429 // TODO: Reuse a Buffer.
430 buf := NewBuffer(nil)
431 for i := 0; i < l; i++ {
432 p.valEnc(buf, s[i])
433 }
434
435 o.buf = append(o.buf, p.tagcode...)
436 o.EncodeVarint(uint64(len(buf.buf)))
437 o.buf = append(o.buf, buf.buf...)
438 return nil
439}
440
Rob Pikeaaa3a622010-03-20 22:32:34 -0700441// Encode a slice of slice of bytes ([][]byte).
Rob Pikea17fdd92011-11-02 12:43:05 -0700442func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700443 ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
444 l := len(ss)
445 if l == 0 {
446 return ErrNil
447 }
448 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800449 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700450 s := ss[i]
451 o.EncodeRawBytes(s)
452 }
453 return nil
454}
455
456// Encode a slice of strings ([]string).
Rob Pikea17fdd92011-11-02 12:43:05 -0700457func (o *Buffer) enc_slice_string(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700458 ss := *(*[]string)(unsafe.Pointer(base + p.offset))
459 l := len(ss)
460 for i := 0; i < l; i++ {
Rob Pike99fa2b62010-12-02 10:39:42 -0800461 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700462 s := ss[i]
463 o.EncodeStringBytes(s)
464 }
465 return nil
466}
467
468// Encode a slice of message structs ([]*struct).
Rob Pikea17fdd92011-11-02 12:43:05 -0700469func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) error {
David Symondsa80b2822012-03-14 14:31:25 +1100470 s := *(*[]unsafe.Pointer)(unsafe.Pointer(base + p.offset))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700471 l := len(s)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700472
473 for i := 0; i < l; i++ {
David Symondsa80b2822012-03-14 14:31:25 +1100474 structp := s[i]
475 if structp == nil {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700476 return ErrRepeatedHasNil
477 }
478
479 // Can the object marshal itself?
David Symondsa80b2822012-03-14 14:31:25 +1100480 if p.isMarshaler {
David Symonds6a6f82c2012-08-22 09:18:54 +1000481 m := reflect.NewAt(p.stype, structp).Interface().(Marshaler)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700482 data, err := m.Marshal()
483 if err != nil {
484 return err
485 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800486 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700487 o.EncodeRawBytes(data)
488 continue
489 }
490
491 obuf := o.buf
492 o.buf = o.bufalloc()
493
David Symonds6a6f82c2012-08-22 09:18:54 +1000494 err := o.enc_struct(p.stype, p.sprop, uintptr(structp))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700495
496 nbuf := o.buf
497 o.buf = obuf
498 if err != nil {
499 o.buffree(nbuf)
500 if err == ErrNil {
501 return ErrRepeatedHasNil
502 }
503 return err
504 }
Rob Pike99fa2b62010-12-02 10:39:42 -0800505 o.buf = append(o.buf, p.tagcode...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700506 o.EncodeRawBytes(nbuf)
507
508 o.buffree(nbuf)
509 }
510 return nil
511}
512
513// Encode a slice of group structs ([]*struct).
Rob Pikea17fdd92011-11-02 12:43:05 -0700514func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700515 s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
516 l := len(s)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700517
518 for i := 0; i < l; i++ {
519 v := s[i]
520 if v == nil {
521 return ErrRepeatedHasNil
522 }
523
524 o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
525
526 b := uintptr(unsafe.Pointer(v))
David Symonds6a6f82c2012-08-22 09:18:54 +1000527 err := o.enc_struct(p.stype, p.sprop, b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700528
529 if err != nil {
530 if err == ErrNil {
531 return ErrRepeatedHasNil
532 }
533 return err
534 }
535
536 o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
537 }
538 return nil
539}
540
541// Encode an extension map.
Rob Pikea17fdd92011-11-02 12:43:05 -0700542func (o *Buffer) enc_map(p *Properties, base uintptr) error {
David Symonds1d72f7a2011-08-19 18:28:52 +1000543 v := *(*map[int32]Extension)(unsafe.Pointer(base + p.offset))
544 if err := encodeExtensionMap(v); err != nil {
545 return err
546 }
547 for _, e := range v {
548 o.buf = append(o.buf, e.enc...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700549 }
550 return nil
551}
552
553// Encode a struct.
David Symondsc0287172012-08-15 11:10:30 +1000554func (o *Buffer) enc_struct(t reflect.Type, prop *StructProperties, base uintptr) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700555 required := prop.reqCount
David Symondsd15e81b2011-10-03 14:31:12 -0700556 // Encode fields in tag order so that decoders may use optimizations
557 // that depend on the ordering.
558 // http://code.google.com/apis/protocolbuffers/docs/encoding.html#order
559 for _, i := range prop.order {
560 p := prop.Prop[i]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700561 if p.enc != nil {
562 err := p.enc(o, p, base)
563 if err != nil {
564 if err != ErrNil {
565 return err
566 }
567 } else if p.Required {
568 required--
569 }
570 }
571 }
572 // See if we encoded all required fields.
573 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100574 return &ErrRequiredNotSet{t}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700575 }
576
David Symonds10c93ba2012-08-04 16:38:08 +1000577 // Add unrecognized fields at the end.
578 v := *(*[]byte)(unsafe.Pointer(base + prop.unrecOffset))
579 if prop.unrecOffset > 0 && len(v) > 0 {
580 o.buf = append(o.buf, v...)
581 }
582
Rob Pikeaaa3a622010-03-20 22:32:34 -0700583 return nil
584}