Finish development of fastnbt
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
package fastnbt
|
package fastnbt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -8,10 +9,6 @@ import (
|
|||||||
"github.com/Tnze/go-mc/nbt"
|
"github.com/Tnze/go-mc/nbt"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func (v *Value) Parse(data []byte) {
|
|
||||||
// // TODO
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (v *Value) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error {
|
func (v *Value) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error {
|
||||||
v.tag = tagType
|
v.tag = tagType
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
@ -49,7 +46,7 @@ func (v *Value) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v.data = append(v.data[:0], make([]byte, 4+n)...)
|
v.data = append(v.data[:0], make([]byte, 4+n)...)
|
||||||
v.data[0], v.data[1], v.data[2], v.data[3] = byte(n>>24), byte(n>>16), byte(n>>8), byte(n)
|
binary.BigEndian.PutUint32(v.data, uint32(n))
|
||||||
|
|
||||||
_, err = io.ReadFull(r, v.data[4:])
|
_, err = io.ReadFull(r, v.data[4:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -63,7 +60,7 @@ func (v *Value) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v.data = append(v.data[:0], make([]byte, 2+n)...)
|
v.data = append(v.data[:0], make([]byte, 2+n)...)
|
||||||
v.data[0], v.data[1] = byte(n>>8), byte(n)
|
binary.BigEndian.PutUint16(v.data, uint16(n))
|
||||||
|
|
||||||
_, err = io.ReadFull(r, v.data[2:])
|
_, err = io.ReadFull(r, v.data[2:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -119,7 +116,7 @@ func (v *Value) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v.data = append(v.data[:0], make([]byte, 4+n*4)...)
|
v.data = append(v.data[:0], make([]byte, 4+n*4)...)
|
||||||
v.data[0], v.data[1], v.data[2], v.data[3] = byte(n>>24), byte(n>>16), byte(n>>8), byte(n)
|
binary.BigEndian.PutUint32(v.data, uint32(n))
|
||||||
|
|
||||||
_, err = io.ReadFull(r, v.data[4:])
|
_, err = io.ReadFull(r, v.data[4:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -133,7 +130,7 @@ func (v *Value) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v.data = append(v.data[:0], make([]byte, 4+n*8)...)
|
v.data = append(v.data[:0], make([]byte, 4+n*8)...)
|
||||||
v.data[0], v.data[1], v.data[2], v.data[3] = byte(n>>24), byte(n>>16), byte(n>>8), byte(n)
|
binary.BigEndian.PutUint32(v.data, uint32(n))
|
||||||
|
|
||||||
_, err = io.ReadFull(r, v.data[4:])
|
_, err = io.ReadFull(r, v.data[4:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -161,14 +158,13 @@ func readTag(r nbt.DecoderReader) (tagType byte, tagName string, err error) {
|
|||||||
func readInt16(r nbt.DecoderReader) (int16, error) {
|
func readInt16(r nbt.DecoderReader) (int16, error) {
|
||||||
var data [2]byte
|
var data [2]byte
|
||||||
_, err := io.ReadFull(r, data[:])
|
_, err := io.ReadFull(r, data[:])
|
||||||
return int16(data[0])<<8 | int16(data[1]), err
|
return int16(binary.BigEndian.Uint16(data[:])), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func readInt32(r nbt.DecoderReader) (int32, error) {
|
func readInt32(r nbt.DecoderReader) (int32, error) {
|
||||||
var data [4]byte
|
var data [4]byte
|
||||||
_, err := io.ReadFull(r, data[:])
|
_, err := io.ReadFull(r, data[:])
|
||||||
return int32(data[0])<<24 | int32(data[1])<<16 |
|
return int32(binary.BigEndian.Uint32(data[:])), err
|
||||||
int32(data[2])<<8 | int32(data[3]), err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func readString(r nbt.DecoderReader) (string, error) {
|
func readString(r nbt.DecoderReader) (string, error) {
|
||||||
|
@ -12,6 +12,10 @@ func (v *Value) TagType() byte { return v.tag }
|
|||||||
func (v *Value) MarshalNBT(w io.Writer) (err error) {
|
func (v *Value) MarshalNBT(w io.Writer) (err error) {
|
||||||
switch v.tag {
|
switch v.tag {
|
||||||
case nbt.TagEnd:
|
case nbt.TagEnd:
|
||||||
|
_, err = w.Write([]byte{0})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
case nbt.TagByte, nbt.TagShort, nbt.TagInt, nbt.TagLong, nbt.TagFloat, nbt.TagDouble,
|
case nbt.TagByte, nbt.TagShort, nbt.TagInt, nbt.TagLong, nbt.TagFloat, nbt.TagDouble,
|
||||||
nbt.TagByteArray, nbt.TagString, nbt.TagIntArray, nbt.TagLongArray:
|
nbt.TagByteArray, nbt.TagString, nbt.TagIntArray, nbt.TagLongArray:
|
||||||
|
@ -1 +1,75 @@
|
|||||||
package fastnbt
|
package fastnbt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/nbt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValue_new(t *testing.T) {
|
||||||
|
if val := NewBoolean(true); val.Boolean() != true {
|
||||||
|
t.Error("encode bool error")
|
||||||
|
}
|
||||||
|
if val := NewBoolean(false); val.Boolean() != false {
|
||||||
|
t.Error("encode bool error")
|
||||||
|
}
|
||||||
|
if val := NewByte(127); val.Byte() != 127 {
|
||||||
|
t.Error("encode byte error")
|
||||||
|
}
|
||||||
|
if val := NewShort(32767); val.Short() != 32767 {
|
||||||
|
t.Error("encode short error")
|
||||||
|
}
|
||||||
|
if val := NewInt(2147483647); val.Int() != 2147483647 {
|
||||||
|
t.Error("encode int error")
|
||||||
|
}
|
||||||
|
if val := NewLong(9223372036854775807); val.Long() != 9223372036854775807 {
|
||||||
|
t.Error("encode long error")
|
||||||
|
}
|
||||||
|
if val := NewString("HELLO WORLD THIS IS A TEST STRING ÅÄÖ!"); val.String() != "HELLO WORLD THIS IS A TEST STRING ÅÄÖ!" {
|
||||||
|
t.Error("encode string error")
|
||||||
|
}
|
||||||
|
if val := NewFloat(0.49823147); val.Float() != 0.49823147 {
|
||||||
|
t.Error("encode float error")
|
||||||
|
}
|
||||||
|
if val := NewDouble(0.4931287132182315); val.Double() != 0.4931287132182315 {
|
||||||
|
t.Error("encode double error")
|
||||||
|
}
|
||||||
|
|
||||||
|
byteArray := make([]byte, 1000)
|
||||||
|
for n := 0; n < 1000; n++ {
|
||||||
|
byteArray[n] = byte((n*n*255 + n*7) % 100)
|
||||||
|
}
|
||||||
|
if val := NewByteArray(byteArray); !bytes.Equal(byteArray, val.ByteArray()) {
|
||||||
|
t.Error("encode byteArray error")
|
||||||
|
}
|
||||||
|
|
||||||
|
val := NewCompound()
|
||||||
|
val.Set("a", NewString("tnze"))
|
||||||
|
if val.Get("a").String() != "tnze" || val.Compound().Len() != 1 {
|
||||||
|
t.Error("encode compound error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValue_bigTest(t *testing.T) {
|
||||||
|
data, err := nbt.Marshal(nbt.StringifiedMessage(bigTestSNBT))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var val Value
|
||||||
|
err = nbt.Unmarshal(data, &val)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data2 []byte
|
||||||
|
data2, err = nbt.Marshal(&val)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(data, data2) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fastnbt
|
package fastnbt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/nbt"
|
"github.com/Tnze/go-mc/nbt"
|
||||||
@ -13,7 +14,69 @@ type Value struct {
|
|||||||
tag byte // nbt.Tag*
|
tag byte // nbt.Tag*
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Value) Bool() bool {
|
func NewBoolean(v bool) *Value {
|
||||||
|
data := byte(0)
|
||||||
|
if v {
|
||||||
|
data = 1
|
||||||
|
}
|
||||||
|
return &Value{tag: nbt.TagByte, data: []byte{data}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewByte(v int8) *Value {
|
||||||
|
return &Value{tag: nbt.TagByte, data: []byte{byte(v)}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShort(v int16) *Value {
|
||||||
|
data := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(data, uint16(v))
|
||||||
|
return &Value{tag: nbt.TagShort, data: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInt(v int32) *Value {
|
||||||
|
data := make([]byte, 4)
|
||||||
|
binary.BigEndian.PutUint32(data, uint32(v))
|
||||||
|
return &Value{tag: nbt.TagInt, data: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLong(v int64) *Value {
|
||||||
|
data := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(data, uint64(v))
|
||||||
|
return &Value{tag: nbt.TagLong, data: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFloat(f float32) *Value {
|
||||||
|
data := make([]byte, 4)
|
||||||
|
binary.BigEndian.PutUint32(data, math.Float32bits(f))
|
||||||
|
return &Value{tag: nbt.TagFloat, data: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDouble(d float64) *Value {
|
||||||
|
data := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(data, math.Float64bits(d))
|
||||||
|
return &Value{tag: nbt.TagDouble, data: data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewByteArray(v []byte) *Value {
|
||||||
|
data := make([]byte, 4, 4+len(v))
|
||||||
|
binary.BigEndian.PutUint32(data, uint32(len(v)))
|
||||||
|
return &Value{tag: nbt.TagByteArray, data: append(data, v...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewString(str string) *Value {
|
||||||
|
data := make([]byte, 2, 2+len(str))
|
||||||
|
binary.BigEndian.PutUint16(data, uint16(len(str)))
|
||||||
|
return &Value{tag: nbt.TagString, data: append(data, str...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewList(elems ...*Value) *Value {
|
||||||
|
return &Value{tag: nbt.TagList, list: elems}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCompound() *Value {
|
||||||
|
return &Value{tag: nbt.TagCompound}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Value) Boolean() bool {
|
||||||
if v.tag != nbt.TagByte {
|
if v.tag != nbt.TagByte {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -31,51 +94,45 @@ func (v *Value) Short() int16 {
|
|||||||
if v.tag != nbt.TagShort {
|
if v.tag != nbt.TagShort {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return int16(v.data[0])<<8 | int16(v.data[1])
|
return int16(binary.BigEndian.Uint16(v.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Value) Int() int32 {
|
func (v *Value) Int() int32 {
|
||||||
if v.tag != nbt.TagInt {
|
if v.tag != nbt.TagInt {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return int32(v.data[0])<<24 | int32(v.data[1])<<16 |
|
return int32(binary.BigEndian.Uint32(v.data))
|
||||||
int32(v.data[2])<<8 | int32(v.data[3])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Value) Long() int64 {
|
func (v *Value) Long() int64 {
|
||||||
if v.tag != nbt.TagLong {
|
if v.tag != nbt.TagLong {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return int64(v.data[0])<<56 | int64(v.data[1])<<48 |
|
return int64(binary.BigEndian.Uint64(v.data))
|
||||||
int64(v.data[2])<<40 | int64(v.data[3])<<32 |
|
|
||||||
int64(v.data[4])<<24 | int64(v.data[5])<<16 |
|
|
||||||
int64(v.data[6])<<8 | int64(v.data[7])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Value) Float() float32 {
|
func (v *Value) Float() float32 {
|
||||||
if v.tag != nbt.TagFloat {
|
if v.tag != nbt.TagFloat {
|
||||||
return 0
|
return float32(math.NaN())
|
||||||
}
|
}
|
||||||
return math.Float32frombits(
|
return math.Float32frombits(binary.BigEndian.Uint32(v.data))
|
||||||
uint32(v.data[0])<<24 | uint32(v.data[1])<<16 |
|
|
||||||
uint32(v.data[2])<<8 | uint32(v.data[3]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Value) Double() float64 {
|
func (v *Value) Double() float64 {
|
||||||
if v.tag != nbt.TagDouble {
|
if v.tag != nbt.TagDouble {
|
||||||
return 0
|
return math.NaN()
|
||||||
}
|
}
|
||||||
return math.Float64frombits(
|
return math.Float64frombits(binary.BigEndian.Uint64(v.data))
|
||||||
uint64(v.data[0])<<56 | uint64(v.data[1])<<48 |
|
|
||||||
uint64(v.data[2])<<40 | uint64(v.data[3])<<32 |
|
|
||||||
uint64(v.data[4])<<24 | uint64(v.data[5])<<16 |
|
|
||||||
uint64(v.data[6])<<8 | uint64(v.data[7]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Value) List() []*Value {
|
func (v *Value) List() []*Value {
|
||||||
return v.list
|
return v.list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Value) Compound() *Compound {
|
||||||
|
return &v.comp
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Value) ByteArray() []byte {
|
func (v *Value) ByteArray() []byte {
|
||||||
if v.tag != nbt.TagByteArray {
|
if v.tag != nbt.TagByteArray {
|
||||||
return nil
|
return nil
|
||||||
@ -83,6 +140,15 @@ func (v *Value) ByteArray() []byte {
|
|||||||
return v.data[4:]
|
return v.data[4:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Value) IntArray() []int32 {
|
||||||
|
length := binary.BigEndian.Uint32(v.data)
|
||||||
|
ret := make([]int32, length)
|
||||||
|
for i := uint32(0); i < length; i += 4 {
|
||||||
|
ret[i] = int32(binary.BigEndian.Uint32(v.data[i:]))
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Value) String() string {
|
func (v *Value) String() string {
|
||||||
if v.tag != nbt.TagString {
|
if v.tag != nbt.TagString {
|
||||||
return ""
|
return ""
|
||||||
|
Reference in New Issue
Block a user