moonproto

Protocol Buffers · MoonBit

Protocol Buffers for MoonBit.

Binary, JSON and text encodings, the descriptor model, and a protoc plugin that writes ordinary structs — no hidden dynamic message.

$ moon add moonbitstack/moonproto
envelope.protosource
message Envelope {
  int32  id     = 1;
  string name   = 2;
  map<string, int32> counts = 3;
  Color  color  = 4;
}
wire17 bytes

08 2a 12 04 6d 6f 6f 6e 1a 05 0a 01 61 10 01 20 01

decoded4 fields
1 id42
2 name"moon"
3 counts{"a": 1}
4 colorBLUE
5wire types
15scalar kinds
3encodings
2editions · 2023, 2024

One message, three encodings

Every encoder walks the same descriptor through the same trait, so a message type implements the mapping once.

1 binary
// 17 bytes, field 1 to 4
08 2a
12 04 6d 6f 6f 6e
1a 05 0a 01 61 10 01
20 01
2 JSON
{
  "id": 42,
  "name": "moon",
  "counts": {
    "a": 1
  },
  "color": "BLUE"
}
3 text
id: 42
name: "moon"
counts {
  key: "a"
  value: 1
}
color: BLUE

What is in the box

One module, thirteen packages. Import the ones a program needs.

0x08

Binary

Varints, fixed-width numbers, length-delimited values and groups. Unknown fields are kept and written back.

{ }

JSON

64-bit integers as strings, enums by name, bytes in base64, and the well-known type forms.

a: 1

Text

The full grammar: groups, lists, separators, octal and hexadecimal literals, comments.

struct

Generated structs

protoc-gen-mbt writes a struct whose fields are the protobuf fields. Repeated becomes Array, map becomes Map, oneof becomes an enum.

desc

Descriptors at run time

A .proto parser builds the descriptor model in memory, so a schema can be read without a code generation step.

reflect

One trait

Encode, decode, size, merge, JSON and text all reach a message through reflect.Message.

Take a message apart

The playground writes a schema to bytes, then reads the bytes back as JSON and text. Every value comes from this library.

Open the playground