Skip to content

Commit

Permalink
binary: Move varint utils to new package
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Jun 23, 2024
1 parent a31dba8 commit 53e8bec
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 81 deletions.
18 changes: 18 additions & 0 deletions common/binary/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package binary

import (
"encoding/binary"
"reflect"
)

func DataSize(t reflect.Value) int {
return dataSize(t)
}

func EncodeValue(order binary.ByteOrder, buf []byte, v reflect.Value) {
(&encoder{order: order, buf: buf}).value(v)
}

func DecodeValue(order binary.ByteOrder, buf []byte, v reflect.Value) {
(&decoder{order: order, buf: buf}).value(v)
}
138 changes: 63 additions & 75 deletions common/binary/varint_data.go → common/varbin/data.go
Original file line number Diff line number Diff line change
@@ -1,57 +1,48 @@
package binary
package varbin

import (
"errors"
"io"
"reflect"

"github.com/sagernet/sing/common/binary"
E "github.com/sagernet/sing/common/exceptions"
)

type Reader interface {
io.Reader
io.ByteReader
}

type Writer interface {
io.Writer
io.ByteWriter
}

func ReadData(r Reader, order ByteOrder, rawData any) error {
func Read(r Reader, order binary.ByteOrder, rawData any) error {
switch data := rawData.(type) {
case *[]bool:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]int8:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]uint8:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]int16:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]uint16:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]int32:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]uint32:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]int64:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]uint64:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]float32:
return readBaseData(r, order, data)
return readBase(r, order, data)
case *[]float64:
return readBaseData(r, order, data)
return readBase(r, order, data)
default:
if intBaseDataSize(rawData) != 0 {
return Read(r, order, rawData)
return binary.Read(r, order, rawData)
}
}
return readData(r, order, reflect.Indirect(reflect.ValueOf(rawData)))
return read(r, order, reflect.Indirect(reflect.ValueOf(rawData)))
}

