Skip to content

Commit

Permalink
warp
Browse files Browse the repository at this point in the history
  • Loading branch information
vasylNaumenko committed Aug 14, 2024
1 parent 4de4d4d commit c842911
Show file tree
Hide file tree
Showing 212 changed files with 20,914 additions and 100 deletions.
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.SILENT:
.EXPORT_ALL_VARIABLES:

.PHONY: b
b:
rm -rf /tmp/e2e-test-landslide/nodes/
./scripts/build.sh /tmp/e2e-test-landslide/avalanchego/plugins/pjSL9ksard4YE96omaiTkGL5H6XX2W5VEo3ZgWC9S2P6gzs9A


ba:
BASEDIR=/tmp/e2e-test-landslide AVALANCHEGO_BUILD_PATH=/tmp/e2e-test-landslide/avalanchego ./scripts/install_avalanchego_release.sh
.PHONY: ba

.PHONY: w
w:
rm -rf /tmp/e2e-test-landslide/nodes/
./scripts/build_wasm.sh /tmp/e2e-test-landslide/avalanchego/plugins/pjSL9ksard4YE96omaiTkGL5H6XX2W5VEo3ZgWC9S2P6gzs9A
26 changes: 26 additions & 0 deletions codec/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package codec

import (
"errors"

"github.com/consideritdone/landslidevm/utils/wrappers"
)

var (
ErrUnsupportedType = errors.New("unsupported type")
ErrMaxSliceLenExceeded = errors.New("max slice length exceeded")
ErrDoesNotImplementInterface = errors.New("does not implement interface")
ErrUnexportedField = errors.New("unexported field")
ErrExtraSpace = errors.New("trailing buffer space")
ErrMarshalZeroLength = errors.New("can't marshal zero length value")
ErrUnmarshalZeroLength = errors.New("can't unmarshal zero length value")
)

// Codec marshals and unmarshals
type Codec interface {
MarshalInto(interface{}, *wrappers.Packer) error
Unmarshal([]byte, interface{}) error

// Returns the size, in bytes, of [value] when it's marshaled
Size(value interface{}) (int, error)
}
7 changes: 7 additions & 0 deletions codec/general_codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package codec

// GeneralCodec marshals and unmarshals structs including interfaces
type GeneralCodec interface {
Codec
Registry
}
144 changes: 144 additions & 0 deletions codec/hierarchycodec/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package hierarchycodec

import (
"fmt"
"reflect"
"sync"

"github.com/consideritdone/landslidevm/utils/bimap"

"github.com/consideritdone/landslidevm/utils/wrappers"

"github.com/consideritdone/landslidevm/codec"
"github.com/consideritdone/landslidevm/codec/reflectcodec"
)

var (
_ Codec = (*hierarchyCodec)(nil)
_ codec.Codec = (*hierarchyCodec)(nil)
_ codec.Registry = (*hierarchyCodec)(nil)
_ codec.GeneralCodec = (*hierarchyCodec)(nil)
)

// Codec marshals and unmarshals
type Codec interface {
codec.Registry
codec.Codec
SkipRegistrations(int)
NextGroup()
}

type typeID struct {
groupID uint16
typeID uint16
}

// Codec handles marshaling and unmarshaling of structs
type hierarchyCodec struct {
codec.Codec

lock sync.RWMutex
currentGroupID uint16
nextTypeID uint16
registeredTypes *bimap.BiMap[typeID, reflect.Type]
}

// New returns a new, concurrency-safe codec
func New(tagNames []string) Codec {
hCodec := &hierarchyCodec{
currentGroupID: 0,
nextTypeID: 0,
registeredTypes: bimap.New[typeID, reflect.Type](),
}
hCodec.Codec = reflectcodec.New(hCodec, tagNames)
return hCodec
}

// NewDefault returns a new codec with reasonable default values
func NewDefault() Codec {
return New([]string{reflectcodec.DefaultTagName})
}

// SkipRegistrations some number of type IDs
func (c *hierarchyCodec) SkipRegistrations(num int) {
c.lock.Lock()
c.nextTypeID += uint16(num)
c.lock.Unlock()
}

// NextGroup moves to the next group registry
func (c *hierarchyCodec) NextGroup() {
c.lock.Lock()
c.currentGroupID++
c.nextTypeID = 0
c.lock.Unlock()
}

// RegisterType is used to register types that may be unmarshaled into an interface
// [val] is a value of the type being registered
func (c *hierarchyCodec) RegisterType(val interface{}) error {
c.lock.Lock()
defer c.lock.Unlock()

valType := reflect.TypeOf(val)
if c.registeredTypes.HasValue(valType) {
return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType)
}

valTypeID := typeID{
groupID: c.currentGroupID,
typeID: c.nextTypeID,
}
c.nextTypeID++

c.registeredTypes.Put(valTypeID, valType)
return nil
}

func (*hierarchyCodec) PrefixSize(reflect.Type) int {
// see PackPrefix implementation
return wrappers.ShortLen + wrappers.ShortLen
}

func (c *hierarchyCodec) PackPrefix(p *wrappers.Packer, valueType reflect.Type) error {
c.lock.RLock()
defer c.lock.RUnlock()

typeID, ok := c.registeredTypes.GetKey(valueType) // Get the type ID of the value being marshaled
if !ok {
return fmt.Errorf("can't marshal unregistered type %q", valueType)
}
// Pack type ID so we know what to unmarshal this into
p.PackShort(typeID.groupID)
p.PackShort(typeID.typeID)
return p.Err
}

