mirror of
https://github.com/chaisql/chai.git
synced 2025-10-07 08:30:52 +08:00
111 lines
2.2 KiB
Go
111 lines
2.2 KiB
Go
package encoding
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
"github.com/chaisql/chai/internal/object"
|
|
"github.com/chaisql/chai/internal/types"
|
|
)
|
|
|
|
func EncodeArray(dst []byte, a types.Array) ([]byte, error) {
|
|
if a == nil {
|
|
dst = EncodeArrayLength(dst, 0)
|
|
return dst, nil
|
|
}
|
|
|
|
l, err := object.ArrayLength(a)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if l == 0 {
|
|
return append(dst, byte(ArrayValue), 0), nil
|
|
}
|
|
|
|
dst = EncodeArrayLength(dst, l)
|
|
|
|
err = a.Iterate(func(i int, value types.Value) error {
|
|
dst, err = EncodeValue(dst, value, false)
|
|
return err
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return dst, nil
|
|
}
|
|
|
|
func EncodeArrayLength(dst []byte, l int) []byte {
|
|
// encode the length as a varint
|
|
buf := make([]byte, binary.MaxVarintLen64+1)
|
|
buf[0] = ArrayValue
|
|
n := binary.PutUvarint(buf[1:], uint64(l))
|
|
return append(dst, buf[:n+1]...)
|
|
}
|
|
|
|
func DecodeArray(b []byte, intAsDouble bool) types.Array {
|
|
return &EncodedArray{
|
|
enc: b[1:],
|
|
intAsDouble: intAsDouble,
|
|
}
|
|
}
|
|
|
|
// An EncodedArray implements the types.Array interface on top of an
|
|
// encoded representation of an array.
|
|
// It is useful for avoiding decoding the entire array when
|
|
// only a few values are needed.
|
|
type EncodedArray struct {
|
|
enc []byte
|
|
intAsDouble bool
|
|
}
|
|
|
|
// Iterate goes through all the values of the array and calls the
|
|
// given function by passing each one of them.
|
|
// If the given function returns an error, the iteration stops.
|
|
func (e *EncodedArray) Iterate(fn func(i int, value types.Value) error) error {
|
|
l, n := binary.Uvarint(e.enc)
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
b := e.enc[n:]
|
|
|
|
ll := int(l)
|
|
for i := 0; i < ll; i++ {
|
|
v, n := DecodeValue(b, e.intAsDouble)
|
|
b = b[n:]
|
|
|
|
err := fn(i, v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetByIndex returns a value by index of the array.
|
|
func (e *EncodedArray) GetByIndex(idx int) (v types.Value, err error) {
|
|
l, n := binary.Uvarint(e.enc)
|
|
if l == 0 {
|
|
return nil, types.ErrValueNotFound
|
|
}
|
|
b := e.enc[n:]
|
|
|
|
ll := int(l)
|
|
for i := 0; i < ll; i++ {
|
|
if i == idx {
|
|
v, _ := DecodeValue(b, e.intAsDouble)
|
|
return v, nil
|
|
}
|
|
|
|
n = Skip(b)
|
|
b = b[n:]
|
|
}
|
|
|
|
err = types.ErrValueNotFound
|
|
return
|
|
}
|
|
|
|
func (e *EncodedArray) MarshalJSON() ([]byte, error) {
|
|
return object.MarshalJSONArray(e)
|
|
}
|