func readBaseData[T any](r Reader, order ByteOrder, data *[]T) error {
dataLen, err := ReadUvarint(r)
func readBase[T any](r Reader, order binary.ByteOrder, data *[]T) error {
dataLen, err := binary.ReadUvarint(r)
if err != nil {
return E.Cause(err, "slice length")
}
Expand All @@ -60,15 +51,15 @@ func readBaseData[T any](r Reader, order ByteOrder, data *[]T) error {
return nil
}
dataSlices := make([]T, dataLen)
err = Read(r, order, dataSlices)
err = binary.Read(r, order, dataSlices)
if err != nil {
return err
}
*data = dataSlices
return nil
}

func readData(r Reader, order ByteOrder, data reflect.Value) error {
func read(r Reader, order binary.ByteOrder, data reflect.Value) error {
switch data.Kind() {
case reflect.Pointer:
pointerValue, err := r.ReadByte()
Expand All @@ -82,9 +73,9 @@ func readData(r Reader, order ByteOrder, data reflect.Value) error {
if data.IsNil() {
data.Set(reflect.New(data.Type().Elem()))
}
return readData(r, order, data.Elem())
return read(r, order, data.Elem())
case reflect.String:
stringLength, err := ReadUvarint(r)
stringLength, err := binary.ReadUvarint(r)
if err != nil {
return E.Cause(err, "string length")
}
Expand All @@ -100,25 +91,24 @@ func readData(r Reader, order ByteOrder, data reflect.Value) error {
}
case reflect.Array:
arrayLen := data.Len()
itemSize := sizeof(data.Type())
itemSize := data.Type().Elem().Len()
if itemSize > 0 {
buf := make([]byte, itemSize*arrayLen)
_, err := io.ReadFull(r, buf)
if err != nil {
return err
}
d := &decoder{order: order, buf: buf}
d.value(data)
binary.DecodeValue(order, buf, data)
} else {
for i := 0; i < arrayLen; i++ {
err := readData(r, order, data.Index(i))
err := read(r, order, data.Index(i))
if err != nil {
return E.Cause(err, "[", i, "]")
}
}
}
case reflect.Slice:
sliceLength, err := ReadUvarint(r)
sliceLength, err := binary.ReadUvarint(r)
if err != nil {
return E.Cause(err, "slice length")
}
Expand All @@ -127,7 +117,7 @@ func readData(r Reader, order ByteOrder, data reflect.Value) error {
} else {
dataSlices := makeBaseDataSlices(data, int(sliceLength))
if dataSlices != nil {
err = Read(r, order, dataSlices)
err = binary.Read(r, order, dataSlices)
if err != nil {
return err
}
Expand All @@ -139,27 +129,27 @@ func readData(r Reader, order ByteOrder, data reflect.Value) error {
data.Set(reflect.MakeSlice(data.Type(), int(sliceLength), int(sliceLength)))
}
for i := 0; i < int(sliceLength); i++ {
err = readData(r, order, data.Index(i))
err = read(r, order, data.Index(i))
if err != nil {
return E.Cause(err, "[", i, "]")
}
}
}
}
case reflect.Map:
mapLength, err := ReadUvarint(r)
mapLength, err := binary.ReadUvarint(r)
if err != nil {
return E.Cause(err, "map length")
}
data.Set(reflect.MakeMap(data.Type()))
for index := 0; index < int(mapLength); index++ {
key := reflect.New(data.Type().Key()).Elem()
err = readData(r, order, key)
err = read(r, order, key)
if err != nil {
return E.Cause(err, "[", index, "].key")
}
value := reflect.New(data.Type().Elem()).Elem()
err = readData(r, order, value)
err = read(r, order, value)
if err != nil {
return E.Cause(err, "[", index, "].value")
}
Expand All @@ -172,71 +162,71 @@ func readData(r Reader, order ByteOrder, data reflect.Value) error {
field := data.Field(i)
fieldName := fieldType.Field(i).Name
if field.CanSet() || fieldName != "_" {
err := readData(r, order, field)
err := read(r, order, field)
if err != nil {
return E.Cause(err, fieldName)
}
}
}
default:
size := dataSize(data)
size := binary.DataSize(data)
if size < 0 {
return errors.New("invalid type " + reflect.TypeOf(data).String())
}
d := &decoder{order: order, buf: make([]byte, size)}
_, err := io.ReadFull(r, d.buf)
buf := make([]byte, size)
_, err := io.ReadFull(r, buf)
if err != nil {
return err
}
d.value(data)
binary.DecodeValue(order, buf, data)
}
return nil
}

func WriteData(writer Writer, order ByteOrder, rawData any) error {
func Write(writer Writer, order binary.ByteOrder, rawData any) error {
switch data := rawData.(type) {
case []bool:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []int8:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []uint8:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []int16:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []uint16:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []int32:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []uint32:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []int64:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []uint64:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []float32:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
case []float64:
return writeBaseData(writer, order, data)
return writeBase(writer, order, data)
default:
if intBaseDataSize(rawData) != 0 {
return Write(writer, order, rawData)
return binary.Write(writer, order, rawData)
}
}
return writeData(writer, order, reflect.Indirect(reflect.ValueOf(rawData)))
return write(writer, order, reflect.Indirect(reflect.ValueOf(rawData)))
}

func writeBaseData[T any](writer Writer, order ByteOrder, data []T) error {
func writeBase[T any](writer Writer, order binary.ByteOrder, data []T) error {
_, err := WriteUvarint(writer, uint64(len(data)))
if err != nil {
return err
}
if len(data) > 0 {
return Write(writer, order, data)
return binary.Write(writer, order, data)
}
return nil
}

func writeData(writer Writer, order ByteOrder, data reflect.Value) error {
func write(writer Writer, order binary.ByteOrder, data reflect.Value) error {
switch data.Kind() {
case reflect.Pointer:
if data.IsNil() {
Expand All @@ -249,7 +239,7 @@ func writeData(writer Writer, order ByteOrder, data reflect.Value) error {
if err != nil {
return err
}
return writeData(writer, order, data.Elem())
return write(writer, order, data.Elem())
}
case reflect.String:
stringValue := data.String()
Expand All @@ -269,15 +259,14 @@ func writeData(writer Writer, order ByteOrder, data reflect.Value) error {
itemSize := intItemBaseDataSize(data)
if itemSize > 0 {
buf := make([]byte, itemSize*dataLen)
e := &encoder{order: order, buf: buf}
e.value(data)
binary.EncodeValue(order, buf, data)
_, err := writer.Write(buf)
if err != nil {
return E.Cause(err, reflect.TypeOf(data).String())
}
} else {
for i := 0; i < dataLen; i++ {
err := writeData(writer, order, data.Index(i))
err := write(writer, order, data.Index(i))
if err != nil {
return E.Cause(err, "[", i, "]")
}
Expand All @@ -293,13 +282,13 @@ func writeData(writer Writer, order ByteOrder, data reflect.Value) error {
if dataLen > 0 {
dataSlices := baseDataSlices(data)
if dataSlices != nil {
err = Write(writer, order, dataSlices)
err = binary.Write(writer, order, dataSlices)
if err != nil {
return err
}
} else {
for i := 0; i < dataLen; i++ {
err = writeData(writer, order, data.Index(i))
err = write(writer, order, data.Index(i))
if err != nil {
return E.Cause(err, "[", i, "]")
}
Expand All @@ -314,11 +303,11 @@ func writeData(writer Writer, order ByteOrder, data reflect.Value) error {
}
if dataLen > 0 {
for index, key := range data.MapKeys() {
err = writeData(writer, order, key)
err = write(writer, order, key)
if err != nil {
return E.Cause(err, "[", index, "].key")
}
err = writeData(writer, order, data.MapIndex(key))
err = write(writer, order, data.MapIndex(key))
if err != nil {
return E.Cause(err, "[", index, "].value")
}
Expand All @@ -331,20 +320,19 @@ func writeData(writer Writer, order ByteOrder, data reflect.Value) error {
field := data.Field(i)
fieldName := fieldType.Field(i).Name
if field.CanSet() || fieldName != "_" {
err := writeData(writer, order, field)
err := write(writer, order, field)
if err != nil {
return E.Cause(err, fieldName)
}
}
}
default:
size := dataSize(data)
size := binary.DataSize(data)
if size < 0 {
return errors.New("binary.Write: some values are not fixed-sized in type " + data.Type().String())
}
buf := make([]byte, size)
e := &encoder{order: order, buf: buf}
e.value(data)
binary.EncodeValue(order, buf, data)
_, err := writer.Write(buf)
if err != nil {
return E.Cause(err, reflect.TypeOf(data).String())
Expand Down
Loading

0 comments on commit 53e8bec

Please sign in to comment.