You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.5 KiB
Go

package codec
import (
"bytes"
"encoding/binary"
"reflect"
"github.com/noahlann/nnet/pkg/codec"
)
// BinaryCodec 二进制编解码器
type BinaryCodec struct {
byteOrder binary.ByteOrder
}
// NewBinaryCodec 创建二进制编解码器
func NewBinaryCodec() codec.Codec {
return &BinaryCodec{
byteOrder: binary.BigEndian,
}
}
// NewBinaryCodecWithByteOrder 使用指定的字节序创建二进制编解码器
func NewBinaryCodecWithByteOrder(byteOrder binary.ByteOrder) codec.Codec {
return &BinaryCodec{
byteOrder: byteOrder,
}
}
// Encode 编码
func (c *BinaryCodec) Encode(v interface{}) ([]byte, error) {
buf := new(bytes.Buffer)
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if err := binary.Write(buf, c.byteOrder, rv.Interface()); err != nil {
return nil, err
}
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if err := binary.Write(buf, c.byteOrder, rv.Interface()); err != nil {
return nil, err
}
case reflect.Slice:
if rv.Type().Elem().Kind() == reflect.Uint8 {
// byte slice
return rv.Bytes(), nil
}
// 其他类型的slice需要特殊处理
return nil, codec.NewError("unsupported slice type")
case reflect.Array:
if rv.Type().Elem().Kind() == reflect.Uint8 {
// byte array
result := make([]byte, rv.Len())
reflect.Copy(reflect.ValueOf(result), rv)
return result, nil
}
return nil, codec.NewError("unsupported array type")
default:
return nil, codec.NewError("unsupported type: " + rv.Kind().String())
}
return buf.Bytes(), nil
}
// Decode 解码
func (c *BinaryCodec) Decode(data []byte, v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return codec.NewError("decode target must be a pointer")
}
rv = rv.Elem()
buf := bytes.NewReader(data)
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if err := binary.Read(buf, c.byteOrder, v); err != nil {
return err
}
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if err := binary.Read(buf, c.byteOrder, v); err != nil {
return err
}
case reflect.Slice:
if rv.Type().Elem().Kind() == reflect.Uint8 {
// byte slice
rv.SetBytes(data)
return nil
}
return codec.NewError("unsupported slice type")
default:
return codec.NewError("unsupported type: " + rv.Kind().String())
}
return nil
}
// Name 获取编解码器名称
func (c *BinaryCodec) Name() string {
return "binary"
}