Files
JsonRPC-Rust/libjrpc/src/compile.rs
Fabian Stamm ffacba2e96 Finish implementation of typescript generator.
The implementation is still untested and will
have issues
2025-05-27 19:58:40 +02:00

152 lines
3.7 KiB
Rust

use std::{collections::HashMap, path::PathBuf};
use anyhow::{Context, Result};
use crate::{
ir::{EnumDefinition, ServiceDefinition, TypeDefinition},
IR,
};
pub trait Compile {
fn new(options: &HashMap<String, String>) -> Result<Self>
where
Self: Sized;
fn name(&self) -> String;
fn start(&mut self, ctx: &mut CompileContext) -> Result<()>;
fn generate_type(
&mut self,
ctx: &mut CompileContext,
definition: &TypeDefinition,
) -> Result<()>;
fn generate_enum(
&mut self,
ctx: &mut CompileContext,
definition: &EnumDefinition,
) -> Result<()>;
fn generate_service(
&mut self,
ctx: &mut CompileContext,
definition: &ServiceDefinition,
) -> Result<()>;
fn finalize(&mut self, ctx: &mut CompileContext, ir: &IR) -> Result<()>;
}
pub struct CompileContext {
output_folder: PathBuf,
}
impl CompileContext {
pub fn new(output_folder: &str) -> Self {
CompileContext {
output_folder: output_folder.into(),
}
}
pub fn to_snake(name: &str) -> String {
let mut result = String::new();
let mut last_upper = false;
for c in name.chars() {
if c.is_uppercase() {
if last_upper {
result.push(c.to_ascii_lowercase());
} else {
if !result.is_empty() {
result.push('_');
}
result.push(c.to_ascii_lowercase());
}
last_upper = true;
} else {
result.push(c);
last_upper = false;
}
}
result
}
pub fn strip_template_ignores(content: &str) -> String {
let mut result = String::new();
let mut ignore = false;
for line in content.lines() {
if ignore {
ignore = false;
continue;
}
if line.trim().contains("@template-ignore") {
ignore = true;
continue;
}
result.push_str(line);
result.push_str("\n");
}
result
}
pub fn write_file(&self, filename: &str, content: &str) -> Result<()> {
let res_path = self.output_folder.clone().join(filename);
let res_dir = res_path.parent().context("Path has no parent!")?;
std::fs::create_dir_all(res_dir)?;
std::fs::write(res_path, content)?;
Ok(())
}
}
pub struct FileGenerator {
content: Vec<String>,
}
impl FileGenerator {
pub fn new() -> Self {
FileGenerator {
content: Vec::new(),
}
}
pub fn a<T: ToString>(&mut self, indent: usize, content: T) {
let line = " ".repeat(indent) + &content.to_string();
self.content.push(line);
}
pub fn a0<T: ToString>(&mut self, content: T) {
self.a(0, content);
}
pub fn a1<T: ToString>(&mut self, content: T) {
self.a(1, content);
}
pub fn a2<T: ToString>(&mut self, content: T) {
self.a(2, content);
}
pub fn a3<T: ToString>(&mut self, content: T) {
self.a(3, content);
}
pub fn a4<T: ToString>(&mut self, content: T) {
self.a(4, content);
}
pub fn a5<T: ToString>(&mut self, content: T) {
self.a(5, content);
}
pub fn a6<T: ToString>(&mut self, content: T) {
self.a(6, content);
}
// pub fn add_line(&mut self, line: &str) {
// self.content.push(line.to_string());
// }
pub fn get_content(&self) -> String {
self.content.join("\n")
}
pub fn into_content(self) -> String {
self.get_content()
}
}