Skip to content

Commit

Permalink
varbin: Unique pointer value format for array or map value
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Jun 24, 2024
1 parent 4745c34 commit 0b4c0a1
Showing 1 changed file with 37 additions and 29 deletions.
66 changes: 37 additions & 29 deletions common/varbin/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func Read(r io.Reader, order binary.ByteOrder, rawData any) error {
return binary.Read(reader, order, rawData)
}
}
return read(reader, order, reflect.Indirect(reflect.ValueOf(rawData)))
return read(reader, order, reflect.Indirect(reflect.ValueOf(rawData)), false)
}

func ReadValue[T any](r io.Reader, order binary.ByteOrder) (T, error) {
Expand Down Expand Up @@ -72,21 +72,23 @@ func readBase[T any](r Reader, order binary.ByteOrder, data *[]T) error {
return nil
}

func read(r Reader, order binary.ByteOrder, data reflect.Value) error {
func read(r Reader, order binary.ByteOrder, data reflect.Value, isArrayMapValue bool) error {
switch data.Kind() {
case reflect.Pointer:
pointerValue, err := r.ReadByte()
if err != nil {
return err
}
if pointerValue == 0 {
data.SetZero()
return nil
if !isArrayMapValue {
pointerValue, err := r.ReadByte()
if err != nil {
return err
}
if pointerValue == 0 {
data.SetZero()
return nil
}
}
if data.IsNil() {
data.Set(reflect.New(data.Type().Elem()))
}
return read(r, order, data.Elem())
return read(r, order, data.Elem(), false)
case reflect.String:
stringLength, err := binary.ReadUvarint(r)
if err != nil {
Expand Down Expand Up @@ -114,7 +116,7 @@ func read(r Reader, order binary.ByteOrder, data reflect.Value) error {
binary.DecodeValue(order, buf, data)
} else {
for i := 0; i < arrayLen; i++ {
err := read(r, order, data.Index(i))
err := read(r, order, data.Index(i), true)
if err != nil {
return E.Cause(err, "[", i, "]")
}
Expand Down Expand Up @@ -147,7 +149,7 @@ func read(r Reader, order binary.ByteOrder, data reflect.Value) error {
data.Set(reflect.MakeSlice(data.Type(), itemLength, itemLength))
}
for i := 0; i < itemLength; i++ {
err := read(r, order, data.Index(i))
err := read(r, order, data.Index(i), true)
if err != nil {
return E.Cause(err, "[", i, "]")
}
Expand All @@ -162,12 +164,12 @@ func read(r Reader, order binary.ByteOrder, data reflect.Value) error {
data.Set(reflect.MakeMap(data.Type()))
for index := 0; index < int(mapLength); index++ {
key := reflect.New(data.Type().Key()).Elem()
err = read(r, order, key)
err = read(r, order, key, false)
if err != nil {
return E.Cause(err, "[", index, "].key")
}
value := reflect.New(data.Type().Elem()).Elem()
err = read(r, order, value)
err = read(r, order, value, true)
if err != nil {
return E.Cause(err, "[", index, "].value")
}
Expand All @@ -180,7 +182,7 @@ func read(r Reader, order binary.ByteOrder, data reflect.Value) error {
field := data.Field(i)
fieldName := fieldType.Field(i).Name
if field.CanSet() || fieldName != "_" {
err := read(r, order, field)
err := read(r, order, field, false)
if err != nil {
return E.Cause(err, fieldName)
}
Expand Down Expand Up @@ -239,7 +241,7 @@ func Write(w io.Writer, order binary.ByteOrder, rawData any) error {
case []float64:
return writeBase(writer, order, data)
}
err := write(writer, order, reflect.Indirect(reflect.ValueOf(rawData)))
err := write(writer, order, reflect.Indirect(reflect.ValueOf(rawData)), false)
if err != nil {
return err
}
Expand All @@ -263,20 +265,26 @@ func writeBase[T any](writer Writer, order binary.ByteOrder, data []T) error {
return nil
}

func write(writer Writer, order binary.ByteOrder, data reflect.Value) error {
func write(writer Writer, order binary.ByteOrder, data reflect.Value, isArrayOrMapValue bool) error {
switch data.Kind() {
case reflect.Pointer:
if data.IsNil() {
err := writer.WriteByte(0)
if err != nil {
return err
if isArrayOrMapValue {
return E.New("nil array or map value")
} else {
err := writer.WriteByte(0)
if err != nil {
return err
}
}
} else {
err := writer.WriteByte(1)
if err != nil {
return err
if !isArrayOrMapValue {
err := writer.WriteByte(1)
if err != nil {
return err
}
}
return write(writer, order, data.Elem())
return write(writer, order, data.Elem(), false)
}
case reflect.String:
stringValue := data.String()
Expand All @@ -303,7 +311,7 @@ func write(writer Writer, order binary.ByteOrder, data reflect.Value) error {
}
} else {
for i := 0; i < dataLen; i++ {
err := write(writer, order, data.Index(i))
err := write(writer, order, data.Index(i), true)
if err != nil {
return E.Cause(err, "[", i, "]")
}
Expand All @@ -325,7 +333,7 @@ func write(writer Writer, order binary.ByteOrder, data reflect.Value) error {
}
} else {
for i := 0; i < dataLen; i++ {
err = write(writer, order, data.Index(i))
err = write(writer, order, data.Index(i), true)
if err != nil {
return E.Cause(err, "[", i, "]")
}
Expand All @@ -340,11 +348,11 @@ func write(writer Writer, order binary.ByteOrder, data reflect.Value) error {
}
if dataLen > 0 {
for index, key := range data.MapKeys() {
err = write(writer, order, key)
err = write(writer, order, key, false)
if err != nil {
return E.Cause(err, "[", index, "].key")
}
err = write(writer, order, data.MapIndex(key))
err = write(writer, order, data.MapIndex(key), true)
if err != nil {
return E.Cause(err, "[", index, "].value")
}
Expand All @@ -357,7 +365,7 @@ func write(writer Writer, order binary.ByteOrder, data reflect.Value) error {
field := data.Field(i)
fieldName := fieldType.Field(i).Name
if field.CanSet() || fieldName != "_" {
err := write(writer, order, field)
err := write(writer, order, field, false)
if err != nil {
return E.Cause(err, fieldName)
}
Expand Down

0 comments on commit 0b4c0a1

Please sign in to comment.