Warning: This package is a work in progress. After some preliminary testing, I think I might change a lot of how this package is structured.
Cod is a schemaless serialization library for generating serialization code for your structs. This is for generating code that encodes and decodes data as quickly as possible. By default we use variable length encoding for all unsigned and signed integers larger than 16 bits.
Install
You just need to run this to get the binary: go install github.com/unitoftime/cod/cmd/cod
You will also need to add ~/go/bin/ (or windows equivalent is) to your path so you can reference binaries from there
You can then add //go:generate cod
to one of your go files in your package. This will run the cod binary every time you execute go generate
. Finally you can tag structures that you want to generate code for as follows:
- Structs:
//cod:struct
- Unions:
//cod:union <UnionDefName>
- Union Definitions:
//cod:def
Notables
- Generated file is called
cod_encode.go
and will reside in the package you generated from
- See below for list of struct method names that are reserved
Disclaimers
- AST Parsing and code generation is tricky to get right. If you do find a situation where the code is not generated correctly, please let me know by opening an issue.
- Map serialization is not deterministic. This is because looping over a map is not deterministic. I can maybe add this in the future if people want it.
- There's no versioning info included in the serialized data by default. If you want to support multiple encodings, then you'll need to include them all in a tagged union
- Currently, tagged unions can support a maximum of 255 different types
Supports
- Basic data types
- Custom Structs
- Slices and Maps
- "Hand-Crafted" Encoders and Decoders (Just implement the two normally generated functions)
- Serializes private fields by default (TODO to be able to turn that off)
TODOs
- Multiple backends (ie different swappable serialization schemes)
- Generated Size functions (to let you measure the size of the thing you want to serialize)
- Ability to selectively turn off variable length encoding with a tag:
cod:"fixed"
(or something)
- Ability to prevent a field from serializing (ie disable fields)
- Automatic bitpacking for structs that are just a long list of bools (or similar)
- Immediate panics when writing invalid types to a union (or come up with some type-safe way to prevent it)
- Would be nice to have a way to autocast a struct to another struct. That way you can easily serialize types that you dont own. This seems hard to get right though.
- Some tag to just say "encode this field as a uint64 or an int64"
Syntax
Custom Types
Add the //cod:struct
to indicate that its a struct, or create a serializable union with //cod:union <CSV list of union types>
:
//cod:struct
type Person struct {
Name string
Age uint8
FavoriteThings map[string]Thing
SomeListOfNumbers []int64
}
//cod:union ThingUnionDef
type Thing cod.Union
//cod:def
type ThingUnionDef struct {
Ball
Hat
}
//cod:struct
type Ball struct {
Color string
}
//cod:struct
type Hat struct {
Material string
}
Generated Functions
All types will have two methods generated for them:
EncodeCod([]byte) []byte
DecodeCod([]byte) (int, error)
Unions will also get the following methods
Get() any // Guaranteed to return one of the unionable types or nil
Set(any) // Must pass in only a unionable type or nil
New<TYPE>(v any) <TYPE> // A Constructor: Where <TYPE> is the name of the union
// ---------------
// For cod:structs
// ---------------
func (t Person) EncodeCod(bs []byte) []byte {
// ... Generated Code ...
}
func (t *Person) DecodeCod(bs []byte) (int, error) {
// ... Generated Code ...
}
// ... Other Structs ...
// ---------------
// For cod:unions
// ---------------
func (t <TYPE>) EncodeCod(bs []byte) []byte {
// ... Generated Code ...
}
func (t *<TYPE>) DecodeCod(bs []byte) (int, error) {
// ... Generated Code ...
}
func (t <TYPE>) Get() any {
// ... Generated Code ...
}
func (t *<TYPE>) Set(v any) {
// ... Generated Code ...
}
func New<TYPE>(v any) <TYPE> {
// ... Generated Code ...
}
Inspirations
- https://github.com/mus-format/mus-go
- https://github.com/alecthomas/go_serialization_benchmarks
- https://github.com/Kelindar/binary