Apply the waring in nbt/README.md

This commit is contained in:
Tnze
2021-06-22 11:18:18 +08:00
parent 4e6349dfda
commit 4f9779df88
4 changed files with 74 additions and 49 deletions

View File

@ -1,11 +1,11 @@
# NBT [![Go Reference](https://pkg.go.dev/badge/github.com/Tnze/go-mc/nbt.svg)](https://pkg.go.dev/github.com/Tnze/go-mc/nbt) # NBT [![Go Reference](https://pkg.go.dev/badge/github.com/Tnze/go-mc/nbt.svg)](https://pkg.go.dev/github.com/Tnze/go-mc/nbt)
This package implement the [Named Binary Tag](https://wiki.vg/NBT) format of Minecraft.
The API is very similar to the standard library `encoding/json`. If you (high probability) have used that, it is easy to use this. This package implement the [Named Binary Tag](https://wiki.vg/NBT) format of Minecraft.
# Basic Usage The API is very similar to the standard library `encoding/json`. If you (high probability) have used that, it is easy to
> I don't know why `Marshal` looks like that, and **I will change it** to `func Marshal(v interface{}) ([]byte, error)`. use this.
> **Use `Encoder` is recommended now.**
## Basic Usage
For the following NBT tag: For the following NBT tag:
@ -20,7 +20,6 @@ To read and write would look like:
```go ```go
package main package main
import "bytes"
import "github.com/Tnze/go-mc/nbt" import "github.com/Tnze/go-mc/nbt"
type Compound struct { type Compound struct {
@ -28,27 +27,26 @@ type Compound struct {
} }
func main() { func main() {
var out bytes.Buffer
banana := Compound{Name: "Bananrama"} banana := Compound{Name: "Bananrama"}
_ = nbt.Marshal(&out, banana) data, _ := nbt.Marshal(banana)
var rama Compound var rama Compound
_ = nbt.Unmarshal(out.Bytes(), &rama) _ = nbt.Unmarshal(data, &rama)
} }
``` ```
## Struct field tags
# Struct field tags
There are two tags supported: There are two tags supported:
- nbt - nbt
- nbt_type - nbt_type
The `nbt` tag is used to change the name of the NBT Tag field, whereas the `nbt_type` The `nbt` tag is used to change the name of the NBT Tag field, whereas the `nbt_type`
tag is used to enforce a certain NBT Tag type when it is ambiguous. tag is used to enforce a certain NBT Tag type when it is ambiguous.
For example: For example:
```go ```go
type Compound struct { type Compound struct {
LongArray []int64 LongArray []int64
@ -56,5 +54,25 @@ type Compound struct {
} }
``` ```
## Stringified NBT
You can transform SNBT string into binary NBT by using go-mc, which could be useful when parsing command, but the
reverse conversion is not supported at the moment.
```go
package main
import (
"bytes"
"github.com/Tnze/go-mc/nbt"
)
func main() {
var buf bytes.Buffer
e := nbt.NewEncoder(&buf)
err := e.WriteSNBT(`{Tnze: 1, 'sp ace': [I;1,2,3]}`)
if err != nil {
panic(err)
}
}
```

View File

@ -1,6 +1,7 @@
package nbt package nbt
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -10,8 +11,10 @@ import (
"strings" "strings"
) )
func Marshal(w io.Writer, v interface{}, optionalTagName ...string) error { func Marshal(v interface{}, optionalTagName ...string) ([]byte, error) {
return NewEncoder(w).Encode(v, optionalTagName...) var buf bytes.Buffer
err := NewEncoder(&buf).Encode(v, optionalTagName...)
return buf.Bytes(), err
} }
type Encoder struct { type Encoder struct {

View File

@ -17,11 +17,10 @@ func TestMarshal_IntArray(t *testing.T) {
0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0xf6,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
} }
var buf bytes.Buffer if data, err := Marshal(v); err != nil {
if err := Marshal(&buf, v); err != nil {
t.Error(err) t.Error(err)
} else if !bytes.Equal(buf.Bytes(), out) { } else if !bytes.Equal(data, out) {
t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) t.Errorf("output binary not right: get % 02x, want % 02x ", data, out)
} }
// Test marshal in a struct // Test marshal in a struct
@ -35,11 +34,10 @@ func TestMarshal_IntArray(t *testing.T) {
0x00, 0x00, 0x00, 0x03, // 3 0x00, 0x00, 0x00, 0x03, // 3
TagEnd, TagEnd,
} }
buf.Reset() if data, err := Marshal(v2); err != nil {
if err := Marshal(&buf, v2); err != nil {
t.Error(err) t.Error(err)
} else if !bytes.Equal(buf.Bytes(), out) { } else if !bytes.Equal(data, out) {
t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) t.Errorf("output binary not right: get % 02x, want % 02x ", data, out)
} }
} }
@ -51,11 +49,10 @@ func TestMarshal_FloatArray(t *testing.T) {
0xc2, 0xc8, 0x00, 0x00, // -100 0xc2, 0xc8, 0x00, 0x00, // -100
0x7f, 0xc0, 0x00, 0x00, // NaN 0x7f, 0xc0, 0x00, 0x00, // NaN
} }
var buf bytes.Buffer if data, err := Marshal(v); err != nil {
if err := Marshal(&buf, v); err != nil {
t.Error(err) t.Error(err)
} else if !bytes.Equal(buf.Bytes(), out) { } else if !bytes.Equal(data, out) {
t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) t.Errorf("output binary not right: get % 02x, want % 02x ", data, out)
} }
} }
@ -64,11 +61,10 @@ func TestMarshal_String(t *testing.T) {
out := []byte{TagString, 0x00, 0x00, 0, 4, out := []byte{TagString, 0x00, 0x00, 0, 4,
'T', 'e', 's', 't'} 'T', 'e', 's', 't'}
var buf bytes.Buffer if data, err := Marshal(v); err != nil {
if err := Marshal(&buf, v); err != nil {
t.Error(err) t.Error(err)
} else if !bytes.Equal(buf.Bytes(), out) { } else if !bytes.Equal(data, out) {
t.Errorf("output binary not right: got % 02x, want % 02x ", buf.Bytes(), out) t.Errorf("output binary not right: got % 02x, want % 02x ", data, out)
} }
} }
@ -103,12 +99,11 @@ func TestMarshal_InterfaceArray(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
w := &bytes.Buffer{} data, err := Marshal(tt.args)
err := Marshal(w, tt.args)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} else if !bytes.Equal(w.Bytes(), tt.want) { } else if !bytes.Equal(data, tt.want) {
t.Errorf("Marshal([]interface{}) got = % 02x, want % 02x", w.Bytes(), tt.want) t.Errorf("Marshal([]interface{}) got = % 02x, want % 02x", data, tt.want)
return return
} }
}) })
@ -158,12 +153,11 @@ func TestMarshal_StructArray(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
w := &bytes.Buffer{} data, err := Marshal(tt.args)
err := Marshal(w, tt.args)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} else if !bytes.Equal(w.Bytes(), tt.want) { } else if !bytes.Equal(data, tt.want) {
t.Errorf("Marshal([]struct{}) got = % 02x, want % 02x", w.Bytes(), tt.want) t.Errorf("Marshal([]struct{}) got = % 02x, want % 02x", data, tt.want)
return return
} }
}) })
@ -171,8 +165,7 @@ func TestMarshal_StructArray(t *testing.T) {
} }
func TestMarshal_bigTest(t *testing.T) { func TestMarshal_bigTest(t *testing.T) {
var b bytes.Buffer data, err := Marshal(MakeBigTestStruct(), "Level")
err := Marshal(&b, MakeBigTestStruct(), "Level")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -183,8 +176,8 @@ func TestMarshal_bigTest(t *testing.T) {
t.Error(err) t.Error(err)
} }
if !bytes.Equal(b.Bytes(), want) { if !bytes.Equal(data, want) {
t.Errorf("got:\n[% 2x]\nwant:\n[% 2x]", b.Bytes(), want) t.Errorf("got:\n[% 2x]\nwant:\n[% 2x]", data, want)
} }
} }
@ -194,8 +187,8 @@ func TestMarshal_map(t *testing.T) {
"Xi_Xi_Mi": {0, 0, 4, 7, 2}, "Xi_Xi_Mi": {0, 0, 4, 7, 2},
} }
var buf bytes.Buffer b, err := Marshal(v)
if err := Marshal(&buf, v); err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -204,7 +197,7 @@ func TestMarshal_map(t *testing.T) {
XXM []int32 `nbt:"Xi_Xi_Mi"` XXM []int32 `nbt:"Xi_Xi_Mi"`
} }
if err := NewDecoder(&buf).Decode(&data); err != nil { if err := NewDecoder(bytes.NewReader(b)).Decode(&data); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(data.Tnze, v["Tnze"]) { if !reflect.DeepEqual(data.Tnze, v["Tnze"]) {

View File

@ -28,13 +28,24 @@ func ExampleMarshal() {
Name string `nbt:"name"` Name string `nbt:"name"`
}{"Tnze"} }{"Tnze"}
var buf bytes.Buffer data, err := Marshal(value)
if err := Marshal(&buf, value); err != nil { if err != nil {
panic(err) panic(err)
} }
fmt.Printf("% 02x ", buf.Bytes()) fmt.Printf("% 02x ", data)
// Output: // Output:
// 0a 00 00 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 00 // 0a 00 00 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 00
} }
func ExampleEncoder_WriteSNBT() {
var buf bytes.Buffer
if err := NewEncoder(&buf).WriteSNBT(`{ name: [Tnze, "Xi_Xi_Mi"]}`); err != nil {
panic(err)
}
fmt.Printf("% 02x ", buf.Bytes())
// Output:
// 0a 00 00 09 00 04 6e 61 6d 65 08 00 00 00 02 00 04 54 6e 7a 65 00 08 58 69 5f 58 69 5f 4d 69 00
}