All notable changes to pbwire. Versions follow SemVer; VERSION is the
source of truth and scripts/sync-versions.sh propagates it to every
binding manifest.
pbw_encode_delimited_to() and pbw_decode_delimited_ctx[_limits](): the
caller-buffer and pbw_ctx twins of the length-delimited framing, so a
framed stream decodes into a workspace arena with no per-frame malloc and
a frame is written without one either. The declared frame length is now
checked against max_bytes in pbw_decode_delimited_limits() too, before
the body is decoded, matching pbw_istream_next().bindings/embedded: pbwe_encode_delimited, pbwe_decode_delimited and
pbwe_decode_delimited_desc, so the facade covers both the bare and the
length-prefixed form without carrying varint code of its own.SECURITY.md: vulnerability reporting policy and supported versions.NOTICE: third-party attributions (descriptor.proto wire shape, test
baselines).scripts/release-check.sh (make release-check): release dry-run — version
consistency, tag-vs-VERSION match, changelog entry, artifact presence.tests/fuzz_decode.c (make fuzz): stdin-fed decode/encode/visit fuzz
harness; CI runs it on a fixed corpus plus a short deterministic mutation
burst.FeatureSet support in pbw_descriptor_set_load(): file-level
and per-field field_presence / repeated_field_encoding are honored
instead of treating every edition as proto3 defaults.FileDescriptorSet services are loaded and queryable
(pbw_schema_service_*, pbw_service_*); the core still does no RPC.message_set_wire_format decode
group items into their extension fields and re-encode them byte-identically.bindings/MIGRATING.md: per-language migration notes from the official
runtimes.examples/gateway/: proto3 + JSON + unknown-field passthrough tutorial.pbw_descriptor_set_load_limits(): the pbw_limits byte/nesting caps applied
to the descriptor set itself (PBW_ERR_LIMIT on oversize/hostile sets), plus
a tests/data/fuzz-desc/ corpus replayed by make fuzz through it.pbw_service_resolve(): service + method name to input/output descriptors,
so a transport can route without the core doing RPC.pbw_timestamp/duration_from_millis,
pbw_fieldmask_path_count/at (the to_millis side already existed).tests/data/fuzz-json/ + tests/data/fuzz-text/ corpora: make fuzz replays
the JSON mapping and text format through the same harness as the wire bytes.scripts/check-llms.sh (+ CI docs-sync job): llms.txt must name every
public pbw_* function, so the AI-retrieval summary cannot drift from the API.test_threads under ThreadSanitizer; nightly runs every ubuntu-capable
binding self-check; release artifacts carry SLSA provenance attestations.
New binding-asan job: the Python/Ruby/Node extensions build instrumented
and run their suites under ASan (LEAK detection stays on for Python; the
Ruby/Node interpreters leak on their own, so they run ASan-only).PBW_EXTRA_CFLAGS hook in the Ruby/Node build.sh drivers (empty by
default; the ASan job passes -fsanitize=address through it).Schema <-> MessageType references are GC-tracked
now (dropping a schema in a loop holds RSS flat; ASan/LSan clean).pbw_schema_error() after
pbw_schema_free() on the load-failure path (found by the ASan job).GenericCodec/PbCodec.setRetainCap(bytes) caps the per-thread
encode buffer (1 MiB default, 0 keeps nothing); Kotlin/Scala/Clojure
inherit it through the shared runtime.pbwire:set_opts([{retain_cap, Bytes}]) caps every scheduler
context (existing and future, under the cache lock); Elixir passes
retain_cap: through Pbwire.load_schema/2 (needs Hex :pbwire past
this release to take effect).binding-asan (PR): Python/Ruby/Node extensions built with
-fsanitize=address, run under their own suites.ports (PR): 32-bit (-m32 ILP32) and big-endian (s390x under
qemu-user) through scripts/check-ports.sh.api-docs (PR): Doxygen renders the public headers, uploaded as an
artifact.codegen-linux / codegen-apple (nightly): every binding's
generated-model test, split by toolchain family.make api-docs (Doxyfile): API reference from include/, the protobuf
importer headers included; output lands in build/doxygen/html.ROADMAP.md: what is done, what is never, what is next.docs/examples.md: one runnable round trip per binding, with the exact command.src/wkt.c (pbw_any_pack,
pbw_any_type_url/payload, pbw_timestamp/duration_to_millis) over field
numbers only; the core still special-cases no WKT.bindings/embedded/: static-memory facade over the C core for
microcontrollers — pbwe_open/build/decode/encode over one pbw_ctx,
caller-owned encode buffers, pbwe_set_limits for bounded input,
pbwe_open's descriptor limit for the startup allocation and
pbwe_decode_desc for a type fixed at build time. Covered by make test
and ctest, formatted and gated with the rest of the C sources..proto file or message named after a host keyword
produced code that did not compile. Go, Rust and Zig now sanitize the
derived package/module identifiers (struct.proto becomes package
struct_pbwire, module r#struct, alias struct_pbwire), Dart imports
sibling models under an _imp_ prefix (a dep message named Value was
ambiguous with the runtime), Lua requires siblings under _imp_<stem> (a dep
file named meta shadowed the file's own schema module and a dep named after
a Lua keyword was a syntax error), and a oneof enum member in the Java model
emitted Kind.KindCase instead of Kind<Prop>Case.src/wkt.c: pbw_timestamp/duration_to_millis() could overflow int64
when the nanosecond remainder pushed a seconds value at the edge of the
representable millisecond range over the bound (signed-integer overflow is
undefined behaviour). The range check now leaves room for the sub-second
part and reports PBW_ERR_LIMIT.src/wire.c: the non-'.' decimal-separator fallback could return an end
pointer before the start of the number when the host locale's separator is
multi-byte and the parse stopped inside it.src/json.c: the JSON printer recursed over nested messages without the
PBW_MAX_DEPTH cap the text printer and both codecs apply, so a hand-built
tree deep enough to pass pbw_message_new's checks could overflow the stack
in pbw_json_print(). It now reports PBW_ERR_LIMIT at the same depth as
every other formatter.pbwire_elixir never reached Hex in any release, because
mix hex.publish runs mix docs first and the docs task aborts when
ExDoc is not a dependency. ExDoc is a only: :dev, runtime: false
dependency now, so the published package carries HexDocs without costing
consumers a dependency. The nested else: inside Pbwire.Schema.nif_opts/1
is parenthesized (Elixir 1.20 warns about the keyword ambiguity).Schema.load() / Schema.from_file() leaked the partially built
schema pbw_descriptor_set_load() hands back on failure, and reported only
"invalid data" instead of the loader's reason (every other binding already
frees and surfaces it).LEN) run for a repeated closed (proto2)
enum whose field number is 1..15 was swallowed whole into the unknown bytes,
because the link-time one-byte tag map omitted the packed-form entry for
closed enums. The reference parser keeps known values in the field and moves
each unknown value into the unknown set as one unpacked item; the map now
routes that form to read_packed(), which does the same. (Multi-byte tags,
resolved through fnum_map, always took this path.) An all-unknown run now
leaves the field absent, like an empty packed run, instead of presenting an
empty list.Big-endian correctness, found by the new s390x gate:
encode.c: precomputed tag words were written with a 32-bit store, which
byte-reverses on a big-endian host (every tag was wrong). They now go
through w_tag_word_le, which keeps the one-store fast path where the host
byte order matches the wire and spells it byte by byte elsewhere.uint32_t first (same for the parser direction).bindings/c/runtime/pbw_struct.c: fixed-width member reads and writes
copied 4 bytes into/out of a uint64_t, which lands in the wrong half on
big-endian. ld_member/st_member go through the matching integer width.-m32) correctness: the struct self-check compared doubles with
==, which x87 excess precision makes unreliable; it compares bit patterns
now (double_bits).\\u surrogate-pair
combining and Any store-error normalization).sanitizers (ASan+UBSan make test), difftest-short
(fixed-seed differential run), fuzz-short, and coverage (core-only
gcov floor) jobs; conformance also runs on a nightly schedule.bindings/embedded: static-schema facade over the C core, including the
length-delimited encode/decode entry points.pbw_encode_delimited_to(),
pbw_decode_delimited_ctx[_limits](), and
pbw_descriptor_set_load_limits() for hostile descriptor sets.FeatureSet and MessageSet wire format
are loaded and queryable; the core still does no RPC.pbw_limits depth propagation through JSON and text parsing,
list form accepted in text format, unused internal helpers removed.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |