macros: Add alias attribute to ruma_enum
This commit is contained in:
		
							parent
							
								
									9b870cd9af
								
							
						
					
					
						commit
						af61a62202
					
				| @ -12,6 +12,8 @@ enum MyEnum { | |||||||
|     #[ruma_enum(rename = "m.third")] |     #[ruma_enum(rename = "m.third")] | ||||||
|     Third, |     Third, | ||||||
|     HelloWorld, |     HelloWorld, | ||||||
|  |     #[ruma_enum(rename = "io.ruma.unstable", alias = "m.stable", alias = "hs.notareal.unstable")] | ||||||
|  |     Stable, | ||||||
|     _Custom(PrivOwnedStr), |     _Custom(PrivOwnedStr), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -21,6 +23,7 @@ fn as_ref_str() { | |||||||
|     assert_eq!(MyEnum::Second.as_ref(), "second"); |     assert_eq!(MyEnum::Second.as_ref(), "second"); | ||||||
|     assert_eq!(MyEnum::Third.as_ref(), "m.third"); |     assert_eq!(MyEnum::Third.as_ref(), "m.third"); | ||||||
|     assert_eq!(MyEnum::HelloWorld.as_ref(), "hello_world"); |     assert_eq!(MyEnum::HelloWorld.as_ref(), "hello_world"); | ||||||
|  |     assert_eq!(MyEnum::Stable.as_ref(), "io.ruma.unstable"); | ||||||
|     assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).as_ref(), "HelloWorld"); |     assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).as_ref(), "HelloWorld"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -30,6 +33,7 @@ fn display() { | |||||||
|     assert_eq!(MyEnum::Second.to_string(), "second"); |     assert_eq!(MyEnum::Second.to_string(), "second"); | ||||||
|     assert_eq!(MyEnum::Third.to_string(), "m.third"); |     assert_eq!(MyEnum::Third.to_string(), "m.third"); | ||||||
|     assert_eq!(MyEnum::HelloWorld.to_string(), "hello_world"); |     assert_eq!(MyEnum::HelloWorld.to_string(), "hello_world"); | ||||||
|  |     assert_eq!(MyEnum::Stable.to_string(), "io.ruma.unstable"); | ||||||
|     assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).to_string(), "HelloWorld"); |     assert_eq!(MyEnum::_Custom(PrivOwnedStr("HelloWorld".into())).to_string(), "HelloWorld"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -39,6 +43,9 @@ fn from_string() { | |||||||
|     assert_eq!(MyEnum::from("second"), MyEnum::Second); |     assert_eq!(MyEnum::from("second"), MyEnum::Second); | ||||||
|     assert_eq!(MyEnum::from("m.third"), MyEnum::Third); |     assert_eq!(MyEnum::from("m.third"), MyEnum::Third); | ||||||
|     assert_eq!(MyEnum::from("hello_world"), MyEnum::HelloWorld); |     assert_eq!(MyEnum::from("hello_world"), MyEnum::HelloWorld); | ||||||
|  |     assert_eq!(MyEnum::from("io.ruma.unstable"), MyEnum::Stable); | ||||||
|  |     assert_eq!(MyEnum::from("m.stable"), MyEnum::Stable); | ||||||
|  |     assert_eq!(MyEnum::from("hs.notareal.unstable"), MyEnum::Stable); | ||||||
|     assert_eq!(MyEnum::from("HelloWorld"), MyEnum::_Custom(PrivOwnedStr("HelloWorld".into()))); |     assert_eq!(MyEnum::from("HelloWorld"), MyEnum::_Custom(PrivOwnedStr("HelloWorld".into()))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -46,6 +53,7 @@ fn from_string() { | |||||||
| fn serialize() { | fn serialize() { | ||||||
|     assert_eq!(to_json_value(MyEnum::First).unwrap(), json!("first")); |     assert_eq!(to_json_value(MyEnum::First).unwrap(), json!("first")); | ||||||
|     assert_eq!(to_json_value(MyEnum::HelloWorld).unwrap(), json!("hello_world")); |     assert_eq!(to_json_value(MyEnum::HelloWorld).unwrap(), json!("hello_world")); | ||||||
|  |     assert_eq!(to_json_value(MyEnum::Stable).unwrap(), json!("io.ruma.unstable")); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         to_json_value(MyEnum::_Custom(PrivOwnedStr("\\\n\\".into()))).unwrap(), |         to_json_value(MyEnum::_Custom(PrivOwnedStr("\\\n\\".into()))).unwrap(), | ||||||
|         json!("\\\n\\") |         json!("\\\n\\") | ||||||
| @ -56,6 +64,9 @@ fn serialize() { | |||||||
| fn deserialize() { | fn deserialize() { | ||||||
|     assert_eq!(from_json_value::<MyEnum>(json!("first")).unwrap(), MyEnum::First); |     assert_eq!(from_json_value::<MyEnum>(json!("first")).unwrap(), MyEnum::First); | ||||||
|     assert_eq!(from_json_value::<MyEnum>(json!("hello_world")).unwrap(), MyEnum::HelloWorld); |     assert_eq!(from_json_value::<MyEnum>(json!("hello_world")).unwrap(), MyEnum::HelloWorld); | ||||||
|  |     assert_eq!(from_json_value::<MyEnum>(json!("io.ruma.unstable")).unwrap(), MyEnum::Stable); | ||||||
|  |     assert_eq!(from_json_value::<MyEnum>(json!("m.stable")).unwrap(), MyEnum::Stable); | ||||||
|  |     assert_eq!(from_json_value::<MyEnum>(json!("hs.notareal.unstable")).unwrap(), MyEnum::Stable); | ||||||
|     assert_eq!( |     assert_eq!( | ||||||
|         from_json_value::<MyEnum>(json!("\\\n\\")).unwrap(), |         from_json_value::<MyEnum>(json!("\\\n\\")).unwrap(), | ||||||
|         MyEnum::_Custom(PrivOwnedStr("\\\n\\".into())) |         MyEnum::_Custom(PrivOwnedStr("\\\n\\".into())) | ||||||
|  | |||||||
| @ -6,23 +6,36 @@ use syn::{ | |||||||
| use super::case::RenameRule; | use super::case::RenameRule; | ||||||
| 
 | 
 | ||||||
| mod kw { | mod kw { | ||||||
|  |     syn::custom_keyword!(alias); | ||||||
|     syn::custom_keyword!(rename); |     syn::custom_keyword!(rename); | ||||||
|     syn::custom_keyword!(rename_all); |     syn::custom_keyword!(rename_all); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct RenameAttr(LitStr); | #[derive(Default)] | ||||||
| 
 | pub struct EnumAttrs { | ||||||
| impl RenameAttr { |     pub rename: Option<LitStr>, | ||||||
|     pub fn into_inner(self) -> LitStr { |     pub aliases: Vec<LitStr>, | ||||||
|         self.0 |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Parse for RenameAttr { | pub enum Attr { | ||||||
|  |     Alias(LitStr), | ||||||
|  |     Rename(LitStr), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Parse for Attr { | ||||||
|     fn parse(input: ParseStream<'_>) -> syn::Result<Self> { |     fn parse(input: ParseStream<'_>) -> syn::Result<Self> { | ||||||
|         let _: kw::rename = input.parse()?; |         let lookahead = input.lookahead1(); | ||||||
|         let _: Token![=] = input.parse()?; |         if lookahead.peek(kw::alias) { | ||||||
|         Ok(Self(input.parse()?)) |             let _: kw::alias = input.parse()?; | ||||||
|  |             let _: Token![=] = input.parse()?; | ||||||
|  |             Ok(Self::Alias(input.parse()?)) | ||||||
|  |         } else if lookahead.peek(kw::rename) { | ||||||
|  |             let _: kw::rename = input.parse()?; | ||||||
|  |             let _: Token![=] = input.parse()?; | ||||||
|  |             Ok(Self::Rename(input.parse()?)) | ||||||
|  |         } else { | ||||||
|  |             Err(lookahead.error()) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,7 +2,10 @@ use proc_macro2::TokenStream; | |||||||
| use quote::{quote, ToTokens}; | use quote::{quote, ToTokens}; | ||||||
| use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum}; | use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum}; | ||||||
| 
 | 
 | ||||||
| use super::util::{get_rename, get_rename_rule}; | use super::{ | ||||||
|  |     attr::EnumAttrs, | ||||||
|  |     util::{get_enum_attributes, get_rename_rule}, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> { | pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> { | ||||||
|     let enum_name = &input.ident; |     let enum_name = &input.ident; | ||||||
| @ -12,7 +15,8 @@ pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> { | |||||||
|         .iter() |         .iter() | ||||||
|         .map(|v| { |         .map(|v| { | ||||||
|             let variant_name = &v.ident; |             let variant_name = &v.ident; | ||||||
|             let (field_capture, variant_str) = match (get_rename(v)?, &v.fields) { |             let EnumAttrs { rename, .. } = get_enum_attributes(v)?; | ||||||
|  |             let (field_capture, variant_str) = match (rename, &v.fields) { | ||||||
|                 (None, Fields::Unit) => ( |                 (None, Fields::Unit) => ( | ||||||
|                     None, |                     None, | ||||||
|                     rename_rule.apply_to_variant(&variant_name.to_string()).into_token_stream(), |                     rename_rule.apply_to_variant(&variant_name.to_string()).into_token_stream(), | ||||||
|  | |||||||
| @ -2,7 +2,10 @@ use proc_macro2::{Span, TokenStream}; | |||||||
| use quote::{quote, ToTokens}; | use quote::{quote, ToTokens}; | ||||||
| use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum}; | use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum}; | ||||||
| 
 | 
 | ||||||
| use super::util::{get_rename, get_rename_rule}; | use super::{ | ||||||
|  |     attr::EnumAttrs, | ||||||
|  |     util::{get_enum_attributes, get_rename_rule}, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> { | pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> { | ||||||
|     let enum_name = &input.ident; |     let enum_name = &input.ident; | ||||||
| @ -13,7 +16,8 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> { | |||||||
|         .iter() |         .iter() | ||||||
|         .map(|v| { |         .map(|v| { | ||||||
|             let variant_name = &v.ident; |             let variant_name = &v.ident; | ||||||
|             let variant_str = match (get_rename(v)?, &v.fields) { |             let EnumAttrs { rename, aliases } = get_enum_attributes(v)?; | ||||||
|  |             let variant_str = match (rename, &v.fields) { | ||||||
|                 (None, Fields::Unit) => Some( |                 (None, Fields::Unit) => Some( | ||||||
|                     rename_rule.apply_to_variant(&variant_name.to_string()).into_token_stream(), |                     rename_rule.apply_to_variant(&variant_name.to_string()).into_token_stream(), | ||||||
|                 ), |                 ), | ||||||
| @ -56,7 +60,12 @@ pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> { | |||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             Ok(variant_str.map(|s| quote! { #s => #enum_name :: #variant_name })) |             Ok(variant_str.map(|s| { | ||||||
|  |                 quote! { | ||||||
|  |                     #( #aliases => #enum_name :: #variant_name, )* | ||||||
|  |                     #s => #enum_name :: #variant_name | ||||||
|  |                 } | ||||||
|  |             })) | ||||||
|         }) |         }) | ||||||
|         .collect::<syn::Result<_>>()?; |         .collect::<syn::Result<_>>()?; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| use proc_macro2::Span; | use proc_macro2::Span; | ||||||
| use syn::{ItemEnum, LitStr, Variant}; | use syn::{punctuated::Punctuated, ItemEnum, Token, Variant}; | ||||||
| 
 | 
 | ||||||
| use super::{ | use super::{ | ||||||
|     attr::{RenameAllAttr, RenameAttr}, |     attr::{Attr, EnumAttrs, RenameAllAttr}, | ||||||
|     case::RenameRule, |     case::RenameRule, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -24,16 +24,32 @@ pub fn get_rename_rule(input: &ItemEnum) -> syn::Result<RenameRule> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn get_rename(input: &Variant) -> syn::Result<Option<LitStr>> { | pub fn get_enum_attributes(input: &Variant) -> syn::Result<EnumAttrs> { | ||||||
|     let renames: Vec<_> = input |     let mut attributes = EnumAttrs::default(); | ||||||
|         .attrs |  | ||||||
|         .iter() |  | ||||||
|         .filter(|attr| attr.path.is_ident("ruma_enum")) |  | ||||||
|         .map(|attr| attr.parse_args::<RenameAttr>().map(RenameAttr::into_inner)) |  | ||||||
|         .collect::<syn::Result<_>>()?; |  | ||||||
| 
 | 
 | ||||||
|     match renames.len() { |     for attr in &input.attrs { | ||||||
|         0 | 1 => Ok(renames.into_iter().next()), |         if !attr.path.is_ident("ruma_enum") { | ||||||
|         _ => Err(syn::Error::new(Span::call_site(), "found multiple ruma_enum(rename) attributes")), |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let enum_attrs = attr.parse_args_with(Punctuated::<_, Token![,]>::parse_terminated)?; | ||||||
|  |         for enum_attr in enum_attrs { | ||||||
|  |             match enum_attr { | ||||||
|  |                 Attr::Rename(s) => { | ||||||
|  |                     if attributes.rename.is_some() { | ||||||
|  |                         return Err(syn::Error::new( | ||||||
|  |                             Span::call_site(), | ||||||
|  |                             "found multiple ruma_enum(rename) attributes", | ||||||
|  |                         )); | ||||||
|  |                     } | ||||||
|  |                     attributes.rename = Some(s); | ||||||
|  |                 } | ||||||
|  |                 Attr::Alias(s) => { | ||||||
|  |                     attributes.aliases.push(s); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     Ok(attributes) | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user