From b67a6ed8a9ab4254d02408143ddd66084f61ea8b Mon Sep 17 00:00:00 2001 From: Adam Leyshon Date: Mon, 12 Jul 2021 22:33:26 +0100 Subject: [PATCH 1/2] Add support for `rustCustomDerive` and `rustCustomUse` metadata for Structs. This allows us to additional `use` statements or `derive` macros on generated structs. `rustCustomUse` is a string of use statments separated by `;` It supports single and multi-import statements. For example: `serde::{Deserialize, Serialize}` or `serde::Serialize` are both valid. `rustCustomUse` is a string of derive identifers separated by `,` For example: `FromSqlRow,AsExpression,Debug,Default` --- crates/target_rust/src/lib.rs | 50 ++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/crates/target_rust/src/lib.rs b/crates/target_rust/src/lib.rs index 5c7ae462..b032be85 100644 --- a/crates/target_rust/src/lib.rs +++ b/crates/target_rust/src/lib.rs @@ -4,6 +4,7 @@ use lazy_static::lazy_static; use serde_json::Value; use std::collections::{BTreeMap, BTreeSet}; use std::io::Write; +use jtd_codegen::error::Error; lazy_static! { static ref KEYWORDS: BTreeSet = include_str!("keywords") @@ -234,15 +235,62 @@ 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)?; From dc0bf810ff8a0bb845fbf256318aacf6b703d679 Mon Sep 17 00:00:00 2001 From: Adam Leyshon Date: Thu, 15 Jul 2021 09:01:06 +0100 Subject: [PATCH 2/2] rustfmt --- crates/target_rust/src/lib.rs | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/crates/target_rust/src/lib.rs b/crates/target_rust/src/lib.rs index b032be85..b6215cef 100644 --- a/crates/target_rust/src/lib.rs +++ b/crates/target_rust/src/lib.rs @@ -1,10 +1,10 @@ +use jtd_codegen::error::Error; use jtd_codegen::target::{self, inflect, metadata}; use jtd_codegen::Result; use lazy_static::lazy_static; use serde_json::Value; use std::collections::{BTreeMap, BTreeSet}; use std::io::Write; -use jtd_codegen::error::Error; lazy_static! { static ref KEYWORDS: BTreeSet = include_str!("keywords") @@ -238,9 +238,7 @@ impl jtd_codegen::target::Target for Target { let mut derives = vec!["Serialize", "Deserialize"]; if let Some(s) = metadata.get("rustCustomDerive").and_then(|v| v.as_str()) { - derives.extend( - s.split(",") - ); + derives.extend(s.split(",")); } state @@ -251,29 +249,21 @@ impl jtd_codegen::target::Target for Target { 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(";") - ); + custom_use.extend(s.split(";")); } - for cu in custom_use - { + 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) - ) - ) - ); + return Err(Error::Io(std::io::Error::new( + std::io::ErrorKind::Other, + format!("Invalid custom use statement: {:?}", cu), + ))); } - if last_part.starts_with('{') - { + 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(","))