165 lines
6.0 KiB
Rust
165 lines
6.0 KiB
Rust
#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
|
|
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
|
|
|
|
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{parse_macro_input, DeriveInput, ItemEnum};
|
|
|
|
use deserialize_from_cow_str::expand_deserialize_from_cow_str;
|
|
use display_as_ref_str::expand_display_as_ref_str;
|
|
use enum_as_ref_str::expand_enum_as_ref_str;
|
|
use enum_from_string::expand_enum_from_string;
|
|
use eq_as_ref_str::expand_partial_eq_as_ref_str;
|
|
use ord_as_ref_str::{expand_ord_as_ref_str, expand_partial_ord_as_ref_str};
|
|
use outgoing::expand_derive_outgoing;
|
|
use serialize_as_ref_str::expand_serialize_as_ref_str;
|
|
|
|
mod attr;
|
|
mod case;
|
|
mod deserialize_from_cow_str;
|
|
mod display_as_ref_str;
|
|
mod enum_as_ref_str;
|
|
mod enum_from_string;
|
|
mod eq_as_ref_str;
|
|
mod ord_as_ref_str;
|
|
mod outgoing;
|
|
mod serialize_as_ref_str;
|
|
mod util;
|
|
|
|
/// Derive the `Outgoing` trait, possibly generating an 'Incoming' version of the struct this
|
|
/// derive macro is used on. Specifically, if no lifetime variables are used on any of the fields
|
|
/// of the struct, this simple implementation will be generated:
|
|
///
|
|
/// ```ignore
|
|
/// # // TODO: "ignore" this doctest until it is more extensively documented. (See #541)
|
|
/// impl Outgoing for MyType {
|
|
/// type Incoming = Self;
|
|
/// }
|
|
/// ```
|
|
/*
|
|
|
|
TODO: Extend docs. Previously:
|
|
|
|
If, however, `#[wrap_incoming]` is used (which is the only reason you should ever use this
|
|
derive macro manually), a new struct `IncomingT` (where `T` is the type this derive is used on)
|
|
is generated, with all of the fields with `#[wrap_incoming]` replaced:
|
|
|
|
```ignore
|
|
#[derive(Outgoing)]
|
|
struct MyType {
|
|
pub foo: Foo,
|
|
#[wrap_incoming]
|
|
pub bar: Bar,
|
|
#[wrap_incoming(Baz)]
|
|
pub baz: Option<Baz>,
|
|
#[wrap_incoming(with EventResult)]
|
|
pub x: XEvent,
|
|
#[wrap_incoming(YEvent with EventResult)]
|
|
pub ys: Vec<YEvent>,
|
|
}
|
|
|
|
// generated
|
|
struct IncomingMyType {
|
|
pub foo: Foo,
|
|
pub bar: IncomingBar,
|
|
pub baz: Option<IncomingBaz>,
|
|
pub x: EventResult<XEvent>,
|
|
pub ys: Vec<EventResult<YEvent>>,
|
|
}
|
|
```
|
|
|
|
*/
|
|
#[proc_macro_derive(Outgoing, attributes(incoming_derive))]
|
|
pub fn derive_outgoing(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_derive_outgoing(input).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
#[proc_macro_derive(AsRefStr, attributes(ruma_enum))]
|
|
pub fn derive_enum_as_ref_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as ItemEnum);
|
|
expand_enum_as_ref_str(&input).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
#[proc_macro_derive(FromString, attributes(ruma_enum))]
|
|
pub fn derive_enum_from_string(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as ItemEnum);
|
|
expand_enum_from_string(&input).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
// 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`.
|
|
|
|
#[proc_macro_derive(DisplayAsRefStr)]
|
|
pub fn derive_display_as_ref_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_display_as_ref_str(&input.ident).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
#[proc_macro_derive(SerializeAsRefStr)]
|
|
pub fn derive_serialize_as_ref_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_serialize_as_ref_str(&input.ident).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
#[proc_macro_derive(DeserializeFromCowStr)]
|
|
pub fn derive_deserialize_from_cow_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_deserialize_from_cow_str(&input.ident)
|
|
.unwrap_or_else(syn::Error::into_compile_error)
|
|
.into()
|
|
}
|
|
|
|
#[proc_macro_derive(PartialOrdAsRefStr)]
|
|
pub fn derive_partial_ord_as_ref_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_partial_ord_as_ref_str(&input.ident)
|
|
.unwrap_or_else(syn::Error::into_compile_error)
|
|
.into()
|
|
}
|
|
|
|
#[proc_macro_derive(OrdAsRefStr)]
|
|
pub fn derive_ord_as_ref_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_ord_as_ref_str(&input.ident).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
#[proc_macro_derive(PartialEqAsRefStr)]
|
|
pub fn derive_partial_eq_as_ref_str(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand_partial_eq_as_ref_str(&input.ident).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
/// Shorthand for the derives `AsRefStr`, `FromString`, `DisplayAsRefStr`, `SerializeAsRefStr` and
|
|
/// `DeserializeFromCowStr`.
|
|
#[proc_macro_derive(StringEnum, attributes(ruma_enum))]
|
|
pub fn derive_string_enum(input: TokenStream) -> TokenStream {
|
|
fn expand_all(input: ItemEnum) -> syn::Result<proc_macro2::TokenStream> {
|
|
let as_ref_str_impl = expand_enum_as_ref_str(&input)?;
|
|
let from_string_impl = expand_enum_from_string(&input)?;
|
|
let display_impl = expand_display_as_ref_str(&input.ident)?;
|
|
let serialize_impl = expand_serialize_as_ref_str(&input.ident)?;
|
|
let deserialize_impl = expand_deserialize_from_cow_str(&input.ident)?;
|
|
|
|
Ok(quote! {
|
|
#as_ref_str_impl
|
|
#from_string_impl
|
|
#display_impl
|
|
#serialize_impl
|
|
#deserialize_impl
|
|
})
|
|
}
|
|
|
|
let input = parse_macro_input!(input as ItemEnum);
|
|
expand_all(input).unwrap_or_else(syn::Error::into_compile_error).into()
|
|
}
|
|
|
|
/// A derive macro that generates no code, but registers the serde attribute so both `#[serde(...)]`
|
|
/// and `#[cfg_attr(..., serde(...))]` are accepted on the type, its fields and (in case the input
|
|
/// is an enum) variants fields.
|
|
#[doc(hidden)]
|
|
#[proc_macro_derive(_FakeDeriveSerde, attributes(serde))]
|
|
pub fn fake_derive_serde(_input: TokenStream) -> TokenStream {
|
|
TokenStream::new()
|
|
}
|