Add tests and examples for pk.Opt and pk.Tuple.
This commit is contained in:
@ -99,27 +99,6 @@ func TestVarLong_ReadFrom(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAry_ReadFrom(t *testing.T) {
|
|
||||||
var num pk.Int = 2
|
|
||||||
var ary []pk.String
|
|
||||||
var bin = []byte{
|
|
||||||
4, 'T', 'n', 'z', 'e',
|
|
||||||
0,
|
|
||||||
}
|
|
||||||
var data = pk.Ary{Len: &num, Ary: &ary}
|
|
||||||
if _, err := data.ReadFrom(bytes.NewReader(bin)); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(ary) != int(num) {
|
|
||||||
t.Fatalf("length not match: %d != %d", len(ary), num)
|
|
||||||
}
|
|
||||||
for i, v := range []string{"Tnze", ""} {
|
|
||||||
if string(ary[i]) != v {
|
|
||||||
t.Errorf("want %q, get %q", v, ary[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:embed joingame_test.bin
|
//go:embed joingame_test.bin
|
||||||
var testJoinGameData []byte
|
var testJoinGameData []byte
|
||||||
|
|
||||||
|
@ -70,22 +70,25 @@ func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Opt struct {
|
type Opt struct {
|
||||||
Has interface{} // Boolean, *Boolean or func() bool
|
Has interface{} // Pointer of bool, or `func() bool`
|
||||||
Field interface{} // FieldEncoder, FieldDecoder or both (Field)
|
Field interface{} // FieldEncoder, FieldDecoder or both (Field)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Opt) has() bool {
|
func (o Opt) has() bool {
|
||||||
switch o.Has.(type) {
|
v := reflect.ValueOf(o.Has)
|
||||||
case Boolean:
|
for {
|
||||||
return bool(o.Has.(Boolean))
|
switch v.Kind() {
|
||||||
case *Boolean:
|
case reflect.Ptr:
|
||||||
return bool(*o.Has.(*Boolean))
|
v = v.Elem()
|
||||||
case func() bool:
|
case reflect.Bool:
|
||||||
return o.Has.(func() bool)()
|
return v.Bool()
|
||||||
|
case reflect.Func:
|
||||||
|
return v.Interface().(func() bool)()
|
||||||
default:
|
default:
|
||||||
panic(errors.New("unsupported Has value"))
|
panic(errors.New("unsupported Has value"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (o Opt) WriteTo(w io.Writer) (int64, error) {
|
func (o Opt) WriteTo(w io.Writer) (int64, error) {
|
||||||
if o.has() {
|
if o.has() {
|
||||||
|
@ -2,9 +2,9 @@ package packet_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"fmt"
|
||||||
|
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleAry_WriteTo() {
|
func ExampleAry_WriteTo() {
|
||||||
@ -42,6 +42,27 @@ func ExampleAry_ReadFrom() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAry_ReadFrom(t *testing.T) {
|
||||||
|
var num pk.Int = 2
|
||||||
|
var ary []pk.String
|
||||||
|
var bin = []byte{
|
||||||
|
4, 'T', 'n', 'z', 'e',
|
||||||
|
0,
|
||||||
|
}
|
||||||
|
var data = pk.Ary{Len: &num, Ary: &ary}
|
||||||
|
if _, err := data.ReadFrom(bytes.NewReader(bin)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(ary) != int(num) {
|
||||||
|
t.Fatalf("length not match: %d != %d", len(ary), num)
|
||||||
|
}
|
||||||
|
for i, v := range []string{"Tnze", ""} {
|
||||||
|
if string(ary[i]) != v {
|
||||||
|
t.Errorf("want %q, get %q", v, ary[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAry_WriteTo(t *testing.T) {
|
func TestAry_WriteTo(t *testing.T) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
want := []byte{
|
want := []byte{
|
||||||
@ -51,6 +72,7 @@ func TestAry_WriteTo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
int3, long3, varint3, varlong3 := pk.Int(3), pk.Long(3), pk.VarInt(3), pk.VarLong(3)
|
int3, long3, varint3, varlong3 := pk.Int(3), pk.Long(3), pk.VarInt(3), pk.VarLong(3)
|
||||||
for _, item := range [...]pk.Ary{
|
for _, item := range [...]pk.Ary{
|
||||||
|
{Len: 3, Ary: []pk.Int{1, 2, 3}},
|
||||||
{Len: int3, Ary: []pk.Int{1, 2, 3}},
|
{Len: int3, Ary: []pk.Int{1, 2, 3}},
|
||||||
{Len: long3, Ary: []pk.Int{1, 2, 3}},
|
{Len: long3, Ary: []pk.Int{1, 2, 3}},
|
||||||
{Len: varint3, Ary: []pk.Int{1, 2, 3}},
|
{Len: varint3, Ary: []pk.Int{1, 2, 3}},
|
||||||
@ -70,3 +92,97 @@ func TestAry_WriteTo(t *testing.T) {
|
|||||||
buf.Reset()
|
buf.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleOpt_ReadFrom() {
|
||||||
|
var has pk.Boolean
|
||||||
|
|
||||||
|
var data pk.String
|
||||||
|
p1 := pk.Packet{Data: []byte{
|
||||||
|
0x01, // pk.Boolean(true)
|
||||||
|
4, 'T', 'n', 'z', 'e', // pk.String
|
||||||
|
}}
|
||||||
|
if err := p1.Scan(
|
||||||
|
&has,
|
||||||
|
pk.Opt{
|
||||||
|
Has: &has, Field: &data,
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
var data2 pk.String = "WILL NOT BE READ, WILL NOT BE COVERED"
|
||||||
|
p2 := pk.Packet{Data: []byte{
|
||||||
|
0x00, // pk.Boolean(false)
|
||||||
|
// empty
|
||||||
|
}}
|
||||||
|
if err := p2.Scan(
|
||||||
|
&has,
|
||||||
|
pk.Opt{
|
||||||
|
Has: &has, Field: &data2,
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Tnze
|
||||||
|
// WILL NOT BE READ, WILL NOT BE COVERED
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOpt_ReadFrom_func() {
|
||||||
|
// As an example, we define this packet as this:
|
||||||
|
// +------+-----------------+----------------------------------+
|
||||||
|
// | Name | Type | Notes |
|
||||||
|
// +------+-----------------+----------------------------------+
|
||||||
|
// | Flag | Unsigned Byte | Odd if the following is present. |
|
||||||
|
// +------+-----------------+----------------------------------+
|
||||||
|
// | User | Optional String | The player's name. |
|
||||||
|
// +------+-----------------+----------------------------------+
|
||||||
|
// So we need a function to decide if the User field is present.
|
||||||
|
var flag pk.Byte
|
||||||
|
var data pk.String
|
||||||
|
p := pk.Packet{Data: []byte{
|
||||||
|
0b_0010_0011, // pk.Byte(flag)
|
||||||
|
4, 'T', 'n', 'z', 'e', // pk.String
|
||||||
|
}}
|
||||||
|
if err := p.Scan(
|
||||||
|
&flag,
|
||||||
|
pk.Opt{
|
||||||
|
Has: func() bool {
|
||||||
|
return flag&1 != 0
|
||||||
|
},
|
||||||
|
Field: &data,
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output: Tnze
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleTuple_ReadFrom() {
|
||||||
|
// When you need to read an "Optional Array of X":
|
||||||
|
var has pk.Boolean
|
||||||
|
var arylen pk.Int
|
||||||
|
var ary []pk.String
|
||||||
|
|
||||||
|
var p pk.Packet // = conn.ReadPacket()
|
||||||
|
if err := p.Scan(
|
||||||
|
&has,
|
||||||
|
pk.Opt{
|
||||||
|
Has: &has,
|
||||||
|
Field: pk.Tuple{
|
||||||
|
&arylen,
|
||||||
|
pk.Ary{
|
||||||
|
Len: &arylen,
|
||||||
|
Ary: &ary,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user