diff --git a/crates/target_rust/src/lib.rs b/crates/target_rust/src/lib.rs index 5c7ae462..b6215cef 100644 --- a/crates/target_rust/src/lib.rs +++ b/crates/target_rust/src/lib.rs @@ -1,3 +1,4 @@ +use jtd_codegen::error::Error; use jtd_codegen::target::{self, inflect, metadata}; use jtd_codegen::Result; use lazy_static::lazy_static; @@ -234,15 +235,52 @@ impl jtd_codegen::target::Target for Target { return Ok(Some(s.into())); } + let mut derives = vec!["Serialize", "Deserialize"]; + + if let Some(s) = metadata.get("rustCustomDerive").and_then(|v| v.as_str()) { + derives.extend(s.split(",")); + } + state .imports .entry("serde".into()) .or_default() .extend(vec!["Deserialize".to_owned(), "Serialize".to_owned()]); + let mut custom_use = Vec::<&str>::new(); + if let Some(s) = metadata.get("rustCustomUse").and_then(|v| v.as_str()) { + custom_use.extend(s.split(";")); + } + for cu in custom_use { + // custom::path::{import,export} or custom::path::single + let mut use_imports = Vec::<&str>::new(); + let mut path_parts = cu.split("::").collect::>(); + let mut last_part = path_parts.pop().unwrap(); + // If there are no path_parts or the last part was "", panic! + if path_parts.len() < 1 || last_part.trim().len() < 1 { + return Err(Error::Io(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Invalid custom use statement: {:?}", cu), + ))); + } + if last_part.starts_with('{') { + // Strip the first/last chars and split + last_part = &last_part[1..last_part.len() - 1]; + use_imports.extend(last_part.split(",")) + } else { + // No, just push it into the imports list + use_imports.push(last_part); + } + state + .imports + .entry(path_parts.join("::").into()) + .or_default() + .extend(use_imports.drain(..).map(|i| i.trim().to_owned())); + } + writeln!(out)?; write!(out, "{}", description(&metadata, 0))?; - writeln!(out, "#[derive(Serialize, Deserialize)]")?; + writeln!(out, "#[derive({})]", derives.join(", "))?; if fields.is_empty() { writeln!(out, "pub struct {} {{}}", name)?;