Protocol Buffers for MoonBit.
| Wire types | 5 |
| Scalar kinds | 15 |
| Syntax shapes generated and checked | 4 (proto2, proto3, editions 2023, editions 2024) |
| Official binary and JSON conformance cases passing | 2737 / 2737 |
| Official text format conformance cases passing | 440 / 440 |
| Declared conformance omissions | 0 |
| Package | Carries |
|---|---|
| wire | tags, varints, fixed-width numbers, length-delimited values, groups, zig-zag, and the reader that reports where it stopped |
| reflect | Value, Message, Enum, ListField, MapField, the descriptor records, and the global registries |
| desc | building runtime descriptors from the descriptor shape, and converting back |
| proto | binary encode and decode, size, merge, clone, equal, reset, required checks, extensions on the wire |
| json | the JSON mapping: 64-bit integers as strings, enums by name, base64 bytes, maps as objects, extensions in brackets, the Timestamp, Duration, wrapper, FieldMask and Any forms, and arbitrary JSON through Struct, Value and ListValue |
| text | the text format: fields and separators, braces and angle brackets, groups, lists, every literal form, comments, expanded Any, extensions in brackets |
| delim | varint size-delimited messages over a byte source |
| dynamic | messages, enums and extensions built at run time from descriptors |
| known | the well-known types; a thin layer over known/google/protobuf, which the plugin generated |
| parser | the .proto language: proto2, proto3 and editions, messages, maps, oneofs, groups, enums, services, reserved and extension ranges, features and custom options |
| gen | the plugin protocol and the MoonBit code generator: a request in, generated files out |
| conformance | the conformance protocol: read one format, write another, report the error |
| cmd/protoc-gen-mbt | the protoc plugin binary |
| cmd/conformance-mbt | the conformance testee: 4-byte length frames on standard input and output |
| cmd/interop-mbt | the MoonBit half of the bidirectional interop program |
pub struct Envelope {
mut i32 : Int32 // proto3, implicit presence
mut name : String? // explicit presence
nums : Array[Int32] // repeated
counts : Map[String, Int32] // map
mut pick : Envelope_Pick // oneof, as an enum
mut unknown_fields : Bytes
}let schema =
"syntax = \"proto3\";\n" +
"package hello;\n" +
"message Request { string name = 1; int32 count = 2; repeated int32 nums = 3; }\n"
let parsed = @parser.parse("hello.proto", schema) catch { _ => abort("bad schema") }
let file = @desc.build_file(parsed) catch { _ => abort("bad descriptor") }
let request = file.messages[0]
assert_eq(request.full_name, "hello.Request")
assert_eq(request.fields.length(), 3)let message = @dynamic.Message::new(request)
let name = request.field_by_name("name").unwrap()
message.set(name, @reflect.String("moon"))
let bytes = @proto.encode(message) catch { _ => abort("encode failed") }
assert_eq(bytes.length(), 6)
let back = @dynamic.Message::new(request)
@proto.decode(bytes, back) catch { _ => abort("decode failed") }
assert_eq(back.get(name).string(), "moon")let json = @json.encode(message) catch { _ => abort("JSON failed") }
assert_eq(json, "{\"name\":\"moon\"}")let text = @text.encode(message) catch { _ => abort("text failed") }
assert_eq(text, "name: \"moon\"\n")@known.register_all()
let stamp = @protobuf.Timestamp::new()
stamp.set_seconds(1_700_000_000L)
let stamp_json = @json.encode(stamp) catch { _ => abort("JSON failed") }
assert_eq(stamp_json, "\"2023-11-14T22:13:20Z\"")protoc -I . --plugin=protoc-gen-mbt=path/to/protoc-gen-mbt \
--mbt_out=src hello.proto| Suite | Cases | Passed | Skipped | Expected failures | Unexpected failures |
|---|---|---|---|---|---|
| Binary and JSON (failure_list.txt) | 2737 | 2737 | 0 | 0 | 0 |
| Text format (text_format_failure_list.txt) | 440 | 440 | 0 | 0 | 0 |
| Area | What is read |
|---|---|
| Fields | name: value, name value for message values, ; or , closing a field, { ... } and < ... > bodies |
| Groups | the group's type name or its own field name, in any case, with or without a colon, as a declared field or as an extension |
| Repeated | one element per name, or a bracketed list with , between elements |
| Scalars | decimal, 0x hexadecimal and leading-zero octal integers with a range check per width; decimal and exponent floats with an optional f suffix, .5 and -.5 forms, case-insensitive inf/infinity/nan, overflow to infinity and underflow to a signed zero |
| Strings | single or double quotes, adjacent literals joined, \a \b \f \n \r \t \v \? \\ \' \", \xNN, octal and \u/\U escapes, no raw line feed |
| Names | extensions and expanded Any payloads in brackets, where whitespace and comments are dropped and a % must introduce two hex digits |
| Refusals | an out-of-range integer, a hexadecimal or octal float literal, a number a closed enum does not declare, and a name the schema neither declares nor reserves |
| Schema | Shape covered | Warnings |
|---|---|---|
| tests/shapes/proto2.proto | required, defaults, packed repeats, extension range and a top-level extension | 0 |
| tests/shapes/proto3.proto | every scalar, repeated messages, map, enum, oneof | 0 |
| tests/shapes/edition2023.proto | file-level implicit presence, per-field packed and expanded encoding | 0 |
| tests/shapes/edition2024.proto | current edition naming rules, explicit presence, a closed enum and a delimited (group-encoded) field | 0 |
| Invariant broken | Tests that fail |
|---|---|
| Varint ten-octet limit | protowire: the largest varint takes ten octets, an eleventh overflows; varint refuses an eleventh octet |
| Unknown-field preservation | proto: Marshal and Unmarshal keep a scalar alongside an unknown field; unknown fields survive a round-trip |
| 64-bit integers as JSON strings | protojson: 64-bit integers are strings on the wire; binary to JSON keeps every scalar and the composite fields; the scalar mapping and its fixed text |
| Script | Checks |
|---|---|
| scripts/setup-protoc.sh | pins protoc 36.2 and prints PROTOC / PROTOC_INCLUDE |
| scripts/conformance.sh | runs the official runner with both failure lists, or the framing self-check when no runner is present |
| scripts/check-failure-lists.sh | the binary/JSON list is empty; every text-format entry has a name and a reason |
| scripts/check-conformance-types.sh | the checked-in descriptors match the pinned descriptor set |
| scripts/vendor_conformance_descriptors.sh | regenerates that descriptor set from a protobuf 36.2 checkout |
| scripts/check-codegen.sh | the four generated schemas compile warning-free |
| scripts/check-gointerop.sh | the checked-in Go schema is exactly what protoc-gen-go v1.36.12 emits |
| scripts/interop.sh | the fixture's reference bytes are what protoc itself encodes |
| scripts/interop-go.sh | Go and MoonBit encode and decode each other's bytes |
| scripts/mutation-check.sh | the three mutation checks above |
| scripts/generate-known.sh | regenerates the well-known package from the protobuf includes |
| scripts/check_snippets.py | every MoonBit block in this file and in the skill compiles against the source |
Install
Download zipProtocol Buffers for MoonBit.