Skip to main content

protoc_gen_rust_temporal/
lib.rs

1//! `protoc-gen-rust-temporal` library entry point.
2//!
3//! The binary in `main.rs` is a thin stdin/stdout shell; the actual
4//! `CodeGeneratorRequest -> CodeGeneratorResponse` pipeline lives here so
5//! tests (and the eventual golden harness) can exercise it without spawning a
6//! subprocess.
7//!
8//! Phase 0 ships only the plumbing: `run_with_pool` accepts a descriptor pool
9//! that already has `temporal.v1.*` extensions attached (per `main.rs`'s
10//! descriptor-pool extraction trick), plus the set of files the caller asked
11//! the plugin to generate. Phase 1 wires up `parse → validate → render`.
12
13use std::collections::HashSet;
14
15use anyhow::Result;
16use prost_reflect::DescriptorPool;
17use prost_types::compiler::code_generator_response::File;
18
19pub mod model;
20pub mod parse;
21pub mod render;
22pub mod validate;
23
24/// Generated prost types for cludden's `temporal.v1.*` annotation schema and
25/// the transitively-referenced `temporal.api.enums.v1` enums. The parser uses
26/// `prost-reflect` against the descriptor pool, but these types are exposed
27/// for downstream introspection (e.g. tests round-tripping options).
28pub mod temporal {
29    pub mod v1 {
30        include!(concat!(env!("OUT_DIR"), "/temporal.v1.rs"));
31    }
32    pub mod api {
33        pub mod enums {
34            pub mod v1 {
35                include!(concat!(env!("OUT_DIR"), "/temporal.api.enums.v1.rs"));
36            }
37        }
38    }
39}
40
41/// Run the plugin pipeline against a fully-populated descriptor pool.
42///
43/// `files_to_generate` is the set of `.proto` file paths the plugin was asked
44/// to emit code for (mirrors `CodeGeneratorRequest::file_to_generate`).
45pub fn run_with_pool(
46    pool: &DescriptorPool,
47    files_to_generate: &HashSet<String>,
48) -> Result<Vec<File>> {
49    let services = parse::parse(pool, files_to_generate)?;
50    let mut files = Vec::with_capacity(services.len());
51    for service in &services {
52        validate::validate(service)?;
53        let content = render::render(service);
54        let name = output_file_name(service);
55        files.push(File {
56            name: Some(name),
57            insertion_point: None,
58            content: Some(content),
59            generated_code_info: None,
60        });
61    }
62    Ok(files)
63}
64
65/// Output path for the generated module file. Matches cludden's convention:
66/// the source proto's directory, with `_temporal.rs` appended to the file
67/// stem so consumer build scripts can `include!` it deterministically.
68fn output_file_name(svc: &crate::model::ServiceModel) -> String {
69    let stem = svc.source_file.trim_end_matches(".proto");
70    format!("{stem}_temporal.rs")
71}