Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,24 @@ jobs:
# what a commit's CI proves. Find the newest tag with:
# gh release list --repo mas-bandwidth/serialize --limit 1
# Bump family-wide, deliberately, in its own commit per repo. SERIALIZE_TAG
# below is the ONE place this repository names a version of the reference.
# below is the ONE place this repository names a RELEASE of the reference; the
# corpus commit beside it names the vendoring and is a different pin for a
# different job, explained where it is declared.
# (The spec-sync job above deliberately stays on upstream main: drift DETECTION
# is that job's whole purpose.)
interop:
name: interop with the C++ reference
runs-on: ubuntu-latest
env:
SERIALIZE_TAG: v1.16.0
# TWO PINS, TWO JOBS FOR THEM. SERIALIZE_TAG above is the wire
# compatibility pin and is a released tag. SERIALIZE_CORPUS_COMMIT is the
# commit STANDARD.md and conformance/ in this repository are vendored
# from, and the reference conformance runner is built from it, because a
# runner older than the corpus cannot drive the operations the corpus
# carries. The spec-sync job proves this repository's vendored copies
# match upstream main, so this commit is upstream main at the vendoring.
SERIALIZE_CORPUS_COMMIT: 7e0515e952f3373d001ec1899adf9dffb823e1c5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
Expand All @@ -100,15 +110,20 @@ jobs:
- name: Check out the C++ reference at the pinned release
run: git clone --quiet --depth 1 --branch "$SERIALIZE_TAG" https://github.com/mas-bandwidth/serialize.git /tmp/cpp-serialize

- name: Check out the C++ reference at the corpus commit
run: |
git clone --quiet https://github.com/mas-bandwidth/serialize.git /tmp/cpp-serialize-corpus
git -C /tmp/cpp-serialize-corpus checkout --quiet "$SERIALIZE_CORPUS_COMMIT"

# Asserts stay ON (no -DNDEBUG): they are the C++ half of "API misuse
# panics", and the degenerate ranges the message carries must pass with the
# library's own checks enabled rather than around them. No -ffp-contract=off
# either: the compressed float arithmetic is pinned in the library's source,
# and building with default flags proves that rather than masking it.
- name: Build the C++ halves against the pinned library
- name: Build the C++ halves
run: |
c++ -O2 -std=c++17 -Wall -I /tmp/cpp-serialize -o /tmp/cpp_interop interop/interop.cpp
c++ -O2 -std=c++17 -Wall -I /tmp/cpp-serialize -o /tmp/cpp_conformance /tmp/cpp-serialize/conformance.cpp
c++ -O2 -std=c++17 -Wall -I /tmp/cpp-serialize-corpus -o /tmp/cpp_conformance /tmp/cpp-serialize-corpus/conformance.cpp

- name: Both halves write byte identical wire data
run: |
Expand Down
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ specification in
[mas-bandwidth/serialize](https://github.com/mas-bandwidth/serialize),
which CI checks for drift — is the authority on every byte.

Version 1.1.1 (`SerializeUtil.VERSION`).
Version 1.1.2 (`SerializeUtil.VERSION`).

## Getting it

Expand All @@ -26,7 +26,7 @@ package is not yet published: there is no artifact on Maven Central under any
coordinate, and there is no Maven or Gradle build here to produce one.
Publishing it is a separate round.

Fifteen files under `src/serialize/`, zero dependencies, Java 17 language
Sixteen files under `src/serialize/`, zero dependencies, Java 17 language
level. Take it either way:

**Copy the package in** — drop `src/serialize/` into your own source tree and
Expand Down Expand Up @@ -85,6 +85,9 @@ primitive-specialized holder cells (`IntRef`, `LongRef`, `BoolRef`,
pairs of long halves, mirroring the family's emulated pair types.
- **Utilities**: `SerializeUtil` — `bitsRequired` / `64` / `128`, zig-zag
conversion, the compressed-float step count.
- **Composition**: `serializeObject`, which runs a nested `Serializer`
inline and contributes no bytes of its own — no framing, no length
prefix, no alignment inserted around it.
- **The bitpacker underneath**: `BitWriter` and `BitReader`, the family
wire in branchless 64-bit window loads. Every stream and both
bitpackers expose `reset(...)` for allocation-free reuse.
Expand Down Expand Up @@ -146,11 +149,19 @@ gates.

The suite runs every vector in [`conformance/`](conformance), the
family's shared corpus, vendored from mas-bandwidth/serialize and
checked for drift by CI: an accepted vector must decode to the stated
value and consume the stated bits, a refused vector must be refused, and
nothing regenerates its own expectations. It also pins the family's
golden vectors byte for byte — the golden wire message covering every
operation class, the discriminating compressed-float vectors (bit
checked for drift by CI. The directory is discovered at run time rather
than named in the source, and a vector whose operation the runner cannot
drive fails rather than being skipped. An accepted vector must decode to
the stated value and consume the stated bits; a vector marked
`writer = canonical` is re-emitted through the write stream and compared
byte for byte, flush included; a vector carrying `measure_at_least` is
held to that floor on the measure stream. A refused vector must be
refused, must leave the caller's scalar destination unwritten, and must
leave the stream terminal, which is checked by behavior: every later step
refuses too, and a further read fails, consumes no bits and writes
nothing. Nothing regenerates its own expectations. The suite also pins
the family's golden vectors byte for byte — the golden wire message
covering every operation class, the discriminating compressed-float vectors (bit
patterns, not tolerances), the string and wide-string pins, every
relative-integer tier, and the fixed point shapes at every group count —
plus a sabotage sweep proving every consumed bit of the golden stream is
Expand Down
Loading
Loading