func TestMarshalSimpleTypes(test *testing.T) { //null var null interface{} tdata, err := Marshal(null) checkError(test, "nil", tdata, err, -1, []byte{24, 0}) //bool var b bool tdata, err = Marshal(b) checkError(test, "bool false", tdata, err, -1, []byte{24, 1, 0}) b = true tdata, err = Marshal(b) checkError(test, "bool true", tdata, err, -1, []byte{24, 1, 1}) //int8 var i8 int8 tdata, err = Marshal(i8) checkError(test, "i8", tdata, err, -1, []byte{24, 2, 0}) i8 = 23 tdata, err = Marshal(i8) checkError(test, "i8 23", tdata, err, -1, []byte{24, 2, 46}) i8 = -23 tdata, err = Marshal(i8) checkError(test, "i8 -23", tdata, err, -1, []byte{24, 2, 45}) i8 = 127 tdata, err = Marshal(i8) checkError(test, "i8 127", tdata, err, -1, []byte{24, 2, 254, 1}) i8 = -128 tdata, err = Marshal(i8) checkError(test, "i8 -128", tdata, err, -1, []byte{24, 2, 255, 1}) var u8 uint8 = 0xff tdata, err = Marshal(int8(u8)) checkError(test, "u8 255", tdata, err, -1, []byte{24, 2, 1}) //uint8(0xff) == int8(-1) //int16 var i16 int16 = 23 tdata, err = Marshal(i16) checkError(test, "i16 23", tdata, err, -1, []byte{24, 3, 46}) i16 = -23 tdata, err = Marshal(i16) checkError(test, "i16 -23", tdata, err, -1, []byte{24, 3, 45}) i16 = 32767 tdata, err = Marshal(i16) checkError(test, "i16 32767", tdata, err, -1, []byte{24, 3, 254, 255, 3}) i16 = -32768 tdata, err = Marshal(i16) checkError(test, "i16 -32768", tdata, err, -1, []byte{24, 3, 255, 255, 3}) var u16 uint16 = 0xffff tdata, err = Marshal(int16(u16)) checkError(test, "u16 65535", tdata, err, -1, []byte{24, 3, 1}) //uint16(0xffff) == int16(-1) //int32 var i32 int32 = 23 tdata, err = Marshal(i32) checkError(test, "i32 23", tdata, err, -1, []byte{24, 4, 46}) i32 = -23 tdata, err = Marshal(i32) checkError(test, "i32 -23", tdata, err, -1, []byte{24, 4, 45}) i32 = 0x7fffffff tdata, err = Marshal(i32) checkError(test, fmt.Sprintf("i32 %d", i32), tdata, err, -1, []byte{24, 4, 254, 255, 255, 255, 15}) i32 = -(0x7fffffff) - 1 tdata, err = Marshal(i32) checkError(test, fmt.Sprintf("i32 %d", i32), tdata, err, -1, []byte{24, 4, 255, 255, 255, 255, 15}) var i = 23 tdata, err = Marshal(i) checkError(test, "i 23", tdata, err, -1, []byte{24, 4, 46}) var u32 uint32 = 0xffffffff tdata, err = Marshal(int32(u32)) checkError(test, "u32 4294967295", tdata, err, -1, []byte{24, 4, 1}) //uint32(0xffffffff) == int32(-1) i32 = 23 pt := ptrtest{1, &i32, nil} tdata, err = Marshal(pt) checkError(test, "pt.Pi32 &23", tdata, err, -1, []byte{0x18, 0x40, 0x13, 0x03, 0x03, 0x49, 0x33, 0x32, 0x04, 0x04, 0x50, 0x69, 0x33, 0x32, 0x04, 0x04, 0x4f, 0x69, 0x33, 0x32, 0x10, 0x40, 0x02, 0x2e, 0x00}) pt.Oi32 = &i32 tdata, err = Marshal(pt) checkError(test, "pt.Pi32 &23 pt.Oi32 = &23", tdata, err, -1, []byte{0x18, 0x40, 0x13, 0x03, 0x03, 0x49, 0x33, 0x32, 0x04, 0x04, 0x50, 0x69, 0x33, 0x32, 0x04, 0x04, 0x4f, 0x69, 0x33, 0x32, 0x10, 0x40, 0x02, 0x2e, 0x04, 0x2e}) //int64 var i64 int64 = 23 tdata, err = Marshal(i64) checkError(test, "i64 23", tdata, err, -1, []byte{24, 5, 46}) i64 = -23 tdata, err = Marshal(i64) checkError(test, "i64 -23", tdata, err, -1, []byte{24, 5, 45}) i64 = 0x7fffffffffffffff tdata, err = Marshal(i64) checkError(test, fmt.Sprintf("i64 %d", i64), tdata, err, -1, []byte{24, 5, 254, 255, 255, 255, 255, 255, 255, 255, 255, 1}) i64 = -i64 - 1 tdata, err = Marshal(i64) checkError(test, fmt.Sprintf("i64 %d", i64), tdata, err, -1, []byte{24, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1}) var u64 uint64 = 0xffffffffffffffff tdata, err = Marshal(int64(u64)) checkError(test, "u64 18446744073709551615", tdata, err, -1, []byte{24, 5, 1}) //uint64(0xffffffffffffffff) == int64(-1) //float32 var f32 float32 tdata, err = Marshal(f32) checkError(test, "f32", tdata, err, -1, []byte{24, 6, 0, 0, 0, 0}) f32 = 23.57 tdata, err = Marshal(f32) checkError(test, "f32 23.57", tdata, err, -1, []byte{24, 6, 65, 188, 143, 92}) //float64 var f64 float64 tdata, err = Marshal(f64) checkError(test, "f64", tdata, err, -1, []byte{24, 7, 0, 0, 0, 0, 0, 0, 0, 0}) f64 = 23.57 tdata, err = Marshal(f64) checkError(test, "f64 23.57", tdata, err, -1, []byte{24, 7, 64, 55, 145, 235, 133, 30, 184, 82}) //bytes var bs []byte tdata, err = Marshal(bs) checkError(test, "bytes nil slice", tdata, err, -1, []byte{24, 0}) bs = make([]byte, 0) //empty byte slice tdata, err = Marshal(bs) checkError(test, "bytes empty slice", tdata, err, -1, []byte{24, 8, 0}) bs = []byte{1, 2, 3, 4, 5} //initialize byte slice tdata, err = Marshal(bs) checkError(test, "bytes slice with 5 elements", tdata, err, -1, []byte{24, 8, 5, 1, 2, 3, 4, 5}) var ba [2]byte tdata, err = Marshal(&ba) // checkError(test, "bytes pointer to array of length 2", tdata, err, -1, []byte{24, 8, 2, 0, 0}) tdata, err = Marshal(ba) //this is slower, reflect has a hard time with array values instead of slices checkError(test, "bytes array of length 2", tdata, err, -1, []byte{24, 8, 2, 0, 0}) //string var s string tdata, err = Marshal(s) checkError(test, "s empty string", tdata, err, -1, []byte{24, 32}) s = "foo" tdata, err = Marshal(s) checkError(test, "s tiny", tdata, err, -1, []byte{24, 35, 102, 111, 111}) tdata, err = Marshal(&s) checkError(test, "s pointer to tiny", tdata, err, -1, []byte{24, 35, 102, 111, 111}) s = "*can* fit into the tiny format" tdata, err = Marshal(s) checkError(test, "s largest tiny", tdata, err, -1, []byte{24, 62, 42, 99, 97, 110, 42, 32, 102, 105, 116, 32, 105, 110, 116, 111, 32, 116, 104, 101, 32, 116, 105, 110, 121, 32, 102, 111, 114, 109, 97, 116}) s = "*can't* fit into the tiny format" tdata, err = Marshal(s) checkError(test, "s not tiny", tdata, err, -1, []byte{24, 9, 32, 42, 99, 97, 110, 39, 116, 42, 32, 102, 105, 116, 32, 105, 110, 116, 111, 32, 116, 104, 101, 32, 116, 105, 110, 121, 32, 102, 111, 114, 109, 97, 116}) s = "tiny 姚冀清" tdata, err = Marshal(s) checkError(test, "s tiny multibyte", tdata, err, -1, []byte{24, 46, 116, 105, 110, 121, 32, 229, 167, 154, 229, 134, 128, 230, 184, 133}) s = "looks tiny but is bigger姚冀清" tdata, err = Marshal(s) checkError(test, "s not quite tiny multibyte", tdata, err, -1, []byte{24, 9, 33, 108, 111, 111, 107, 115, 32, 116, 105, 110, 121, 32, 98, 117, 116, 32, 105, 115, 32, 98, 105, 103, 103, 101, 114, 229, 167, 154, 229, 134, 128, 230, 184, 133}) //timestamp ts, _ := rdl.TimestampParse("2015-05-16T19:50:21.002Z") tdata, err = Marshal(ts) checkError(test, "timestamp", tdata, err, -1, []byte{24, 10, 65, 213, 85, 231, 223, 64, 32, 197}) //uuid u := rdl.ParseUUID("373ab4c4-fc05-11e4-a198-14109fe4729f") tdata, err = Marshal(u) checkError(test, "uuid", tdata, err, -1, []byte{24, 12, 55, 58, 180, 196, 252, 5, 17, 228, 161, 152, 20, 16, 159, 228, 114, 159}) //symbol sym := rdl.Symbol("foo") tdata, err = Marshal(sym) checkError(test, "sym", tdata, err, -1, []byte{24, 11, 0, 3, 102, 111, 111}) sym2 := rdl.Symbol("bar") enc := NewEncoder(nil) enc.Encode(sym) enc.Encode(sym2) enc.Encode(sym) enc.Encode(sym2) tdata = enc.Bytes() checkError(test, "sym reuse", tdata, err, -1, []byte{24, 11, 0, 3, 102, 111, 111, 11, 1, 3, 98, 97, 114, 11, 0, 11, 1}) }
func (d *Decoder) DecodeReflect(v reflect.Value) error { again: var tag int if d.pendingTag >= 0 { tag = d.pendingTag d.pendingTag = -1 } else { tag = int(d.ParseUnsigned()) } if d.err != nil { return d.err } if tag >= FirstUserTag { idx := int(tag - FirstUserTag) if idx < len(d.types) { ttype := d.types[idx] return d.decodeTypeReflect(ttype, v) } ttype := d.parseType() if ttype == nil { d.err = fmt.Errorf("First use of a user tag must be followed by a typedef.") return d.err } d.types = append(d.types, ttype) goto again } else { if (tag & TinyStrTagMask) == TinyStrTag { n := tag & TinyStrDataMask tinybuf := make([]byte, n) d.err = d.readBytes(tinybuf) if d.err == nil { s := string(tinybuf) if v.Kind() == reflect.Interface { vv := reflect.New(reflect.TypeOf(s)) v.Set(vv) } else { v.SetString(s) } } return d.err } switch tag { case NullTag: //already zeroed return nil case BoolTag: b := d.ParseBool() if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(b))) } else { v.SetBool(b) } return d.err case Int8Tag: n := int8(d.ParseInt()) if d.err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(n))) } else { v.SetInt(int64(n)) } } return d.err case Int16Tag: n := int16(d.ParseInt()) if d.err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(n))) } else { v.SetInt(int64(n)) } } return d.err case Int32Tag: n := d.ParseInt() if d.err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(n))) } else { v.SetInt(int64(n)) } } return d.err case Int64Tag: n := d.ParseInt64() if d.err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(n))) } else { v.SetInt(n) } } return d.err case Float32Tag: n, err := d.ParseFloat32() if err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(n))) } else { v.SetFloat(float64(n)) } } return err case Float64Tag: n, err := d.ParseFloat64() if err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(n))) } else { v.SetFloat(n) } } return err case BytesTag: b, err := d.ParseBytes() if err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(b))) } else { v.SetBytes(b) } } return err case StringTag: s, err := d.ParseString() if err == nil { if v.Kind() == reflect.Interface { v.Set(reflect.New(reflect.TypeOf(s))) } else { v.SetString(s) } } return err case SymbolTag: s, err := d.ParseSymbol() if err == nil { v.Set(reflect.ValueOf(rdl.Symbol(s))) } return err case TimestampTag: ts, err := d.ParseTimestamp() if err == nil { v.Set(reflect.ValueOf(ts)) } return err case UUIDTag: u, err := d.ParseUUID() if err == nil { v.Set(reflect.ValueOf(u)) } return err case StructTag: return d.DecodeStructReflect(v) case ArrayTag: return d.DecodeArrayReflect(v) case MapTag: return d.DecodeMapReflect(v) } } return fmt.Errorf("Unexpected tag value: 0x%02x", tag) }
func TestMarshalMaps(test *testing.T) { var tdata []byte var err error var expected []byte //maps with more than one entry may fail due to randomized hash order. So just check length. mbad := make(map[int]interface{}) tdata, err = Marshal(mbad) if err == nil { test.Errorf("Map with non-string key did not get rejected as expected") } //generic map var m map[string]interface{} tdata, err = Marshal(m) checkError(test, "nil generic map", tdata, err, -1, []byte{24, 0}) m = make(map[string]interface{}) tdata, err = Marshal(m) checkError(test, "nil generic map", tdata, err, -1, []byte{24, 14, 0}) //m["foo"] = int32(23) m["foo"] = 23 //int and int32 get encoded the same tdata, err = Marshal(m) checkError(test, "generic map of one string-to-int32", tdata, err, -1, []byte{24, 14, 1, 35, 102, 111, 111, 4, 46}) m["bar"] = "blah" tdata, err = Marshal(m) expected = []byte{24, 14, 2, 35, 102, 111, 111, 4, 46, 35, 98, 97, 114, 36, 98, 108, 97, 104} checkError(test, "generic map of two items", tdata, err, len(expected), nil) //other key types m2 := make(map[rdl.Symbol]interface{}) tdata, err = Marshal(m2) checkError(test, "empty symbol-to-any map", tdata, err, -1, []byte{24, 14, 0}) m2 = make(map[rdl.Symbol]interface{}) //m2[rdl.Symbol("foo")] = "bar" m2["foo"] = "bar" //a symbol *is* a string, so you can just pass it in tdata, err = Marshal(m2) //checkError(test, "symbol-to-any map, 1 entry", tdata, err, -1, []byte{24, 14, 1, 11, 0, 3, 102, 111, 111, 35, 98, 97, 114}) m2["bar"] = rdl.Symbol("foo") tdata, err = Marshal(m2) expected = []byte{24, 14, 2, 11, 0, 3, 102, 111, 111, 35, 98, 97, 114, 11, 1, 3, 98, 97, 114, 11, 0} //checkError(test, "symbol-to-any map, 2 entries", tdata, err, len(expected), nil) var mmm map[rdl.Symbol]interface{} err = Unmarshal(tdata, &mmm) if err != nil { test.Errorf("Cannot unmarshal map[Symbol]interface{}") } //typed map var mii map[int]int tdata, err = Marshal(mii) if err == nil { //the type gets rejected, even though its nil value could have been encoded, to avoid programming errors test.Errorf("Map with non-string key did not get rejected as expected") } msi := make(map[string]int) tdata, err = Marshal(msi) checkError(test, "map<string,int> empty", tdata, err, -1, []byte{24, 64, 18, 9, 4, 64, 0}) //defines a new type tag (64), uses it msi = make(map[string]int) msi["foo"] = 23 tdata, err = Marshal(msi) checkError(test, "map<string,int> 1 entry", tdata, err, -1, []byte{24, 64, 18, 9, 4, 64, 1, 3, 102, 111, 111, 46}) var mmmm interface{} err = Unmarshal(tdata, &mmmm) if err != nil { test.Errorf("Cannot generic unmarshal map[string]int") } msymi := make(map[rdl.Symbol]int) msymi["foo"] = 23 tdata, err = Marshal(msymi) //checkError(test, "map<rdl.Symbol,int> 1 entry", tdata, err, -1, []byte{24, 64, 18, 11, 4, 64, 1, 3, 102, 111, 111, 46}) msi["bar"] = 57 tdata, err = Marshal(msi) expected = []byte{24, 64, 18, 9, 4, 64, 2, 3, 102, 111, 111, 46, 3, 98, 97, 114, 114} checkError(test, "map<string,int> 2 entries", tdata, err, len(expected), nil) }