Bebop is a simple and fast serialisation format. You write bebop schemas, and from these bop files different tools produce source code in a number of different languages for serialising and deserialising data to and from the bebop wire format.
This repo builds a tool that generates Go source code from bop files.
One way you could use this is:
go get wellquite.org/bebop/cmd/bebop@latest
- Create your bop file, e.g.
protocol.bop
Alongside it, create a
generate.go
file, with the following content:package mypackage //go:generate go run wellquite.org/bebop/cmd/bebop -i ./protocol.bop -o ./protocol.go -p my/full/package/name/mypackage
Then, whenever you do a
go generate ./...
in your project, thisbebop
tool will generateprotocol.go
from yourprotocol.bop
schema definition.
What features are supported?
Basically everything I could figure out from the upstream
documentation; apart from the readonly
flag which can't really be
implemented in Go.
- All the basic types (including
guid
anddate
) - All the composite types (arrays and maps, to any nested depth)
- Consts, Enums (including the
flags
flag), Structs, Messages and Unions - Opcodes, deprecated flags, comments
- Imports
Generated API
Imagine a bebop enum
, struct
, message
or union
, named
Foo
. This tool will generate the following API:
// EncodeBebop writes the value to the writer, serialized as Bebop.
func (*Foo) EncodeBebop(writer io.Writer) error
// DecodeBebop attempts to read Bebop from the reader and to
// deserialize it into the value.
func (*Foo) DecodeBebop(reader io.Reader) error
// MarshalBebop writes the value into the buf, serialized as
// Bebop. The slice of the buf written to is returned. If the buf is too
// small, a new buf is created, written to, and returned.
func (*Foo) MarshalBebop(buf []byte) ([]byte, error)
// UnmarshalBebop attempts to read Bebop from the buf and to
// deserialize it into the value.
func (*Foo) UnmarshalBebop(buf []byte) (int, error)
// SizeBebop returns the number of bytes this value uses when
// serialized to Bebop.
func (*Foo) SizeBebop() int
If you have specified an opcode, there will be:
// [opcode(653)]
func (*Foo) Opcode() uint32
Because I support imports, more functions must be public than one
might like, because they may be needed by other generated code in
other packages. All the functions that are not intended for public use
have comments // Not intended for public use.
and all those
functions are named starting Bebop
.