can parse TAG_String

This commit is contained in:
JunDao
2019-05-18 01:08:32 +08:00
parent 94fb6502db
commit 9cdab82ea3
4 changed files with 189 additions and 0 deletions

44
nbt/nbt.go Normal file
View File

@ -0,0 +1,44 @@
package nbt
import (
"bufio"
"io"
)
//Tag type IDs
const (
TagEnd byte = iota
TagByte
TagShort
TagInt
TagLong
TagFloat
TagDouble
TagByteArray
TagString
TagList
TagCompound
TagIntArray
TagLongArray
)
type Decoder struct {
r interface {
io.ByteReader
io.Reader
}
nameless bool
}
func NewDecoder(r io.Reader) *Decoder {
d := new(Decoder)
if br, ok := r.(interface {
io.ByteReader
io.Reader
}); ok {
d.r = br
} else {
d.r = bufio.NewReader(r)
}
return d
}

42
nbt/nbt_test.go Normal file
View File

@ -0,0 +1,42 @@
package nbt
import "testing"
func TestUnmarshal_simple(t *testing.T) {
var data = []byte{
0x0a, 0x00, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x08, 0x00,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x09, 0x42,
0x61, 0x6e, 0x61, 0x6e, 0x72, 0x61, 0x6d, 0x61,
0x00,
}
var value struct {
Name string `nbt:"name"`
}
if err := Unmarshal(data, &value); err != nil {
t.Fatal(err)
}
if value.Name != "Bananrama" {
t.Errorf("Unmarshal NBT fail: get %q, want %q", value.Name, "Bananrama")
}
}
func TestUnmarshal_string(t *testing.T) {
var data = []byte{
0x08, 0x00, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x09,
0x42, 0x61, 0x6e, 0x61, 0x6e, 0x72, 0x61, 0x6d, 0x61,
}
var Name string
if err := Unmarshal(data, &Name); err != nil {
t.Fatal(err)
}
if Name != "Bananrama" {
t.Errorf("Unmarshal NBT fail: get %q, want %q", Name, "Bananrama")
}
}

81
nbt/read.go Normal file
View File

@ -0,0 +1,81 @@
package nbt
import (
"bytes"
"errors"
"fmt"
"reflect"
)
func Unmarshal(data []byte, v interface{}) error {
return NewDecoder(bytes.NewReader(data)).Decode(v)
}
func (d *Decoder) Decode(v interface{}) error {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Ptr {
return errors.New("non-pointer passed to Unmarshal")
}
return d.unmarshal(val.Elem())
}
// func (d *Decoder) unmarshalInt(val reflect.Value) error {
// }
func (d *Decoder) unmarshal(val reflect.Value) error {
tagType, err := d.r.ReadByte()
if err != nil {
return err
}
var tagName string
if !d.nameless { //Read Tag
if tagName, err = d.readString(); err != nil {
return err
}
}
switch tagType {
default:
return fmt.Errorf("unknown tag 0x%2x", tagType)
case TagString:
if val.Kind() != reflect.String {
return errors.New("cannot unmarshal TAG_String into " + val.Kind().String())
}
s, err := d.readString()
if err != nil {
return err
}
val.SetString(s)
case TagCompound:
if val.Kind() != reflect.Struct {
return errors.New("cannot unmarshal TAG_Compound into " + val.Kind().String())
}
fmt.Println("TagName:", tagName)
}
return nil
}
func (d *Decoder) readNByte(n int) (buf []byte, err error) {
buf = make([]byte, n)
_, err = d.r.Read(buf) //what happend if (returned n) != (argument n) ?
return
}
func (d *Decoder) readInt16() (int16, error) {
data, err := d.readNByte(2)
return int16(data[0])<<4 | int16(data[1]), err
}
func (d *Decoder) readString() (string, error) {
length, err := d.readInt16()
if err != nil {
return "", err
}
buf, err := d.readNByte(int(length))
return string(buf), err
}

22
nbt/typeinfo.go Normal file
View File

@ -0,0 +1,22 @@
package nbt
import (
"reflect"
)
type typeInfo struct {
}
func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
tinfo := new(typeInfo)
if typ.Kind() == reflect.Struct {
n := typ.NumField()
for i := 0; i < n; i++ {
f := typ.Field(i)
if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("nbt") == "-" {
continue // Private field
}
}
}
return tinfo, nil
}