From 62a49eb839ccb9ddaef07f0b42f0dbf5ddbc8c98 Mon Sep 17 00:00:00 2001 From: Rain Date: Tue, 10 Feb 2026 13:24:50 -0800 Subject: [PATCH] [spr] initial version Created using spr 1.3.6-beta.1 --- typify-impl/src/lib.rs | 2 ++ typify-impl/src/util.rs | 26 ++++++++++++++++++++++- typify/src/lib.rs | 1 + typify/tests/schemas/rust-collisions.json | 4 ++++ typify/tests/schemas/rust-collisions.rs | 20 +++++++++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/typify-impl/src/lib.rs b/typify-impl/src/lib.rs index 812d0606..a10b2afe 100644 --- a/typify-impl/src/lib.rs +++ b/typify-impl/src/lib.rs @@ -20,6 +20,8 @@ use type_entry::{ use crate::util::{sanitize, Case}; +pub use crate::util::accept_as_ident; + #[cfg(test)] mod test_util; diff --git a/typify-impl/src/util.rs b/typify-impl/src/util.rs index 825681ce..c46352f6 100644 --- a/typify-impl/src/util.rs +++ b/typify-impl/src/util.rs @@ -797,13 +797,35 @@ pub(crate) fn sanitize(input: &str, case: Case) -> String { }; // Make sure the string is a valid Rust identifier. - if syn::parse_str::(&out).is_ok() { + if accept_as_ident(&out) { out } else { format!("{}_", out) } } +/// Return true if the string is a valid Rust identifier. +/// +/// If this function returns false, typify adds a trailing underscore to it. For +/// example, `fn` becomes `fn_`. +pub fn accept_as_ident(ident: &str) -> bool { + // Adapted from https://docs.rs/syn/2.0.114/src/syn/ident.rs.html#60-74. The + // main change is adding `gen` to the list. + match ident { + "_" | + // Based on https://doc.rust-lang.org/1.65.0/reference/keywords.html + "abstract" | "as" | "async" | "await" | "become" | "box" | "break" | + "const" | "continue" | "crate" | "do" | "dyn" | "else" | "enum" | + "extern" | "false" | "final" | "fn" | "for" | "gen" | "if" | "impl" | + "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | + "override" | "priv" | "pub" | "ref" | "return" | "Self" | "self" | + "static" | "struct" | "super" | "trait" | "true" | "try" | "type" | + "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | + "while" | "yield" => false, + _ => true, + } +} + pub(crate) fn recase(input: &str, case: Case) -> (String, Option) { let new = sanitize(input, case); let rename = if new == input { @@ -1038,6 +1060,8 @@ mod tests { fn test_sanitize() { assert_eq!(sanitize("type", Case::Snake), "type_"); assert_eq!(sanitize("ref", Case::Snake), "ref_"); + assert_eq!(sanitize("gen", Case::Snake), "gen_"); + assert_eq!(sanitize("gen", Case::Pascal), "Gen"); assert_eq!(sanitize("+1", Case::Snake), "plus1"); assert_eq!(sanitize("-1", Case::Snake), "minus1"); assert_eq!(sanitize("@timestamp", Case::Pascal), "Timestamp"); diff --git a/typify/src/lib.rs b/typify/src/lib.rs index 2954bdd7..155c0dba 100644 --- a/typify/src/lib.rs +++ b/typify/src/lib.rs @@ -148,6 +148,7 @@ #![deny(missing_docs)] +pub use typify_impl::accept_as_ident; pub use typify_impl::CrateVers; pub use typify_impl::Error; pub use typify_impl::Type; diff --git a/typify/tests/schemas/rust-collisions.json b/typify/tests/schemas/rust-collisions.json index a2ad573e..d01604d5 100644 --- a/typify/tests/schemas/rust-collisions.json +++ b/typify/tests/schemas/rust-collisions.json @@ -261,6 +261,9 @@ "for": { "type": "string" }, + "gen": { + "type": "string" + }, "if": { "type": "string" }, @@ -391,6 +394,7 @@ "false", "fn", "for", + "gen", "if", "impl", "in", diff --git a/typify/tests/schemas/rust-collisions.rs b/typify/tests/schemas/rust-collisions.rs index d79f96c6..08f0ac88 100644 --- a/typify/tests/schemas/rust-collisions.rs +++ b/typify/tests/schemas/rust-collisions.rs @@ -710,6 +710,7 @@ impl Pin { #[doc = " \"final\","] #[doc = " \"fn\","] #[doc = " \"for\","] +#[doc = " \"gen\","] #[doc = " \"if\","] #[doc = " \"impl\","] #[doc = " \"in\","] @@ -800,6 +801,9 @@ impl Pin { #[doc = " \"for\": {"] #[doc = " \"type\": \"string\""] #[doc = " },"] +#[doc = " \"gen\": {"] +#[doc = " \"type\": \"string\""] +#[doc = " },"] #[doc = " \"if\": {"] #[doc = " \"type\": \"string\""] #[doc = " },"] @@ -937,6 +941,8 @@ pub struct RustKeywordMonster { pub fn_: ::std::string::String, #[serde(rename = "for")] pub for_: ::std::string::String, + #[serde(rename = "gen")] + pub gen_: ::std::string::String, #[serde(rename = "if")] pub if_: ::std::string::String, #[serde(rename = "impl")] @@ -2147,6 +2153,7 @@ pub mod builder { final_: ::std::result::Result<::std::string::String, ::std::string::String>, fn_: ::std::result::Result<::std::string::String, ::std::string::String>, for_: ::std::result::Result<::std::string::String, ::std::string::String>, + gen_: ::std::result::Result<::std::string::String, ::std::string::String>, if_: ::std::result::Result<::std::string::String, ::std::string::String>, impl_: ::std::result::Result<::std::string::String, ::std::string::String>, in_: ::std::result::Result<::std::string::String, ::std::string::String>, @@ -2201,6 +2208,7 @@ pub mod builder { final_: Err("no value supplied for final_".to_string()), fn_: Err("no value supplied for fn_".to_string()), for_: Err("no value supplied for for_".to_string()), + gen_: Err("no value supplied for gen_".to_string()), if_: Err("no value supplied for if_".to_string()), impl_: Err("no value supplied for impl_".to_string()), in_: Err("no value supplied for in_".to_string()), @@ -2426,6 +2434,16 @@ pub mod builder { .map_err(|e| format!("error converting supplied value for for_: {e}")); self } + pub fn gen_(mut self, value: T) -> Self + where + T: ::std::convert::TryInto<::std::string::String>, + T::Error: ::std::fmt::Display, + { + self.gen_ = value + .try_into() + .map_err(|e| format!("error converting supplied value for gen_: {e}")); + self + } pub fn if_(mut self, value: T) -> Self where T: ::std::convert::TryInto<::std::string::String>, @@ -2762,6 +2780,7 @@ pub mod builder { final_: value.final_?, fn_: value.fn_?, for_: value.for_?, + gen_: value.gen_?, if_: value.if_?, impl_: value.impl_?, in_: value.in_?, @@ -2818,6 +2837,7 @@ pub mod builder { final_: Ok(value.final_), fn_: Ok(value.fn_), for_: Ok(value.for_), + gen_: Ok(value.gen_), if_: Ok(value.if_), impl_: Ok(value.impl_), in_: Ok(value.in_),