support unmarshal to interface{} .no TagCompound
This commit is contained in:
@ -13,8 +13,8 @@ func TestUnmarshal_string(t *testing.T) {
|
|||||||
0x42, 0x61, 0x6e, 0x61, 0x6e, 0x72, 0x61, 0x6d, 0x61,
|
0x42, 0x61, 0x6e, 0x61, 0x6e, 0x72, 0x61, 0x6d, 0x61,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Unmarshal to string
|
||||||
var Name string
|
var Name string
|
||||||
|
|
||||||
if err := Unmarshal(data, &Name); err != nil {
|
if err := Unmarshal(data, &Name); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -22,6 +22,16 @@ func TestUnmarshal_string(t *testing.T) {
|
|||||||
if Name != "Bananrama" {
|
if Name != "Bananrama" {
|
||||||
t.Errorf("Unmarshal NBT fail: get %q, want %q", Name, "Bananrama")
|
t.Errorf("Unmarshal NBT fail: get %q, want %q", Name, "Bananrama")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Unmarshal to interface{}
|
||||||
|
var infName interface{}
|
||||||
|
if err := Unmarshal(data, &infName); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if infName != "Bananrama" {
|
||||||
|
t.Errorf("Unmarshal NBT fail: get %q, want %q", Name, "Bananrama")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func TestUnmarshal_simple(t *testing.T) {
|
func TestUnmarshal_simple(t *testing.T) {
|
||||||
var data = []byte{
|
var data = []byte{
|
||||||
@ -188,6 +198,17 @@ func TestUnmarshal_bittest(t *testing.T) {
|
|||||||
if err := NewDecoder(r).Decode(&empty); err != nil {
|
if err := NewDecoder(r).Decode(&empty); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//test unmarshal to interface{}
|
||||||
|
var inf interface{}
|
||||||
|
r, err = gzip.NewReader(bytes.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := NewDecoder(r).Decode(&inf); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(inf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshal_IntArray(t *testing.T) {
|
func TestUnmarshal_IntArray(t *testing.T) {
|
||||||
@ -234,8 +255,9 @@ func TestUnmarshal_LongArray(t *testing.T) {
|
|||||||
0, 0, 0, 0, 0, 0, 0, 3,
|
0, 0, 0, 0, 0, 0, 0, 3,
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
value []int64
|
value []int64
|
||||||
want = []int64{1, 2, 3}
|
infValue interface{}
|
||||||
|
want = []int64{1, 2, 3}
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := Unmarshal(data, &value); err != nil {
|
if err := Unmarshal(data, &value); err != nil {
|
||||||
@ -244,6 +266,43 @@ func TestUnmarshal_LongArray(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(value, want) {
|
if !reflect.DeepEqual(value, want) {
|
||||||
t.Errorf("parse fail, expect %v, get %v", want, value)
|
t.Errorf("parse fail, expect %v, get %v", want, value)
|
||||||
}
|
}
|
||||||
|
// t.Log(value)
|
||||||
|
|
||||||
t.Log(value)
|
if err := Unmarshal(data, &infValue); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(infValue, want) {
|
||||||
|
t.Errorf("parse fail, expect %v, get %v", want, infValue)
|
||||||
|
}
|
||||||
|
// t.Log(infValue)
|
||||||
|
}
|
||||||
|
func TestUnmarshal_ByteArray(t *testing.T) {
|
||||||
|
data := []byte{
|
||||||
|
TagByteArray, 0, 0,
|
||||||
|
0, 0, 0, 7,
|
||||||
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
value []byte
|
||||||
|
infValue interface{}
|
||||||
|
want = []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}
|
||||||
|
)
|
||||||
|
|
||||||
|
//Unmarshal to []byte
|
||||||
|
if err := Unmarshal(data, &value); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(value, want) {
|
||||||
|
t.Errorf("parse fail, expect %v, get %v", want, value)
|
||||||
|
}
|
||||||
|
// t.Log(value)
|
||||||
|
|
||||||
|
//Unmarshal to interface{}
|
||||||
|
if err := Unmarshal(data, &infValue); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(infValue, want) {
|
||||||
|
t.Errorf("parse fail, expect %v, get %v", want, value)
|
||||||
|
}
|
||||||
|
// t.Log(infValue)
|
||||||
}
|
}
|
||||||
|
134
nbt/read.go
134
nbt/read.go
@ -46,6 +46,8 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
val.SetInt(int64(value))
|
val.SetInt(int64(value))
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
val.SetUint(uint64(value))
|
val.SetUint(uint64(value))
|
||||||
|
case reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
case TagShort:
|
case TagShort:
|
||||||
@ -60,6 +62,8 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
val.SetInt(int64(value))
|
val.SetInt(int64(value))
|
||||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
val.SetUint(uint64(value))
|
val.SetUint(uint64(value))
|
||||||
|
case reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
case TagInt:
|
case TagInt:
|
||||||
@ -74,17 +78,24 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
val.SetInt(int64(value))
|
val.SetInt(int64(value))
|
||||||
case reflect.Uint, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint32, reflect.Uint64:
|
||||||
val.SetUint(uint64(value))
|
val.SetUint(uint64(value))
|
||||||
|
case reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
case TagFloat:
|
case TagFloat:
|
||||||
if vk := val.Kind(); vk != reflect.Float32 {
|
|
||||||
return errors.New("cannot parse TagFloat as " + vk.String())
|
|
||||||
}
|
|
||||||
vInt, err := d.readInt32()
|
vInt, err := d.readInt32()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
val.Set(reflect.ValueOf(math.Float32frombits(uint32(vInt))))
|
value := math.Float32frombits(uint32(vInt))
|
||||||
|
switch vk := val.Kind(); vk {
|
||||||
|
default:
|
||||||
|
return errors.New("cannot parse TagFloat as " + vk.String())
|
||||||
|
case reflect.Float32:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
|
case reflect.Float64:
|
||||||
|
val.Set(reflect.ValueOf(float64(value)))
|
||||||
|
}
|
||||||
|
|
||||||
case TagLong:
|
case TagLong:
|
||||||
value, err := d.readInt64()
|
value, err := d.readInt64()
|
||||||
@ -98,33 +109,42 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
val.SetInt(int64(value))
|
val.SetInt(int64(value))
|
||||||
case reflect.Uint, reflect.Uint64:
|
case reflect.Uint, reflect.Uint64:
|
||||||
val.SetUint(uint64(value))
|
val.SetUint(uint64(value))
|
||||||
|
case reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
case TagDouble:
|
case TagDouble:
|
||||||
if vk := val.Kind(); vk != reflect.Float64 {
|
|
||||||
return errors.New("cannot parse TagDouble as " + vk.String())
|
|
||||||
}
|
|
||||||
vInt, err := d.readInt64()
|
vInt, err := d.readInt64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
val.Set(reflect.ValueOf(math.Float64frombits(uint64(vInt))))
|
value := math.Float64frombits(uint64(vInt))
|
||||||
|
|
||||||
|
switch vk := val.Kind(); vk {
|
||||||
|
default:
|
||||||
|
return errors.New("cannot parse TagDouble as " + vk.String())
|
||||||
|
case reflect.Float64:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
|
case reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(value))
|
||||||
|
}
|
||||||
|
|
||||||
case TagString:
|
case TagString:
|
||||||
if vk := val.Kind(); vk != reflect.String {
|
|
||||||
return errors.New("cannot parse TagString as " + vk.String())
|
|
||||||
}
|
|
||||||
s, err := d.readString()
|
s, err := d.readString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
val.SetString(s)
|
switch vk := val.Kind(); vk {
|
||||||
|
default:
|
||||||
|
return errors.New("cannot parse TagString as " + vk.String())
|
||||||
|
case reflect.String:
|
||||||
|
val.SetString(s)
|
||||||
|
case reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(s))
|
||||||
|
}
|
||||||
|
|
||||||
case TagByteArray:
|
case TagByteArray:
|
||||||
var ba []byte
|
var ba []byte
|
||||||
if vt := val.Type(); vt != reflect.TypeOf(ba) {
|
|
||||||
return errors.New("cannot parse TagByteArray to " + vt.String() + ", use []byte in this instance")
|
|
||||||
}
|
|
||||||
aryLen, err := d.readInt32()
|
aryLen, err := d.readInt32()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -132,7 +152,15 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
if ba, err = d.readNByte(int(aryLen)); err != nil {
|
if ba, err = d.readNByte(int(aryLen)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
val.SetBytes(ba)
|
|
||||||
|
switch vt := val.Type(); {
|
||||||
|
default:
|
||||||
|
return errors.New("cannot parse TagByteArray to " + vt.String() + ", use []byte in this instance")
|
||||||
|
case vt == reflect.TypeOf(ba):
|
||||||
|
val.SetBytes(ba)
|
||||||
|
case vt.Kind() == reflect.Interface:
|
||||||
|
val.Set(reflect.ValueOf(ba))
|
||||||
|
}
|
||||||
|
|
||||||
case TagIntArray:
|
case TagIntArray:
|
||||||
aryLen, err := d.readInt32()
|
aryLen, err := d.readInt32()
|
||||||
@ -140,20 +168,23 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
vt := val.Type() //reciver must be []int or []int32
|
vt := val.Type() //reciver must be []int or []int32
|
||||||
if vt.Kind() != reflect.Slice {
|
if vt.Kind() == reflect.Interface {
|
||||||
|
vt = reflect.TypeOf([]int32{}) // pass
|
||||||
|
} else if vt.Kind() != reflect.Slice {
|
||||||
return errors.New("cannot parse TagIntArray to " + vt.String() + ", it must be a slice")
|
return errors.New("cannot parse TagIntArray to " + vt.String() + ", it must be a slice")
|
||||||
} else if tk := val.Type().Elem().Kind(); tk != reflect.Int && tk != reflect.Int32 {
|
} else if tk := val.Type().Elem().Kind(); tk != reflect.Int && tk != reflect.Int32 {
|
||||||
return errors.New("cannot parse TagIntArray to " + vt.String())
|
return errors.New("cannot parse TagIntArray to " + vt.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
val.Set(reflect.MakeSlice(vt, int(aryLen), int(aryLen)))
|
buf := reflect.MakeSlice(vt, int(aryLen), int(aryLen))
|
||||||
for i := 0; i < int(aryLen); i++ {
|
for i := 0; i < int(aryLen); i++ {
|
||||||
value, err := d.readInt32()
|
value, err := d.readInt32()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
val.Index(i).SetInt(int64(value))
|
buf.Index(i).SetInt(int64(value))
|
||||||
}
|
}
|
||||||
|
val.Set(buf)
|
||||||
|
|
||||||
case TagLongArray:
|
case TagLongArray:
|
||||||
aryLen, err := d.readInt32()
|
aryLen, err := d.readInt32()
|
||||||
@ -161,20 +192,23 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
vt := val.Type() //reciver must be []int or []int64
|
vt := val.Type() //reciver must be []int or []int64
|
||||||
if vt.Kind() != reflect.Slice {
|
if vt.Kind() == reflect.Interface {
|
||||||
|
vt = reflect.TypeOf([]int64{}) // pass
|
||||||
|
} else if vt.Kind() != reflect.Slice {
|
||||||
return errors.New("cannot parse TagIntArray to " + vt.String() + ", it must be a slice")
|
return errors.New("cannot parse TagIntArray to " + vt.String() + ", it must be a slice")
|
||||||
} else if val.Type().Elem().Kind() != reflect.Int64 {
|
} else if val.Type().Elem().Kind() != reflect.Int64 {
|
||||||
return errors.New("cannot parse TagIntArray to " + vt.String())
|
return errors.New("cannot parse TagIntArray to " + vt.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
val.Set(reflect.MakeSlice(vt, int(aryLen), int(aryLen)))
|
buf := reflect.MakeSlice(vt, int(aryLen), int(aryLen))
|
||||||
for i := 0; i < int(aryLen); i++ {
|
for i := 0; i < int(aryLen); i++ {
|
||||||
value, err := d.readInt64()
|
value, err := d.readInt64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
val.Index(i).SetInt(value)
|
buf.Index(i).SetInt(value)
|
||||||
}
|
}
|
||||||
|
val.Set(buf)
|
||||||
|
|
||||||
case TagList:
|
case TagList:
|
||||||
listType, err := d.r.ReadByte()
|
listType, err := d.r.ReadByte()
|
||||||
@ -185,50 +219,64 @@ func (d *Decoder) unmarshal(val reflect.Value, tagType byte, tagName string) err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we need parse TAG_List into slice, make a new with right length.
|
// If we need parse TAG_List into slice, make a new with right length.
|
||||||
// Otherwise if we need parse into array, we check if len(array) are enough.
|
// Otherwise if we need parse into array, we check if len(array) are enough.
|
||||||
switch vk := val.Kind(); vk {
|
var buf reflect.Value
|
||||||
|
vk := val.Kind()
|
||||||
|
switch vk {
|
||||||
default:
|
default:
|
||||||
return errors.New("cannot parse TagList as " + vk.String())
|
return errors.New("cannot parse TagList as " + vk.String())
|
||||||
|
case reflect.Interface:
|
||||||
|
fallthrough
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
val.Set(reflect.MakeSlice(val.Type(), int(listLen), int(listLen)))
|
buf = reflect.MakeSlice(val.Type(), int(listLen), int(listLen))
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
if vl := val.Len(); vl < int(listLen) {
|
if vl := val.Len(); vl < int(listLen) {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"TagList %s has len %d, but array %v only has len %d",
|
"TagList %s has len %d, but array %v only has len %d",
|
||||||
tagName, listLen, val.Type(), vl)
|
tagName, listLen, val.Type(), vl)
|
||||||
}
|
}
|
||||||
|
buf = val
|
||||||
}
|
}
|
||||||
for i := 0; i < int(listLen); i++ {
|
for i := 0; i < int(listLen); i++ {
|
||||||
if err := d.unmarshal(val.Index(i), listType, ""); err != nil {
|
if err := d.unmarshal(buf.Index(i), listType, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case TagCompound:
|
if val.Kind() != reflect.Array {
|
||||||
if vk := val.Kind(); vk != reflect.Struct {
|
val.Set(buf)
|
||||||
return errors.New("cannot parse TagCompound as " + vk.String())
|
|
||||||
}
|
}
|
||||||
tinfo := getTypeInfo(val.Type())
|
|
||||||
for {
|
case TagCompound:
|
||||||
tt, tn, err := d.readTag()
|
switch vk := val.Kind(); vk {
|
||||||
if err != nil {
|
default:
|
||||||
return err
|
return errors.New("cannot parse TagCompound as " + vk.String())
|
||||||
}
|
case reflect.Struct:
|
||||||
if tt == TagEnd {
|
tinfo := getTypeInfo(val.Type())
|
||||||
break
|
for {
|
||||||
}
|
tt, tn, err := d.readTag()
|
||||||
field := tinfo.findIndexByName(tn)
|
|
||||||
if field != -1 {
|
|
||||||
err = d.unmarshal(val.Field(field), tt, tn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
if tt == TagEnd {
|
||||||
if err := d.skip(tt); err != nil {
|
break
|
||||||
return err
|
}
|
||||||
|
field := tinfo.findIndexByName(tn)
|
||||||
|
if field != -1 {
|
||||||
|
err = d.unmarshal(val.Field(field), tt, tn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := d.skip(tt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user