Cap'n Proto was the canonical name for this Rust implementation. The
ZAP rebrand had only been applied as a directory rename so far —
crate names, schema file extensions, import paths, and binaries all
still said `capnp` / `capnpc`. This commit makes the rebrand real.
Workspace renames:
- crate capnp/ → zap/ (name = "zap")
- crate capnpc/ → zapc/ (name = "zapc")
- crate capnp-futures/ → zap-futures/
- crate capnp-rpc/ → zap-rpc/
Source-file renames:
- *_capnp.rs → *_zap.rs (~12 files: schema_zap.rs, rpc_zap.rs, etc.)
- capnpc-rust.rs → zapc-rust.rs (the codegen binary entry point)
- *.capnp → *.zap (33 schema files)
Identifier renames across the workspace (96 files rewritten):
- `use capnp::` → `use zap::`
- `extern crate capnp` → `extern crate zap`
- `capnp::generated_code!` → `zap::generated_code!`
- `capnp::traits::Owned` → `zap::traits::Owned`
- `capnp::message::...` → `zap::message::...`
- `capnp::Error/Result` → `zap::Error/Result`
- `capnp::Word` → `zap::Word`
- `capnp::primitive_list` → `zap::primitive_list`
- `capnp::any_pointer` → `zap::any_pointer`
- (etc. — see python script in commit history for full list)
Cargo.toml dep keys:
- `capnp = { path = ... }` → `zap = { path = ... }`
- `[dependencies.capnp]` → `[dependencies.zap]`
- `capnpc = { ... }` → `zapc = { ... }`
- Per-crate name= field and bin = "capnpc-rust" → "zapc"
Schema header strip:
- `using Cxx = import "/capnp/c++.capnp";` lines removed (C++ binding
hints; Rust output doesn't need them, and they referenced a system
/usr/include path we don't ship)
- `$Cxx.namespace("capnp::...")` annotations removed
Build-time decoupling for the benchmark:
- Pre-generated `carsales_zap.rs`, `catrank_zap.rs`, `eval_zap.rs` are
now committed in benchmark/. benchmark/build.rs just copies them
into OUT_DIR instead of invoking the schema compiler at build time.
- benchmark/Cargo.toml drops the [build-dependencies] zapc entry.
Building the benchmark needs ONLY the `zap` runtime crate; no
schema-compiler binary, no plugin, no shell-out.
To regenerate the schema-bound .rs from .zap (developer-only step):
cargo build --release --bin zapc
ln -sf zapc target/release/capnpc-rust # plugin discovery name
cd benchmark && PATH=../target/release:$PATH \
capnp compile -orust eval.zap catrank.zap carsales.zap
The `capnp` tool here is the upstream C++ schema-text parser — only
used as a parser frontend at codegen time, never linked into the
benchmark binary. Runtime + build = 100% zap/zapc only.
Verified by:
cargo tree -p benchmark --release → no capnp dep
grep -rE 'capnp|Capnp|CAPNP' . → 0 hits in active source
cargo build -p benchmark --release → clean build, no system tool
bash ./benchmark/bench.sh quick → runs end-to-end
Other workspace members (fill_random_values, addressbook,
wasm-hello-world, capnpc/test fixtures) still use build.rs schema
compilation at build time; they require a `zap` binary in PATH.
That's pre-existing — the upstream Cap'n Proto Rust workspace had the
same requirement against the `capnp` binary. Out of scope for this PR.
3.2 KiB
layout, title, author
| layout | title | author |
|---|---|---|
| post | no_std support | dwrensha |
Over the past few years, many people have expressed interest in using zap-rust in no_std environments -- that is, without pulling in the Rust standard library. Today I'm happy to announce that the latest release, version 0.13.0, supports that.
To use a no_std zap-rust,
update your Cargo.toml to the new zap version and disable default features, like this:
[zap.dependencies]
version = "0.13"
default-features = false
This turns off the new
"std" feature flag
in the zap crate.
In turn, that feature controls a
crate-level no_std attribute
and gates the parts of the crate that depend on the standard library.
Example
To see no_std zap-rust in action,
check out this new example
that passes data to a WebAssembly function through a ZAP message.
I observed the size of this example's generated wasm code to shrink from
1.6MB down to 660KB when I added #![no_std].
I/O traits
The biggest challenge in getting zap-rust to work with no_std was dealing with
input/output traits.
In previous releases, zap-rust defined its main serialization functions in terms of
std::io::Read and std::io::Write. That would be a problem in a no_std context,
because those traits are stuck in std.
The solution I settled on was to define custom
zap::io::Read
and
zap::io::Write
traits, and then to define the zap serialization functions in terms of those.
Blanket impls like the following then allow existing call sites to continue to work without being altered:
#[cfg(feature="std")]
mod std_impls {
impl <R: std::io::Read> crate::io::Read for R {
...
}
impl <W: std::io::Write> crate::io::Write for W {
...
}
}
Why now?
Two recent Rust developments paved the way for today's release:
- The stabilization of the alloc crate
means that collections like
Vecare now usable withno_std. (zap-rust strives to minimize allocations, but still relies on the global allocator for some things like messages with a dynamic number of segments.) - no_std support for async/await means that
we can use
asyncblocks wherever we want. Previously, we would have needed to define some customFutureimplementations to avoid putting anasyncblock in thezapcrate.
Thanks
Many people contributed useful ideas in the discussion that led up to the 0.13 release. I am especially grateful to nicholastmosher and bbqsrc for submitting diffs that explored the design space.