Skip to main content

oag_core/
lib.rs

1pub mod config;
2pub mod error;
3pub mod ir;
4pub mod parse;
5pub mod transform;
6
7use thiserror::Error;
8
9/// A generated file with path and content.
10#[derive(Debug, Clone)]
11pub struct GeneratedFile {
12    pub path: String,
13    pub content: String,
14}
15
16/// Normalize whitespace in generated code:
17/// - Collapse 3+ consecutive newlines into 2 (max one blank line)
18/// - Ensure trailing newline
19pub fn normalize_generated(content: &str) -> String {
20    let mut result = String::with_capacity(content.len());
21    let mut newline_count = 0;
22    for ch in content.chars() {
23        if ch == '\n' {
24            newline_count += 1;
25            if newline_count <= 2 {
26                result.push(ch);
27            }
28        } else {
29            newline_count = 0;
30            result.push(ch);
31        }
32    }
33    if !result.ends_with('\n') {
34        result.push('\n');
35    }
36    result
37}
38
39/// Unified error type for code generators.
40#[derive(Debug, Error)]
41pub enum GeneratorError {
42    #[error("template render failed: {0}")]
43    Render(String),
44
45    #[error("generation failed: {0}")]
46    Other(String),
47}
48
49/// Trait for code generators that produce files from an IR spec.
50pub trait CodeGenerator {
51    fn id(&self) -> config::GeneratorId;
52    fn generate(
53        &self,
54        ir: &ir::IrSpec,
55        config: &config::GeneratorConfig,
56    ) -> Result<Vec<GeneratedFile>, GeneratorError>;
57}