pax_global_header 0000666 0000000 0000000 00000000064 12153716517 0014522 g ustar 00root root 0000000 0000000 52 comment=75092644046c5e38257395b86ed26c702dc95b92 golang-github-ugorji-go-msgpack-0.0~git20130605.792643/ 0000775 0000000 0000000 00000000000 12153716517 0021733 5 ustar 00root root 0000000 0000000 golang-github-ugorji-go-msgpack-0.0~git20130605.792643/LICENSE 0000664 0000000 0000000 00000003076 12153716517 0022746 0 ustar 00root root 0000000 0000000 go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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. golang-github-ugorji-go-msgpack-0.0~git20130605.792643/README.md 0000664 0000000 0000000 00000004242 12153716517 0023214 0 ustar 00root root 0000000 0000000 # MsgPack library for Go (DEPRECATED) > DEPRECATED as of May 29, 2013. Please use github.com/ugorji/go/codec > which is significantly faster, cleaner, more correct and more complete. > See [https://github.com/ugorji/go/tree/master/codec#readme] > > A complete redesign was done which accomodates multiple codec formats. > It thus became necessary to create a new repository with a different name. > > I hope to retire this repository anytime from July 1, 2013. > > A log message will be printed out at runtime encouraging users to upgrade. ## About go-msgpack Implements: > [http://wiki.msgpack.org/display/MSGPACK/Format+specification] To install: > go get github.com/ugorji/go-msgpack It provides features similar to encoding packages in the standard library (ie json, xml, gob, etc). Supports: * Standard Marshal/Unmarshal interface. * Support for all exported fields (including anonymous fields) * Standard field renaming via tags * Encoding from any value (struct, slice, map, primitives, pointers, interface{}, etc) * Decoding into pointer to any non-nil value (struct, slice, map, int, float32, bool, string, etc) * Decoding into a nil interface{} * Handles time.Time transparently (stores time as 2 element array: seconds since epoch and nanosecond offset) * Provides a Server and Client Codec so msgpack can be used as communication protocol for net/rpc. * Also includes an option for msgpack-rpc: http://wiki.msgpack.org/display/MSGPACK/RPC+specification API docs: http://godoc.org/github.com/ugorji/go-msgpack Usage -----
dec = msgpack.NewDecoder(r, nil) err = dec.Decode(&v) enc = msgpack.NewEncoder(w) err = enc.Encode(v) //methods below are convenience methods over functions above. data, err = msgpack.Marshal(v) err = msgpack.Unmarshal(data, &v, nil) //RPC Server conn, err := listener.Accept() rpcCodec := msgpack.NewRPCServerCodec(conn, nil) rpc.ServeCodec(rpcCodec) //RPC Communication (client side) conn, err = net.Dial("tcp", "localhost:5555") rpcCodec := msgpack.NewRPCClientCodec(conn, nil) client := rpc.NewClientWithCodec(rpcCodec)golang-github-ugorji-go-msgpack-0.0~git20130605.792643/decode.go 0000664 0000000 0000000 00000054331 12153716517 0023513 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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 msgpack // Code here is organized as follows: // Exported methods are not called internally. They are just facades. // Unmarshal calls Decode // Decode calls DecodeValue // DecodeValue calls decodeValue // decodeValue and all other unexported functions use panics (not errors) // and may call other unexported functions (which use panics). // Refactoring halted because we need a solution for map keys which are slices. // Easy way is to convert it to a string. // // To test with it, // - change rpc.go, msgpack_test.go to use // DecoderContainerResolver instead of *DecoderOptions (r:40, m:256, m:466) // &SimpleDecoderContainerResolver instead of &DecoderOptions (m: 467) import ( "io" "bytes" "reflect" "math" "fmt" // "net" "time" // "runtime/debug" "encoding/binary" ) // Some tagging information for error messages. var ( //_ = time.Parse msgTagDec = "msgpack.decoder" msgBadDesc = "Unrecognized descriptor byte: " ) // Default DecoderContainerResolver used when a nil parameter is passed to NewDecoder(). // Sample Usage: // opts := msgpack.DefaultDecoderContainerResolver // makes a copy // opts.BytesStringLiteral = false // change some options // err := msgpack.NewDecoder(r, &opts).Decode(&v) var DefaultDecoderContainerResolver = SimpleDecoderContainerResolver { MapType: nil, SliceType: nil, BytesStringLiteral: true, BytesStringSliceElement: true, BytesStringMapValue: true, } // A Decoder reads and decodes an object from an input stream in the msgpack format. type Decoder struct { r io.Reader dam DecoderContainerResolver x [16]byte //temp byte array re-used internally for efficiency t1, t2, t4, t8 []byte // use these, so no need to constantly re-slice } // DecoderContainerResolver has the DecoderContainer method for getting a usable reflect.Value // when decoding a container (map, array, raw bytes) from a stream into a nil interface{}. type DecoderContainerResolver interface { // DecoderContainer is used to get a proper reflect.Value when decoding // a msgpack map, array or raw bytes (for which the stream defines the length and // corresponding containerType) into a nil interface{}. // // This may be within the context of a container: ([]interface{} or map[XXX]interface{}), // or just a top-level literal. // // The parentcontainer and parentkey define the context // - If decoding into a map, they will be the map and the key in the map (a reflect.Value) // - If decoding into a slice, they will be the slice and the index into the slice (an int) // - Else they will be Invalid/nil // // Custom code can use this callback to determine how specifically to decode something. // A simple implementation exists which just uses some options to do it // (see SimpleDecoderContainerResolver). DecoderContainer(parentcontainer reflect.Value, parentkey interface{}, length int, ct ContainerType) (val reflect.Value) } // SimpleDecoderContainerResolver is a simple DecoderContainerResolver // which uses some simple options to determine how to decode into a nil interface{}. // Most applications will work fine with just this. type SimpleDecoderContainerResolver struct { // If decoding into a nil interface{} and we detect a map in the stream, // we create a map of the type specified. It defaults to creating a // map[interface{}]interface{} if not specified. MapType reflect.Type // If decoding into a nil interface{} and we detect a slice/array in the stream, // we create a slice of the type specified. It defaults to creating a // []interface{} if not specified. SliceType reflect.Type // convert to a string if raw bytes are detected while decoding // into a interface{}, BytesStringLiteral bool // convert to a string if raw bytes are detected while decoding // into a []interface{}, BytesStringSliceElement bool // convert to a string if raw bytes are detected while decoding // into a value in a map[XXX]interface{}, BytesStringMapValue bool } // DecoderContainer supports common cases for decoding into a nil // interface{} depending on the context. // // When decoding into a nil interface{}, the following rules apply as we have // to make assumptions about the specific types you want. // - Maps are decoded as map[interface{}]interface{} // unless you provide a default map type when creating your decoder. // option: MapType // - Lists are always decoded as []interface{} // unless you provide a default slice type when creating your decoder. // option: SliceType // - raw bytes are decoded into []byte or string depending on setting of: // option: BytesStringMapValue (if within a map value, use this setting) // option: BytesStringSliceElement (else if within a slice, use this setting) // option: BytesStringLiteral (else use this setting) func (d SimpleDecoderContainerResolver) DecoderContainer( parentcontainer reflect.Value, parentkey interface{}, length int, ct ContainerType) (rvn reflect.Value) { switch ct { case ContainerMap: if d.MapType != nil { rvn = reflect.MakeMap(d.MapType) } else { rvn = reflect.MakeMap(mapIntfIntfTyp) } case ContainerList: if d.SliceType != nil { rvn = reflect.MakeSlice(d.SliceType, length, length) } else { rvn = reflect.MakeSlice(intfSliceTyp, length, length) } case ContainerRawBytes: rk := parentcontainer.Kind() if (rk == reflect.Invalid && d.BytesStringLiteral) || (rk == reflect.Slice && d.BytesStringSliceElement) || (rk == reflect.Map && d.BytesStringMapValue) { rvm := "" rvn = reflect.ValueOf(&rvm) } else { rvn = reflect.MakeSlice(byteSliceTyp, length, length) } } // fmt.Printf("DecoderContainer: %T, %v\n", rvn.Interface(), rvn.Interface()) return } // NewDecoder returns a Decoder for decoding a stream of bytes into an object. // If nil DecoderContainerResolver is passed, we use DefaultDecoderContainerResolver func NewDecoder(r io.Reader, dam DecoderContainerResolver) (d *Decoder) { if dam == nil { dam = &DefaultDecoderContainerResolver } d = &Decoder{r:r, dam:dam} d.t1, d.t2, d.t4, d.t8 = d.x[:1], d.x[:2], d.x[:4], d.x[:8] return } // Decode decodes the stream from reader and stores the result in the // value pointed to by v. // // If v is a pointer to a non-nil value, we will decode the stream into that value // (if the value type and the stream match. For example: // integer in stream must go into int type (int8...int64), etc // // If you do not know what type of stream it is, pass in a pointer to a nil interface. // We will decode and store a value in that nil interface. // // time.Time is handled transparently, by (en)decoding (to)from a // []int64{Seconds since Epoch, Nanoseconds offset}. // // Sample usages: // // Decoding into a non-nil typed value // var f float32 // err = msgpack.NewDecoder(r, nil).Decode(&f) // // // Decoding into nil interface // var v interface{} // dec := msgpack.NewDecoder(r, nil) // err = dec.Decode(&v) // // // To configure default options, see DefaultDecoderContainerResolver usage. // // or write your own DecoderContainerResolver func (d *Decoder) Decode(v interface{}) (err error) { return d.DecodeValue(reflectValue(v)) } // DecodeValue decodes the stream into a reflect.Value. // The reflect.Value must be a pointer. // See Decoder.Decode documentation. (Decode internally calls DecodeValue). func (d *Decoder) DecodeValue(rv reflect.Value) (err error) { defer panicToErr(&err) // We cannot marshal into a non-pointer or a nil pointer // (at least pass a nil interface so we can marshal into it) if rv.Kind() != reflect.Ptr || rv.IsNil() { var rvi interface{} = rv if rv.IsValid() && rv.CanInterface() { rvi = rv.Interface() } err = fmt.Errorf("%v: DecodeValue: Expecting valid pointer to decode into. Got: %v, %T, %v", msgTagDec, rv.Kind(), rvi, rvi) return } //if a nil pointer is passed, set rv to the underlying value (not pointer). d.decodeValueT(0, -1, true, rv.Elem(), true, true, true) return } func (d *Decoder) decodeValueT(bd byte, containerLen int, readDesc bool, rve reflect.Value, checkWasNilIntf bool, dereferencePtr bool, setToRealValue bool) (rvn reflect.Value) { rvn = rve wasNilIntf, rv := d.decodeValue(bd, containerLen, readDesc, rve) //if wasNilIntf, rv is either a pointer to actual value, a map or slice, or nil/invalid if ((checkWasNilIntf && wasNilIntf) || !checkWasNilIntf) && rv.IsValid() { if dereferencePtr && rv.Kind() == reflect.Ptr { rv = rv.Elem() } if setToRealValue { rve.Set(rv) } rvn = rv } return } func (d *Decoder) nilIntfDecode(bd0 byte, containerLen0 int, readDesc bool, setContainers bool, rv0 reflect.Value) ( rv reflect.Value, bd byte, ct ContainerType, containerLen int, handled bool) { rv, bd, containerLen = rv0, bd0, containerLen0 if readDesc { d.readb(1, d.t1) bd = d.t1[0] } //if we set the reflect.Value to an primitive value, consider it handled and return. handled = true switch { case bd == 0xc0: case bd == 0xc2: rv.Set(reflect.ValueOf(false)) case bd == 0xc3: rv.Set(reflect.ValueOf(true)) case bd == 0xca: rv.Set(reflect.ValueOf(math.Float32frombits(d.readUint32()))) case bd == 0xcb: rv.Set(reflect.ValueOf(math.Float64frombits(d.readUint64()))) case bd == 0xcc: rv.Set(reflect.ValueOf(d.readUint8())) case bd == 0xcd: rv.Set(reflect.ValueOf(d.readUint16())) case bd == 0xce: rv.Set(reflect.ValueOf(d.readUint32())) case bd == 0xcf: rv.Set(reflect.ValueOf(d.readUint64())) case bd == 0xd0: rv.Set(reflect.ValueOf(int8(d.readUint8()))) case bd == 0xd1: rv.Set(reflect.ValueOf(int16(d.readUint16()))) case bd == 0xd2: rv.Set(reflect.ValueOf(int32(d.readUint32()))) case bd == 0xd3: rv.Set(reflect.ValueOf(int64(d.readUint64()))) case bd == 0xda, bd == 0xdb, bd >= 0xa0 && bd <= 0xbf: ct = ContainerRawBytes if containerLen < 0 { containerLen = d.readContainerLen(bd, false, ct) } if setContainers { rv.Set(d.dam.DecoderContainer(reflect.Value{}, nil, containerLen, ct)) rv = rv.Elem() } handled = false case bd == 0xdc, bd == 0xdd, bd >= 0x90 && bd <= 0x9f: ct = ContainerList if containerLen < 0 { containerLen = d.readContainerLen(bd, false, ct) } if setContainers { rv.Set(d.dam.DecoderContainer(reflect.Value{}, nil, containerLen, ct)) } handled = false case bd == 0xde, bd == 0xdf, bd >= 0x80 && bd <= 0x8f: ct = ContainerMap if containerLen < 0 { containerLen = d.readContainerLen(bd, false, ct) } if setContainers { rv.Set(d.dam.DecoderContainer(reflect.Value{}, nil, containerLen, ct)) } handled = false case bd >= 0xe0 && bd <= 0xff, bd >= 0x00 && bd <= 0x7f: // FIXNUM rv.Set(reflect.ValueOf(int8(bd))) default: handled = false d.err("Nil-Deciphered DecodeValue: %s: hex: %x, dec: %d", msgBadDesc, bd, bd) } return } func (d *Decoder) decodeValue(bd byte, containerLen int, readDesc bool, rv0 reflect.Value) ( wasNilIntf bool, rv reflect.Value) { //log(".. enter decode: rv: %v, %T, %v", rv0, rv0.Interface(), rv0.Interface()) //defer func() { // log(".. exit decode: rv: %v, %T, %v", rv, rv.Interface(), rv.Interface()) //}() rv = rv0 if readDesc { d.readb(1, d.t1) bd = d.t1[0] } rk := rv.Kind() wasNilIntf = rk == reflect.Interface && rv.IsNil() //if nil interface, use some hieristics to set the nil interface to an //appropriate value based on the first byte read (byte descriptor bd) if wasNilIntf { var handled bool rv, bd, _, containerLen, handled = d.nilIntfDecode(bd, containerLen, false, true, rv) if handled { return } rk = rv.Kind() } if bd == 0xc0 { rv.Set(reflect.Zero(rv.Type())) //log("== nil decode: rv: %v, %v", rv, rv.Interface()) return } // cases are arranged in sequence of most probable ones switch rk { default: // handles numeral and bool values switch bd { case 0xc2: rv.SetBool(false) case 0xc3: rv.SetBool(true) case 0xca: rv.SetFloat(float64(math.Float32frombits(d.readUint32()))) case 0xcb: rv.SetFloat(math.Float64frombits(d.readUint64())) default: d.err("Unhandled single-byte value: %s: %x", msgBadDesc, bd) } case reflect.String: if containerLen < 0 { containerLen = d.readContainerLen(bd, false, ContainerRawBytes) } if containerLen == 0 { break } bs := make([]byte, containerLen) d.readb(containerLen, bs) rv.SetString(string(bs)) case reflect.Slice: rvtype := rv.Type() rawbytes := rvtype == byteSliceTyp if containerLen < 0 { if rawbytes { containerLen = d.readContainerLen(bd, false, ContainerRawBytes) } else { containerLen = d.readContainerLen(bd, false, ContainerList) } } if containerLen == 0 { break } if rawbytes { var bs []byte= rv.Bytes() rvlen := len(bs) if rvlen == containerLen { } else if rvlen > containerLen { bs = bs[:containerLen] } else { bs = make([]byte, containerLen) rv.Set(reflect.ValueOf(bs)) } d.readb(containerLen, bs) break } if rv.IsNil() { rv.Set(reflect.MakeSlice(rvtype, containerLen, containerLen)) } else { rvlen := rv.Len() if containerLen > rv.Cap() { rv2 := reflect.MakeSlice(rvtype, containerLen, containerLen) if rvlen > 0 { reflect.Copy(rv2, rv) } rv.Set(rv2) } else if containerLen > rvlen { rv.SetLen(containerLen) } } d.decodeValuePostList(rv, containerLen, rvtype.Elem() == intfTyp) case reflect.Array: rvtype := rv.Type() rvlen := rv.Len() rawbytes := rvlen > 0 && rv.Index(0).Kind() == reflect.Uint8 if containerLen < 0 { if rawbytes { containerLen = d.readContainerLen(bd, false, ContainerRawBytes) } else { containerLen = d.readContainerLen(bd, false, ContainerList) } } if containerLen == 0 { break } if rawbytes { var bs []byte = rv.Slice(0, rvlen).Bytes() if rvlen == containerLen { d.readb(containerLen, bs) } else if rvlen > containerLen { d.readb(containerLen, bs[:containerLen]) } else { d.err("Array len: %d must be >= container Len: %d", rvlen, containerLen) } break } rvelemtype := rvtype.Elem() if rvlen < containerLen { d.err("Array len: %d must be >= container Len: %d", rvlen, containerLen) } else if rvlen > containerLen { for j := containerLen; j < rvlen; j++ { rv.Index(j).Set(reflect.Zero(rvelemtype)) } } d.decodeValuePostList(rv, containerLen, rvelemtype == intfTyp) case reflect.Struct: rvtype := rv.Type() if rvtype == timeTyp { tt := [2]int64{} d.decodeValue(bd, -1, false, reflect.ValueOf(&tt).Elem()) rv.Set(reflect.ValueOf(time.Unix(tt[0], tt[1]).UTC())) break } if containerLen < 0 { containerLen = d.readContainerLen(bd, false, ContainerMap) } if containerLen == 0 { break } for j := 0; j < containerLen; j++ { rvkencname := "" rvk := reflect.ValueOf(&rvkencname).Elem() d.decodeValue(0, -1, true, rvk) rvksi := getStructFieldInfos(rvtype).getForEncName(rvkencname) if rvksi == nil { // d.err("DecodeValue: Invalid Enc Field: %s", rvkencname) (skip it) var nilintf0 interface{} d.decodeValueT(0, -1, true, reflect.ValueOf(&nilintf0), true, true, true) } else { d.decodeValueT(0, -1, true, rvksi.field(rv), true, true, true) } } case reflect.Map: if containerLen < 0 { containerLen = d.readContainerLen(bd, false, ContainerMap) } if containerLen == 0 { break } rvtype := rv.Type() ktype, vtype := rvtype.Key(), rvtype.Elem() if rv.IsNil() { rvn := reflect.MakeMap(rvtype) rv.Set(rvn) } for j := 0; j < containerLen; j++ { rvk := reflect.New(ktype).Elem() rvk = d.decodeValueT(0, -1, true, rvk, true, true, false) if ktype == intfTyp && rvk.Type() == byteSliceTyp { rvk = reflect.ValueOf(string(rvk.Bytes())) } rvv := rv.MapIndex(rvk) if !rvv.IsValid() { rvv = reflect.New(vtype).Elem() } if vtype == intfTyp && rvv.IsNil() { rvv, bd0, ct0, containerLen0, handled0 := d.nilIntfDecode(0, -1, true, false, rvv) if !handled0 { if rvv2 := d.dam.DecoderContainer(rv, rvk, containerLen0, ct0); rvv2.IsValid() { rvv2 = d.decodeValueT(bd0, containerLen0, false, rvv2, false, true, false) rvv.Set(rvv2) } else { rvv = d.decodeValueT(bd0, containerLen0, false, rvv, true, true, false) } } } else { rvv = d.decodeValueT(0, -1, true, rvv, true, true, false) } rv.SetMapIndex(rvk, rvv) } case reflect.Ptr: if rv.IsNil() { rv.Set(reflect.New(rv.Type().Elem())) } d.decodeValue(bd, containerLen, false, rv.Elem()) case reflect.Interface: d.decodeValue(bd, containerLen, false, rv.Elem()) case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int8, reflect.Int16: i, _ := d.decodeInteger(bd, true) if rv.OverflowInt(i) { d.err("Overflow int value: %v into kind: %v", i, rk) } else { rv.SetInt(i) } case reflect.Uint8, reflect.Uint64, reflect.Uint, reflect.Uint32, reflect.Uint16: _, ui := d.decodeInteger(bd, false) if rv.OverflowUint(ui) { d.err("Overflow unsigned int value: %v into kind: %v", ui, rk) } else { rv.SetUint(ui) } } return } func (d *Decoder) decodeValuePostList(rv reflect.Value, containerLen int, elemIsIntf bool) { for j := 0; j < containerLen; j++ { rvj := rv.Index(j) if elemIsIntf && rvj.IsNil() { rvj, bd0, ct0, containerLen0, handled0 := d.nilIntfDecode(0, -1, true, false, rvj) // fmt.Printf("intfTyp: %v, %v, %v, %v, %v\n", rvj.Interface(), bd0, ct0, containerLen0, handled0) if !handled0 { if rvj2 := d.dam.DecoderContainer(rv, j, containerLen0, ct0); rvj2.IsValid() { rvj2 = d.decodeValueT(bd0, containerLen0, false, rvj2, false, true, false) rvj.Set(rvj2) } else { d.decodeValueT(bd0, containerLen0, false, rvj, true, true, true) } } } else { d.decodeValueT(0, -1, true, rvj, true, true, true) } } } // decode an integer from the stream func (d *Decoder) decodeInteger(bd byte, sign bool) (i int64, ui uint64) { switch { case bd == 0xcc: ui = uint64(d.readUint8()) if sign { i = int64(ui) } case bd == 0xcd: ui = uint64(d.readUint16()) if sign { i = int64(ui) } case bd == 0xce: ui = uint64(d.readUint32()) if sign { i = int64(ui) } case bd == 0xcf: ui = d.readUint64() if sign { i = int64(ui) } case bd == 0xd0: i = int64(int8(d.readUint8())) if !sign { if i >= 0 { ui = uint64(i) } else { d.err("Assigning negative signed value: %v, to unsigned type", i) } } case bd == 0xd1: i = int64(int16(d.readUint16())) if !sign { if i >= 0 { ui = uint64(i) } else { d.err("Assigning negative signed value: %v, to unsigned type", i) } } case bd == 0xd2: i = int64(int32(d.readUint32())) if !sign { if i >= 0 { ui = uint64(i) } else { d.err("Assigning negative signed value: %v, to unsigned type", i) } } case bd == 0xd3: i = int64(d.readUint64()) if !sign { if i >= 0 { ui = uint64(i) } else { d.err("Assigning negative signed value: %v, to unsigned type", i) } } case bd >= 0x00 && bd <= 0x7f: if sign { i = int64(int8(bd)) } else { ui = uint64(bd) } case bd >= 0xe0 && bd <= 0xff: i = int64(int8(bd)) if !sign { d.err("Assigning negative signed value: %v, to unsigned type", i) } default: d.err("Unhandled single-byte unsigned integer value: %s: %x", msgBadDesc, bd) } return } // read a number of bytes into bs func (d *Decoder) readb(numbytes int, bs []byte) { n, err := io.ReadAtLeast(d.r, bs, numbytes) if err != nil { // propagage io.EOF upwards (it's special, and must be returned AS IS) if err == io.EOF { panic(err) } else { d.err("Error: %v", err) } } else if n != numbytes { d.err("read: Incorrect num bytes read. Expecting: %v, Received: %v", numbytes, n) } } func (d *Decoder) readUint8() uint8 { d.readb(1, d.t1) return d.t1[0] } func (d *Decoder) readUint16() uint16 { d.readb(2, d.t2) return binary.BigEndian.Uint16(d.t2) } func (d *Decoder) readUint32() uint32 { d.readb(4, d.t4) return binary.BigEndian.Uint32(d.t4) } func (d *Decoder) readUint64() uint64 { d.readb(8, d.t8) return binary.BigEndian.Uint64(d.t8) } func (d *Decoder) readContainerLen(bd byte, readDesc bool, ct ContainerType) (l int) { // bd is the byte descriptor. First byte is always descriptive. if readDesc { d.readb(1, d.t1) bd = d.t1[0] } _, b0, b1, b2 := getContainerByteDesc(ct) switch { case bd == b1: l = int(d.readUint16()) case bd == b2: l = int(d.readUint32()) case (b0 & bd) == b0: l = int(b0 ^ bd) default: d.err("readContainerLen: %s: hex: %x, dec: %d", msgBadDesc, bd, bd) } return } func (d *Decoder) err(format string, params ...interface{}) { doPanic(msgTagDec, format, params) } // Unmarshal is a convenience function which decodes a stream of bytes into v. // It delegates to Decoder.Decode. func Unmarshal(data []byte, v interface{}, dam DecoderContainerResolver) error { return NewDecoder(bytes.NewBuffer(data), dam).Decode(v) } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/doc.go 0000664 0000000 0000000 00000007655 12153716517 0023044 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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. */ /* MsgPack library for Go (DEPRECATED - Replacement: go get github.com/ugorji/go/codec) THIS LIBRARY IS DEPRECATED (May 29, 2013) Please use github.com/ugorji/go/codec which is significantly faster, cleaner, more correct and more complete. See [https://github.com/ugorji/go/tree/master/codec#readme] A complete redesign was done which also accomodates multiple codec formats. It thus became necessary to create a new repository with a different name. I hope to retire this repository anytime from July 1, 2013. A log message will be printed out at runtime encouraging users to upgrade. Implements: http://wiki.msgpack.org/display/MSGPACK/Format+specification It provides features similar to encoding packages in the standard library (ie json, xml, gob, etc). Supports: - Standard Marshal/Unmarshal interface. - Standard field renaming via tags - Encoding from any value (struct, slice, map, primitives, pointers, interface{}, etc) - Decoding into pointer to any non-nil value (struct, slice, map, int, float32, bool, string, etc) - Decoding into a nil interface{} - Handles time.Time transparently - Provides a Server and Client Codec so msgpack can be used as communication protocol for net/rpc. Also includes an option for msgpack-rpc: http://wiki.msgpack.org/display/MSGPACK/RPC+specification Usage dec = msgpack.NewDecoder(r, nil) err = dec.Decode(&v) enc = msgpack.NewEncoder(w) err = enc.Encode(v) //methods below are convenience methods over functions above. data, err = msgpack.Marshal(v) err = msgpack.Unmarshal(data, &v, nil) //RPC Server conn, err := listener.Accept() rpcCodec := msgpack.NewRPCServerCodec(conn, nil) rpc.ServeCodec(rpcCodec) //RPC Communication (client side) conn, err = net.Dial("tcp", "localhost:5555") rpcCodec := msgpack.NewRPCClientCodec(conn, nil) client := rpc.NewClientWithCodec(rpcCodec) */ package msgpack import golog "log" func init() { //printout deprecation notice golog.Print(` ************************************************ package github.com/ugorji/go-msgpack has been deprecated (05/29/2013). It will be retired anytime from July 1, 2013. Please update to faster and much much better github.com/ugorji/go/codec. See https://github.com/ugorji/go/tree/master/codec#readme for more information. ************************************************ `) } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/encode.go 0000664 0000000 0000000 00000024533 12153716517 0023526 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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 msgpack // Code here is organized as follows: // Exported methods are not called internally. They are just facades. // Marshal calls Encode // Encode calls EncodeValue // EncodeValue calls encodeValue // encodeValue and all other unexported functions use panics (not errors) // and may call other unexported functions (which use panics). // import ( "io" "bytes" "reflect" "math" "time" "encoding/binary" ) var ( // Some tagging information for error messages. msgTagEnc = "msgpack.encoder" ) // An Encoder writes an object to an output stream in the msgpack format. type Encoder struct { w io.Writer x [16]byte //temp byte array re-used internally for efficiency t1, t2, t3, t31, t5, t51, t9, t91 []byte // use these, so no need to constantly re-slice } // NewDecoder returns an Encoder for encoding an object. func NewEncoder(w io.Writer) (e *Encoder) { e = &Encoder{w:w} e.t1, e.t2, e.t3, e.t31, e.t5, e.t51, e.t9, e.t91 = e.x[:1], e.x[:2], e.x[:3], e.x[1:3], e.x[:5], e.x[1:5], e.x[:9], e.x[1:9] return } // Encode writes an object into a stream in the MsgPack format. // // time.Time is handled transparently, by (en)decoding (to)from a // []int64{Seconds since Epoch, Nanoseconds offset}. // // Struct values encode as maps. Each exported struct field is encoded unless: // - the field's tag is "-", or // - the field is empty and its tag specifies the "omitempty" option. // // The empty values are false, 0, any nil pointer or interface value, // and any array, slice, map, or string of length zero. // // Anonymous fields are encoded inline if no msgpack tag is present. // Else they are encoded as regular fields. // // The object's default key string is the struct field name but can be // specified in the struct field's tag value. // The "msgpack" key in struct field's tag value is the key name, // followed by an optional comma and options. // // To set an option on all fields (e.g. omitempty on all fields), you // can create a field called _struct, and set flags on it. // // Examples: // // type MyStruct struct { // _struct bool `msgpack:",omitempty"` //set omitempty for every field // Field1 string `msgpack:"-"` //skip this field // Field2 int `msgpack:"myName"` //Use key "myName" in encode stream // Field3 int32 `msgpack:",omitempty"` //use key "Field3". Omit if empty. // Field4 bool `msgpack:"f4,omitempty"` //use key "f4". Omit if empty. // ... // } // func (e *Encoder) Encode(v interface{}) (err error) { return e.EncodeValue(reflectValue(v)) } // EncodeValue encodes a reflect.Value. func (e *Encoder) EncodeValue(rv reflect.Value) (err error) { defer panicToErr(&err) e.encodeValue(rv) return } func (e *Encoder) encode(v interface{}) { e.encodeValue(reflectValue(v)) } func (e *Encoder) encodeValue(rv reflect.Value) { //log("++ enter encode rv: %v, %v", rv, rv.Interface()) //defer func() { // log("++ exit encode rv: %v, %v", rv, rv.Interface()) //}() // Tested with a type assertion for all common types first, but this increased encoding time // sometimes by up to 20% (weird). So just use the reflect.Kind switch alone. // ensure more common cases appear early in switch. switch rk := rv.Kind(); rk { case reflect.Bool: e.encBool(rv.Bool()) case reflect.String: e.encString(rv.String()) case reflect.Int, reflect.Int8, reflect.Int64, reflect.Int32, reflect.Int16: e.encInt(rv.Int()) case reflect.Uint8, reflect.Uint64, reflect.Uint, reflect.Uint32, reflect.Uint16: e.encUint(rv.Uint()) case reflect.Float64: e.t9[0] = 0xcb binary.BigEndian.PutUint64(e.t91, math.Float64bits(rv.Float())) e.writeb(9, e.t9) case reflect.Float32: e.t5[0] = 0xca binary.BigEndian.PutUint32(e.t51, math.Float32bits(float32(rv.Float()))) e.writeb(5, e.t5) case reflect.Slice: if rv.IsNil() { e.encNil() break } l := rv.Len() if rv.Type() == byteSliceTyp { e.writeContainerLen(ContainerRawBytes, l) if l > 0 { e.writeb(l, rv.Bytes()) } break } e.writeContainerLen(ContainerList, l) for j := 0; j < l; j++ { e.encode(rv.Index(j)) } case reflect.Array: l := rv.Len() // this should not happen (a 0-elem array makes no sense) ... but just in case if l == 0 { e.writeContainerLen(ContainerList, l) break } // log("---- %v", rv.Type()) // if rv.Type().Elem().Kind == reflect.Uint8 { // surprisingly expensive (check 1st value instead) if rv.Index(0).Kind() == reflect.Uint8 { e.writeContainerLen(ContainerRawBytes, l) e.writeb(l, rv.Slice(0, l).Bytes()) break } e.writeContainerLen(ContainerList, l) for j := 0; j < l; j++ { e.encode(rv.Index(j)) } case reflect.Map: if rv.IsNil() { e.encNil() break } e.writeContainerLen(ContainerMap, rv.Len()) for _, mk := range rv.MapKeys() { e.encode(mk) e.encode(rv.MapIndex(mk)) } case reflect.Struct: rt := rv.Type() //treat time.Time specially if rt == timeTyp { tt := rv.Interface().(time.Time) e.encode([2]int64{tt.Unix(), int64(tt.Nanosecond())}) break } e.encodeStruct(rt, rv) case reflect.Ptr, reflect.Interface: if rv.IsNil() { e.encNil() break } e.encodeValue(rv.Elem()) case reflect.Invalid: e.encNil() default: e.err("Unsupported kind: %s, for: %#v", rk, rv) } return } func (e *Encoder) writeContainerLen(ct ContainerType, l int) { locutoff, b0, b1, b2 := getContainerByteDesc(ct) switch { case l < locutoff: e.t1[0] = (b0 | byte(l)) e.writeb(1, e.t1) case l < 65536: e.t3[0] = b1 binary.BigEndian.PutUint16(e.t31, uint16(l)) e.writeb(3, e.t3) default: e.t5[0] = b2 binary.BigEndian.PutUint32(e.t51, uint32(l)) e.writeb(5, e.t5) } } func (e *Encoder) encNil() { e.t1[0] = 0xc0 e.writeb(1, e.t1) } func (e *Encoder) encInt(i int64) { switch { case i < math.MinInt32 || i > math.MaxInt32: e.t9[0] = 0xd3 binary.BigEndian.PutUint64(e.t91, uint64(i)) e.writeb(9, e.t9) case i < math.MinInt16 || i > math.MaxInt16: e.t5[0] = 0xd2 binary.BigEndian.PutUint32(e.t51, uint32(i)) e.writeb(5, e.t5) case i < math.MinInt8 || i > math.MaxInt8: e.t3[0] = 0xd1 binary.BigEndian.PutUint16(e.t31, uint16(i)) e.writeb(3, e.t3) case i < -32: e.t2[0], e.t2[1] = 0xd0, byte(i) e.writeb(2, e.t2) case i >= -32 && i <= math.MaxInt8: e.t1[0] = byte(i) e.writeb(1, e.t1) default: e.err("encInt64: Unreachable block") } } func (e *Encoder) encUint(i uint64) { switch { case i <= math.MaxInt8: e.t1[0] = byte(i) e.writeb(1, e.t1) case i <= math.MaxUint8: e.t2[0], e.t2[1] = 0xcc, byte(i) e.writeb(2, e.t2) case i <= math.MaxUint16: e.t3[0] = 0xcd binary.BigEndian.PutUint16(e.t31, uint16(i)) e.writeb(3, e.t3) case i <= math.MaxUint32: e.t5[0] = 0xce binary.BigEndian.PutUint32(e.t51, uint32(i)) e.writeb(5, e.t5) default: e.t9[0] = 0xcf binary.BigEndian.PutUint64(e.t91, i) e.writeb(9, e.t9) } } func (e *Encoder) encBool(b bool) { if b { e.t1[0] = 0xc3 } else { e.t1[0] = 0xc2 } e.writeb(1, e.t1) } func (e *Encoder) encodeStruct(rt reflect.Type, rv reflect.Value) { sis := getStructFieldInfos(rt) // e.writeContainerLen(ContainerMap, len(sis.sis)) // for _, si := range sis.sis { // e.encode(si.encNameBs) // e.encode(si.field(rv)) // } // return encNames := make([][]byte, len(sis.sis)) rvals := make([]reflect.Value, len(sis.sis)) newlen := 0 for _, si := range sis.sis { rval0 := si.field(rv) if si.omitEmpty && isEmptyValue(rval0) { continue } encNames[newlen] = si.encNameBs rvals[newlen] = rval0 newlen++ } e.writeContainerLen(ContainerMap, newlen) for j := 0; j < newlen; j++ { e.encode(encNames[j]) e.encode(rvals[j]) } } func (e *Encoder) encString(s string) { numbytes := len(s) e.writeContainerLen(ContainerRawBytes, numbytes) // e.encode([]byte(s)) // using io.WriteString is faster n, err := io.WriteString(e.w, s) if err != nil { e.err("Error: %v", err) } if n != numbytes { e.err("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", numbytes, n) } } func (e *Encoder) writeb(numbytes int, bs []byte) { // no sanity checking. Assume callers pass valid arguments. It's pkg-private: we can control it. n, err := e.w.Write(bs) if err != nil { // propagage io.EOF upwards (it's special, and must be returned AS IS) if err == io.EOF { panic(err) } else { e.err("Error: %v", err) } } if n != numbytes { e.err("write: Incorrect num bytes written. Expecting: %v, Wrote: %v", numbytes, n) } } func (e *Encoder) err(format string, params ...interface{}) { doPanic(msgTagEnc, format, params) } // Marshal is a convenience function which encodes v to a stream of bytes. // It delegates to Encoder.Encode. func Marshal(v interface{}) (b []byte, err error) { bs := new(bytes.Buffer) if err = NewEncoder(bs).Encode(v); err == nil { b = bs.Bytes() } return } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/helper.go 0000664 0000000 0000000 00000013457 12153716517 0023553 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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 msgpack import ( "unicode" "unicode/utf8" "reflect" "sync" "strings" "fmt" "time" ) type ContainerType byte const ( ContainerRawBytes = ContainerType('b') ContainerList = ContainerType('a') ContainerMap = ContainerType('m') ) var ( structInfoFieldName = "_struct" cachedStructFieldInfos = make(map[reflect.Type]*structFieldInfos, 4) cachedStructFieldInfosMutex sync.Mutex nilIntfSlice = []interface{}(nil) intfSliceTyp = reflect.TypeOf(nilIntfSlice) intfTyp = intfSliceTyp.Elem() byteSliceTyp = reflect.TypeOf([]byte(nil)) timeTyp = reflect.TypeOf(time.Time{}) mapStringIntfTyp = reflect.TypeOf(map[string]interface{}(nil)) mapIntfIntfTyp = reflect.TypeOf(map[interface{}]interface{}(nil)) ) type structFieldInfo struct { i int // field index in struct is []int tag string omitEmpty bool encName string // encode name encNameBs []byte name string // field name } type structFieldInfos struct { sis []*structFieldInfo } func (si *structFieldInfo) field(struc reflect.Value) (rv reflect.Value) { if si.i > -1 { rv = struc.Field(si.i) } else { rv = struc.FieldByIndex(si.is) } return } // linear search. faster than binary search in my testing up to 16-field structs. func (sis *structFieldInfos) getForEncName(name string) (si *structFieldInfo) { for _, si = range sis.sis { if si.encName == name { return } } si = nil return } func getStructFieldInfos(rt reflect.Type) (sis *structFieldInfos) { sis, ok := cachedStructFieldInfos[rt] if ok { return } cachedStructFieldInfosMutex.Lock() defer cachedStructFieldInfosMutex.Unlock() sis = new(structFieldInfos) var siInfo *structFieldInfo if f, ok := rt.FieldByName(structInfoFieldName); ok { siInfo = parseStructFieldInfo(structInfoFieldName, f.Tag.Get("msgpack")) } rgetStructFieldInfos(rt, nil, sis, siInfo) cachedStructFieldInfos[rt] = sis return } func rgetStructFieldInfos(rt reflect.Type, indexstack []int, sis *structFieldInfos, siInfo *structFieldInfo) { for j := 0; j < rt.NumField(); j++ { f := rt.Field(j) stag := f.Tag.Get("msgpack") if stag == "-" { continue } if r1, _ := utf8.DecodeRuneInString(f.Name); r1 == utf8.RuneError || !unicode.IsUpper(r1) { continue } if f.Anonymous { //if anonymous, inline it if there is no msgpack tag, else treat as regular field if stag == "" { rgetStructFieldInfos(f.Type, append2Is(indexstack, j), sis, siInfo) continue } } si := parseStructFieldInfo(f.Name, stag) if len(indexstack) == 0 { si.i = j } else { si.i = -1 si.is = append2Is(indexstack, j) } if siInfo != nil { if siInfo.omitEmpty { si.omitEmpty = true } } sis.sis = append(sis.sis, si) } } func append2Is(indexstack []int, j int) (indexstack2 []int) { // istack2 := indexstack //make copy (not sufficient ... since it'd still share array) indexstack2 = make([]int, len(indexstack)+1) copy(indexstack2, indexstack) indexstack2[len(indexstack2)-1] = j return } func parseStructFieldInfo(fname string, stag string) (si *structFieldInfo) { if fname == "" { panic("parseStructFieldInfo: No Field Name") } si = &structFieldInfo { name: fname, encName: fname, tag: stag, } if stag != "" { for i, s := range strings.Split(si.tag, ",") { if i == 0 { if s != "" { si.encName = s } } else { if s == "omitempty" { si.omitEmpty = true } } } } si.encNameBs = []byte(si.encName) return } func getContainerByteDesc(ct ContainerType) (cutoff int, b0, b1, b2 byte) { switch ct { case ContainerRawBytes: cutoff = 32 b0, b1, b2 = 0xa0, 0xda, 0xdb case ContainerList: cutoff = 16 b0, b1, b2 = 0x90, 0xdc, 0xdd case ContainerMap: cutoff = 16 b0, b1, b2 = 0x80, 0xde, 0xdf default: panic(fmt.Errorf("getContainerByteDesc: Unknown container type: %v", ct)) } return } func reflectValue(v interface{}) (rv reflect.Value) { rv, ok := v.(reflect.Value) if !ok { rv = reflect.ValueOf(v) } return } func panicToErr(err *error) { if x := recover(); x != nil { panicToErrT(x, err) } } func doPanic(tag string, format string, params []interface{}) { params2 := make([]interface{}, len(params) + 1) params2[0] = tag copy(params2[1:], params) panic(fmt.Errorf("%s: " + format, params2...)) } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/helper.py 0000775 0000000 0000000 00000004137 12153716517 0023574 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python # This will create golden files in a directory passed to it. # A Test calls this internally to create the golden files # So it can process them (so we don't have to checkin the files). import msgpack, sys, os def get_test_data_list(): # get list with all primitive types, and a combo type l = [ -8, -1616, -32323232, -6464646464646464, 8, 1616, 32323232, 6464646464646464, 8, -3232.0, -6464646464.0, 3232.0, 6464646464.0, False, True, None, 1328148122000002, "someday", "", "bytestring", [ -8, -1616, -32323232, -6464646464646464, 8, 1616, 32323232, 6464646464646464, 8, -3232.0, -6464646464.0, 3232.0, 6464646464.0, False, True, None, 1328148122000002, "someday", "", "bytestring" ], { "true": True, "false": False }, { "true": "True", "false": False, "int64(0)": 0 }, { "list": [1616, 32323232, True, -3232.0, {"TRUE":True, "FALSE":False}, [True, False] ], "int32":32323232, "bool": True, "LONG STRING": "123456789012345678901234567890123456789012345678901234567890", "SHORT STRING": "1234567890" }, { True: "true", 8: False, "false": 0 } ] return l def build_test_data(destdir): l = get_test_data_list() for i in range(len(l)): packer = msgpack.Packer() serialized = packer.pack(l[i]) f = open(os.path.join(destdir, str(i) + '.golden'), 'wb') f.write(serialized) f.close() def doMain(args): if len(args) == 2 and args[0] == "testdata": build_test_data(args[1]) else: print("Usage: build.py [testdata]") if __name__ == "__main__": doMain(sys.argv[1:]) golang-github-ugorji-go-msgpack-0.0~git20130605.792643/helper_internal.go 0000664 0000000 0000000 00000010457 12153716517 0025444 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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 msgpack // All non-std package dependencies live in this file, // so porting to different environment is easy (just update functions). import ( "testing" "reflect" "fmt" "errors" ) var ( raisePanicAfterRecover = false showLog = true debugging = false testLogToT = true failNowOnFail = true ) func checkErrT(t *testing.T, err error) { if err != nil { logT(t, err.Error()) failT(t) } } func checkEqualT(t *testing.T, v1 interface{}, v2 interface{}) { if !reflect.DeepEqual(v1, v2) { logT(t, "Do not match: v1: %v, v2: %v", v1, v2) failT(t) } } func panicToErrT(panicVal interface{}, err *error) { switch xerr := panicVal.(type) { case error: *err = xerr case string: *err = errors.New(xerr) default: *err = fmt.Errorf("%v", panicVal) } if raisePanicAfterRecover { panic(panicVal) } return } func isEmptyValue(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: return v.Len() == 0 case reflect.Bool: return !v.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Interface, reflect.Ptr: return v.IsNil() } return false } func approxDataSize(rv reflect.Value) (sum int) { switch rk := rv.Kind(); rk { case reflect.Invalid: case reflect.Ptr, reflect.Interface: sum += int(rv.Type().Size()) sum += approxDataSize(rv.Elem()) case reflect.Slice: sum += int(rv.Type().Size()) for j := 0; j < rv.Len(); j++ { sum += approxDataSize(rv.Index(j)) } case reflect.String: sum += int(rv.Type().Size()) sum += rv.Len() case reflect.Map: sum += int(rv.Type().Size()) for _, mk := range rv.MapKeys() { sum += approxDataSize(mk) sum += approxDataSize(rv.MapIndex(mk)) } case reflect.Struct: //struct size already includes the full data size. //sum += int(rv.Type().Size()) for j := 0; j < rv.NumField(); j++ { sum += approxDataSize(rv.Field(j)) } default: //pure value types sum += int(rv.Type().Size()) } return } func logT(x interface{}, format string, args ...interface{}) { if t, ok := x.(*testing.T); ok && t != nil && testLogToT { t.Logf(format, args...) } else if b, ok := x.(*testing.B); ok && b != nil && testLogToT { b.Logf(format, args...) } else { log(format, args...) } } func failT(t *testing.T) { if failNowOnFail { t.FailNow() } else { t.Fail() } } func log(format string, args ...interface{}) { if showLog || debugging { if len(format) == 0 || format[len(format)-1] != '\n' { format = format + "\n" } fmt.Printf(format, args...) } } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/msgpack_bench_test.go 0000664 0000000 0000000 00000015024 12153716517 0026107 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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 msgpack import ( "launchpad.net/mgo/bson" "encoding/json" "encoding/gob" "testing" "bytes" "reflect" "time" "runtime" "flag" ) var ( //depth of 0 maps to ~400bytes json-encoded string, 1 maps to ~1400 bytes, etc benchDepth = 0 benchBs []byte benchTs TestStruc benchDoInitBench = flag.Bool("mb", false, "Run Bench Init") ) type benchFn func(buf *bytes.Buffer, ts *TestStruc) error func init() { flag.Parse() gob.Register(new(TestStruc)) benchTs = newTestStruc(benchDepth, true) approxSize := approxDataSize(reflect.ValueOf(benchTs)) //benchBs = make([]byte, 1024 * 4 * d) //initialize benchBs large enough to hold double approx size //(to fit all encodings without expansion) benchBs = make([]byte, approxSize * 2) if *benchDoInitBench { logT(nil, "") logT(nil, "..............................................") logT(nil, "BENCHMARK INIT: %v", time.Now()) logT(nil, "TO RUN FULL BENCHMARK comparing MsgPack, JSON,BSON,GOB, " + "use \"go test -test.bench .\"") logT(nil, "Benchmark: " + "\n\tinit []byte size: %d, " + "\n\tStruct recursive Depth: %d, " + "\n\tApproxDeepSize Of benchmark Struct: %d, ", len(benchBs), benchDepth, approxSize, ) benchCheck() logT(nil, "..............................................") } } func benchCheck() { fn := func(name string, encfn benchFn, decfn benchFn) { benchBs = benchBs[0:0] buf := bytes.NewBuffer(benchBs) var err error runtime.GC() tnow := time.Now() if err = encfn(buf, &benchTs); err != nil { logT(nil, "\t%10s: **** Error encoding benchTs: %v", name, err) } encDur := time.Now().Sub(tnow) encLen := buf.Len() //log("\t%10s: encLen: %v, len: %v, cap: %v\n", name, encLen, len(benchBs), cap(benchBs)) buf = bytes.NewBuffer(benchBs[0:encLen]) runtime.GC() tnow = time.Now() if err = decfn(buf, new(TestStruc)); err != nil { logT(nil, "\t%10s: **** Error decoding into new TestStruc: %v", name, err) } decDur := time.Now().Sub(tnow) logT(nil, "\t%10s: Encode Size: %5d, Encode Time: %8v, Decode Time: %8v", name, encLen, encDur, decDur) } logT(nil, "Benchmark One-Pass Unscientific Marshal Sizes:") fn("msgpack", fnMsgpackEncodeFn, fnMsgpackDecodeFn) fn("gob", fnGobEncodeFn, fnGobDecodeFn) fn("bson", fnBsonEncodeFn, fnBsonDecodeFn) fn("json", fnJsonEncodeFn, fnJsonDecodeFn) } func fnBenchmarkEncode(b *testing.B, encfn benchFn) { //benchOnce.Do(benchInit) runtime.GC() b.ResetTimer() for i := 0; i < b.N; i++ { benchBs = benchBs[0:0] buf := bytes.NewBuffer(benchBs) if err := encfn(buf, &benchTs); err != nil { logT(b, "Error encoding benchTs: %v", err) b.FailNow() } } } func fnBenchmarkDecode(b *testing.B, encfn benchFn, decfn benchFn) { var err error benchBs = benchBs[0:0] buf := bytes.NewBuffer(benchBs) if err = encfn(buf, &benchTs); err != nil { logT(b, "Error encoding benchTs: %v", err) b.FailNow() } encLen := buf.Len() benchBs = benchBs[0:encLen] runtime.GC() b.ResetTimer() for i := 0; i < b.N; i++ { ts := new(TestStruc) buf = bytes.NewBuffer(benchBs) if err = decfn(buf, ts); err != nil { logT(b, "Error decoding into new TestStruc: %v", err) b.FailNow() } if ts.I64slice[2] != int64(3) { logT(b, "Error: Decode failed by checking values") b.FailNow() } } } func fnMsgpackEncodeFn(buf *bytes.Buffer, ts *TestStruc) error { return NewEncoder(buf).Encode(ts) } func fnMsgpackDecodeFn(buf *bytes.Buffer, ts *TestStruc) error { //return NewDecoder(buf, nil).Decode(ts) return NewDecoder(buf, testDecOpts(nil, nil, false, false, false)).Decode(ts) } func fnGobEncodeFn(buf *bytes.Buffer, ts *TestStruc) error { return gob.NewEncoder(buf).Encode(ts) } func fnGobDecodeFn(buf *bytes.Buffer, ts *TestStruc) error { return gob.NewDecoder(buf).Decode(ts) } func fnJsonEncodeFn(buf *bytes.Buffer, ts *TestStruc) error { return json.NewEncoder(buf).Encode(ts) } func fnJsonDecodeFn(buf *bytes.Buffer, ts *TestStruc) error { return json.NewDecoder(buf).Decode(ts) } func fnBsonEncodeFn(buf *bytes.Buffer, ts *TestStruc) error { bs, err := bson.Marshal(ts) if err == nil { buf.Write(bs) } return err } func fnBsonDecodeFn(buf *bytes.Buffer, ts *TestStruc) error { return bson.Unmarshal(buf.Bytes(), ts) } func Benchmark__Msgpack__Encode(b *testing.B) { fnBenchmarkEncode(b, fnMsgpackEncodeFn) } func Benchmark__Gob______Encode(b *testing.B) { fnBenchmarkEncode(b, fnGobEncodeFn) } func Benchmark__Bson_____Encode(b *testing.B) { fnBenchmarkEncode(b, fnBsonEncodeFn) } func Benchmark__Json_____Encode(b *testing.B) { fnBenchmarkEncode(b, fnJsonEncodeFn) } func Benchmark__Msgpack__Decode(b *testing.B) { fnBenchmarkDecode(b, fnMsgpackEncodeFn, fnMsgpackDecodeFn) } func Benchmark__Gob______Decode(b *testing.B) { fnBenchmarkDecode(b, fnGobEncodeFn, fnGobDecodeFn) } func Benchmark__Bson_____Decode(b *testing.B) { fnBenchmarkDecode(b, fnBsonEncodeFn, fnBsonDecodeFn) } func Benchmark__Json_____Decode(b *testing.B) { fnBenchmarkDecode(b, fnJsonEncodeFn, fnJsonDecodeFn) } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/msgpack_test.go 0000664 0000000 0000000 00000044305 12153716517 0024754 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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 msgpack // Test works by using a slice of interfaces. // It can test for encoding/decoding into/from a nil interface{} // or passing the object to encode/decode into. // // There are basically 2 main tests here. // First test internally encodes and decodes things and verifies that // the artifact was as expected. // Second test will use python msgpack to create a bunch of golden files, // read those files, and compare them to what it should be. It then // writes those files back out and compares the byte streams. // // Taken together, the tests are pretty extensive. import ( "reflect" "testing" "net/rpc" "bytes" "time" "os" "os/exec" "io/ioutil" "path/filepath" "strconv" "net" ) var ( skipVerifyVal interface{} = &(struct{}{}) timeToCompare = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC) //time.Time{} // //"2012-02-02T02:02:02.000002000Z" //1328148122000002 timeToCompareAs interface{} = timeToCompare.UnixNano() table []interface{} // main items we encode tableVerify []interface{} // we verify encoded things against this after decode tableTestNilVerify []interface{} // for nil interface, use this to verify (rules are different) tablePythonVerify []interface{} // for verifying for python, since Python sometimes // will encode a float32 as float64, or large int as uint testRpcInt = new(TestRpcInt) ) type AnonInTestStruc struct { AS string AI64 int64 AI16 int16 AUi64 uint64 ASslice []string AI64slice []int64 } type TestStruc struct { S string I64 int64 I16 int16 Ui64 uint64 Ui8 uint8 B bool By byte Sslice []string I64slice []int64 I16slice []int16 Ui64slice []uint64 Ui8slice []uint8 Bslice []bool Byslice []byte Islice []interface{} Iptrslice []*int64 AnonInTestStruc //M map[interface{}]interface{} `json:"-",bson:"-"` Ms map[string]interface{} Msi64 map[string]int64 Nintf interface{} //don't set this, so we can test for nil T time.Time Nmap map[string]bool //don't set this, so we can test for nil Nslice []byte //don't set this, so we can test for nil Nint64 *int64 Nteststruc *TestStruc } type TestRpcInt struct { i int } func (r *TestRpcInt) Update(n int, res *int) error { r.i = n; *res = r.i; return nil } func (r *TestRpcInt) Square(ignore int, res *int) error { *res = r.i * r.i; return nil } func (r *TestRpcInt) Mult(n int, res *int) error { *res = r.i * n; return nil } func init() { primitives := []interface{} { int8(-8), int16(-1616), int32(-32323232), int64(-6464646464646464), uint8(8), uint16(1616), uint32(32323232), uint64(6464646464646464), byte(8), float32(-3232.0), float64(-6464646464.0), float32(3232.0), float64(6464646464.0), false, true, nil, timeToCompare, "someday", "", "bytestring", } mapsAndStrucs := []interface{}{ map[string]bool{ "true":true, "false":false, }, map[string]interface{}{ "true": "True", "false": false, "int64(0)": int8(0), }, //add a complex combo map in here. (map has list which has map) //note that after the first thing, everything else should be generic. map[string]interface{}{ "list": []interface{}{ int16(1616), int32(32323232), true, float32(-3232.0), map[string]interface{} { "TRUE":true, "FALSE":false, }, []interface{}{true, false}, }, "int32": int32(32323232), "bool": true, "LONG STRING": "123456789012345678901234567890123456789012345678901234567890", "SHORT STRING": "1234567890", }, map[interface{}]interface{}{ true: "true", int8(8): false, "false": int8(0), }, newTestStruc(0, false), } table = []interface{}{} table = append(table, primitives...) //0-19 are primitives table = append(table, primitives) //20 is a list of primitives table = append(table, mapsAndStrucs...) //21-24 are maps. 25 is a *struct // we verify against the same table, but skip 23 // because interface{} equality is not defined exact for exact objects or nil. var a, b []interface{} var c map[string]interface{} a = make([]interface{}, len(table)) copy(a, table) b = make([]interface{}, len(a[20].([]interface{}))) copy(b, a[20].([]interface{})) a[20] = b b[0], b[4], b[8], b[16], b[19] = int8(-8), int8(8), int8(8), []interface {}{int32(1328148122), int16(2000)}, "bytestring" a[23] = skipVerifyVal //a[25] = skipVerifyVal tableVerify = a //when decoding into nil, for testing, //we treat each []byte as string, and uint < 127 are decoded as int8. a = make([]interface{}, len(tableVerify)) copy(a, tableVerify) a[0], a[4], a[8], a[16], a[19] = int8(-8), int8(8), int8(8), []interface {}{int32(1328148122), int16(2000)}, "bytestring" a[21] = map[string]interface{}{"true":true, "false":false} a[23] = table[23] a[25] = skipVerifyVal tableTestNilVerify = a //python msgpack encodes large positive numbers as unsigned, and all floats as float64 a = make([]interface{}, len(tableTestNilVerify)-2) copy(a, tableTestNilVerify) a[23] = table[23] a[9], a[11], a[16] = float64(-3232.0), float64(3232.0), uint64(1328148122000002) b = make([]interface{}, len(a[20].([]interface{}))) copy(b, a[20].([]interface{})) a[20] = b b[9], b[11], b[16] = float64(-3232.0), float64(3232.0), uint64(1328148122000002) c = make(map[string]interface{}) for k, v := range a[23].(map[string]interface{}) { c[k] = v } a[23] = c c["int32"] = uint32(32323232) b = c["list"].([]interface{}) b[0], b[1], b[3] = uint16(1616), uint32(32323232), float64(-3232.0) tablePythonVerify = a } func newTestStruc(depth int, bench bool) (ts TestStruc) { var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464 ts = TestStruc { S: "some string", I64: 64, I16: 16, Ui64: 64, Ui8: 160, B: true, By: 5, Sslice: []string{"one", "two", "three"}, I64slice: []int64{1, 2, 3}, I16slice: []int16{4, 5, 6}, Ui64slice: []uint64{7, 8, 9}, Ui8slice: []uint8{10, 11, 12}, Bslice: []bool{true, false, true, false}, Byslice: []byte{13, 14, 15}, Islice: []interface{}{"true", true, "no", false, int8(88), float64(0.4)}, Ms: map[string]interface{}{ "true": "true", "int64(9)": false, }, Msi64: map[string]int64{ "one": 1, "two": 2, }, T: timeToCompare, AnonInTestStruc: AnonInTestStruc{ AS: "A-String", AI64: 64, AI16: 16, AUi64: 64, ASslice: []string{"Aone", "Atwo", "Athree"}, AI64slice: []int64{1, 2, 3}, }, } //For benchmarks, some things will not work. if !bench { //json and bson require string keys in maps //ts.M = map[interface{}]interface{}{ // true: "true", // int8(9): false, //} //gob cannot encode nil in element in array (encodeArray: nil element) ts.Iptrslice = []*int64{nil, &i64a, nil, &i64b, nil, &i64c, nil, &i64d, nil} } if depth > 0 { depth-- ts.Ms["TestStruc." + strconv.Itoa(depth)] = newTestStruc(depth, bench) ts.Islice = append(ts.Islice, newTestStruc(depth, bench)) } return } // doTestMsgpacks allows us test for different variations based on arguments passed. func doTestMsgpacks(t *testing.T, testNil bool, opts DecoderContainerResolver, // *DecoderOptions DecoderContainerResolver, vs []interface{}, vsVerify []interface{}) { //if testNil, then just test for when a pointer to a nil interface{} is passed. It should work. //Current setup allows us test (at least manually) the nil interface or typed interface. logT(t, "================ TestNil: %v ================\n", testNil) for i, v0 := range vs { logT(t, "..............................................") logT(t, " Testing: #%d: %T, %#v\n", i, v0, v0) b0, err := Marshal(v0) if err != nil { logT(t, err.Error()) failT(t) continue } logT(t, " Encoded bytes: len: %v, %v\n", len(b0), b0) var v1 interface{} dec := NewDecoder(bytes.NewBuffer(b0), opts) if testNil { err = dec.Decode(&v1) } else { v0rt := intfTyp if v0 != nil { v0rt = reflect.TypeOf(v0) } v1 = reflect.New(v0rt).Interface() err = dec.Decode(v1) } if v1 != nil { logT(t, " v1 returned: %T, %#v", v1, v1) //we always indirect, because ptr to typed value may be passed (if not testNil) v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() } if err != nil { logT(t, "-------- Error: %v. Partial return: %v", err, v1) failT(t) continue } v0check := vsVerify[i] if v0check == skipVerifyVal { logT(t, " Nil Check skipped: Decoded: %T, %#v\n", v1, v1) continue } if reflect.DeepEqual(v0check, v1) { logT(t, "++++++++ Before and After marshal matched\n") } else { logT(t, "-------- Before and After marshal do not match: " + "(%T). ====> AGAINST: %T, %#v, DECODED: %T, %#v\n", v0, v0check, v0check, v1, v1) failT(t) } } } func TestMsgpacks(t *testing.T) { doTestMsgpacks(t, false, testDecOpts(nil, nil, false, true, true), table, tableVerify) } func TestMsgpacksNilStringMap(t *testing.T) { doTestMsgpacks(t, true, testDecOpts(mapStringIntfTyp, nil, true, true, true), table[:24], tableTestNilVerify[:24]) } func TestMsgpacksNilIntf(t *testing.T) { doTestMsgpacks(t, true, testDecOpts(nil, nil, false, true, true), table[24:], tableTestNilVerify[24:]) } func TestDecodeToTypedNil(t *testing.T) { b, err := Marshal(32) var i *int32 if err = Unmarshal(b, i, nil); err == nil { logT(t, "------- Expecting error because we cannot unmarshal to int32 nil ptr") t.FailNow() } var i2 int32 = 0 if err = Unmarshal(b, &i2, nil); err != nil { logT(t, "------- Cannot unmarshal to int32 ptr. Error: %v", err) t.FailNow() } if i2 != int32(32) { logT(t, "------- didn't unmarshal to 32: Received: %d", *i) t.FailNow() } } func TestDecodePtr(t *testing.T) { ts := newTestStruc(0, false) b, err := Marshal(&ts) if err != nil { logT(t, "------- Cannot Marshal pointer to struct. Error: %v", err) t.FailNow() } else if len(b) < 40 { logT(t, "------- Size must be > 40. Size: %d", len(b)) t.FailNow() } ts2 := new(TestStruc) err = Unmarshal(b, &ts2, nil) if err != nil { logT(t, "------- Cannot Unmarshal pointer to struct. Error: %v", err) t.FailNow() } else if ts2.I64 != 64 { logT(t, "------- Unmarshal wrong. Expect I64 = 64. Got: %v", ts2.I64) t.FailNow() } } func TestIntfDecode(t *testing.T) { m := map[string]int{"A":2, "B":3, } p := []interface{}{m} bs, err := Marshal(p) if err != nil { logT(t, "Error marshalling p: %v, Err: %v", p, err) t.FailNow() } m2 := map[string]int{} p2 := []interface{}{m2} err = Unmarshal(bs, &p2, nil) if err != nil { logT(t, "Error unmarshalling into &p2: %v, Err: %v", p2, err) t.FailNow() } if m2["A"] != 2 || m2["B"] != 3 { logT(t, "m2 not as expected: expecting: %v, got: %v", m, m2) t.FailNow() } // log("m: %v, m2: %v, p: %v, p2: %v", m, m2, p, p2) if reflect.DeepEqual(p, p2) { logT(t, "p and p2 match") } else { logT(t, "Not Equal: p: %v, p2: %v", p, p2) t.FailNow() } if reflect.DeepEqual(m, m2) { logT(t, "m and m2 match") } else { logT(t, "Not Equal: m: %v, m2: %v", m, m2) t.FailNow() } } func TestDecodeStructSubset(t *testing.T) { // test that we can decode a subset of the stream m := map[string]interface{}{"A": 5, "B": 99, "C": 333, } bs, err := Marshal(m) if err != nil { logT(t, "Error marshalling m: %v, Err: %v", m, err) t.FailNow() } type ttt struct { A uint8 C int32 } var t2 ttt err = Unmarshal(bs, &t2, nil) if err != nil { logT(t, "Error unmarshalling into &t2: %v, Err: %v", t2, err) t.FailNow() } t3 := ttt{5, 333} if !reflect.DeepEqual(t2, t3) { logT(t, "Not Equal: t2: %v, t3: %v", t2, t3) t.FailNow() } } // comment out for now func TestRpcAll(t *testing.T) { testRpc(t, true, true, true, true) } func TestRpc(t *testing.T) { testRpc(t, true, true, false, true) } func TestCustomRpc(t *testing.T) { testRpc(t, true, false, true, true) } func testRpc(t *testing.T, callClose, doBasic, doCustom, doExit bool) { srv := rpc.NewServer() srv.Register(testRpcInt) ln, err := net.Listen("tcp", "127.0.0.1:0") // log("listener: %v", ln.Addr()) checkErrT(t, err) defer ln.Close() var opts DecoderContainerResolver serverExitChan := make(chan bool, 1) serverFn := func() { for { conn1, err1 := ln.Accept() if err1 != nil { continue } bs := make([]byte, 1) n1, err1 := conn1.Read(bs) if n1 != 1 || err1 != nil { conn1.Close() continue } var sc rpc.ServerCodec switch bs[0] { case 'B': sc = NewRPCServerCodec(conn1, opts) case 'C': sc = NewCustomRPCServerCodec(conn1, opts) case 'X': serverExitChan <- true conn1.Close() return // exit serverFn goroutine } if sc == nil { conn1.Close() continue } srv.ServeCodec(sc) // for { // if err1 = srv.ServeRequest(sc); err1 != nil { // break // } // } // if callClose { // sc.Close() // } } } clientFn := func(cc rpc.ClientCodec) { cl := rpc.NewClientWithCodec(cc) if callClose { defer cl.Close() } var up, sq, mult int // log("Calling client") checkErrT(t, cl.Call("TestRpcInt.Update", 5, &up)) // log("Called TestRpcInt.Update") checkEqualT(t, testRpcInt.i, 5) checkEqualT(t, up, 5) checkErrT(t, cl.Call("TestRpcInt.Square", 1, &sq)) checkEqualT(t, sq, 25) checkErrT(t, cl.Call("TestRpcInt.Mult", 20, &mult)) checkEqualT(t, mult, 100) } connFn := func(req byte) (bs net.Conn) { // log("calling f1") bs, err2 := net.Dial(ln.Addr().Network(), ln.Addr().String()) // log("f1. bs: %v, err2: %v", bs, err2) checkErrT(t, err2) n1, err2 := bs.Write([]byte{req}) checkErrT(t, err2) checkEqualT(t, n1, 1) return } go serverFn() if doBasic { bs := connFn('B') cc := NewRPCClientCodec(bs, opts) clientFn(cc) } if doCustom { bs := connFn('C') cc := NewCustomRPCClientCodec(bs, opts) clientFn(cc) } if doExit { bs := connFn('X') <- serverExitChan bs.Close() } } // Comprehensive testing that generates data encoded from python msgpack, // and validates that our code can read and write it out accordingly. func TestPythonGenStreams(t *testing.T) { logT(t, "TestPythonGenStreams") tmpdir, err := ioutil.TempDir("", "golang-msgpack-test") if err != nil { logT(t, "-------- Unable to create temp directory\n") t.FailNow() } defer os.RemoveAll(tmpdir) logT(t, "tmpdir: %v", tmpdir) cmd := exec.Command("python", "helper.py", "testdata", tmpdir) //cmd.Stdin = strings.NewReader("some input") //cmd.Stdout = &out var cmdout []byte if cmdout, err = cmd.CombinedOutput(); err != nil { logT(t, "-------- Error running python build.py. Err: %v", err) logT(t, " %v", string(cmdout)) t.FailNow() } for i, v := range tablePythonVerify { //load up the golden file based on number //decode it //compare to in-mem object //encode it again //compare to output stream logT(t, "..............................................") logT(t, " Testing: #%d: %T, %#v\n", i, v, v) var bss []byte bss, err = ioutil.ReadFile(filepath.Join(tmpdir, strconv.Itoa(i) + ".golden")) if err != nil { logT(t, "-------- Error reading golden file: %d. Err: %v", i, err) failT(t) continue } dec := NewDecoder(bytes.NewBuffer(bss), testDecOpts(mapStringIntfTyp, nil, true, true, true)) var v1 interface{} if err = dec.Decode(&v1); err != nil { logT(t, "-------- Error decoding stream: %d: Err: %v", i, err) failT(t) continue } if v == skipVerifyVal { continue } //no need to indirect, because we pass a nil ptr, so we already have the value //if v1 != nil { v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() } if reflect.DeepEqual(v, v1) { logT(t, "++++++++ Objects match") } else { logT(t, "-------- Objects do not match: Source: %T. Decoded: %T", v, v1) logT(t, "-------- AGAINST: %#v", v) logT(t, "-------- DECODED: %#v", v1) failT(t) } bsb := new(bytes.Buffer) if err = NewEncoder(bsb).Encode(v1); err != nil { logT(t, "Error encoding to stream: %d: Err: %v", i, err) failT(t) continue } if reflect.DeepEqual(bsb.Bytes(), bss) { logT(t, "++++++++ Bytes match") } else { logT(t, "???????? Bytes do not match") xs := "--------" if reflect.ValueOf(v).Kind() == reflect.Map { xs = " " logT(t, "%s It's a map. Ok that they don't match (dependent on ordering).", xs) } else { logT(t, "%s It's not a map. They should match.", xs) failT(t) } logT(t, "%s FROM_FILE: %4d] %v", xs, len(bss), bss) logT(t, "%s ENCODED: %4d] %v", xs, len(bsb.Bytes()), bsb.Bytes()) } } } func testDecOpts(MapType reflect.Type, SliceType reflect.Type, BytesStringLiteral bool, BytesStringSliceElement bool, BytesStringMapValue bool) DecoderContainerResolver { return &SimpleDecoderContainerResolver { MapType, SliceType, BytesStringLiteral, BytesStringSliceElement, BytesStringMapValue, } } golang-github-ugorji-go-msgpack-0.0~git20130605.792643/rpc.go 0000664 0000000 0000000 00000017614 12153716517 0023057 0 ustar 00root root 0000000 0000000 /* go-msgpack - Msgpack library for Go. Provides pack/unpack and net/rpc support. https://github.com/ugorji/go-msgpack Copyright (c) 2012, Ugorji Nwoke. All rights reserved. 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 the author 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 HOLDER 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. */ /* RPC An RPC Client and Server Codec is implemented, so that msgpack can be used with the standard net/rpc package. It supports both a basic net/rpc serialization, and the custom format defined at http://wiki.msgpack.org/display/MSGPACK/RPC+specification */ package msgpack import ( "fmt" "strings" "net/rpc" "io" ) type rpcCodec struct { rwc io.ReadWriteCloser dec *Decoder enc *Encoder } type basicRpcCodec struct { rpcCodec } type customRpcCodec struct { rpcCodec } func newRPCCodec(conn io.ReadWriteCloser, opts DecoderContainerResolver) (rpcCodec) { return rpcCodec{ rwc: conn, dec: NewDecoder(conn, opts), enc: NewEncoder(conn), } } // NewRPCClientCodec uses basic msgpack serialization for rpc communication from client side. // // Sample Usage: // conn, err = net.Dial("tcp", "localhost:5555") // codec, err := msgpack.NewRPCClientCodec(conn, nil) // client := rpc.NewClientWithCodec(codec) // ... (see rpc package for how to use an rpc client) func NewRPCClientCodec(conn io.ReadWriteCloser, opts DecoderContainerResolver) (rpc.ClientCodec) { return &basicRpcCodec{ newRPCCodec(conn, opts) } } // NewRPCServerCodec uses basic msgpack serialization for rpc communication from the server side. func NewRPCServerCodec(conn io.ReadWriteCloser, opts DecoderContainerResolver) (rpc.ServerCodec) { return &basicRpcCodec{ newRPCCodec(conn, opts) } } // NewCustomRPCClientCodec uses msgpack serialization for rpc communication from client side, // but uses a custom protocol defined at http://wiki.msgpack.org/display/MSGPACK/RPC+specification func NewCustomRPCClientCodec(conn io.ReadWriteCloser, opts DecoderContainerResolver) (rpc.ClientCodec) { return &customRpcCodec{ newRPCCodec(conn, opts) } } // NewCustomRPCServerCodec uses msgpack serialization for rpc communication from server side, // but uses a custom protocol defined at http://wiki.msgpack.org/display/MSGPACK/RPC+specification func NewCustomRPCServerCodec(conn io.ReadWriteCloser, opts DecoderContainerResolver) (rpc.ServerCodec) { return &customRpcCodec{ newRPCCodec(conn, opts) } } // /////////////// RPC Codec Shared Methods /////////////////// func (c *rpcCodec) write(objs ...interface{}) (err error) { for _, obj := range objs { if err = c.enc.Encode(obj); err != nil { return } } return } func (c *rpcCodec) read(objs ...interface{}) (err error) { for _, obj := range objs { if err = c.dec.Decode(obj); err != nil { return } } return } // maybeEOF is used to possibly return EOF for functions (e.g. ReadXXXHeader) that // should return EOF if underlying connection was closed. // This is important because rpc uses goroutines on clients (to support sync and async models) // and on the server. Consequently, for calling Client.Close to work for example, the // ReadRequestHeader and ReadResponseHeader methods should return EOF if underlying network // connection was closed (e.g. by Client.Close). // // It's a best effort, as there's no general error returned for Using Closed Network Connection. func (c *rpcCodec) maybeEOF(err error) (errx error) { if err == nil { return nil } // defer func() { fmt.Printf("maybeEOF: orig: %T, %v, returning: %T, %v\n", err, err, errx, errx) }() if err == io.EOF || err == io.ErrUnexpectedEOF { return io.EOF } errstr := err.Error() if strings.HasSuffix(errstr, "use of closed network connection") { return io.EOF } // switch nerr := err.(type) { // case *net.OpError: // println(" ***** *net.OpError ***** ", nerr.Err.Error()) // if nerr.Err.Error() == "use of closed network connection" { // return io.EOF // } // } return err } func (c *rpcCodec) Close() error { // fmt.Printf("Calling rpcCodec.Close: %v\n----------------------\n", string(debug.Stack())) return c.rwc.Close() } func (c *rpcCodec) ReadResponseBody(body interface{}) error { return c.dec.Decode(body) } // /////////////// Basic RPC Codec /////////////////// func (c *basicRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error { return c.write(r, body) } func (c *basicRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error { return c.write(r, body) } func (c *basicRpcCodec) ReadRequestBody(body interface{}) error { return c.dec.Decode(body) } func (c *basicRpcCodec) ReadResponseHeader(r *rpc.Response) error { return c.maybeEOF(c.dec.Decode(r)) } func (c *basicRpcCodec) ReadRequestHeader(r *rpc.Request) error { return c.maybeEOF(c.dec.Decode(r)) } // /////////////// Custom RPC Codec /////////////////// func (c *customRpcCodec) WriteRequest(r *rpc.Request, body interface{}) error { return c.writeCustomBody(0, r.Seq, r.ServiceMethod, body) } func (c *customRpcCodec) WriteResponse(r *rpc.Response, body interface{}) error { return c.writeCustomBody(1, r.Seq, r.Error, body) } func (c *customRpcCodec) ReadRequestBody(body interface{}) error { return c.dec.Decode(body) } func (c *customRpcCodec) ReadResponseHeader(r *rpc.Response) error { return c.maybeEOF(c.parseCustomHeader(1, &r.Seq, &r.Error)) } func (c *customRpcCodec) ReadRequestHeader(r *rpc.Request) error { return c.maybeEOF(c.parseCustomHeader(0, &r.Seq, &r.ServiceMethod)) } func (c *customRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) { // We read the response header by hand // so that the body can be decoded on its own from the stream at a later time. bs := make([]byte, 1) n, err := c.rwc.Read(bs) if err != nil { return } if n != 1 { err = fmt.Errorf("Couldn't read array descriptor: No bytes read") return } const fia byte = 0x94 //four item array descriptor value if bs[0] != fia { err = fmt.Errorf("Unexpected value for array descriptor: Expecting %v. Received %v", fia, bs[0]) return } var b byte if err = c.read(&b, msgid, methodOrError); err != nil { return } if b != expectTypeByte { err = fmt.Errorf("Unexpected byte descriptor in header. Expecting %v. Received %v", expectTypeByte, b) return } return } func (c *customRpcCodec) writeCustomBody(typeByte byte, msgid uint64, methodOrError string, body interface{}) (err error) { var moe interface{} = methodOrError // response needs nil error (not ""), and only one of error or body can be nil if typeByte == 1 { if methodOrError == "" { moe = nil } if moe != nil && body != nil { body = nil } } r2 := []interface{}{ typeByte, uint32(msgid), moe, body } return c.enc.Encode(r2) }