Partly implemented ShortVec
This commit is contained in:
parent
d0cb5433d3
commit
1b77746a25
121
nativetypes.go
121
nativetypes.go
|
@ -1,11 +1,14 @@
|
||||||
package solana
|
package solana
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/lunixbochs/struc"
|
||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -177,3 +180,121 @@ func (i *U64) UnmarshalJSON(data []byte) error {
|
||||||
|
|
||||||
return nil
|
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