blob: 9c323b29e16fb20d823c83383667ebdba62c4388 [file] [log] [blame]
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 Google Inc. All rights reserved.
// http://code.google.com/p/goprotobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
/*
* Routines for encoding data into the wire format for protocol buffers.
*/
import (
"bytes"
"os"
"reflect"
"runtime"
"unsafe"
)
// ErrRequiredNotSet is the error returned if Marshal is called with
// a protocol buffer struct whose required fields have not
// all been initialized.
var ErrRequiredNotSet = os.NewError("required fields not set")
// ErrRepeatedHasNil is the error returned if Marshal is called with
// a protocol buffer struct with a repeated field containing a nil element.
var ErrRepeatedHasNil = os.NewError("repeated field has nil")
// ErrNil is the error returned if Marshal is called with nil.
var ErrNil = os.NewError("marshal called with nil")
// The fundamental encoders that put bytes on the wire.
// Those that take integer types all accept uint64 and are
// therefore of type valueEncoder.
// EncodeVarint returns the varint encoding of x.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
// Not used by the package itself, but helpful to clients
// wishing to use the same encoding.
func EncodeVarint(x uint64) []byte {
var buf [16]byte
var n int
for n = 0; x > 127; n++ {
buf[n] = 0x80 | uint8(x&0x7F)
x >>= 7
}
buf[n] = uint8(x)
n++
return buf[0:n]
}
// EncodeVarint writes a varint-encoded integer to the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) EncodeVarint(x uint64) os.Error {
l := len(p.buf)
c := cap(p.buf)
if l+10 > c {
c += c/2 + 10
obuf := make([]byte, c)
copy(obuf, p.buf)
p.buf = obuf
}
p.buf = p.buf[0:c]
for {
if x < 1<<7 {
break
}
p.buf[l] = uint8(x&0x7f | 0x80)
l++
x >>= 7
}
p.buf[l] = uint8(x)
p.buf = p.buf[0 : l+1]
return nil
}
// EncodeFixed64 writes a 64-bit integer to the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
func (p *Buffer) EncodeFixed64(x uint64) os.Error {
l := len(p.buf)
c := cap(p.buf)
if l+8 > c {
c += c/2 + 8
obuf := make([]byte, c)
copy(obuf, p.buf)
p.buf = obuf
}
p.buf = p.buf[0 : l+8]
p.buf[l] = uint8(x)
p.buf[l+1] = uint8(x >> 8)
p.buf[l+2] = uint8(x >> 16)
p.buf[l+3] = uint8(x >> 24)
p.buf[l+4] = uint8(x >> 32)
p.buf[l+5] = uint8(x >> 40)
p.buf[l+6] = uint8(x >> 48)
p.buf[l+7] = uint8(x >> 56)
return nil
}
// EncodeFixed32 writes a 32-bit integer to the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
func (p *Buffer) EncodeFixed32(x uint64) os.Error {
l := len(p.buf)
c := cap(p.buf)
if l+4 > c {
c += c/2 + 4
obuf := make([]byte, c)
copy(obuf, p.buf)
p.buf = obuf
}
p.buf = p.buf[0 : l+4]
p.buf[l] = uint8(x)
p.buf[l+1] = uint8(x >> 8)
p.buf[l+2] = uint8(x >> 16)
p.buf[l+3] = uint8(x >> 24)
return nil
}
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
// to the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) EncodeZigzag64(x uint64) os.Error {
// use signed number to get arithmetic right shift.
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
// to the Buffer.
// This is the format used for the sint32 protocol buffer type.
func (p *Buffer) EncodeZigzag32(x uint64) os.Error {
// use signed number to get arithmetic right shift.
return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
}
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
func (p *Buffer) EncodeRawBytes(b []byte) os.Error {
lb := len(b)
p.EncodeVarint(uint64(lb))
p.buf = bytes.Add(p.buf, b)
return nil
}
// EncodeStringBytes writes an encoded string to the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) EncodeStringBytes(s string) os.Error {
// this works because strings and slices are the same.
y := *(*[]byte)(unsafe.Pointer(&s))
p.EncodeRawBytes(y)
return nil
}
// Marshaler is the interface representing objects that can marshal themselves.
type Marshaler interface {
Marshal() ([]byte, os.Error)
}
// Marshal takes the protocol buffer struct represented by pb
// and encodes it into the wire format, returning the data.
func Marshal(pb interface{}) ([]byte, os.Error) {
// Can the object marshal itself?
if m, ok := pb.(Marshaler); ok {
return m.Marshal()
}
p := NewBuffer(nil)
err := p.Marshal(pb)
if err != nil {
return nil, err
}
return p.buf, err
}
// Marshal takes the protocol buffer struct represented by pb
// and encodes it into the wire format, writing the result to the
// Buffer.
func (p *Buffer) Marshal(pb interface{}) os.Error {
// Can the object marshal itself?
if m, ok := pb.(Marshaler); ok {
data, err := m.Marshal()
if err != nil {
return err
}
p.buf = bytes.Add(p.buf, data)
return nil
}
mstat := runtime.MemStats.Mallocs
t, b, err := getbase(pb)
if err == nil {
err = p.enc_struct(t.Elem().(*reflect.StructType), b)
}
mstat = runtime.MemStats.Mallocs - mstat
stats.Emalloc += mstat
stats.Encode++
return err
}
// Individual type encoders.
// Encode a bool.
func (o *Buffer) enc_bool(p *Properties, base uintptr) os.Error {
v := *(**uint8)(unsafe.Pointer(base + p.offset))
if v == nil {
return ErrNil
}
x := *v
if x != 0 {
x = 1
}
o.buf = bytes.Add(o.buf, p.tagcode)
p.valEnc(o, uint64(x))
return nil
}
// Encode an int32.
func (o *Buffer) enc_int32(p *Properties, base uintptr) os.Error {
v := *(**uint32)(unsafe.Pointer(base + p.offset))
if v == nil {
return ErrNil
}
x := *v
o.buf = bytes.Add(o.buf, p.tagcode)
p.valEnc(o, uint64(x))
return nil
}
// Encode an int64.
func (o *Buffer) enc_int64(p *Properties, base uintptr) os.Error {
v := *(**uint64)(unsafe.Pointer(base + p.offset))
if v == nil {
return ErrNil
}
x := *v
o.buf = bytes.Add(o.buf, p.tagcode)
p.valEnc(o, uint64(x))
return nil
}
// Encode a string.
func (o *Buffer) enc_string(p *Properties, base uintptr) os.Error {
v := *(**string)(unsafe.Pointer(base + p.offset))
if v == nil {
return ErrNil
}
x := *v
o.buf = bytes.Add(o.buf, p.tagcode)
o.EncodeStringBytes(x)
return nil
}
// Encode a message struct.
func (o *Buffer) enc_struct_message(p *Properties, base uintptr) os.Error {
// Can the object marshal itself?
iv := unsafe.Unreflect(p.stype, unsafe.Pointer(base+p.offset))
if m, ok := iv.(Marshaler); ok {
data, err := m.Marshal()
if err != nil {
return err
}
o.buf = bytes.Add(o.buf, p.tagcode)
o.EncodeRawBytes(data)
return nil
}
v := *(**struct{})(unsafe.Pointer(base + p.offset))
if v == nil {
return ErrNil
}
// need the length before we can write out the message itself,
// so marshal into a separate byte buffer first.
obuf := o.buf
o.buf = o.bufalloc()
b := uintptr(unsafe.Pointer(v))
typ := p.stype.Elem().(*reflect.StructType)
err := o.enc_struct(typ, b)
nbuf := o.buf
o.buf = obuf
if err != nil {
o.buffree(nbuf)
return err
}
o.buf = bytes.Add(o.buf, p.tagcode)
o.EncodeRawBytes(nbuf)
o.buffree(nbuf)
return nil
}
// Encode a group struct.
func (o *Buffer) enc_struct_group(p *Properties, base uintptr) os.Error {
v := *(**struct{})(unsafe.Pointer(base + p.offset))
if v == nil {
return ErrNil
}
o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
b := uintptr(unsafe.Pointer(v))
typ := p.stype.Elem().(*reflect.StructType)
err := o.enc_struct(typ, b)
if err != nil {
return err
}
o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
return nil
}
// Encode a slice of bools ([]bool).
func (o *Buffer) enc_slice_bool(p *Properties, base uintptr) os.Error {
s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
l := len(s)
if l == 0 {
return ErrNil
}
for _, x := range s {
o.buf = bytes.Add(o.buf, p.tagcode)
if x != 0 {
x = 1
}
p.valEnc(o, uint64(x))
}
return nil
}
// Encode a slice of bytes ([]byte).
func (o *Buffer) enc_slice_byte(p *Properties, base uintptr) os.Error {
s := *(*[]uint8)(unsafe.Pointer(base + p.offset))
// if the field is required, we must send something, even if it's an empty array.
if !p.Required {
l := len(s)
if l == 0 {
return ErrNil
}
// check default
if l == len(p.Default) {
same := true
for i := 0; i < len(p.Default); i++ {
if p.Default[i] != s[i] {
same = false
break
}
}
if same {
return ErrNil
}
}
}
o.buf = bytes.Add(o.buf, p.tagcode)
o.EncodeRawBytes(s)
return nil
}
// Encode a slice of int32s ([]int32).
func (o *Buffer) enc_slice_int32(p *Properties, base uintptr) os.Error {
s := *(*[]uint32)(unsafe.Pointer(base + p.offset))
l := len(s)
if l == 0 {
return ErrNil
}
for i := 0; i < l; i++ {
o.buf = bytes.Add(o.buf, p.tagcode)
x := s[i]
p.valEnc(o, uint64(x))
}
return nil
}
// Encode a slice of int64s ([]int64).
func (o *Buffer) enc_slice_int64(p *Properties, base uintptr) os.Error {
s := *(*[]uint64)(unsafe.Pointer(base + p.offset))
l := len(s)
if l == 0 {
return ErrNil
}
for i := 0; i < l; i++ {
o.buf = bytes.Add(o.buf, p.tagcode)
x := s[i]
p.valEnc(o, uint64(x))
}
return nil
}
// Encode a slice of slice of bytes ([][]byte).
func (o *Buffer) enc_slice_slice_byte(p *Properties, base uintptr) os.Error {
ss := *(*[][]uint8)(unsafe.Pointer(base + p.offset))
l := len(ss)
if l == 0 {
return ErrNil
}
for i := 0; i < l; i++ {
o.buf = bytes.Add(o.buf, p.tagcode)
s := ss[i]
o.EncodeRawBytes(s)
}
return nil
}
// Encode a slice of strings ([]string).
func (o *Buffer) enc_slice_string(p *Properties, base uintptr) os.Error {
ss := *(*[]string)(unsafe.Pointer(base + p.offset))
l := len(ss)
for i := 0; i < l; i++ {
o.buf = bytes.Add(o.buf, p.tagcode)
s := ss[i]
o.EncodeStringBytes(s)
}
return nil
}
// Encode a slice of message structs ([]*struct).
func (o *Buffer) enc_slice_struct_message(p *Properties, base uintptr) os.Error {
s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
l := len(s)
typ := p.stype.Elem().(*reflect.StructType)
for i := 0; i < l; i++ {
v := s[i]
if v == nil {
return ErrRepeatedHasNil
}
// Can the object marshal itself?
iv := unsafe.Unreflect(p.stype, unsafe.Pointer(&s[i]))
if m, ok := iv.(Marshaler); ok {
data, err := m.Marshal()
if err != nil {
return err
}
o.buf = bytes.Add(o.buf, p.tagcode)
o.EncodeRawBytes(data)
continue
}
obuf := o.buf
o.buf = o.bufalloc()
b := uintptr(unsafe.Pointer(v))
err := o.enc_struct(typ, b)
nbuf := o.buf
o.buf = obuf
if err != nil {
o.buffree(nbuf)
if err == ErrNil {
return ErrRepeatedHasNil
}
return err
}
o.buf = bytes.Add(o.buf, p.tagcode)
o.EncodeRawBytes(nbuf)
o.buffree(nbuf)
}
return nil
}
// Encode a slice of group structs ([]*struct).
func (o *Buffer) enc_slice_struct_group(p *Properties, base uintptr) os.Error {
s := *(*[]*struct{})(unsafe.Pointer(base + p.offset))
l := len(s)
typ := p.stype.Elem().(*reflect.StructType)
for i := 0; i < l; i++ {
v := s[i]
if v == nil {
return ErrRepeatedHasNil
}
o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
b := uintptr(unsafe.Pointer(v))
err := o.enc_struct(typ, b)
if err != nil {
if err == ErrNil {
return ErrRepeatedHasNil
}
return err
}
o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
}
return nil
}
// Encode an extension map.
func (o *Buffer) enc_map(p *Properties, base uintptr) os.Error {
v := *(*map[int32][]byte)(unsafe.Pointer(base + p.offset))
for _, b := range v {
o.buf = bytes.Add(o.buf, b)
}
return nil
}
// Encode a struct.
func (o *Buffer) enc_struct(t *reflect.StructType, base uintptr) os.Error {
prop := GetProperties(t)
required := prop.reqCount
for _, p := range prop.Prop {
if p.enc != nil {
err := p.enc(o, p, base)
if err != nil {
if err != ErrNil {
return err
}
} else if p.Required {
required--
}
}
}
// See if we encoded all required fields.
if required > 0 {
return ErrRequiredNotSet
}
return nil
}