Skip to content

Commit

Permalink
Added direct insertion of a byte array, instead of reading one byte a…
Browse files Browse the repository at this point in the history
…t a time.
  • Loading branch information
ghostiam committed Apr 3, 2024
1 parent 09ba9cd commit 54308c8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
10 changes: 10 additions & 0 deletions binstruct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,3 +891,13 @@ func Test_LeAndBeInOneStruct(t *testing.T) {
require.NoError(t, err)
require.Equal(t, wantBE, actual)
}

func Test_sliceSkipWithoutPanic(t *testing.T) {
var v struct {
_ []int8 `bin:"len:2"`
I int32
}
err := UnmarshalBE([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, &v)
require.NoError(t, err)
require.Equal(t, int32(0x02030405), v.I)
}
3 changes: 2 additions & 1 deletion example02_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"

"github.com/davecgh/go-spew/spew"

"github.com/ghostiam/binstruct"
)

Expand Down Expand Up @@ -146,7 +147,7 @@ func Example_decodeCustom() {
// },
// TypeLen: (int16) 4,
// Type: (string) (len=4) "test",
// B: ([]uint8) (len=3 cap=4) {
// B: ([]uint8) (len=3 cap=3) {
// 00000000 68 69 21 |hi!|
// }
// }
Expand Down
64 changes: 44 additions & 20 deletions unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ func (u *unmarshal) unmarshal(v interface{}, parentStructValues []reflect.Value)
return nil
}

func (u *unmarshal) setValueToField(structValue, fieldValue reflect.Value, fieldData *fieldReadData, parentStructValues []reflect.Value) error {
func (u *unmarshal) setValueToField(
structValue, fieldValue reflect.Value, fieldData *fieldReadData, parentStructValues []reflect.Value,
) error {
if fieldData == nil {
fieldData = &fieldReadData{}
}
Expand Down Expand Up @@ -239,37 +241,42 @@ or
return errors.New("need set tag with len for slice")
}

for i := int64(0); i < *fieldData.Length; i++ {
tmpV := reflect.New(fieldValue.Type().Elem()).Elem()
err = u.setValueToField(structValue, tmpV, fieldData.ElemFieldData, parentStructValues)
arrLen := int(*fieldData.Length)

// If slice of bytes, read bytes and set to slice.
if fieldValue.Type().Elem().Kind() == reflect.Uint8 {
n, b, err := u.r.ReadBytes(arrLen)
if err != nil {
return err
}

if n != arrLen {
return fmt.Errorf("expected %d, got %d", *fieldData.Length, n)
}

if fieldValue.CanSet() {
fieldValue.Set(reflect.Append(fieldValue, tmpV))
fieldValue.SetBytes(b)
}

return nil
}

if fieldValue.CanSet() {
// Create slice before populate.
fieldValue.Set(reflect.MakeSlice(fieldValue.Type(), arrLen, arrLen))
}

return u.setArrayValueToField(arrLen, structValue, fieldValue, fieldData, parentStructValues)

case reflect.Array:
var arrLen int64
arrLen := fieldValue.Len()

if fieldData.Length != nil {
arrLen = *fieldData.Length
arrLen = int(*fieldData.Length)
}

if arrLen == 0 {
arrLen = int64(fieldValue.Len())
}
return u.setArrayValueToField(arrLen, structValue, fieldValue, fieldData, parentStructValues)

for i := int64(0); i < arrLen; i++ {
tmpV := reflect.New(fieldValue.Type().Elem()).Elem()
err = u.setValueToField(structValue, tmpV, fieldData.ElemFieldData, parentStructValues)
if err != nil {
return err
}
if fieldValue.CanSet() {
fieldValue.Index(int(i)).Set(tmpV)
}
}
case reflect.Struct:
err = u.unmarshal(fieldValue.Addr().Interface(), append(parentStructValues, structValue))
if err != nil {
Expand All @@ -282,6 +289,23 @@ or
return nil
}

func (u *unmarshal) setArrayValueToField(
arrLen int, structValue, fieldValue reflect.Value, fieldData *fieldReadData, parentStructValues []reflect.Value,
) error {
for i := 0; i < arrLen; i++ {
tmpV := reflect.New(fieldValue.Type().Elem()).Elem()
err := u.setValueToField(structValue, tmpV, fieldData.ElemFieldData, parentStructValues)
if err != nil {
return err
}
if fieldValue.CanSet() {
fieldValue.Index(i).Set(tmpV)
}
}

return nil
}

func callFunc(r Reader, funcName string, structValue, fieldValue reflect.Value) (bool, error) {
// Call methods
m := structValue.Addr().MethodByName(funcName)
Expand Down

0 comments on commit 54308c8

Please sign in to comment.