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