Skip to main content

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}