mproto_codegen/codegen/rust/
package.rs1use std::io::Write;
2use std::path::Path;
3
4use genco::prelude::*;
5
6use crate::{ast::TypeDef, codegen::CodegenCx, Database, Module};
7
8const CARGO_TOML: &'static str = include_str!("templates/cargo.toml");
9
10pub fn rust_package_gen(
11 root_dir: impl AsRef<Path>,
12 pkg_name: &str,
13 type_defs: &[TypeDef],
14) -> std::io::Result<()> {
15 let local_module = Module::from_type_defs(type_defs.into());
16 let db = Database::new(local_module);
17
18 let pkg_root = root_dir.as_ref().join(pkg_name).join("rust");
19 let src_dir = pkg_root.join("src");
20
21 std::fs::create_dir_all(&pkg_root)?;
22 std::fs::create_dir_all(&src_dir)?;
23
24 let mut cargo_toml_file = std::fs::File::create(pkg_root.join("Cargo.toml"))?;
26 cargo_toml_file.write_all(CARGO_TOML.replace("PKG_NAME", pkg_name).as_bytes())?;
27
28 rust_module_gen(&db, src_dir.join("lib.rs"), type_defs, true)?;
30
31 Ok(())
32}
33
34pub fn rust_module_gen(
35 db: &Database,
36 path: impl AsRef<Path>,
37 type_defs: &[TypeDef],
38 is_crate: bool,
39) -> std::io::Result<()> {
40 let fmt = genco::fmt::Config::from_lang::<genco::lang::Rust>()
42 .with_indentation(genco::fmt::Indentation::Space(4));
43 let config = genco::lang::rust::Config::default();
44 let mut lib_rs_file = std::fs::File::create(path)?;
45
46 if is_crate {
47 lib_rs_file.write_all(b"#![cfg_attr(not(feature = \"std\"), no_std)]\n\n")?;
48 lib_rs_file.write_all(
49 b"#[cfg(all(not(feature = \"std\"), feature = \"alloc\"))]\nextern crate alloc;\n\n",
50 )?;
51 }
52
53 let mut w = genco::fmt::IoWriter::new(lib_rs_file);
54 let mut tokens = genco::lang::rust::Tokens::new();
55
56 let codegen_cx = CodegenCx::new(db, None, is_crate);
57
58 for type_def in type_defs {
59 let type_tokens = crate::codegen::rust::rust_type_def(&codegen_cx, type_def);
60 tokens = quote! {
61 $tokens
62
63 $type_tokens
64 };
65 }
66
67 tokens
68 .format_file(&mut w.as_formatter(&fmt), &config)
69 .expect("format rust file");
70
71 Ok(())
72}