source: code/trunk/vendor/git.sr.ht/~sircmpwn/go-bare/README.md@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 3.1 KB
RevLine 
[822]1# go-bare [![godocs.io](https://godocs.io/git.sr.ht/~sircmpwn/go-bare?status.svg)](https://godocs.io/git.sr.ht/~sircmpwn/go-bare) [![builds.sr.ht status](https://builds.sr.ht/~sircmpwn/go-bare.svg)](https://builds.sr.ht/~sircmpwn/go-bare?)
2
3An implementation of the [BARE](https://baremessages.org) message format
4for Go.
5
6**Status**
7
8This mostly works, but you may run into some edge cases with union types.
9
10## Code generation
11
12An example is provided in the `examples` directory. Here is a basic
13introduction:
14
15```
16$ cat schema.bare
17type Address {
18 address: [4]string
19 city: string
20 state: string
21 country: string
22}
23$ go run git.sr.ht/~sircmpwn/go-bare/cmd/gen -p models schema.bare models/gen.go
24```
25
26Then you can write something like the following:
27
28```go
29import "models"
30
31/* ... */
32
33bytes := []byte{ /* ... */ }
34var addr Address
35err := addr.Decode(bytes)
36```
37
38You can also add custom types and skip generating them by passing the `-s
39TypeName` flag to gen, then providing your own implementation. For example, to
40rig up time.Time with a custom "Time" BARE type, add this to your BARE schema:
41
42```
43type Time string
44```
45
46Then pass `-s Time` to gen, and provide your own implementation of Time in the
47same package. See `examples/time.go` for an example of such an implementation.
48
49## Marshal usage
50
51For many use-cases, it may be more convenient to write your types manually and
52use Marshal and Unmarshal directly. If you choose this approach, you may also
53use `git.sr.ht/~sircmpwn/go-bare/schema.SchemaFor` to generate a BARE schema
54language document describing your structs.
55
56```go
57package main
58
59import (
60 "fmt"
61 "git.sr.ht/~sircmpwn/go-bare"
62)
63
64// type Coordinates {
65// x: int
66// y: int
67// z: int
68// q: optional<int>
69// }
70type Coordinates struct {
71 X uint
72 Y uint
73 Z uint
74 Q *uint
75}
76
77func main() {
78 var coords Coordinates
79 payload := []byte{0x01, 0x02, 0x03, 0x01, 0x04}
80 err := bare.Unmarshal(payload, &coords)
81 if err != nil {
82 panic(err)
83 }
84 fmt.Printf("coords: %d, %d, %d (%d)\n",
85 coords.X, coords.Y, coords.Z, *coords.Q) /* coords: 1, 2, 3 (4) */
86}
87```
88
89### Unions
90
91To use union types, you need to define an interface to represent the union of
92possible values, and this interface needs to implement `bare.Union`:
93
94```go
95type Person interface {
96 Union
97}
98```
99
100Then, for each possible union type, implement the interface:
101
102```go
103type Employee struct { /* ... */ }
104func (e Employee) IsUnion() {}
105
106type Customer struct { /* ... */ }
107func (c Customer) IsUnion() {}
108```
109
110The IsUnion function is necessary to make the type compatible with the Union
111interface. Then, to marshal and unmarshal using this union type, you need to
112tell go-bare about your union:
113
114```go
115func init() {
116 // The first argument is a pointer of the union interface, and the
117 // subsequent arguments are values of each possible subtype, in ascending
118 // order of union tag:
119 bare.RegisterUnion((*Person)(nil)).
120 Member(*new(Employee), 0).
121 Member(*new(Customer), 1)
122}
123```
124
125This is all done for you if you use code generation.
126
127## Contributing, getting help
128
129Send patches and questions to
130[~sircmpwn/public-inbox@lists.sr.ht](mailto:~sircmpwn/public-inbox@lists.sr.ht)
Note: See TracBrowser for help on using the repository browser.