Add Zig 0.16 CLI port (spec parser + URL builder)#2
Merged
Conversation
Narrow Zig parallel to the Rust ItemSpec::parse and fetch::build_url, kept minimal so a later wasm target can be compared against a same-scope Rust wasm build. Network, zstd, and rendering stay in the Rust crate. https: //claude.ai/code/session_01Ei65b8fDC7sABmKnq1Wgne Co-authored-by: Claude <noreply@anthropic.com>
Restructures zig/ into lib/ (Zig sources) + src/ (TypeScript worker), matching mattzcarey/zigflare. build.zig now produces a wasm32-freestanding ReleaseSmall artifact exporting alloc, free, and resolve_url; the native CLI moves to `zig build cli` and goes through the same resolveUrl core so both surfaces are in lockstep. The worker at src/index.ts loads md_docrs.wasm, marshals the spec and optional target triple across the WASM boundary, and returns the resolved docs.rs rustdoc JSON URL. No network / zstd / rendering yet — keeps the artifact directly comparable to an equivalent Rust wasm32 build. https: //claude.ai/code/session_01Ei65b8fDC7sABmKnq1Wgne Co-authored-by: Claude <noreply@anthropic.com>
Turns the root crate into a workspace and feature-gates the HTTP / server / CLI surface (reqwest, zstd, tokio, axum, tower-http, tracing, clap) behind the `http`, `server`, and `cli` features so the pure pipeline — spec, resolve, render, cache — now compiles for `wasm32-unknown-unknown`. Adds a new `rust-wasm` workspace member exposing the exact same C ABI as `zig/lib/wasm.zig`: alloc(len) -> *u8 free(ptr, len) resolve_url(spec, target, out, out_cap) -> u32 render_markdown(json, spec, target, *len_out) -> *u8 (behind `render`) The no_mangle exports are gated to `target_arch = "wasm32"` so host tests don't shadow libc's free and cause infinite recursion during dealloc. Current sizes for `--profile wasm-release`: * resolve_url only (`--no-default-features`): 35,939 bytes * full pipeline (+render_markdown): 414,560 bytes The Zig worker at `zig/src/index.ts` works against either .wasm without changes. Porting render_markdown to Zig is the follow-up; that's where the JSON→Markdown comparison becomes apples-to-apples. https: //claude.ai/code/session_01Ei65b8fDC7sABmKnq1Wgne Co-authored-by: Claude <noreply@anthropic.com>
The previous fingerprint (0xb3f2a91c4d6e7058) was rejected by Zig 0.16's stricter validator. Replace it with the value Zig derives from the package name (.md_docrs_zig) so 'zig build' succeeds out of the box. Co-authored-by: Claude <noreply@anthropic.com>
Zig 0.16 removed std.heap.GeneralPurposeAllocator and std.process.argsAlloc in favour of main(init: std.process.Init) with an arena + Io handed in by the startup shim. cli.zig now takes that parameter, returns an exit code (!u8), and uses the new Io.File.Writer for stdout/stderr, so 'zig build cli' and 'zig build run -- ...' both succeed against the shipped 0.16.0 stdlib. Expand the native-CLI section of zig/README.md with concrete spec examples and document the exit-code convention so the binary is actually usable, not just buildable. Co-authored-by: Claude <noreply@anthropic.com>
Adds a new workspace member at wasm/ (md-docrs-wasm-compare) that loads each .wasm artifact inside an embedded wasmtime host, drives the shared resolve_url ABI through a fixed spec list, and reports byte size, output parity, and median / p95 per-call latency in one table. An optional 'wasmer' cargo feature swaps the runtime to wasmer under --runtime wasmer so ABI cost and JIT cost can be separated. wasm/build.sh builds zig (ReleaseSmall) + rust-minimal (no-default-features) + rust-full (render_markdown) and stages them as zig.wasm / rust-minimal.wasm / rust-full.wasm under wasm/artifacts/, which the harness picks up by default via CARGO_MANIFEST_DIR. Missing artifacts are skipped rather than erroring so partial runs still print something useful. Parity confirmed against all three modules on the default spec list (serde, tokio@1.52.1::sync::Mutex, anyhow::Error with target override, rustdoc-types@0.57::Crate): byte-identical output from every artifact under both runtimes. Co-authored-by: Claude <noreply@anthropic.com>
5cbf26e to
789a0c4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
zig/tree with a Zig 0.16 port of the CLI's pure-logic surface: spec grammar parsing (src/spec.zig) and docs.rs URL construction (src/url.zig), driven fromsrc/main.zig.spec.rsandfetch.rstest cases.Follow-ups
wasm32-wasi(orwasm32-unknown-unknown) targets on both sides and compare.wasmsizes.Test plan
cd zig && zig build test(requires Zig 0.16 — not installed in this sandbox, so not yet executed here)cd zig && zig build run -- serde::de::Deserializeprintshttps://docs.rs/crate/serde/latest/json/57.zstcd zig && zig build run -- tokio@1.52.1::sync::Mutex --target x86_64-unknown-linux-gnuprints the target-scoped URLhttps://claude.ai/code/session_01Ei65b8fDC7sABmKnq1Wgne