Documentation ¶
Overview ¶
Package vamp implements the Vampire binary data serialization format for Go.
While Vampire does not provide zero-copy characteristics it gives you "direct access" to values i.e., you can navigate any path down into nested structures without parsing too many other parts that come before the value you are looking for. This feature makes any value directly accessible – “perviam” in Latin. Just because “Vampire” sounds much cooler the format is called Vampire in the end. But vamp is the package name to Go for because its shorter and still associated with vampires.
Type Promotion ¶
TODO: float32 → float64; sized ints; machine int/uint.
Date and Duration ¶
By default as int64 <-> Unix time with millis.
Example (Size) ¶
buf, _ := NewTypeWriteBuffer(Size16, 0, nil) WriteType(buf, ptestType) fmt.Println("Type:\t", len(buf.Bytes()), "byte", ptestType.String()) in := ptestAnimal{ Age: 4, Name: "Candy", Owners: []string{"Mary", "Joe"}, Male: true, } buf.Reset(ptestType, Size16, 0) err := ptestType.Write(buf, in) if err != nil { fmt.Println(err) return } fmt.Println("Vamp:\t", len(buf.Bytes()), "byte", hex.EncodeToString(buf.Bytes())) res, err := json.Marshal(in) if err != nil { fmt.Println(err) return } fmt.Println("JSON:\t", len(res), "byte", string(res)) res, err = jsoniter.Marshal(in) if err != nil { fmt.Println(err) return } fmt.Println("Jsoniter:", len(res), "byte", string(res)) var gobb bytes.Buffer err = gob.NewEncoder(&gobb).Encode(in) if err != nil { fmt.Println(err) return } fmt.Println("GOB :\t", gobb.Len(), "byte") res, err = cbor.Marshal(in) if err != nil { fmt.Println(err) return } fmt.Println("CBOR:\t", len(res), "byte")
Output: Type: 54 byte {age:int8 name:"Size8" owners:[Size8 "Size8"] male:bool} Vamp: 26 byte 040504000206000143616e64790403000304004d6172794a6f65 JSON: 60 byte {"Age":4,"Name":"Candy","Owners":["Mary","Joe"],"Male":true} Jsoniter: 60 byte {"Age":4,"Name":"Candy","Owners":["Mary","Joe"],"Male":true} GOB : 113 byte CBOR: 40 byte
Index ¶
- Constants
- Variables
- func ResetTypeBuffer(buf *Buffer, off SizeRange, prefix int)
- func WriteType(buf *Buffer, t Type) error
- type Alt
- type AnyMarshaler
- type ArrayMarshaler
- type ArrayType
- func (t *ArrayType) DynNo() uint
- func (t *ArrayType) Elem() Type
- func (a *ArrayType) Equals(t Type) bool
- func (t *ArrayType) FixSize() uint
- func (a *ArrayType) Hash(h hash.Hash)
- func (t *ArrayType) Index(buf *ReadBuffer, i uint) (revert uint)
- func (t *ArrayType) Len(buf *ReadBuffer) uint
- func (t *ArrayType) LenRange() SizeRange
- func (t *ArrayType) Read(buf *ReadBuffer, into any) error
- func (t *ArrayType) ReadArray(buf *ReadBuffer, ls ArrayUnmarshaler) error
- func (t *ArrayType) ReadOpt(buf *ReadBuffer, into any) (ok bool, err error)
- func (t *ArrayType) String() string
- func (t *ArrayType) VampRecordRead(rt *RecordType, buf *ReadBuffer) error
- func (t *ArrayType) VampRecordWrite(rt *RecordType, buf *Buffer) error
- func (t *ArrayType) VampUnionAlt() (uint, any)
- func (t *ArrayType) Write(buf *Buffer, ls any) (err error)
- func (t *ArrayType) WriteArray(buf *Buffer, ls ArrayMarshaler) error
- func (t *ArrayType) WriteOptNone(buf *Buffer) error
- func (t *ArrayType) WriteOptOne(buf *Buffer, value any) error
- type ArrayUnmarshaler
- type Buffer
- type BytesMode
- type BytesType
- func (t BytesType) DynNo() uint
- func (s BytesType) Equals(t Type) bool
- func (t BytesType) FixSize() uint
- func (s BytesType) Hash(h hash.Hash)
- func (t BytesType) LenRange() SizeRange
- func (t BytesType) Read(buf *ReadBuffer, into any) (err error)
- func (t BytesType) ReadBytes(buf *ReadBuffer) []byte
- func (t BytesType) ReadString(buf *ReadBuffer) string
- func (t BytesType) String() string
- func (t *BytesType) VampFromUint8(v uint8) error
- func (t BytesType) VampToUint8() (uint8, error)
- func (t BytesType) VampUnionAlt() (uint, any)
- func (t BytesType) Write(buf *Buffer, value any) error
- func (t BytesType) WriteBytes(buf *Buffer, data []byte) error
- func (t BytesType) WriteString(buf *Buffer, s string) error
- type Header
- type ListIterator
- type ListMarshaler
- type ListType
- func (t *ListType) DynNo() uint
- func (t *ListType) Elem() Type
- func (l *ListType) Equals(t Type) bool
- func (t *ListType) FixSize() uint
- func (a *ListType) Hash(h hash.Hash)
- func (t *ListType) LenRange() SizeRange
- func (t *ListType) ListLen(buf *ReadBuffer) (len uint, ok bool)
- func (t *ListType) Next(buf *ReadBuffer) (revert uint, ok bool)
- func (t *ListType) Read(buf *ReadBuffer, into any) error
- func (t *ListType) ReadList(buf *ReadBuffer, into ListUnmarshaler) error
- func (t *ListType) String() string
- func (t *ListType) VampRecordRead(rt *RecordType, buf *ReadBuffer) error
- func (t *ListType) VampRecordWrite(rt *RecordType, buf *Buffer) error
- func (t *ListType) VampUnionAlt() (uint, any)
- func (t *ListType) Write(buf *Buffer, val any) error
- func (t *ListType) WriteList(buf *Buffer, ls ListMarshaler) error
- type ListUnmarshaler
- type ReadBuffer
- func NewReadBuffer(t Type, buf []byte, search bool) (*ReadBuffer, error)
- func NewReadBufferOffSize(t Type, off SizeRange, buf []byte) (*ReadBuffer, error)
- func NewTypeReadBuffer(buf []byte, search bool) (*ReadBuffer, error)
- func NewTypeReadBufferOffSize(off SizeRange, buf []byte) (*ReadBuffer, error)
- type RecordMarshaler
- type RecordType
- func (t *RecordType) DynNo() uint
- func (r *RecordType) Equals(t Type) bool
- func (t *RecordType) Field(buf *ReadBuffer, i uint) (revert uint)
- func (t *RecordType) FieldName(i uint) string
- func (t *RecordType) FieldType(i uint) Type
- func (t *RecordType) FixSize() uint
- func (r *RecordType) Hash(h hash.Hash)
- func (t *RecordType) NumField() uint
- func (t *RecordType) Read(buf *ReadBuffer, out any) (err error)
- func (t *RecordType) ReadFields(buf *ReadBuffer, outs ...any) error
- func (t *RecordType) SetNames(ns ...string) *RecordType
- func (t *RecordType) String() string
- func (t *RecordType) VampArrayFinish() error
- func (t *RecordType) VampArrayLen() uint
- func (t *RecordType) VampArrayReader(i uint) (any, error)
- func (t *RecordType) VampArrayResize(l uint) error
- func (t *RecordType) VampArrayWriter(i uint) (any, error)
- func (t *RecordType) VampUnionAlt() (uint, any)
- func (t *RecordType) Write(buf *Buffer, values any) error
- func (t *RecordType) WriteFields(buf *Buffer, values ...any) error
- type RecordUnmarshaler
- type Reflect
- type SizeRange
- type Type
- type UnionMarshaler
- type UnionType
- func (t *UnionType) Alt(i uint) Type
- func (t *UnionType) AltRange() SizeRange
- func (t *UnionType) DynNo() uint
- func (u *UnionType) Equals(t Type) bool
- func (t *UnionType) FixSize() uint
- func (u *UnionType) Hash(h hash.Hash)
- func (t *UnionType) NumAlts() uint
- func (t *UnionType) Read(buf *ReadBuffer, into any) error
- func (t *UnionType) ReadAlt(buf *ReadBuffer, selectVal func(uint) any) (any, error)
- func (t *UnionType) String() string
- func (t *UnionType) VampRecordRead(rt *RecordType, buf *ReadBuffer) error
- func (t *UnionType) VampRecordWrite(rt *RecordType, buf *Buffer) error
- func (t *UnionType) VampUnionAlt() (uint, any)
- func (t *UnionType) WithAltReader(f func(uint, any) (any, error)) *UnionType
- func (t *UnionType) Write(buf *Buffer, value any) error
- func (t *UnionType) WriteAlt(buf *Buffer, alt uint, value any) error
- type UnionUnmarshaler
Examples ¶
Constants ¶
const ( Version = 0 HeaderSize = len(Header{}) )
Variables ¶
var ( BoolType boolType Int8Type int8Type Int16Type int16Type Int32Type int32Type Int64Type int64Type Uint8Type uint8Type Uint16Type uint16Type Uint32Type uint32Type Uint64Type uint64Type Float32Type float32Type Float64Type float64Type )
Vampire Basic Types
Each <N>Type variable implements Type and represents a Vampire type that corresponds directly to a Go type <n> where <n> is <N> folded to lower case e.g., BoolType corresponds to Go's bool type.
Marshaler and Unmarshaler interfaces are not explicitly defined for basic types. To implement user defined (un-)marshaling to or from <N>Type a value has to implement methods that match the following convention:
The marshaler for writing <n> to <N>Type:
interface{ VampTo<N>() (<n>, error) }
The unmarshaler for reading <n> from <N>Type:
interface{ VampFrom<N>(<n>) error }
var AnyType anyType
Functions ¶
func ResetTypeBuffer ¶
Types ¶
type Alt ¶
func (Alt) VampUnionAlt ¶
type AnyMarshaler ¶
type ArrayMarshaler ¶
type ArrayType ¶
type ArrayType struct {
// contains filtered or unexported fields
}
Example ¶
a := []string{"boo", "bar", "baz"} t, _ := TypeOf(a) fmt.Println(t) buf, _ := NewWriteBuffer(t, Size16, 0, nil) t.Write(buf, a) var out []string t.Read(&buf.ReadBuffer, &out) fmt.Printf("%[1]T=%[1]v\n", out)
Output: [Size32 "Size16"] []string=[boo bar baz]
func NewOptionalType ¶
NewOptionalType returns an ArrayType with length of Size8 – the smallest sufficient size range. This is the recommended way to represent optional values.
Example ¶
et, _ := NewBytesType(Size8) ot := NewOptionalType(et) buf, _ := NewWriteBuffer(ot, Size8, 0, nil) ot.WriteOptOne(buf, "Hello, optional!") var out string ok, _ := ot.ReadOpt(&buf.ReadBuffer, &out) fmt.Println(ok, out) buf.Reset(ot, Size16, 0) ot.WriteOptNone(buf) out = "-" ok, _ = ot.ReadOpt(&buf.ReadBuffer, &out) fmt.Println(ok, out)
Output: true Hello, optional! false -
func (*ArrayType) Len ¶
func (t *ArrayType) Len(buf *ReadBuffer) uint
func (*ArrayType) ReadArray ¶
func (t *ArrayType) ReadArray(buf *ReadBuffer, ls ArrayUnmarshaler) error
func (*ArrayType) ReadOpt ¶
func (t *ArrayType) ReadOpt(buf *ReadBuffer, into any) (ok bool, err error)
func (*ArrayType) VampRecordRead ¶
func (t *ArrayType) VampRecordRead(rt *RecordType, buf *ReadBuffer) error
func (*ArrayType) VampRecordWrite ¶
func (t *ArrayType) VampRecordWrite(rt *RecordType, buf *Buffer) error
func (*ArrayType) VampUnionAlt ¶
func (*ArrayType) WriteArray ¶
func (t *ArrayType) WriteArray(buf *Buffer, ls ArrayMarshaler) error
func (*ArrayType) WriteOptNone ¶
type ArrayUnmarshaler ¶
type BytesType ¶
type BytesType struct {
// contains filtered or unexported fields
}
func NewBytesType ¶
func (BytesType) Read ¶
func (t BytesType) Read(buf *ReadBuffer, into any) (err error)
User Defined Unmarshaling
Unmarshaling from byte array:
interface{ VampFromBytes([]byte) error } // must copy its argument
Unmarshaling from string:
interface{ VampFromString(string) error }
func (BytesType) ReadBytes ¶
func (t BytesType) ReadBytes(buf *ReadBuffer) []byte
func (BytesType) ReadString ¶
func (t BytesType) ReadString(buf *ReadBuffer) string
func (*BytesType) VampFromUint8 ¶
func (BytesType) VampToUint8 ¶
func (BytesType) VampUnionAlt ¶
type Header ¶
type Header [4]byte
Header is the VMP header that can be written to buffers to mark the data to be Vampire encoded and to provide the offsetSize used for the data.
The VMP header is "VMPn" where n == offsetSize.Size().
Example ¶
fmt.Println(HeaderFor(Size16))
Output: Vampire-v0+16bit
func ParseHeader ¶
type ListIterator ¶
type ListMarshaler ¶
type ListMarshaler interface {
VampListIter() ListIterator
}
type ListType ¶
type ListType struct {
// contains filtered or unexported fields
}
Example ¶
a := []string{"boo", "bar", "baz"} t, _ := NewListType(Size32, catch.MustRet(NewBytesType(Size16))) fmt.Println(t) buf, _ := NewWriteBuffer(t, Size16, 0, nil) t.Write(buf, a) var out any t.Read(&buf.ReadBuffer, &out) fmt.Printf("%[1]T=%[1]v\n", out)
Output: (Size32 "Size16") []interface {}=[boo bar baz]
func (*ListType) Next ¶
func (t *ListType) Next(buf *ReadBuffer) (revert uint, ok bool)
TODO Test ListType.Next()
func (*ListType) ReadList ¶
func (t *ListType) ReadList(buf *ReadBuffer, into ListUnmarshaler) error
func (*ListType) VampRecordRead ¶
func (t *ListType) VampRecordRead(rt *RecordType, buf *ReadBuffer) error
func (*ListType) VampRecordWrite ¶
func (t *ListType) VampRecordWrite(rt *RecordType, buf *Buffer) error
func (*ListType) VampUnionAlt ¶
type ListUnmarshaler ¶
type ReadBuffer ¶
type ReadBuffer struct {
// contains filtered or unexported fields
}
ReadBuffer adapts a Vampire encoded byte array to be used for read-only access. One has to use the specific Type that matches the encoded data to read the data from the buffer.
func NewReadBuffer ¶
func NewReadBuffer(t Type, buf []byte, search bool) (*ReadBuffer, error)
NewReadBufferOffSize wraps buf for read access when the offsetSize is provided by a VMP Header in buf. When search is true NewReadBuffer scans for the first valid VMP header and uses it's offsetSize. Otherwise the VMP header must start at buf[0].
func NewReadBufferOffSize ¶
func NewReadBufferOffSize(t Type, off SizeRange, buf []byte) (*ReadBuffer, error)
NewReadBufferOffSize wraps buf for read access when the offsetSize used for the encoded data is known. The first byte of the data of Type t must be buf[0].
func NewTypeReadBuffer ¶
func NewTypeReadBuffer(buf []byte, search bool) (*ReadBuffer, error)
func NewTypeReadBufferOffSize ¶
func NewTypeReadBufferOffSize(off SizeRange, buf []byte) (*ReadBuffer, error)
func (*ReadBuffer) AllBytes ¶
func (b *ReadBuffer) AllBytes() []byte
func (*ReadBuffer) Bytes ¶
func (b *ReadBuffer) Bytes() []byte
func (*ReadBuffer) Offset ¶
func (b *ReadBuffer) Offset() SizeRange
func (*ReadBuffer) SliceFix ¶
func (b *ReadBuffer) SliceFix(off uint) (revert uint)
func (*ReadBuffer) Unslice ¶
func (b *ReadBuffer) Unslice(revert uint)
type RecordMarshaler ¶
type RecordMarshaler interface {
VampRecordWrite(*RecordType, *Buffer) error
}
type RecordType ¶
type RecordType struct {
// contains filtered or unexported fields
}
TODO Slice to field
Example ¶
r := struct { Name string Age uint8 }{ Name: "John Doe", Age: 44, } t, _ := TypeOf(r) fmt.Println(t) buf, _ := NewWriteBuffer(t, Size16, 0, nil) t.Write(buf, r) var out any t.Read(&buf.ReadBuffer, &out) fmt.Printf("%[1]T=%[1]v\n", out)
Output: {Name:"Size16" Age:uint8} []interface {}=[John Doe 44]
func NewRecordType ¶
func NewRecordType(fields ...Type) (*RecordType, error)
func (*RecordType) DynNo ¶
func (t *RecordType) DynNo() uint
func (*RecordType) Equals ¶
func (r *RecordType) Equals(t Type) bool
func (*RecordType) Field ¶
func (t *RecordType) Field(buf *ReadBuffer, i uint) (revert uint)
func (*RecordType) FieldName ¶
func (t *RecordType) FieldName(i uint) string
func (*RecordType) FieldType ¶
func (t *RecordType) FieldType(i uint) Type
func (*RecordType) FixSize ¶
func (t *RecordType) FixSize() uint
func (*RecordType) Hash ¶
func (r *RecordType) Hash(h hash.Hash)
func (*RecordType) NumField ¶
func (t *RecordType) NumField() uint
func (*RecordType) Read ¶
func (t *RecordType) Read(buf *ReadBuffer, out any) (err error)
func (*RecordType) ReadFields ¶
func (t *RecordType) ReadFields(buf *ReadBuffer, outs ...any) error
func (*RecordType) SetNames ¶
func (t *RecordType) SetNames(ns ...string) *RecordType
func (*RecordType) String ¶
func (t *RecordType) String() string
func (*RecordType) VampArrayFinish ¶
func (t *RecordType) VampArrayFinish() error
func (*RecordType) VampArrayLen ¶
func (t *RecordType) VampArrayLen() uint
func (*RecordType) VampArrayReader ¶
func (t *RecordType) VampArrayReader(i uint) (any, error)
func (*RecordType) VampArrayResize ¶
func (t *RecordType) VampArrayResize(l uint) error
func (*RecordType) VampArrayWriter ¶
func (t *RecordType) VampArrayWriter(i uint) (any, error)
func (*RecordType) VampUnionAlt ¶
func (t *RecordType) VampUnionAlt() (uint, any)
func (*RecordType) WriteFields ¶
func (t *RecordType) WriteFields(buf *Buffer, values ...any) error
type RecordUnmarshaler ¶
type RecordUnmarshaler interface {
VampRecordRead(*RecordType, *ReadBuffer) error
}
type Reflect ¶
type Reflect struct {
// contains filtered or unexported fields
}
func DefaultReflect ¶
func DefaultReflect() Reflect
func (Reflect) StringSize ¶
ignores invalid SizeRanges
type SizeRange ¶
type SizeRange uint8
SizeRange defines the range that is used for buffer offsets, string length and any sort of ranges of size in byte that is used in Vampire encoding.
func (SizeRange) Check ¶
Check checks if size is withing the SizeRange s. Only if size is not in s' range an error is returned.
func (SizeRange) Max ¶
Max returns the maximum uint of SizeRange s. SizeRange s is expected to be s.Valid()==true.
func (SizeRange) Size ¶
Size returns the number of bytes used for the size range in Vampire encoding. SizeRange s is expected to be s.Valid()==true.
func (SizeRange) Valid ¶
Valid returns true only for the supported size ranges as defined by the provided SizeRange constants.
func (*SizeRange) VampFromUint8 ¶
SizeRange can be decoded from a Vampire Uint8.
func (SizeRange) VampToUint8 ¶
SizeRange can be encoded as Vampire Uint8.
type Type ¶
type Type interface { FixSize() uint DynNo() uint Write(b *Buffer, value any) error Read(b *ReadBuffer, into any) error Equals(t Type) bool Hash(hash.Hash) fmt.Stringer }
func ReadType ¶
func ReadType(buf *ReadBuffer) (t Type, err error)
func TypeOf ¶
Example ¶
type animal struct { Age int `vamp:"age,size=8"` Name string `vamp:",size=8"` Owners []string `vamp:",size=8:8"` Male bool `vamp:"-"` } t, err := TypeOf(animal{}) if err != nil { fmt.Println(err) } else { fmt.Println(t.String()) }
Output: {age:int8 Name:"Size8" Owners:[Size8 "Size8"]}
type UnionMarshaler ¶
type UnionType ¶
type UnionType struct { AltReader func(alt uint, into any) (reader any, err error) // contains filtered or unexported fields }
Example ¶
type address struct { Street string No string } type geocoos struct { Lat, Lon float64 } addrType, _ := TypeOf(address{}) geoType, _ := TypeOf(geocoos{}) placeType, _ := NewUnionType(Size8, addrType, geoType) fmt.Println(placeType) buf, _ := NewWriteBuffer(placeType, Size16, 0, nil) placeType.Write(buf, Alt{S: 0, V: address{Street: "Justroad", No: "33a"}}) var out any placeType.Read(&buf.ReadBuffer, &out) fmt.Printf("%[1]T=%[1]v\n", out) buf.Reset(placeType, Size16, 0) placeType.Write(buf, Alt{S: 1, V: geocoos{Lat: 33.321, Lon: 44.123}}) placeType.Read(&buf.ReadBuffer, &out) fmt.Printf("%[1]T=%[1]v\n", out)
Output: <Size8 {Street:"Size16" No:"Size16"}|{Lat:float64 Lon:float64}> []interface {}=[Justroad 33a] []interface {}=[33.321 44.123]
func (*UnionType) VampRecordRead ¶
func (t *UnionType) VampRecordRead(rt *RecordType, buf *ReadBuffer) error
func (*UnionType) VampRecordWrite ¶
func (t *UnionType) VampRecordWrite(rt *RecordType, buf *Buffer) error