zapc/lib.rs
1//! zapc — ZAP schema compiler.
2//!
3//! Parses `.zap` schema files into an in-memory IR (`Schema`) and
4//! emits Rust readers/writers via `codegen::emit_rust`. Hand-rolled
5//! parser — no dependency on upstream Cap'n Proto tooling.
6//!
7//! # Schema syntax
8//!
9//! ```text
10//! @0xc0a8b5e0e5f0a000; // file id (random 64-bit, hex)
11//!
12//! struct KeysSnapshot {
13//! application @0 :Text;
14//! seq @1 :UInt64;
15//! jwksJson @2 :Data;
16//! }
17//!
18//! struct Ping { nonce @0 :UInt64; }
19//! ```
20//!
21//! Supported types: `Bool`, `UInt8/16/32/64`, `Int8/16/32/64`,
22//! `Float32/64`, `Text` (UTF-8 string), `Data` (byte slice).
23//!
24//! Each field has a stable index. The on-wire layout is the canonical
25//! ZAP packing (matches Go luxfi/zap):
26//!
27//! - Fixed-size primitives are packed at the field offset (computed
28//! from field index × max(field-size, alignment)).
29//! - `Text` and `Data` store an i32 LE relative offset + u32 LE
30//! length at the field offset; payload bytes follow the struct.
31//! - Structs are 8-byte aligned.
32
33pub mod codegen;
34pub mod parser;
35
36pub use codegen::emit_rust;
37pub use parser::{Field, FieldType, Schema, Struct};
38
39#[derive(Debug, thiserror::Error)]
40pub enum Error {
41 #[error("zapc: parse error at {0}: {1}")]
42 Parse(String, String),
43 #[error("zapc: io: {0}")]
44 Io(#[from] std::io::Error),
45}
46
47pub type Result<T> = std::result::Result<T, Error>;
48
49/// Convenience for build.rs callers — parse + emit in one shot.
50///
51/// `out_path` is typically `concat!(env!("OUT_DIR"), "/zap_schema.rs")`.
52pub fn compile_to_rust(schema_path: &std::path::Path, out_path: &std::path::Path) -> Result<()> {
53 let src = std::fs::read_to_string(schema_path)?;
54 let schema = parser::parse(&src)?;
55 let rs = codegen::emit_rust(&schema);
56 std::fs::write(out_path, rs)?;
57 Ok(())
58}