Partly implemented ShortVec
This commit is contained in:
parent
d0cb5433d3
commit
1b77746a25
121
nativetypes.go
121
nativetypes.go
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue