From bfe176c5a991df7b9338953cb2a8cad7c7b4cfe4 Mon Sep 17 00:00:00 2001 From: David Vennik Date: Wed, 13 Sep 2023 11:37:39 +0100 Subject: [PATCH] first few types implemented --- pkg/splicer/i32/int32.go | 16 +++++-- pkg/splicer/magic/magic.go | 82 +++++++++++++++++++++++++++++++++ pkg/splicer/magic/magic_test.go | 1 + pkg/splicer/splicer.go | 18 +++++--- 4 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 pkg/splicer/magic/magic.go create mode 100644 pkg/splicer/magic/magic_test.go diff --git a/pkg/splicer/i32/int32.go b/pkg/splicer/i32/int32.go index 5e824080..0ff51dbf 100644 --- a/pkg/splicer/i32/int32.go +++ b/pkg/splicer/i32/int32.go @@ -18,6 +18,8 @@ func New() *S { return &S{b: make([]byte, Len)} } // // The remaining bytes, if any, are returned for further processing. func NewFrom(b []byte) (s *S, rem []byte) { + // If the bytes are less than Len the input is invalid and nil will be + // returned. if len(b) < Len { return } @@ -50,14 +52,20 @@ func (s *S) Write(by []byte) (out []byte) { func (s *S) Len() int { return len(s.b) } func (s *S) Get() (v interface{}) { - val := int32(binary.BigEndian.Uint32(s.b)) - return &val + if len(s.b) >= Len { + val := int32(binary.BigEndian.Uint32(s.b)) + return &val + } + return } -func (s *S) Put(bits interface{}) interface{} { +func (s *S) Put(v interface{}) interface{} { + if len(s.b) < Len { + s.b = make([]byte, Len) + } var tv *int32 var ok bool - if tv, ok = bits.(*int32); ok { + if tv, ok = v.(*int32); ok { binary.BigEndian.PutUint32(s.b[:Len], uint32(*tv)) } return s diff --git a/pkg/splicer/magic/magic.go b/pkg/splicer/magic/magic.go new file mode 100644 index 00000000..1818dd43 --- /dev/null +++ b/pkg/splicer/magic/magic.go @@ -0,0 +1,82 @@ +package magic + +const Len = 4 + +type Bytes struct { + bytes []byte +} + +// New allocates bytes to store a new magic.Bytes in. Note that this allocates +// memory. +func New() *Bytes { return &Bytes{bytes: make([]byte, Len)} } + +// NewFrom creates a 32-bit integer from raw bytes, if the slice is at least Len +// bytes long. This can be used to snip out an encoded segment which should +// return a value from a call to Get. +// +// The remaining bytes, if any, are returned for further processing. +func NewFrom(b []byte) (s *Bytes, rem []byte) { + if len(b) < Len { + return + } + // This slices the input, meaning no copy is required, only allocating the + // slice pointer. + s = &Bytes{bytes: b[:Len]} + if len(b) > Len { + rem = b[Len:] + } + return +} + +func (m Bytes) Len() (l int) { return len(m.bytes) } + +func (m Bytes) Read() (o []byte) { + if len(m.bytes) >= Len { + o = m.bytes[:Len] + } + return +} + +func (m Bytes) Write(b []byte) (o []byte) { + if len(b) >= Len { + m.bytes = b[:3] + // If there is more, return the excess. + if len(b) > Len { + o = b[Len:] + } + } + return +} + +func (m Bytes) Get() (v interface{}) { + if len(m.bytes) >= Len { + val := string(m.bytes[:Len]) + v = &val + } + return +} + +func (m Bytes) Put(v interface{}) (o interface{}) { + var tv *string + var ok bool + if tv, ok = v.(*string); ok { + bytes := []byte(*tv) + if len(bytes) == Len { + m.bytes = bytes + } + } + return +} + +// Assert takes an interface and if it is a duration.Time, returns the time.Time +// value. If it is not the expected type, nil is returned. +func Assert(v interface{}) (t *string) { + var tv *Bytes + var ok bool + if tv, ok = v.(*Bytes); ok { + tt := tv.Get() + // If this fails the return is nil, indicating failure. + t, _ = tt.(*string) + } + return +} diff --git a/pkg/splicer/magic/magic_test.go b/pkg/splicer/magic/magic_test.go new file mode 100644 index 00000000..5ea4f8c7 --- /dev/null +++ b/pkg/splicer/magic/magic_test.go @@ -0,0 +1 @@ +package magic diff --git a/pkg/splicer/splicer.go b/pkg/splicer/splicer.go index 72f2f04a..b3efa75c 100644 --- a/pkg/splicer/splicer.go +++ b/pkg/splicer/splicer.go @@ -19,14 +19,14 @@ type Splice interface { // Len returns the number of bytes used to encode the Splice. This returns // zero if no value has been encoded yet. - Len() int + Len() (l int) // Read returns the wire/storage form of the data. - Read() []byte + Read() (o []byte) // Write stores the decoded data from the head of the slice and returns the // remainder. If the input bytes are not long enough, abort and return nil. - Write(b []byte) []byte + Write(b []byte) (o []byte) } // Accessor is a generic interface, for decoding and encoding runtime forms of @@ -34,11 +34,17 @@ type Splice interface { // above. type Accessor interface { - // Get returns the decoded value wrapped in an interface{}. + // Get returns the decoded value as a pointer wrapped in an interface{}. Get() (v interface{}) - // Put - Put(v interface{}) interface{} + // Put inserts a pointer to a value that is expected to be the underlying + // type. + Put(v interface{}) (o interface{}) +} + +type SpliceAccessor interface { + Splice + Accessor } type Serializers []Splice