diff --git a/definitions/example.yml b/definitions/example.yml new file mode 100644 index 0000000..bbb0f94 --- /dev/null +++ b/definitions/example.yml @@ -0,0 +1,21 @@ +--- +entities: + - name: Player + package: org.hexalite.generation.entity + feature_flag: example + fields: + a: + kind: + kotlin: java.util.UUID + rust: String + sql: 'uuid().not_null().primary_key()' + test_c: + kind: + kotlin: Int + rust: u32 + sql: 'integer().not_null().default(0)' + hello_d: + kind: + kotlin: String + rust: String + sql: 'varchar(255).not_null().default("")' diff --git a/definitions/rust/Cargo.toml b/definitions/rust/Cargo.toml index 1bb156f..6910ce2 100644 --- a/definitions/rust/Cargo.toml +++ b/definitions/rust/Cargo.toml @@ -13,3 +13,4 @@ syn = "^1" quote = "^1" serde = { version = "^1", features = ["derive"] } serde_yaml = "^0.8" +home = "^0" \ No newline at end of file diff --git a/definitions/rust/generated/Cargo.toml b/definitions/rust/generated/Cargo.toml index e9e9bfe..d20ec50 100644 --- a/definitions/rust/generated/Cargo.toml +++ b/definitions/rust/generated/Cargo.toml @@ -4,5 +4,9 @@ version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +example = [] +default = ["example"] [dependencies] +definitions-generator = { path = "../" } \ No newline at end of file diff --git a/definitions/rust/generated/src/lib.rs b/definitions/rust/generated/src/lib.rs index 8b13789..efb10da 100644 --- a/definitions/rust/generated/src/lib.rs +++ b/definitions/rust/generated/src/lib.rs @@ -1 +1,2 @@ - +#[cfg(feature = "example")] +definitions_generator::generate_entity_definitions!("definitions/example.yml"); diff --git a/definitions/rust/src/lib.rs b/definitions/rust/src/lib.rs index 55a728b..763dcd4 100644 --- a/definitions/rust/src/lib.rs +++ b/definitions/rust/src/lib.rs @@ -1 +1,69 @@ -mod specification; \ No newline at end of file +use std::fs; + +use proc_macro::TokenStream; +use quote::format_ident; +use specification::SpecificationRoot; + +mod specification; + +#[proc_macro] +pub fn generate_entity_definitions(item: TokenStream) -> TokenStream { + let mut path = item.to_string(); + path.pop(); + path.remove(0); + + let code = path + .split("|") + .map(|path| { + let home = home::home_dir().expect("Could not find home directory"); + + let root = home + .join(".hexalite") + .join("dev") + .canonicalize() + .expect("Could not find ~/.hexalite/dev directory"); + + let file = root.join(path); + let file = fs::read_to_string(&file) + .expect(format!("Nao achou em {}", file.display()).as_str()); + + let specification: SpecificationRoot = + serde_yaml::from_str(file.as_str()).expect("Could not parse specification"); + + let quotes = specification + .entities + .iter() + .map(|specification| { + let struct_fields_name = specification + .fields + .iter() + .map(|(name, _)| format_ident!("{}", name.clone().trim().to_string())) + .collect::>(); + let struct_fields_kind = specification + .fields + .iter() + .map(|(_, field)| format_ident!("{}", field.kind.rust.trim().to_string())) + .collect::>(); + let name = format_ident!("{}", specification.name.trim()); + + quote::quote! { + #[derive(Debug, Clone)] + pub struct #name { + #(pub #struct_fields_name: #struct_fields_kind),* + } + } + }) + .collect::>(); + + quote::quote! { + #(#quotes) + * + } + }) + .collect::>(); + + TokenStream::from(quote::quote! { + #(#code) + * + }) +} diff --git a/definitions/rust/src/specification.rs b/definitions/rust/src/specification.rs index bb42606..ffca736 100644 --- a/definitions/rust/src/specification.rs +++ b/definitions/rust/src/specification.rs @@ -9,21 +9,27 @@ use serde::Deserialize; #[derive(Debug, Clone, Deserialize)] pub struct SpecificationRoot { - pub name: String, - pub location: RustAndKotlinType, - pub feature_flag: String, - pub fields: HashMap + pub entities: Vec } #[derive(Debug, Clone, Deserialize)] -pub struct RustAndKotlinType { - pub rust: String, - pub kotlin: String +pub struct SpecificationEntity { + pub name: String, + #[serde(rename = "package")] + pub kotlin_package: String, + pub feature_flag: String, + pub fields: HashMap } #[derive(Debug, Clone, Deserialize)] pub struct SpecificationField { - pub kind: RustAndKotlinType, + pub kind: SpecificationFieldKind, #[serde(default)] pub sql: Option, } + +#[derive(Debug, Clone, Deserialize)] +pub struct SpecificationFieldKind { + pub rust: String, + pub kotlin: String +}