Skip to content

Commit

Permalink
add decoding implementation for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
siscia committed Mar 8, 2022
1 parent 8b84116 commit 8c2c58c
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions ua/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ func decode(b []byte, val reflect.Value, name string) (n int, err error) {
val.SetString(buf.ReadString())
case reflect.Slice:
return decodeSlice(b, val, name)
case reflect.Array:
return decodeArray(b, val, name)
case reflect.Ptr:
return decode(b, val.Elem(), name)
case reflect.Struct:
Expand Down Expand Up @@ -163,3 +165,50 @@ func decodeSlice(b []byte, val reflect.Value, name string) (int, error) {

return pos, nil
}

func decodeArray(b []byte, val reflect.Value, name string) (int, error) {
buf := NewBuffer(b)
n := buf.ReadUint32()
if buf.Error() != nil {
return buf.Pos(), buf.Error()
}

if n == null {
return buf.Pos(), nil
}

if n > math.MaxInt32 {
return buf.Pos(), errors.Errorf("array too large: %d", n)
}

if n > uint32(val.Len()) {
return buf.Pos(), errors.Errorf("array too large, it does not fit into the type: encoded array len = %d, array len = %d", n, val.Len())
}

// elemType is the type of the slice elements
// e.g. *Foo for []*Foo
elemType := val.Type().Elem()
// fmt.Println("elemType: ", elemType.String())

pos := buf.Pos()
// a is a pointer to an array [n]*Foo, where n is know at compile time
a := reflect.New(val.Type()).Elem()
for i := 0; i < int(n); i++ {

// if the slice elements are pointers we need to create
// them before we can marshal data into them.
if elemType.Kind() == reflect.Ptr {
a.Index(i).Set(reflect.New(elemType.Elem()))
}

ename := fmt.Sprintf("%s[%d]", name, i)
m, err := decode(b[pos:], a.Index(i), ename)
if err != nil {
return pos, err
}
pos += m
}
val.Set(a)

return pos, nil
}

0 comments on commit 8c2c58c

Please sign in to comment.