Skip to main content

brk_bindgen/generators/
mod.rs

1//! Code generators for client libraries.
2//!
3//! Each language has its own submodule with focused files:
4//! - `types.rs` - Type definitions
5//! - `client.rs` - Base client and pattern factories
6//! - `tree.rs` - Tree structure generation
7//! - `api.rs` - API method generation
8//! - `mod.rs` - Entry point
9
10use std::{fmt::Write, fs, io, path::Path};
11
12pub mod javascript;
13pub mod python;
14pub mod rust;
15
16pub use javascript::generate_javascript_client;
17pub use python::generate_python_client;
18pub use rust::generate_rust_client;
19
20/// Types that are manually defined as generics in client code, not from schema.
21pub const MANUAL_GENERIC_TYPES: &[&str] = &["SeriesData", "SeriesEndpoint"];
22
23/// Write a multi-line description with the given prefix for each line.
24/// `empty_prefix` is used for blank lines (e.g., "   *" without trailing space).
25pub fn write_description(output: &mut String, desc: &str, prefix: &str, empty_prefix: &str) {
26    for line in desc.lines() {
27        if line.is_empty() {
28            writeln!(output, "{}", empty_prefix).unwrap();
29        } else {
30            writeln!(output, "{}{}", prefix, line).unwrap();
31        }
32    }
33}
34
35/// Replace generic types with their Any variants in return types.
36/// Used by JS and Python generators.
37pub fn normalize_return_type(return_type: &str) -> String {
38    let mut result = return_type.to_string();
39    for type_name in MANUAL_GENERIC_TYPES {
40        result = result.replace(type_name, &format!("Any{}", type_name));
41    }
42    result
43}
44
45/// Write content to a file only if it differs from existing content.
46/// Preserves mtime when unchanged, avoiding unnecessary cargo rebuilds.
47pub fn write_if_changed(path: &Path, content: &str) -> io::Result<()> {
48    if let Ok(existing) = fs::read_to_string(path)
49        && existing == content
50    {
51        return Ok(());
52    }
53    fs::write(path, content)
54}