func (c *hierarchyCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type) (reflect.Value, error) {
c.lock.RLock()
defer c.lock.RUnlock()

groupID := p.UnpackShort() // Get the group ID
typeIDShort := p.UnpackShort() // Get the type ID
if p.Err != nil {
return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %w", p.Err)
}
t := typeID{
groupID: groupID,
typeID: typeIDShort,
}
// Get a type that implements the interface
implementingType, ok := c.registeredTypes.GetValue(t)
if !ok {
return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: unknown type ID %+v", t)
}
// Ensure type actually does implement the interface
if !implementingType.Implements(valueType) {
return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s %w %s",
implementingType,
codec.ErrDoesNotImplementInterface,
valueType,
)
}
return reflect.New(implementingType).Elem(), nil // instance of the proper type
}
26 changes: 26 additions & 0 deletions codec/hierarchycodec/codec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package hierarchycodec

import (
"testing"

"github.com/consideritdone/landslidevm/codec"
)

func TestVectors(t *testing.T) {
for _, test := range codec.Tests {
c := NewDefault()
test(c, t)
}
}

func TestMultipleTags(t *testing.T) {
for _, test := range codec.MultipleTagsTests {
c := New([]string{"tag1", "tag2"})
test(c, t)
}
}

func FuzzStructUnmarshalHierarchyCodec(f *testing.F) {
c := NewDefault()
codec.FuzzStructUnmarshal(c, f)
}
117 changes: 117 additions & 0 deletions codec/linearcodec/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package linearcodec

import (
"fmt"
"reflect"
"sync"

"github.com/consideritdone/landslidevm/utils/bimap"

"github.com/consideritdone/landslidevm/utils/wrappers"

"github.com/consideritdone/landslidevm/codec"
"github.com/consideritdone/landslidevm/codec/reflectcodec"
)

var (
_ Codec = (*linearCodec)(nil)
_ codec.Codec = (*linearCodec)(nil)
_ codec.Registry = (*linearCodec)(nil)
_ codec.GeneralCodec = (*linearCodec)(nil)
)

// Codec marshals and unmarshals
type Codec interface {
codec.Registry
codec.Codec
SkipRegistrations(int)
}

// Codec handles marshaling and unmarshaling of structs
type linearCodec struct {
codec.Codec

lock sync.RWMutex
nextTypeID uint32
registeredTypes *bimap.BiMap[uint32, reflect.Type]
}

// New returns a new, concurrency-safe codec; it allow to specify tagNames.
func New(tagNames []string) Codec {
hCodec := &linearCodec{
nextTypeID: 0,
registeredTypes: bimap.New[uint32, reflect.Type](),
}
hCodec.Codec = reflectcodec.New(hCodec, tagNames)
return hCodec
}

// NewDefault is a convenience constructor; it returns a new codec with default
// tagNames.
func NewDefault() Codec {
return New([]string{reflectcodec.DefaultTagName})
}

// Skip some number of type IDs
func (c *linearCodec) SkipRegistrations(num int) {
c.lock.Lock()
c.nextTypeID += uint32(num)
c.lock.Unlock()
}

// RegisterType is used to register types that may be unmarshaled into an interface
// [val] is a value of the type being registered
func (c *linearCodec) RegisterType(val interface{}) error {
c.lock.Lock()
defer c.lock.Unlock()

valType := reflect.TypeOf(val)
if c.registeredTypes.HasValue(valType) {
return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType)
}

c.registeredTypes.Put(c.nextTypeID, valType)
c.nextTypeID++
return nil
}

func (*linearCodec) PrefixSize(reflect.Type) int {
// see PackPrefix implementation
return wrappers.IntLen
}

func (c *linearCodec) PackPrefix(p *wrappers.Packer, valueType reflect.Type) error {
c.lock.RLock()
defer c.lock.RUnlock()

typeID, ok := c.registeredTypes.GetKey(valueType) // Get the type ID of the value being marshaled
if !ok {
return fmt.Errorf("can't marshal unregistered type %q", valueType)
}
p.PackInt(typeID) // Pack type ID so we know what to unmarshal this into
return p.Err
}

func (c *linearCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type) (reflect.Value, error) {
c.lock.RLock()
defer c.lock.RUnlock()

typeID := p.UnpackInt() // Get the type ID
if p.Err != nil {
return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %w", p.Err)
}
// Get a type that implements the interface
implementingType, ok := c.registeredTypes.GetValue(typeID)
if !ok {
return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: unknown type ID %d", typeID)
}
// Ensure type actually does implement the interface
if !implementingType.Implements(valueType) {
return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %s %w %s",
implementingType,
codec.ErrDoesNotImplementInterface,
valueType,
)
}
return reflect.New(implementingType).Elem(), nil // instance of the proper type
}
26 changes: 26 additions & 0 deletions codec/linearcodec/codec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package linearcodec

import (
"testing"

"github.com/consideritdone/landslidevm/codec"
)

func TestVectors(t *testing.T) {
for _, test := range codec.Tests {
c := NewDefault()
test(c, t)
}
}

func TestMultipleTags(t *testing.T) {
for _, test := range codec.MultipleTagsTests {
c := New([]string{"tag1", "tag2"})
test(c, t)
}
}

func FuzzStructUnmarshalLinearCodec(f *testing.F) {
c := NewDefault()
codec.FuzzStructUnmarshal(c, f)
}
Loading

0 comments on commit c842911

Please sign in to comment.