blob: 1c2bb3b4828114102d7e5f835d91a2e888a21107 [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 decoding protocol buffer data to construct in-memory representations.
36 */
37
38import (
Rob Pikeaaa3a622010-03-20 22:32:34 -070039 "fmt"
40 "io"
41 "os"
42 "reflect"
43 "runtime"
44 "unsafe"
45)
46
47// ErrWrongType occurs when the wire encoding for the field disagrees with
48// that specified in the type being decoded. This is usually caused by attempting
49// to convert an encoded protocol buffer into a struct of the wrong type.
50var ErrWrongType = os.NewError("field/encoding mismatch: wrong type for field")
51
52// The fundamental decoders that interpret bytes on the wire.
53// Those that take integer types all return uint64 and are
54// therefore of type valueDecoder.
55
56// DecodeVarint reads a varint-encoded integer from the slice.
57// It returns the integer and the number of bytes consumed, or
58// zero if there is not enough.
59// This is the format for the
60// int32, int64, uint32, uint64, bool, and enum
61// protocol buffer types.
62func DecodeVarint(buf []byte) (x uint64, n int) {
63 // x, n already 0
64 for shift := uint(0); ; shift += 7 {
65 if n >= len(buf) {
66 return 0, 0
67 }
68 b := uint64(buf[n])
69 n++
70 x |= (b & 0x7F) << shift
71 if (b & 0x80) == 0 {
72 break
73 }
74 }
75 return x, n
76}
77
78// DecodeVarint reads a varint-encoded integer from the Buffer.
79// This is the format for the
80// int32, int64, uint32, uint64, bool, and enum
81// protocol buffer types.
82func (p *Buffer) DecodeVarint() (x uint64, err os.Error) {
83 // x, err already 0
84
85 i := p.index
86 l := len(p.buf)
87
88 for shift := uint(0); ; shift += 7 {
89 if i >= l {
90 err = io.ErrUnexpectedEOF
91 return
92 }
93 b := p.buf[i]
94 i++
95 x |= (uint64(b) & 0x7F) << shift
96 if b < 0x80 {
97 break
98 }
99 }
100 p.index = i
101 return
102}
103
104// DecodeFixed64 reads a 64-bit integer from the Buffer.
105// This is the format for the
106// fixed64, sfixed64, and double protocol buffer types.
107func (p *Buffer) DecodeFixed64() (x uint64, err os.Error) {
108 // x, err already 0
109 i := p.index + 8
110 if i > len(p.buf) {
111 err = io.ErrUnexpectedEOF
112 return
113 }
114 p.index = i
115
116 x = uint64(p.buf[i-8])
117 x |= uint64(p.buf[i-7]) << 8
118 x |= uint64(p.buf[i-6]) << 16
119 x |= uint64(p.buf[i-5]) << 24
120 x |= uint64(p.buf[i-4]) << 32
121 x |= uint64(p.buf[i-3]) << 40
122 x |= uint64(p.buf[i-2]) << 48
123 x |= uint64(p.buf[i-1]) << 56
124 return
125}
126
127// DecodeFixed32 reads a 32-bit integer from the Buffer.
128// This is the format for the
129// fixed32, sfixed32, and float protocol buffer types.
130func (p *Buffer) DecodeFixed32() (x uint64, err os.Error) {
131 // x, err already 0
132 i := p.index + 4
133 if i > len(p.buf) {
134 err = io.ErrUnexpectedEOF
135 return
136 }
137 p.index = i
138
139 x = uint64(p.buf[i-4])
140 x |= uint64(p.buf[i-3]) << 8
141 x |= uint64(p.buf[i-2]) << 16
142 x |= uint64(p.buf[i-1]) << 24
143 return
144}
145
146// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
147// from the Buffer.
148// This is the format used for the sint64 protocol buffer type.
149func (p *Buffer) DecodeZigzag64() (x uint64, err os.Error) {
150 x, err = p.DecodeVarint()
151 if err != nil {
152 return
153 }
154 x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
155 return
156}
157
158// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
159// from the Buffer.
160// This is the format used for the sint32 protocol buffer type.
161func (p *Buffer) DecodeZigzag32() (x uint64, err os.Error) {
162 x, err = p.DecodeVarint()
163 if err != nil {
164 return
165 }
166 x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
167 return
168}
169
170// These are not ValueDecoders: they produce an array of bytes or a string.
171// bytes, embedded messages
172
173// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
174// This is the format used for the bytes protocol buffer
175// type and for embedded messages.
176func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err os.Error) {
177 n, err := p.DecodeVarint()
178 if err != nil {
179 return
180 }
181
182 nb := int(n)
183 if p.index+nb > len(p.buf) {
184 err = io.ErrUnexpectedEOF
185 return
186 }
187
188 if !alloc {
189 // todo: check if can get more uses of alloc=false
190 buf = p.buf[p.index : p.index+nb]
191 p.index += nb
192 return
193 }
194
195 buf = make([]byte, nb)
196 copy(buf, p.buf[p.index:])
197 p.index += nb
198 return
199}
200
201// DecodeStringBytes reads an encoded string from the Buffer.
202// This is the format used for the proto2 string type.
203func (p *Buffer) DecodeStringBytes() (s string, err os.Error) {
204 buf, err := p.DecodeRawBytes(false)
205 if err != nil {
206 return
207 }
208 return string(buf), nil
209}
210
211// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
212// If the protocol buffer has extensions, and the field matches, add it as an extension.
213// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
Rob Pike97e934d2011-04-11 12:52:49 -0700214func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base uintptr) os.Error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700215
216 oi := o.index
217
218 err := o.skip(t, tag, wire)
219 if err != nil {
220 return err
221 }
222
223 x := fieldIndex(t, "XXX_unrecognized")
224 if x == nil {
225 return nil
226 }
227
228 p := propByIndex(t, x)
229 ptr := (*[]byte)(unsafe.Pointer(base + p.offset))
230
231 if *ptr == nil {
232 // This is the first skipped element,
233 // allocate a new buffer.
234 *ptr = o.bufalloc()
235 }
236
237 // Add the skipped field to struct field
238 obuf := o.buf
239
240 o.buf = *ptr
241 o.EncodeVarint(uint64(tag<<3 | wire))
Rob Pike99fa2b62010-12-02 10:39:42 -0800242 *ptr = append(o.buf, obuf[oi:o.index]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700243
244 o.buf = obuf
245
246 return nil
247}
248
249// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
Rob Pike97e934d2011-04-11 12:52:49 -0700250func (o *Buffer) skip(t reflect.Type, tag, wire int) os.Error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700251
252 var u uint64
253 var err os.Error
254
255 switch wire {
256 case WireVarint:
257 _, err = o.DecodeVarint()
258 case WireFixed64:
259 _, err = o.DecodeFixed64()
260 case WireBytes:
261 _, err = o.DecodeRawBytes(false)
262 case WireFixed32:
263 _, err = o.DecodeFixed32()
264 case WireStartGroup:
265 for {
266 u, err = o.DecodeVarint()
267 if err != nil {
268 break
269 }
270 fwire := int(u & 0x7)
271 if fwire == WireEndGroup {
272 break
273 }
274 ftag := int(u >> 3)
275 err = o.skip(t, ftag, fwire)
276 if err != nil {
277 break
278 }
279 }
280 default:
281 fmt.Fprintf(os.Stderr, "proto: can't skip wire type %d for %s\n", wire, t)
282 }
283 return err
284}
285
286// Unmarshaler is the interface representing objects that can unmarshal themselves.
287type Unmarshaler interface {
288 Unmarshal([]byte) os.Error
289}
290
291// Unmarshal parses the protocol buffer representation in buf and places the
292// decoded result in pb. If the struct underlying pb does not match
293// the data in buf, the results can be unpredictable.
294func Unmarshal(buf []byte, pb interface{}) os.Error {
295 // If the object can unmarshal itself, let it.
296 if u, ok := pb.(Unmarshaler); ok {
297 return u.Unmarshal(buf)
298 }
299
300 return NewBuffer(buf).Unmarshal(pb)
301}
302
303// Unmarshal parses the protocol buffer representation in the
304// Buffer and places the decoded result in pb. If the struct
305// underlying pb does not match the data in the buffer, the results can be
306// unpredictable.
307func (p *Buffer) Unmarshal(pb interface{}) os.Error {
308 // If the object can unmarshal itself, let it.
309 if u, ok := pb.(Unmarshaler); ok {
310 err := u.Unmarshal(p.buf[p.index:])
311 p.index = len(p.buf)
312 return err
313 }
314
315 mstat := runtime.MemStats.Mallocs
316
317 typ, base, err := getbase(pb)
318 if err != nil {
319 return err
320 }
321
322 err = p.unmarshalType(typ, false, base)
323
324 mstat = runtime.MemStats.Mallocs - mstat
325 stats.Dmalloc += mstat
326 stats.Decode++
327
328 return err
329}
330
331// unmarshalType does the work of unmarshaling a structure.
Rob Pike97e934d2011-04-11 12:52:49 -0700332func (o *Buffer) unmarshalType(t reflect.Type, is_group bool, base uintptr) os.Error {
333 st := t.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700334 prop := GetProperties(st)
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700335 required, reqFields := prop.reqCount, uint64(0)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700336 sbase := getsbase(prop) // scratch area for data items
337
338 var err os.Error
339 for err == nil && o.index < len(o.buf) {
340 oi := o.index
341 var u uint64
342 u, err = o.DecodeVarint()
343 if err != nil {
344 break
345 }
346 wire := int(u & 0x7)
347 if wire == WireEndGroup {
348 if is_group {
349 return nil // input is satisfied
350 }
351 return ErrWrongType
352 }
353 tag := int(u >> 3)
354 fieldnum, ok := prop.tags[tag]
355 if !ok {
356 // Maybe it's an extension?
357 o.ptr = base
358 iv := unsafe.Unreflect(t, unsafe.Pointer(&o.ptr))
359 if e, ok := iv.(extendableProto); ok && isExtensionField(e, int32(tag)) {
360 if err = o.skip(st, tag, wire); err == nil {
Rob Pike99fa2b62010-12-02 10:39:42 -0800361 e.ExtensionMap()[int32(tag)] = append([]byte(nil), o.buf[oi:o.index]...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700362 }
363 continue
364 }
365 err = o.skipAndSave(st, tag, wire, base)
366 continue
367 }
368 p := prop.Prop[fieldnum]
369
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700370 if p.dec == nil {
371 fmt.Fprintf(os.Stderr, "no protobuf decoder for %s.%s\n", t, st.Field(fieldnum).Name)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700372 continue
373 }
David Symonds5b7775e2010-12-01 10:09:04 +1100374 dec := p.dec
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700375 if wire != WireStartGroup && wire != p.WireType {
David Symonds5b7775e2010-12-01 10:09:04 +1100376 if wire == WireBytes && p.packedDec != nil {
377 // a packable field
378 dec = p.packedDec
379 } else {
380 err = ErrWrongType
381 continue
382 }
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700383 }
David Symonds5b7775e2010-12-01 10:09:04 +1100384 err = dec(o, p, base, sbase)
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700385 if err == nil && p.Required {
386 // Successfully decoded a required field.
387 if tag <= 64 {
388 // use bitmap for fields 1-64 to catch field reuse.
389 var mask uint64 = 1 << uint64(tag-1)
390 if reqFields&mask == 0 {
391 // new required field
392 reqFields |= mask
393 required--
394 }
395 } else {
396 // This is imprecise. It can be fooled by a required field
397 // with a tag > 64 that is encoded twice; that's very rare.
398 // A fully correct implementation would require allocating
399 // a data structure, which we would like to avoid.
400 required--
401 }
402 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700403 }
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700404 if err == nil {
405 if is_group {
406 return io.ErrUnexpectedEOF
407 }
408 if required > 0 {
David Symonds5b7775e2010-12-01 10:09:04 +1100409 return &ErrRequiredNotSet{st}
Rob Pikec6d8e4a2010-07-28 15:34:32 -0700410 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700411 }
412 return err
413}
414
415// Make *pslice have base address base, length 0, and capacity startSize.
416func initSlice(pslice unsafe.Pointer, base uintptr) {
417 sp := (*reflect.SliceHeader)(pslice)
418 sp.Data = base
419 sp.Len = 0
420 sp.Cap = startSize
421}
422
423// Individual type decoders
424// For each,
425// u is the decoded value,
426// v is a pointer to the field (pointer) in the struct
427// x is a pointer to the preallocated scratch space to hold the decoded value.
428
429// Decode a bool.
430func (o *Buffer) dec_bool(p *Properties, base uintptr, sbase uintptr) os.Error {
431 u, err := p.valDec(o)
432 if err != nil {
433 return err
434 }
435 v := (**uint8)(unsafe.Pointer(base + p.offset))
436 x := (*uint8)(unsafe.Pointer(sbase + p.scratch))
437 *x = uint8(u)
438 *v = x
439 return nil
440}
441
442// Decode an int32.
443func (o *Buffer) dec_int32(p *Properties, base uintptr, sbase uintptr) os.Error {
444 u, err := p.valDec(o)
445 if err != nil {
446 return err
447 }
448 v := (**int32)(unsafe.Pointer(base + p.offset))
449 x := (*int32)(unsafe.Pointer(sbase + p.scratch))
450 *x = int32(u)
451 *v = x
452 return nil
453}
454
455// Decode an int64.
456func (o *Buffer) dec_int64(p *Properties, base uintptr, sbase uintptr) os.Error {
457 u, err := p.valDec(o)
458 if err != nil {
459 return err
460 }
461 v := (**int64)(unsafe.Pointer(base + p.offset))
462 x := (*int64)(unsafe.Pointer(sbase + p.scratch))
463 *x = int64(u)
464 *v = x
465 return nil
466}
467
468// Decode a string.
469func (o *Buffer) dec_string(p *Properties, base uintptr, sbase uintptr) os.Error {
470 s, err := o.DecodeStringBytes()
471 if err != nil {
472 return err
473 }
474 v := (**string)(unsafe.Pointer(base + p.offset))
475 x := (*string)(unsafe.Pointer(sbase + p.scratch))
476 *x = s
477 *v = x
478 return nil
479}
480
481// Decode a slice of bytes ([]byte).
482func (o *Buffer) dec_slice_byte(p *Properties, base uintptr, sbase uintptr) os.Error {
483 b, err := o.DecodeRawBytes(false)
484 if err != nil {
485 return err
486 }
Mikkel Krautzdb488aa2010-11-29 14:15:51 -0800487
Rob Pikeaaa3a622010-03-20 22:32:34 -0700488 x := (*[]uint8)(unsafe.Pointer(base + p.offset))
489
490 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100491 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700492 initSlice(unsafe.Pointer(x), sbase+p.scratch)
493 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700494 }
495
David Symonds5b7775e2010-12-01 10:09:04 +1100496 *x = append(y, b...)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700497 return nil
498}
499
500// Decode a slice of bools ([]bool).
501func (o *Buffer) dec_slice_bool(p *Properties, base uintptr, sbase uintptr) os.Error {
502 u, err := p.valDec(o)
503 if err != nil {
504 return err
505 }
506 x := (*[]bool)(unsafe.Pointer(base + p.offset))
507
508 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100509 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700510 initSlice(unsafe.Pointer(x), sbase+p.scratch)
511 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700512 }
David Symonds5b7775e2010-12-01 10:09:04 +1100513
514 *x = append(y, u != 0)
515 return nil
516}
517
518// Decode a slice of bools ([]bool) in packed format.
519func (o *Buffer) dec_slice_packed_bool(p *Properties, base uintptr, sbase uintptr) os.Error {
520 x := (*[]bool)(unsafe.Pointer(base + p.offset))
521
522 nn, err := o.DecodeVarint()
523 if err != nil {
524 return err
Rob Pikeaaa3a622010-03-20 22:32:34 -0700525 }
David Symonds5b7775e2010-12-01 10:09:04 +1100526 nb := int(nn) // number of bytes of encoded bools
527
528 y := *x
529 if cap(y) == 0 {
David Symonds56eb29e2011-07-01 11:08:42 +1000530 initSlice(unsafe.Pointer(x), sbase+p.scratch)
David Symonds5b7775e2010-12-01 10:09:04 +1100531 y = *x
532 }
533
534 for i := 0; i < nb; i++ {
535 u, err := p.valDec(o)
536 if err != nil {
537 return err
538 }
539 y = append(y, u != 0)
540 }
541
Rob Pikeaaa3a622010-03-20 22:32:34 -0700542 *x = y
543 return nil
544}
545
546// Decode a slice of int32s ([]int32).
547func (o *Buffer) dec_slice_int32(p *Properties, base uintptr, sbase uintptr) os.Error {
548 u, err := p.valDec(o)
549 if err != nil {
550 return err
551 }
552 x := (*[]int32)(unsafe.Pointer(base + p.offset))
553
554 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100555 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700556 initSlice(unsafe.Pointer(x), sbase+p.scratch)
557 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700558 }
David Symonds5b7775e2010-12-01 10:09:04 +1100559
560 *x = append(y, int32(u))
561 return nil
562}
563
564// Decode a slice of int32s ([]int32) in packed format.
565func (o *Buffer) dec_slice_packed_int32(p *Properties, base uintptr, sbase uintptr) os.Error {
566 x := (*[]int32)(unsafe.Pointer(base + p.offset))
567
568 nn, err := o.DecodeVarint()
569 if err != nil {
570 return err
Rob Pikeaaa3a622010-03-20 22:32:34 -0700571 }
David Symonds5b7775e2010-12-01 10:09:04 +1100572 nb := int(nn) // number of bytes of encoded int32s
573
574 y := *x
575 if cap(y) == 0 {
David Symonds56eb29e2011-07-01 11:08:42 +1000576 initSlice(unsafe.Pointer(x), sbase+p.scratch)
David Symonds5b7775e2010-12-01 10:09:04 +1100577 y = *x
578 }
579
580 fin := o.index + nb
581 for o.index < fin {
582 u, err := p.valDec(o)
583 if err != nil {
584 return err
585 }
586 y = append(y, int32(u))
587 }
588
Rob Pikeaaa3a622010-03-20 22:32:34 -0700589 *x = y
590 return nil
591}
592
593// Decode a slice of int64s ([]int64).
594func (o *Buffer) dec_slice_int64(p *Properties, base uintptr, sbase uintptr) os.Error {
595 u, err := p.valDec(o)
596 if err != nil {
597 return err
598 }
599 x := (*[]int64)(unsafe.Pointer(base + p.offset))
600
601 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100602 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700603 initSlice(unsafe.Pointer(x), sbase+p.scratch)
604 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700605 }
David Symonds5b7775e2010-12-01 10:09:04 +1100606
607 *x = append(y, int64(u))
608 return nil
609}
610
611// Decode a slice of int64s ([]int64) in packed format.
612func (o *Buffer) dec_slice_packed_int64(p *Properties, base uintptr, sbase uintptr) os.Error {
613 x := (*[]int64)(unsafe.Pointer(base + p.offset))
614
615 nn, err := o.DecodeVarint()
616 if err != nil {
617 return err
Rob Pikeaaa3a622010-03-20 22:32:34 -0700618 }
David Symonds5b7775e2010-12-01 10:09:04 +1100619 nb := int(nn) // number of bytes of encoded int64s
620
621 y := *x
622 if cap(y) == 0 {
David Symonds56eb29e2011-07-01 11:08:42 +1000623 initSlice(unsafe.Pointer(x), sbase+p.scratch)
David Symonds5b7775e2010-12-01 10:09:04 +1100624 y = *x
625 }
626
627 fin := o.index + nb
628 for o.index < fin {
629 u, err := p.valDec(o)
630 if err != nil {
631 return err
632 }
633 y = append(y, int64(u))
634 }
635
Rob Pikeaaa3a622010-03-20 22:32:34 -0700636 *x = y
637 return nil
638}
639
640// Decode a slice of strings ([]string).
641func (o *Buffer) dec_slice_string(p *Properties, base uintptr, sbase uintptr) os.Error {
642 s, err := o.DecodeStringBytes()
643 if err != nil {
644 return err
645 }
646 x := (*[]string)(unsafe.Pointer(base + p.offset))
647
648 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100649 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700650 initSlice(unsafe.Pointer(x), sbase+p.scratch)
651 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700652 }
David Symonds5b7775e2010-12-01 10:09:04 +1100653
654 *x = append(y, s)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700655 return nil
656}
657
658// Decode a slice of slice of bytes ([][]byte).
659func (o *Buffer) dec_slice_slice_byte(p *Properties, base uintptr, sbase uintptr) os.Error {
660 b, err := o.DecodeRawBytes(true)
661 if err != nil {
662 return err
663 }
664 x := (*[][]byte)(unsafe.Pointer(base + p.offset))
665
666 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100667 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700668 initSlice(unsafe.Pointer(x), sbase+p.scratch)
669 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700670 }
David Symonds5b7775e2010-12-01 10:09:04 +1100671
672 *x = append(y, b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700673 return nil
674}
675
676// Decode a group.
677func (o *Buffer) dec_struct_group(p *Properties, base uintptr, sbase uintptr) os.Error {
678 ptr := (**struct{})(unsafe.Pointer(base + p.offset))
Rob Pike97e934d2011-04-11 12:52:49 -0700679 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700680 structv := unsafe.New(typ)
681 bas := uintptr(structv)
682 *ptr = (*struct{})(structv)
683
684 err := o.unmarshalType(p.stype, true, bas)
685
686 return err
687}
688
689// Decode an embedded message.
690func (o *Buffer) dec_struct_message(p *Properties, base uintptr, sbase uintptr) (err os.Error) {
691 raw, e := o.DecodeRawBytes(false)
692 if e != nil {
693 return e
694 }
695
696 ptr := (**struct{})(unsafe.Pointer(base + p.offset))
Rob Pike97e934d2011-04-11 12:52:49 -0700697 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700698 structv := unsafe.New(typ)
699 bas := uintptr(structv)
700 *ptr = (*struct{})(structv)
701
702 // If the object can unmarshal itself, let it.
703 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(ptr))
704 if u, ok := iv.(Unmarshaler); ok {
705 return u.Unmarshal(raw)
706 }
707
708 obuf := o.buf
709 oi := o.index
710 o.buf = raw
711 o.index = 0
712
713 err = o.unmarshalType(p.stype, false, bas)
714 o.buf = obuf
715 o.index = oi
716
717 return err
718}
719
720// Decode a slice of embedded messages.
721func (o *Buffer) dec_slice_struct_message(p *Properties, base uintptr, sbase uintptr) os.Error {
722 return o.dec_slice_struct(p, false, base, sbase)
723}
724
725// Decode a slice of embedded groups.
726func (o *Buffer) dec_slice_struct_group(p *Properties, base uintptr, sbase uintptr) os.Error {
727 return o.dec_slice_struct(p, true, base, sbase)
728}
729
730// Decode a slice of structs ([]*struct).
731func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base uintptr, sbase uintptr) os.Error {
732
733 x := (*[]*struct{})(unsafe.Pointer(base + p.offset))
734 y := *x
David Symonds5b7775e2010-12-01 10:09:04 +1100735 if cap(y) == 0 {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700736 initSlice(unsafe.Pointer(x), sbase+p.scratch)
737 y = *x
Rob Pikeaaa3a622010-03-20 22:32:34 -0700738 }
739
Rob Pike97e934d2011-04-11 12:52:49 -0700740 typ := p.stype.Elem()
Rob Pikeaaa3a622010-03-20 22:32:34 -0700741 structv := unsafe.New(typ)
742 bas := uintptr(structv)
David Symonds5b7775e2010-12-01 10:09:04 +1100743 y = append(y, (*struct{})(structv))
744 *x = y
Rob Pikeaaa3a622010-03-20 22:32:34 -0700745
746 if is_group {
747 err := o.unmarshalType(p.stype, is_group, bas)
748 return err
749 }
750
751 raw, err := o.DecodeRawBytes(true)
752 if err != nil {
753 return err
754 }
755
756 // If the object can unmarshal itself, let it.
David Symonds5b7775e2010-12-01 10:09:04 +1100757 iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&y[len(y)-1]))
Rob Pikeaaa3a622010-03-20 22:32:34 -0700758 if u, ok := iv.(Unmarshaler); ok {
759 return u.Unmarshal(raw)
760 }
761
762 obuf := o.buf
763 oi := o.index
764 o.buf = raw
765 o.index = 0
766
767 err = o.unmarshalType(p.stype, is_group, bas)
768
769 o.buf = obuf
770 o.index = oi
771
772 return err
773}