Partly implemented ShortVec

This commit is contained in:
Alexandre Bourget 2020-08-05 15:25:43 -04:00
parent d0cb5433d3
commit 1b77746a25
2 changed files with 151 additions and 0 deletions

View File

@ -1,11 +1,14 @@
package solana
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io"
"strconv"
"github.com/lunixbochs/struc"
"github.com/mr-tron/base58"
)
@ -177,3 +180,121 @@ func (i *U64) UnmarshalJSON(data []byte) error {
return nil
}
///
type ByteWrapper struct {
io.Reader
}
func (w *ByteWrapper) ReadByte() (byte, error) {
var b [1]byte
_, err := w.Read(b[:])
return b[0], err
}
/// ShortVec
type ShortVec uint16
func (v ShortVec) Pack(p []byte, opt *struc.Options) (int, error) {
// JAVASCRIPT
// let rem_len = len;
// for (;;) {
// let elem = rem_len & 0x7f;
// rem_len >>= 7;
// if (rem_len == 0) {
// bytes.push(elem);
// break;
// } else {
// elem |= 0x80;
// bytes.push(elem);
// }
// }
// RUST
// // Pass a non-zero value to serialize_tuple() so that serde_json will
// // generate an open bracket.
// let mut seq = serializer.serialize_tuple(1)?;
// let mut rem_len = self.0;
// loop {
// let mut elem = (rem_len & 0x7f) as u8;
// rem_len >>= 7;
// if rem_len == 0 {
// seq.serialize_element(&elem)?;
// break;
// } else {
// elem |= 0x80;
// seq.serialize_element(&elem)?;
// }
// }
// seq.end()
return 0, nil
}
func (v *ShortVec) Unpack(r io.Reader, length int, opt *struc.Options) error {
var l, s int
for {
// JAVASCRIPT
// let elem = bytes.shift();
// len |= (elem & 0x7f) << (size * 7);
// size += 1;
// if ((elem & 0x80) === 0) {
// break;
// }
}
// RUST
// let mut len: usize = 0;
// let mut size: usize = 0;
// loop {
// let elem: u8 = seq
// .next_element()?
// .ok_or_else(|| de::Error::invalid_length(size, &self))?;
// len |= (elem as usize & 0x7f) << (size * 7);
// size += 1;
// if elem as usize & 0x80 == 0 {
// break;
// }
// if size > size_of::<u16>() + 1 {
// return Err(de::Error::invalid_length(size, &self));
// }
// }
// Ok(ShortU16(len as u16))
// TODO: have a func that would return `size` also, separately? called twice?
return nil
}
func (v *ShortVec) Size(opt *struc.Options) int {
var buf [8]byte
return binary.PutUvarint(buf[:], uint64(*v))
}
func (v *ShortVec) String() string {
return strconv.FormatUint(uint64(*v), 10)
}
var shortVecOverflow = errors.New("short_vec: varint overflows a 16-bit integer")
func readShortVec(r io.ByteReader) (uint64, error) {
var x uint64
var s uint
for i := 0; ; i++ {
b, err := r.ReadByte()
if err != nil {
return x, err
}
if b < 0x80 {
if i > 4 || i == 4 && b > 1 {
return x, shortVecOverflow
}
return x | uint64(b)<<s, nil
}
x |= uint64(b&0x7f) << s
s += 7
}
}

30
nativetypes_test.go Normal file
View File

@ -0,0 +1,30 @@
package solana
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestShortVec(t *testing.T) {
tests := []struct {
input uint16
expect []byte
}{
{input: 0x0, expect: []byte{0x0}},
}
for idx, test := range tests {
t.Run(fmt.Sprintf("%d", idx+1), func(t *testing.T) {
el := ShortVec(test.input)
b := make([]byte, 3)
size, err := el.Pack(b, nil)
require.NoError(t, err)
assert.Equal(t, test.expect, b[:size])
})
}
}