diff --git a/crates/ruma-macros/src/lib.rs b/crates/ruma-macros/src/lib.rs index 6f8440b5..113b76e6 100644 --- a/crates/ruma-macros/src/lib.rs +++ b/crates/ruma-macros/src/lib.rs @@ -33,6 +33,7 @@ use self::{ }, identifiers::IdentifierInput, serde::{ + as_str_as_ref_str::expand_as_str_as_ref_str, deserialize_from_cow_str::expand_deserialize_from_cow_str, display_as_ref_str::expand_display_as_ref_str, enum_as_ref_str::expand_enum_as_ref_str, @@ -267,6 +268,13 @@ pub fn derive_enum_from_string(input: TokenStream) -> TokenStream { // FIXME: The following macros aren't actually interested in type details beyond name (and possibly // generics in the future). They probably shouldn't use `DeriveInput`. +/// Derive the `as_str()` method using the `AsRef` implementation of the type. +#[proc_macro_derive(AsStrAsRefStr, attributes(ruma_enum))] +pub fn derive_as_str_as_ref_str(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + expand_as_str_as_ref_str(&input.ident).unwrap_or_else(syn::Error::into_compile_error).into() +} + /// Derive the `fmt::Display` trait using the `AsRef` implementation of the type. #[proc_macro_derive(DisplayAsRefStr)] pub fn derive_display_as_ref_str(input: TokenStream) -> TokenStream { diff --git a/crates/ruma-macros/src/serde.rs b/crates/ruma-macros/src/serde.rs index 215e789f..9819856c 100644 --- a/crates/ruma-macros/src/serde.rs +++ b/crates/ruma-macros/src/serde.rs @@ -1,5 +1,6 @@ //! Methods and types for (de)serialization. +pub mod as_str_as_ref_str; pub mod attr; pub mod case; pub mod deserialize_from_cow_str; diff --git a/crates/ruma-macros/src/serde/as_str_as_ref_str.rs b/crates/ruma-macros/src/serde/as_str_as_ref_str.rs new file mode 100644 index 00000000..02112050 --- /dev/null +++ b/crates/ruma-macros/src/serde/as_str_as_ref_str.rs @@ -0,0 +1,16 @@ +use proc_macro2::{Ident, TokenStream}; +use quote::quote; + +pub fn expand_as_str_as_ref_str(ident: &Ident) -> syn::Result { + let as_str_doc = format!("Creates a string slice from this `{}`.", ident); + Ok(quote! { + #[automatically_derived] + #[allow(deprecated)] + impl #ident { + #[doc = #as_str_doc] + pub fn as_str(&self) -> &str { + self.as_ref() + } + } + }) +}