From a43d814fbacf4149a098ffdccceab40205c03c6f Mon Sep 17 00:00:00 2001 From: glihm Date: Sat, 10 Feb 2024 12:39:03 -0600 Subject: [PATCH] fix: add support for more rust reserved keywords --- crates/parser/src/tokens/composite.rs | 50 ++++++++++++++++++++++++--- crates/rs/src/expand/struct.rs | 30 ++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/crates/parser/src/tokens/composite.rs b/crates/parser/src/tokens/composite.rs index a1b277f..2705982 100644 --- a/crates/parser/src/tokens/composite.rs +++ b/crates/parser/src/tokens/composite.rs @@ -40,10 +40,8 @@ pub struct Composite { impl Composite { pub fn parse(type_path: &str) -> CainomeResult { - // TODO: find a better way to avoid rust keywords... - let type_path = &type_path.replace("move", "r#move"); - - let generic_args = genericity::extract_generics_args(type_path)?; + let type_path = escape_rust_keywords(type_path); + let generic_args = genericity::extract_generics_args(&type_path)?; Ok(Self { // We want to keep the path with generic for the generic resolution. @@ -149,6 +147,31 @@ pub fn snake_to_pascal_case(s: &str) -> String { .collect() } +/// +pub fn escape_rust_keywords(s: &str) -> String { + let keywords = ["move", "type", "final"]; + + let mut s = s.to_string(); + + for k in keywords { + let k_start = format!("{k}::"); + let k_middle = format!("::{k}::"); + let k_end = format!("::{k}"); + + if s == k { + return format!("r#{k}"); + } else if s.starts_with(&k_start) { + s = s.replace(&k_start, &format!("r#{k}::")); + } else if s.ends_with(&k_end) { + s = s.replace(&k_end, &format!("::r#{k}")); + } else { + s = s.replace(&k_middle, &format!("::r#{k}::")); + } + } + + s +} + /// Extracts the `type_path` with given module `depth`. /// The extraction also converts all everything to `snake_case`. /// @@ -447,4 +470,23 @@ mod tests { Token::GenericArg("A".to_string()), ); } + + #[test] + fn test_escape_rust_keywords() { + assert_eq!(escape_rust_keywords("move"), "r#move",); + + assert_eq!(escape_rust_keywords("move::salut"), "r#move::salut",); + + assert_eq!(escape_rust_keywords("hey::move"), "hey::r#move",); + + assert_eq!( + escape_rust_keywords("hey::move::salut"), + "hey::r#move::salut", + ); + + assert_eq!( + escape_rust_keywords("type::move::final"), + "r#type::r#move::r#final", + ); + } } diff --git a/crates/rs/src/expand/struct.rs b/crates/rs/src/expand/struct.rs index 8c49241..2b5bd10 100644 --- a/crates/rs/src/expand/struct.rs +++ b/crates/rs/src/expand/struct.rs @@ -26,6 +26,10 @@ impl CairoStruct { // TODO: this needs to be done more elegantly... if &inner.name == "type" { members.push(quote!(r#type: #ty)); + } else if &inner.name == "move" { + members.push(quote!(r#move: #ty)); + } else if &inner.name == "final" { + members.push(quote!(r#final: #ty)); } else { members.push(quote!(#name: #ty)); } @@ -99,6 +103,32 @@ impl CairoStruct { let r#type = #ty_punctuated::cairo_deserialize(__felts, __offset)?; __offset += #ty_punctuated::cairo_serialized_size(&r#type); }); + } else if &inner.name == "move" { + names.push(quote!(r#move)); + + sizes.push(quote! { + __size += #ty_punctuated::cairo_serialized_size(&__rust.r#move); + }); + + sers.push(quote!(__out.extend(#ty_punctuated::cairo_serialize(&__rust.r#move));)); + + desers.push(quote! { + let r#move = #ty_punctuated::cairo_deserialize(__felts, __offset)?; + __offset += #ty_punctuated::cairo_serialized_size(&r#move); + }); + } else if &inner.name == "final" { + names.push(quote!(r#final)); + + sizes.push(quote! { + __size += #ty_punctuated::cairo_serialized_size(&__rust.r#final); + }); + + sers.push(quote!(__out.extend(#ty_punctuated::cairo_serialize(&__rust.r#final));)); + + desers.push(quote! { + let r#final = #ty_punctuated::cairo_deserialize(__felts, __offset)?; + __offset += #ty_punctuated::cairo_serialized_size(&r#final); + }); } else { names.push(quote!(#name));