Compare commits
No commits in common. "a05c0343133f49393087c7502379fea118985ee4" and "dd5e7e96d5262c529e0f3c81e589befca56cd614" have entirely different histories.
a05c034313
...
dd5e7e96d5
@ -10,7 +10,6 @@ const uint16Max = 0xFFFF
|
|||||||
type Error string; const (
|
type Error string; const (
|
||||||
ErrWrongBufferLength Error = "wrong buffer length"
|
ErrWrongBufferLength Error = "wrong buffer length"
|
||||||
ErrDataTooLarge Error = "data too large"
|
ErrDataTooLarge Error = "data too large"
|
||||||
ErrGBEUNotTerminated Error = "GBEU not terminated"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error implements the error interface.
|
// Error implements the error interface.
|
||||||
@ -26,8 +25,6 @@ type Int16 interface { ~uint16 | ~int16 }
|
|||||||
type Int32 interface { ~uint32 | ~int32 }
|
type Int32 interface { ~uint32 | ~int32 }
|
||||||
// Int64 is any 64-bit integer.
|
// Int64 is any 64-bit integer.
|
||||||
type Int64 interface { ~uint64 | ~int64 }
|
type Int64 interface { ~uint64 | ~int64 }
|
||||||
// UInt is any unsigned integer.
|
|
||||||
type UInt interface { ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 }
|
|
||||||
// String is any string.
|
// String is any string.
|
||||||
type String interface { ~string }
|
type String interface { ~string }
|
||||||
|
|
||||||
@ -104,50 +101,6 @@ func EncodeI64[T Int64](buffer []byte, value T) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeGBEU decodes an 8 to 64 bit growing integer into the given buffer.
|
|
||||||
func DecodeGBEU[T UInt](data []byte) (T, error) {
|
|
||||||
var value uint64
|
|
||||||
for _, chunk := range data {
|
|
||||||
value *= 0x80
|
|
||||||
value += uint64(chunk & 0x7F)
|
|
||||||
ccb := chunk >> 7
|
|
||||||
if ccb == 0 {
|
|
||||||
return T(value), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("decoding GBEU: %w", ErrGBEUNotTerminated)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeGBEU encodes an 8 to 64 bit growing integer into a given buffer.
|
|
||||||
func EncodeGBEU[T UInt] (buffer []byte, value T) (error) {
|
|
||||||
window := (GBEUSize(value) - 1) * 7
|
|
||||||
|
|
||||||
index := 0
|
|
||||||
for window >= 0 {
|
|
||||||
if index >= len(buffer) { return fmt.Errorf("encoding GBEU: %w", ErrWrongBufferLength) }
|
|
||||||
|
|
||||||
chunk := uint8(value >> window) & 0x7F
|
|
||||||
if window > 0 {
|
|
||||||
chunk |= 0x80
|
|
||||||
}
|
|
||||||
buffer[index] = chunk
|
|
||||||
|
|
||||||
index += 1
|
|
||||||
window -= 7
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GBEUSize returns the size (in octets) of a GBEU integer.
|
|
||||||
func GBEUSize[T UInt] (value T) int {
|
|
||||||
length := 0
|
|
||||||
for {
|
|
||||||
value >>= 7
|
|
||||||
length ++
|
|
||||||
if value == 0 { return length }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeString decodes a string from the given data.
|
// DecodeString decodes a string from the given data.
|
||||||
func DecodeString[T String](data []byte) (T, error) {
|
func DecodeString[T String](data []byte) (T, error) {
|
||||||
return T(data), nil
|
return T(data), nil
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package tape
|
package tape
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "slices"
|
import "slices"
|
||||||
import "errors"
|
import "errors"
|
||||||
import "testing"
|
import "testing"
|
||||||
@ -100,114 +99,6 @@ func TestI64(test *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGBEU(test *testing.T) {
|
|
||||||
var buffer = [16]byte {
|
|
||||||
255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255,
|
|
||||||
255, 255, 255, 255,
|
|
||||||
}
|
|
||||||
err := EncodeGBEU[uint64](buffer[:0], 5)
|
|
||||||
if err == nil { test.Fatal("no error") }
|
|
||||||
if err.Error() != "encoding GBEU: wrong buffer length" { test.Fatal(err) }
|
|
||||||
err = EncodeGBEU[uint64](buffer[:2], 5555555)
|
|
||||||
if err == nil { test.Fatal("no error") }
|
|
||||||
if err.Error() != "encoding GBEU: wrong buffer length" { test.Fatal(err) }
|
|
||||||
_, err = DecodeGBEU[uint64](buffer[:0])
|
|
||||||
if err == nil { test.Fatal("no error") }
|
|
||||||
if err.Error() != "decoding GBEU: GBEU not terminated" { test.Fatal(err) }
|
|
||||||
|
|
||||||
err = EncodeGBEU[uint64](buffer[:], 0x97)
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := []byte { 0x81, 0x17 }, buffer[:2]; !slices.Equal(correct, got) {
|
|
||||||
message := "not equal:"
|
|
||||||
for _, item := range got {
|
|
||||||
message = fmt.Sprintf("%s %x", message, item)
|
|
||||||
}
|
|
||||||
test.Fatal(message)
|
|
||||||
}
|
|
||||||
decoded, err := DecodeGBEU[uint64](buffer[:])
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := uint64(0x97), decoded; correct != got {
|
|
||||||
test.Fatalf("not equal: %x", got)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = EncodeGBEU[uint64](buffer[:], 0x123456)
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := []byte { 0xc8, 0xe8, 0x56 }, buffer[:3]; !slices.Equal(correct, got) {
|
|
||||||
message := "not equal:"
|
|
||||||
for _, item := range got {
|
|
||||||
message = fmt.Sprintf("%s %x", message, item)
|
|
||||||
}
|
|
||||||
test.Fatal(message)
|
|
||||||
}
|
|
||||||
decoded, err = DecodeGBEU[uint64](buffer[:])
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := uint64(0x123456), decoded; correct != got {
|
|
||||||
test.Fatalf("not equal: %x", got)
|
|
||||||
}
|
|
||||||
|
|
||||||
maxGBEU64 := []byte { 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F }
|
|
||||||
err = EncodeGBEU[uint64](buffer[:], 0xFFFFFFFFFFFFFFFF)
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := maxGBEU64, buffer[:10]; !slices.Equal(correct, got) {
|
|
||||||
message := "not equal:"
|
|
||||||
for _, item := range got {
|
|
||||||
message = fmt.Sprintf("%s %x", message, item)
|
|
||||||
}
|
|
||||||
test.Fatal(message)
|
|
||||||
}
|
|
||||||
decoded, err = DecodeGBEU[uint64](buffer[:])
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := uint64(0xFFFFFFFFFFFFFFFF), decoded; correct != got {
|
|
||||||
test.Fatalf("not equal: %x", got)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = EncodeGBEU[uint64](buffer[:], 11)
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := byte(0xb), buffer[0]; correct != got {
|
|
||||||
test.Fatal("not equal:", got)
|
|
||||||
}
|
|
||||||
decoded, err = DecodeGBEU[uint64](buffer[:])
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if correct, got := uint64(0xb), decoded; correct != got {
|
|
||||||
test.Fatalf("not equal: %x", got)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _ = range largeNumberNTestRounds {
|
|
||||||
buffer = [16]byte { }
|
|
||||||
number := uint64(rand.Int())
|
|
||||||
err := EncodeGBEU[uint64](buffer[:], number)
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
decoded, err := DecodeGBEU[uint64](buffer[:])
|
|
||||||
if err != nil { test.Fatal(err) }
|
|
||||||
if decoded != number {
|
|
||||||
test.Error("not equal:")
|
|
||||||
test.Errorf("%d != %d", decoded, number)
|
|
||||||
test.Errorf("%x != %x", decoded, number)
|
|
||||||
test.Fatal(buffer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGBEUSize(test *testing.T) {
|
|
||||||
if correct, got := 3, GBEUSize(uint(0x100000)); correct != got {
|
|
||||||
test.Fatal("not equal:", got)
|
|
||||||
}
|
|
||||||
if correct, got := 3, GBEUSize(uint(0x123456)); correct != got {
|
|
||||||
test.Fatal("not equal:", got)
|
|
||||||
}
|
|
||||||
if correct, got := 4, GBEUSize(uint(0x223456)); correct != got {
|
|
||||||
test.Fatal("not equal:", got)
|
|
||||||
}
|
|
||||||
if correct, got := 1, GBEUSize(uint(0)); correct != got {
|
|
||||||
test.Fatal("not equal:", got)
|
|
||||||
}
|
|
||||||
if correct, got := 1, GBEUSize(uint(127)); correct != got {
|
|
||||||
test.Fatal("not equal:", got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestString(test *testing.T) {
|
func TestString(test *testing.T) {
|
||||||
var buffer [16]byte
|
var buffer [16]byte
|
||||||
err := EncodeString[string](buffer[:], "hello")
|
err := EncodeString[string](buffer[:], "hello")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user