diff --git a/yunq/rust/Cargo.lock b/yunq/rust/Cargo.lock index 7d49b6b..d5f212d 100644 --- a/yunq/rust/Cargo.lock +++ b/yunq/rust/Cargo.lock @@ -97,6 +97,28 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "genco" +version = "0.17.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afac3cbb14db69ac9fef9cdb60d8a87e39a7a527f85a81a923436efa40ad42c6" +dependencies = [ + "genco-macros", + "relative-path", + "smallvec", +] + +[[package]] +name = "genco-macros" +version = "0.17.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553630feadf7b76442b0849fd25fdf89b860d933623aec9693fed19af0400c78" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "heck" version = "0.5.0" @@ -127,6 +149,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "strsim" version = "0.11.1" @@ -234,4 +268,5 @@ name = "yunq" version = "0.1.0" dependencies = [ "clap", + "genco", ] diff --git a/yunq/rust/Cargo.toml b/yunq/rust/Cargo.toml index 2f9645f..8c0c88a 100644 --- a/yunq/rust/Cargo.toml +++ b/yunq/rust/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] clap = { version = "4.5.7", features = ["derive"] } +genco = { version = "0.17.9" } diff --git a/yunq/rust/src/codegen.rs b/yunq/rust/src/codegen.rs new file mode 100644 index 0000000..cf07f24 --- /dev/null +++ b/yunq/rust/src/codegen.rs @@ -0,0 +1,53 @@ +use crate::parser::{Decl, Field, Interface, Message}; +use genco::fmt; +use genco::fmt::FmtWriter; +use genco::prelude::quote_fn; +use genco::prelude::quote_in; +use genco::prelude::rust; +use genco::prelude::FormatInto; +use genco::prelude::Rust; + +pub fn generate_field_def<'a>(field: &'a Field) -> impl FormatInto + 'a { + quote_fn!( + $(field.name.clone()): $(field.field_type.rust_type()), + ) +} + +pub fn generate_message_code<'a>(message: &'a Message) -> impl FormatInto + 'a { + quote_fn!( + struct $(&message.name) {$['\r'] + $(for field in &message.fields => + $[' ']$(generate_field_def(field))$['\r'] + )}$['\n'] + + impl $(&message.name) {$['\r'] + jjj + + }$['\n'] + ) +} + +pub fn generate_code(ast: &Vec) -> Result { + let mut tokens = rust::Tokens::new(); + + for decl in ast { + match decl { + Decl::Message(message) => quote_in!(tokens => $(generate_message_code(message))), + _ => {} + } + } + + let mut w = FmtWriter::new(String::new()); + + let fmt = fmt::Config::from_lang::() + .with_indentation(fmt::Indentation::Space(4)) + .with_newline("\n"); + + let config = rust::Config::default() + // Prettier imports and use. + .with_default_import(rust::ImportMode::Qualified); + + tokens.format_file(&mut w.as_formatter(&fmt), &config)?; + + Ok(w.into_inner()) +} diff --git a/yunq/rust/src/main.rs b/yunq/rust/src/main.rs index b5ae3a0..c9fc119 100644 --- a/yunq/rust/src/main.rs +++ b/yunq/rust/src/main.rs @@ -1,3 +1,4 @@ +mod codegen; mod lexer; mod parser; @@ -27,5 +28,7 @@ fn main() -> Result<(), Box> { println!("{:?}", decl); } + println!("{}", codegen::generate_code(ast_parser.ast())?); + Ok(()) } diff --git a/yunq/rust/src/parser.rs b/yunq/rust/src/parser.rs index 6dd3a18..85d7263 100644 --- a/yunq/rust/src/parser.rs +++ b/yunq/rust/src/parser.rs @@ -16,6 +16,19 @@ pub enum Type { Message(String), } +impl Type { + pub fn rust_type(&self) -> &str { + match self { + Type::U64 => "u64", + Type::I64 => "i64", + Type::String => "String", + Type::Bytes => "Vec", + Type::Capability => "u64", + Type::Message(s) => s, + } + } +} + impl Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( @@ -50,23 +63,23 @@ impl TryFrom<&String> for Type { #[derive(Clone)] pub struct Field { - field_type: Type, - name: String, - number: u64, - repeated: bool, + pub field_type: Type, + pub name: String, + pub number: u64, + pub repeated: bool, } #[derive(Clone)] pub struct Message { - name: String, - fields: Vec, + pub name: String, + pub fields: Vec, } pub struct Method { - name: String, - number: u64, - request: Option, - response: Option, + pub name: String, + pub number: u64, + pub request: Option, + pub response: Option, } impl Debug for Method { @@ -303,7 +316,7 @@ impl<'a> Parser<'a> { Ok(()) } - pub fn ast(&'a mut self) -> &'a Vec { + pub fn ast(&'a self) -> &'a Vec { &self.ast }