bare

package module
v0.0.0-...-cbd509d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2024 License: Apache-2.0 Imports: 9 Imported by: 1

README

go-barish

An implementation of a BARE-like message format for Go. This is a fork of go-bare.

Status

This mostly works, but you may run into some edge cases with union types.

Changes from upstream

Not much yet.

We intend to remove all external dependencies and remove some limitations around integer sizes.

Code generation

An example is provided in the examples directory. Here is a basic introduction:

$ cat schema.bare
type Address {
	address: [4]string
	city: string
	state: string
	country: string
}
$ go run git.sr.ht/~runxiyu/go-bareish/cmd/gen -p models schema.bare models/gen.go

Then you can write something like the following:

import "models"

/* ... */

bytes := []byte{ /* ... */ }
var addr Address
err := addr.Decode(bytes)

You can also add custom types and skip generating them by passing the -s TypeName flag to gen, then providing your own implementation. For example, to rig up time.Time with a custom "Time" BARE type, add this to your BARE schema:

type Time string

Then pass -s Time to gen, and provide your own implementation of Time in the same package. See examples/time.go for an example of such an implementation.

Marshal usage

For many use-cases, it may be more convenient to write your types manually and use Marshal and Unmarshal directly. If you choose this approach, you may also use git.sr.ht/~runxiyu/go-bareish/schema.SchemaFor to generate a BARE schema language document describing your structs.

package main

import (
    "fmt"
    "git.sr.ht/~runxiyu/go-bareish"
)

// type Coordinates {
//    x: int
//    y: int
//    z: int
//    q: optional<int>
// }
type Coordinates struct {
    X uint
    Y uint
    Z uint
    Q *uint
}

func main() {
    var coords Coordinates
    payload := []byte{0x01, 0x02, 0x03, 0x01, 0x04}
    err := bare.Unmarshal(payload, &coords)
    if err != nil {
        panic(err)
    }
    fmt.Printf("coords: %d, %d, %d (%d)\n",
        coords.X, coords.Y, coords.Z, *coords.Q) /* coords: 1, 2, 3 (4) */
}
Unions

To use union types, you need to define an interface to represent the union of possible values, and this interface needs to implement bare.Union:

type Person interface {
	Union
}

Then, for each possible union type, implement the interface:

type Employee struct { /* ... */ }
func (e Employee) IsUnion() {}

type Customer struct { /* ... */ }
func (c Customer) IsUnion() {}

The IsUnion function is necessary to make the type compatible with the Union interface. Then, to marshal and unmarshal using this union type, you need to tell go-bare about your union:

func init() {
    // The first argument is a pointer of the union interface, and the
    // subsequent arguments are values of each possible subtype, in ascending
    // order of union tag:
    bare.RegisterUnion((*Person)(nil)).
      Member(*new(Employee), 0).
      Member(*new(Customer), 1)
}

This is all done for you if you use code generation.

Documentation

Overview

An implementation of the BARE message format for Go.

https://git.sr.ht/~sircmpwn/bare

See the git repository for usage examples:

https://git.sr.ht/~runxiyu/go-bareish

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidStr = errors.New("String contains invalid UTF-8 sequences")
View Source
var ErrLimitExceeded = errors.New("Maximum message size exceeded")

Use MaxUnmarshalBytes to prevent this error from occuring on messages which are large by design.

Functions

func Marshal

func Marshal(val interface{}) ([]byte, error)

Marshals a value (val, which must be a pointer) into a BARE message.

The encoding of each struct field can be customized by the format string stored under the "bare" key in the struct field's tag.

As a special case, if the field tag is "-", the field is always omitted.

func MarshalWriter

func MarshalWriter(w *Writer, val interface{}) error

Marshals a value (val, which must be a pointer) into a BARE message and writes it to a Writer. See Marshal for details.

func MaxArrayLength

func MaxArrayLength(length uint64)

MaxArrayLength sets maximum number of elements in array. Defaults to 4096 elements

func MaxMapSize

func MaxMapSize(size uint64)

MaxMapSize sets maximum size of map. Defaults to 1024 key/value pairs

func MaxUnmarshalBytes

func MaxUnmarshalBytes(bytes uint64)

MaxUnmarshalBytes sets the maximum size of a message decoded by unmarshal. By default, this is set to 32 MiB.

func Unmarshal

func Unmarshal(data []byte, val interface{}) error

Unmarshals a BARE message into val, which must be a pointer to a value of the message type.

func UnmarshalBareReader

func UnmarshalBareReader(r *Reader, val interface{}) error

func UnmarshalReader

func UnmarshalReader(r io.Reader, val interface{}) error

Unmarshals a BARE message into value (val, which must be a pointer), from a reader. See Unmarshal for details.

Types

type Int

type Int int64

Int is a variable-length encoded signed integer.

