mirror of
https://github.com/zap-proto/zip.git
synced 2026-10-19 15:38:57 +00:00
Writing the manifest fragments during macro expansion had a failure nobody would see: rustc reuses a cached expansion, so a macro that did not run left its file saying what the source used to say. A rebuild after deleting one fragment recompiled the crate and did not restore it — measured — which means a service could publish a document that quietly disagreed with its own code, the one failure this whole design exists to prevent. So the description is compiled IN. `#[derive(zip::Wire)]` gives a type `stated()`, its manifest entry as a `&'static str`, and `reach()`, which claims its entry and then asks the types of its fields — the graph is walked by the types themselves, because a macro sees only the item it is on. `#[zip::ops]` joins the ops half to whatever the ops reach and hands back `manifest()`. The service prints it on `--manifest`, so what is projected is what this build declared and there is nothing to go stale. That leaves one shape for a manifest instead of two, so zipc reads a document and no longer merges a directory of fragments; what it refused about a directory it now refuses about the document, in Manifest.Check beside the version rule. The example's build script tolerates the documents not existing yet, which is the state of the one build that makes them.
27 lines
1.1 KiB
Rust
27 lines
1.1 KiB
Rust
// SPDX-License-Identifier: BSD-3-Clause-Eco
|
|
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
//! The documents this service publishes, if they have been projected yet.
|
|
//!
|
|
//! They are checked in, so a clone builds with them in hand. But they are made
|
|
//! FROM this crate — zipc reads the manifest the compiled binary prints — so
|
|
//! the first build of a new service necessarily happens before they exist. This
|
|
//! says so instead of failing: no documents yet, and `make gen` makes them.
|
|
|
|
use std::path::PathBuf;
|
|
|
|
fn main() {
|
|
println!("cargo:rerun-if-changed=gen");
|
|
let out = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR"));
|
|
let mut body = String::new();
|
|
for (name, file) in [("OPENAPI", "gen/openapi.json"), ("MCP", "gen/mcp.json")] {
|
|
let text = std::fs::read_to_string(file).unwrap_or_default();
|
|
body.push_str(&format!(
|
|
"pub const {name}: &str = {:?};\n",
|
|
if text.is_empty() { "" } else { text.as_str() }
|
|
));
|
|
}
|
|
std::fs::write(out.join("documents.rs"), body).expect("write documents.rs");
|
|
}
|