1 // Go support for Protocol Buffers - Google's data interchange format
3 // Copyright 2010 Google Inc. All rights reserved.
4 // http://code.google.com/p/goprotobuf/
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
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
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.
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.
35 * Routines for encoding data into the wire format for protocol buffers.
48 const debug bool = false
50 // Constants that identify the encoding of a value on the wire.
60 const startSize = 10 // initial slice/string sizes
62 // Encoders are defined in encoder.go
63 // An encoder outputs the full representation of a field, including its
64 // tag and encoder type.
65 type encoder func(p *Buffer, prop *Properties, base uintptr) os.Error
67 // A valueEncoder encodes a single integer in a particular encoding.
68 type valueEncoder func(o *Buffer, x uint64) os.Error
70 // Decoders are defined in decode.go
71 // A decoder creates a value from its wire representation.
72 // Unrecognized subelements are saved in unrec.
73 type decoder func(p *Buffer, prop *Properties, base uintptr, sbase uintptr) os.Error
75 // A valueDecoder decodes a single integer in a particular encoding.
76 type valueDecoder func(o *Buffer) (x uint64, err os.Error)
78 // StructProperties represents properties for all the fields of a struct.
79 type StructProperties struct {
80 Prop []*Properties // properties for each field
81 reqCount int // required count
82 tags map[int]int // map from proto tag to struct field number
83 origNames map[string]int // map from original name to struct field number
84 nscratch uintptr // size of scratch space
87 // Properties represents the protocol-specific behavior of a single struct field.
88 type Properties struct {
89 Name string // name of the field, for error messages
90 OrigName string // original name before protocol compiler (always set)
97 Packed bool // relevant for repeated primitives only
98 Enum string // set for enum types only
99 Default string // default value
103 valEnc valueEncoder // set for bool and numeric types only
105 tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
110 valDec valueDecoder // set for bool and numeric types only
112 sizeof uintptr // calculations of scratch space
115 // If this is a packable field, this will be the decoder for the packed version of the field.
119 // String formats the properties in the protobuf struct field tag style.
120 func (p *Properties) String() string {
123 s += strconv.Itoa(p.Tag)
136 if p.OrigName != p.Name {
137 s += ",name=" + p.OrigName
140 s += ",enum=" + p.Enum
142 if len(p.Default) > 0 {
143 s += ",def=" + p.Default
148 // Parse populates p by parsing a string in the protobuf struct field tag style.
149 func (p *Properties) Parse(s string) {
150 // "bytes,49,opt,def=hello!,name=foo"
151 fields := strings.Split(s, ",") // breaks def=, but handled below.
153 fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
160 p.WireType = WireVarint
161 p.valEnc = (*Buffer).EncodeVarint
162 p.valDec = (*Buffer).DecodeVarint
164 p.WireType = WireFixed32
165 p.valEnc = (*Buffer).EncodeFixed32
166 p.valDec = (*Buffer).DecodeFixed32
168 p.WireType = WireFixed64
169 p.valEnc = (*Buffer).EncodeFixed64
170 p.valDec = (*Buffer).DecodeFixed64
172 p.WireType = WireVarint
173 p.valEnc = (*Buffer).EncodeZigzag32
174 p.valDec = (*Buffer).DecodeZigzag32
176 p.WireType = WireVarint
177 p.valEnc = (*Buffer).EncodeZigzag64
178 p.valDec = (*Buffer).DecodeZigzag64
179 case "bytes", "group":
180 p.WireType = WireBytes
181 // no numeric converter for non-numeric types
183 fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
188 p.Tag, err = strconv.Atoi(fields[1])
193 for i := 2; i < len(fields); i++ {
204 case len(f) >= 5 && f[0:5] == "name=":
205 p.OrigName = f[5:len(f)]
206 case len(f) >= 5 && f[0:5] == "enum=":
208 case len(f) >= 4 && f[0:4] == "def=":
209 p.Default = f[4:len(f)] // rest of string
210 if i+1 < len(fields) {
211 // Commas aren't escaped, and def is always last.
212 p.Default += "," + strings.Join(fields[i+1:len(fields)], ",")
219 func logNoSliceEnc(t1, t2 reflect.Type) {
220 fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
223 // Initialize the fields for encoding and decoding.
224 func (p *Properties) setEncAndDec(typ reflect.Type) {
237 switch t1 := typ; t1.Kind() {
239 fmt.Fprintf(os.Stderr, "proto: no coders for %T\n", t1)
243 switch t2 := t1.Elem(); t2.Kind() {
245 fmt.Fprintf(os.Stderr, "proto: no encoder function for %T -> %T\n", t1, t2)
248 p.enc = (*Buffer).enc_bool
249 p.dec = (*Buffer).dec_bool
250 p.alignof = unsafe.Alignof(vbool)
251 p.sizeof = unsafe.Sizeof(vbool)
252 case reflect.Int32, reflect.Uint32:
253 p.enc = (*Buffer).enc_int32
254 p.dec = (*Buffer).dec_int32
255 p.alignof = unsafe.Alignof(vint32)
256 p.sizeof = unsafe.Sizeof(vint32)
257 case reflect.Int64, reflect.Uint64:
258 p.enc = (*Buffer).enc_int64
259 p.dec = (*Buffer).dec_int64
260 p.alignof = unsafe.Alignof(vint64)
261 p.sizeof = unsafe.Sizeof(vint64)
262 case reflect.Float32:
263 p.enc = (*Buffer).enc_int32 // can just treat them as bits
264 p.dec = (*Buffer).dec_int32
265 p.alignof = unsafe.Alignof(vfloat32)
266 p.sizeof = unsafe.Sizeof(vfloat32)
267 case reflect.Float64:
268 p.enc = (*Buffer).enc_int64 // can just treat them as bits
269 p.dec = (*Buffer).dec_int64
270 p.alignof = unsafe.Alignof(vfloat64)
271 p.sizeof = unsafe.Sizeof(vfloat64)
273 p.enc = (*Buffer).enc_string
274 p.dec = (*Buffer).dec_string
275 p.alignof = unsafe.Alignof(vstring)
276 p.sizeof = unsafe.Sizeof(vstring) + startSize*unsafe.Sizeof(vbyte)
279 if p.Wire == "bytes" {
280 p.enc = (*Buffer).enc_struct_message
281 p.dec = (*Buffer).dec_struct_message
283 p.enc = (*Buffer).enc_struct_group
284 p.dec = (*Buffer).dec_struct_group
289 switch t2 := t1.Elem(); t2.Kind() {
291 logNoSliceEnc(t1, t2)
295 p.enc = (*Buffer).enc_slice_packed_bool
297 p.enc = (*Buffer).enc_slice_bool
299 p.dec = (*Buffer).dec_slice_bool
300 p.packedDec = (*Buffer).dec_slice_packed_bool
301 p.alignof = unsafe.Alignof(vbool)
302 p.sizeof = startSize * unsafe.Sizeof(vbool)
303 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
307 p.enc = (*Buffer).enc_slice_packed_int32
309 p.enc = (*Buffer).enc_slice_int32
311 p.dec = (*Buffer).dec_slice_int32
312 p.packedDec = (*Buffer).dec_slice_packed_int32
313 p.alignof = unsafe.Alignof(vint32)
314 p.sizeof = startSize * unsafe.Sizeof(vint32)
317 p.enc = (*Buffer).enc_slice_packed_int64
319 p.enc = (*Buffer).enc_slice_int64
321 p.dec = (*Buffer).dec_slice_int64
322 p.packedDec = (*Buffer).dec_slice_packed_int64
323 p.alignof = unsafe.Alignof(vint64)
324 p.sizeof = startSize * unsafe.Sizeof(vint64)
326 if t2.Kind() == reflect.Uint8 {
327 p.enc = (*Buffer).enc_slice_byte
328 p.dec = (*Buffer).dec_slice_byte
329 p.alignof = unsafe.Alignof(vbyte)
330 p.sizeof = startSize * unsafe.Sizeof(vbyte)
333 logNoSliceEnc(t1, t2)
336 case reflect.Float32, reflect.Float64:
339 // can just treat them as bits
341 p.enc = (*Buffer).enc_slice_packed_int32
343 p.enc = (*Buffer).enc_slice_int32
345 p.dec = (*Buffer).dec_slice_int32
346 p.packedDec = (*Buffer).dec_slice_packed_int32
347 p.alignof = unsafe.Alignof(vfloat32)
348 p.sizeof = startSize * unsafe.Sizeof(vfloat32)
350 // can just treat them as bits
352 p.enc = (*Buffer).enc_slice_packed_int64
354 p.enc = (*Buffer).enc_slice_int64
356 p.dec = (*Buffer).dec_slice_int64
357 p.packedDec = (*Buffer).dec_slice_packed_int64
358 p.alignof = unsafe.Alignof(vfloat64)
359 p.sizeof = startSize * unsafe.Sizeof(vfloat64)
361 logNoSliceEnc(t1, t2)
365 p.enc = (*Buffer).enc_slice_string
366 p.dec = (*Buffer).dec_slice_string
367 p.alignof = unsafe.Alignof(vstring)
368 p.sizeof = startSize * unsafe.Sizeof(vstring)
370 switch t3 := t2.Elem(); t3.Kind() {
372 fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
376 p.enc = (*Buffer).enc_slice_struct_group
377 p.dec = (*Buffer).dec_slice_struct_group
378 if p.Wire == "bytes" {
379 p.enc = (*Buffer).enc_slice_struct_message
380 p.dec = (*Buffer).dec_slice_struct_message
382 p.alignof = unsafe.Alignof(vslice)
383 p.sizeof = startSize * unsafe.Sizeof(vslice)
386 switch t2.Elem().Kind() {
388 fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
391 p.enc = (*Buffer).enc_slice_slice_byte
392 p.dec = (*Buffer).dec_slice_slice_byte
393 p.alignof = unsafe.Alignof(vslice)
394 p.sizeof = startSize * unsafe.Sizeof(vslice)
399 // precalculate tag code
404 x := uint32(p.Tag)<<3 | uint32(wire)
406 for i = 0; x > 127; i++ {
407 p.tagbuf[i] = 0x80 | uint8(x&0x7F)
410 p.tagbuf[i] = uint8(x)
411 p.tagcode = p.tagbuf[0 : i+1]
414 // Init populates the properties from a protocol buffer struct tag.
415 func (p *Properties) Init(typ reflect.Type, name, tag string, offset uintptr) {
416 // "bytes,49,opt,def=hello!"
430 propertiesMap = make(map[reflect.Type]*StructProperties)
433 // GetProperties returns the list of properties for the type represented by t.
434 func GetProperties(t reflect.Type) *StructProperties {
436 if prop, ok := propertiesMap[t]; ok {
443 prop := new(StructProperties)
446 prop.Prop = make([]*Properties, t.NumField())
447 prop.origNames = make(map[string]int)
448 for i := 0; i < t.NumField(); i++ {
451 p.Init(f.Type, f.Name, f.Tag.Get("protobuf"), f.Offset)
452 if f.Name == "XXX_extensions" { // special case
453 var vmap map[int32][]byte
454 p.enc = (*Buffer).enc_map
455 p.dec = nil // not needed
456 p.alignof = unsafe.Alignof(vmap)
457 p.sizeof = unsafe.Sizeof(vmap)
460 prop.origNames[p.OrigName] = i
462 print(i, " ", f.Name, " ", t.String(), " ")
468 if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
469 fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
473 // build required counts
474 // build scratch offsets
477 scratch := uintptr(0)
478 prop.tags = make(map[int]int)
479 for i, p := range prop.Prop {
483 scratch = align(scratch, p.alignof)
488 prop.reqCount = reqCount
489 prop.nscratch = scratch
491 propertiesMap[t] = prop
496 // Alignment of the data in the scratch area. It doesn't have to be
497 // exact, just conservative. Returns the first number >= o that divides s.
498 func align(o uintptr, s uintptr) uintptr {
500 for o%uintptr(s) != 0 {
507 // Return the field index of the named field.
508 // Returns nil if there is no such field.
509 func fieldIndex(t reflect.Type, name string) []int {
510 if field, ok := t.FieldByName(name); ok {
516 // Return the Properties object for the x[0]'th field of the structure.
517 func propByIndex(t reflect.Type, x []int) *Properties {
519 fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
522 prop := GetProperties(t)
523 return prop.Prop[x[0]]
526 // Get the address and type of a pointer to a struct from an interface.
527 // unsafe.Reflect can do this, but does multiple mallocs.
528 func getbase(pb interface{}) (t reflect.Type, b uintptr, err os.Error) {
530 x := *(*[2]uintptr)(unsafe.Pointer(&pb))
537 // get the reflect type of the struct.
538 t = reflect.TypeOf(pb)
542 // Allocate the aux space containing all the decoded data. The structure
543 // handed into Unmarshal is filled with pointers to this newly allocated
545 func getsbase(prop *StructProperties) uintptr {
547 if prop.nscratch == 0 {
551 // allocate the decode space as pointers
552 // so that the GC will scan it for pointers
553 n := uintptr(unsafe.Sizeof(vbyteptr))
554 b := make([]*byte, (prop.nscratch+n-1)/n)
555 sbase := uintptr(unsafe.Pointer(&b[0]))
559 // A global registry of enum types.
560 // The generated code will register the generated maps by calling RegisterEnum.
562 var enumNameMaps = make(map[string]map[int32]string)
563 var enumValueMaps = make(map[string]map[string]int32)
565 // RegisterEnum is called from the generated code to install the enum descriptor
566 // maps into the global table to aid parsing ASCII protocol buffers.
567 func RegisterEnum(typeName string, nameMap map[int32]string, valueMap map[string]int32) {
568 if _, ok := enumNameMaps[typeName]; ok {
569 panic("proto: duplicate enum registered: " + typeName)
571 enumNameMaps[typeName] = nameMap
572 enumValueMaps[typeName] = valueMap