type Marshalable

type Marshalable interface {
	Marshal(w *Writer) error
}

A type which implements this interface will be responsible for marshaling itself when encountered.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

A Reader for BARE primitive types.

func NewReader

func NewReader(base io.Reader) *Reader

Returns a new BARE primitive reader wrapping the given io.Reader.

func (*Reader) ReadBool

func (r *Reader) ReadBool() (bool, error)

func (*Reader) ReadData

func (r *Reader) ReadData() ([]byte, error)

Reads arbitrary data whose length is read from the message.

func (*Reader) ReadDataFixed

func (r *Reader) ReadDataFixed(dest []byte) error

Reads a fixed amount of arbitrary data, defined by the length of the slice.

func (*Reader) ReadF32

func (r *Reader) ReadF32() (float32, error)

func (*Reader) ReadF64

func (r *Reader) ReadF64() (float64, error)

func (*Reader) ReadI16

func (r *Reader) ReadI16() (int16, error)

func (*Reader) ReadI32

func (r *Reader) ReadI32() (int32, error)

func (*Reader) ReadI64

func (r *Reader) ReadI64() (int64, error)

func (*Reader) ReadI8

func (r *Reader) ReadI8() (int8, error)

func (*Reader) ReadInt

func (r *Reader) ReadInt() (int64, error)

func (*Reader) ReadString

func (r *Reader) ReadString() (string, error)

func (*Reader) ReadU16

func (r *Reader) ReadU16() (uint16, error)

func (*Reader) ReadU32

func (r *Reader) ReadU32() (uint32, error)

func (*Reader) ReadU64

func (r *Reader) ReadU64() (uint64, error)

func (*Reader) ReadU8

func (r *Reader) ReadU8() (uint8, error)

func (*Reader) ReadUint

func (r *Reader) ReadUint() (uint64, error)

type Uint

type Uint uint64

Uint is a variable-length encoded unsigned integer.

type Union

type Union interface {
	IsUnion()
}

Any type which is a union member must implement this interface. You must also call RegisterUnion for go-bare to marshal or unmarshal messages which utilize your union type.

type UnionTags

type UnionTags struct {
	// contains filtered or unexported fields
}

func RegisterUnion

func RegisterUnion(iface interface{}) *UnionTags

Registers a union type in this context. Pass the union interface and the list of types associated with it, sorted ascending by their union tag.

func (*UnionTags) Member

func (ut *UnionTags) Member(t interface{}, tag uint64) *UnionTags

func (*UnionTags) TagFor

func (ut *UnionTags) TagFor(v interface{}) (uint64, bool)

func (*UnionTags) TypeFor

func (ut *UnionTags) TypeFor(tag uint64) (reflect.Type, bool)

type Unmarshalable

type Unmarshalable interface {
	Unmarshal(r *Reader) error
}

A type which implements this interface will be responsible for unmarshaling itself when encountered.

type UnsupportedTypeError

type UnsupportedTypeError struct {
	Type reflect.Type
}

func (*UnsupportedTypeError) Error

func (e *UnsupportedTypeError) Error() string

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

A Writer for BARE primitive types.

func NewWriter

func NewWriter(base io.Writer) *Writer

Returns a new BARE primitive writer wrapping the given io.Writer.

func (*Writer) WriteBool

func (w *Writer) WriteBool(b bool) error

func (*Writer) WriteData

func (w *Writer) WriteData(data []byte) error

Writes arbitrary data whose length is encoded into the message.

func (*Writer) WriteDataFixed

func (w *Writer) WriteDataFixed(data []byte) error

Writes a fixed amount of arbitrary data, defined by the length of the slice.

func (*Writer) WriteF32

func (w *Writer) WriteF32(f float32) error

func (*Writer) WriteF64

func (w *Writer) WriteF64(f float64) error

func (*Writer) WriteI16

func (w *Writer) WriteI16(i int16) error

func (*Writer) WriteI32

func (w *Writer) WriteI32(i int32) error

func (*Writer) WriteI64

func (w *Writer) WriteI64(i int64) error

func (*Writer) WriteI8

func (w *Writer) WriteI8(i int8) error

func (*Writer) WriteInt

func (w *Writer) WriteInt(i int64) error

func (*Writer) WriteString

func (w *Writer) WriteString(str string) error

func (*Writer) WriteU16

func (w *Writer) WriteU16(i uint16) error

func (*Writer) WriteU32

func (w *Writer) WriteU32(i uint32) error

func (*Writer) WriteU64

func (w *Writer) WriteU64(i uint64) error

func (*Writer) WriteU8

func (w *Writer) WriteU8(i uint8) error

func (*Writer) WriteUint

func (w *Writer) WriteUint(i uint64) error

Directories

Path Synopsis
cmd
gen

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL