macros: Merge ruma-serde-macros into ruma-macros

This commit is contained in:
Kévin Commaille 2022-03-01 18:02:57 +01:00
parent 9310189350
commit 2a3c78de18
No known key found for this signature in database
GPG Key ID: DD507DAE96E8245C
21 changed files with 189 additions and 202 deletions

1
.github/CODEOWNERS vendored
View File

@ -6,6 +6,5 @@
/crates/ruma-identifiers-validation/ @iinuwa
/crates/ruma-identity-service-api/ @iinuwa
/crates/ruma-macros/ @ruma/macro-owners
/crates/ruma-serde-macros/ @ruma/macro-owners
/crates/ruma-signatures/ @gnieto
/crates/ruma-state-res/ @DevinR528

View File

@ -27,7 +27,6 @@ rand_crate = { package = "rand", version = "0.8.3", optional = true }
ruma-identifiers-validation = { version = "0.7.0", path = "../ruma-identifiers-validation", default-features = false }
ruma-macros = { version = "=0.1.0", path = "../ruma-macros" }
ruma-serde = { version = "0.6.0", path = "../ruma-serde", optional = true }
ruma-serde-macros = { version = "0.6.0", path = "../ruma-serde-macros" }
# Renamed so we can have a serde feature.
serde1 = { package = "serde", version = "1.0.126", optional = true, features = ["derive"] }
url = "2.2.2"

View File

@ -1,8 +1,8 @@
//! Key algorithms used in Matrix spec.
use ruma_macros::{AsRefStr, DisplayAsRefStr, FromString};
#[cfg(feature = "serde")]
use ruma_serde::{DeserializeFromCowStr, SerializeAsRefStr};
use ruma_serde_macros::{AsRefStr, DisplayAsRefStr, FromString};
use crate::PrivOwnedStr;

View File

@ -2,7 +2,7 @@
use std::{cmp::Ordering, convert::TryFrom, str::FromStr};
use ruma_serde_macros::DisplayAsRefStr;
use ruma_macros::DisplayAsRefStr;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};

View File

@ -14,7 +14,7 @@ use ruma_identifiers_validation::{
device_key_id, event_id, key_id, mxc_uri, room_alias_id, room_id, room_version_id, server_name,
user_id,
};
use syn::{parse_macro_input, DeriveInput};
use syn::{parse_macro_input, DeriveInput, ItemEnum};
use self::{
events::{
@ -25,10 +25,21 @@ use self::{
event_type::expand_event_type_enum,
},
identifiers::IdentifierInput,
serde::{
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,
enum_from_string::expand_enum_from_string,
eq_as_ref_str::expand_partial_eq_as_ref_str,
ord_as_ref_str::{expand_ord_as_ref_str, expand_partial_ord_as_ref_str},
outgoing::expand_derive_outgoing,
serialize_as_ref_str::expand_serialize_as_ref_str,
},
};
mod events;
mod identifiers;
mod serde;
/// Generates an enum to represent the various Matrix event types.
///
@ -235,3 +246,150 @@ pub fn user_id(input: TokenStream) -> TokenStream {
output.into()
}
/// 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()
}
/// Derive the `AsRef<str>` trait for an enum.
#[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()
}
/// Derive the `From<T: AsRef<str> + Into<Box<str>>>` trait for an enum.
#[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`.
/// Derive the `fmt::Display` trait using the `AsRef<str>` implementation of the type.
#[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()
}
/// Derive the `Serialize` trait using the `AsRef<str>` implementation of the type.
#[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()
}
/// Derive the `Deserialize` trait using the `From<Cow<str>>` implementation of the type.
#[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()
}
/// Derive the `PartialOrd` trait using the `AsRef<str>` implementation of the type.
#[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()
}
/// Derive the `Ord` trait using the `AsRef<str>` implementation of the type.
#[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()
}
/// Derive the `PartialEq` trait using the `AsRef<str>` implementation of the type.
#[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()
}

View File

@ -0,0 +1,15 @@
//! Methods and types for [ruma-serde].
//!
//! [ruma-events]: https://github.com/ruma/ruma/tree/main/ruma-serde
pub mod attr;
pub mod case;
pub mod deserialize_from_cow_str;
pub mod display_as_ref_str;
pub mod enum_as_ref_str;
pub mod enum_from_string;
pub mod eq_as_ref_str;
pub mod ord_as_ref_str;
pub mod outgoing;
pub mod serialize_as_ref_str;
mod util;

View File

@ -3,7 +3,7 @@ use syn::{
LitStr, Token,
};
use crate::case::RenameRule;
use super::case::RenameRule;
mod kw {
syn::custom_keyword!(rename);

View File

@ -1,7 +1,7 @@
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use crate::util::import_ruma_serde;
use super::util::import_ruma_serde;
pub fn expand_deserialize_from_cow_str(ident: &Ident) -> syn::Result<TokenStream> {
let ruma_serde = import_ruma_serde();

View File

@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum};
use crate::util::{get_rename, get_rename_rule};
use super::util::{get_rename, get_rename_rule};
pub fn expand_enum_as_ref_str(input: &ItemEnum) -> syn::Result<TokenStream> {
let enum_name = &input.ident;

View File

@ -2,7 +2,7 @@ use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use syn::{Fields, FieldsNamed, FieldsUnnamed, ItemEnum};
use crate::util::{get_rename, get_rename_rule};
use super::util::{get_rename, get_rename_rule};
pub fn expand_enum_from_string(input: &ItemEnum) -> syn::Result<TokenStream> {
let enum_name = &input.ident;

View File

@ -9,7 +9,7 @@ use syn::{
PathArguments, Token, Type, TypeGenerics, TypePath, TypeReference, TypeSlice, Variant,
};
use crate::util::import_ruma_serde;
use super::util::import_ruma_serde;
enum StructKind {
Struct,

View File

@ -1,7 +1,7 @@
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use crate::util::import_ruma_serde;
use super::util::import_ruma_serde;
pub fn expand_serialize_as_ref_str(ident: &Ident) -> syn::Result<TokenStream> {
let ruma_serde = import_ruma_serde();

View File

@ -3,7 +3,7 @@ use proc_macro_crate::{crate_name, FoundCrate};
use quote::{format_ident, quote};
use syn::{ItemEnum, LitStr, Variant};
use crate::{
use super::{
attr::{RenameAllAttr, RenameAttr},
case::RenameRule,
};

View File

@ -1,19 +0,0 @@
[package]
categories = ["api-bindings", "web-programming"]
description = "Procedural macros for ruma-serde."
homepage = "https://www.ruma.io/"
keywords = ["matrix", "chat", "messaging", "ruma"]
license = "MIT"
name = "ruma-serde-macros"
repository = "https://github.com/ruma/ruma"
version = "0.6.0"
edition = "2018"
[lib]
proc-macro = true
[dependencies]
proc-macro-crate = "1.0.0"
proc-macro2 = "1.0.24"
quote = "1.0.8"
syn = { version = "1.0.55", features = ["full"] }

View File

@ -1,168 +0,0 @@
#![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 self::{
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,
enum_from_string::expand_enum_from_string,
eq_as_ref_str::expand_partial_eq_as_ref_str,
ord_as_ref_str::{expand_ord_as_ref_str, expand_partial_ord_as_ref_str},
outgoing::expand_derive_outgoing,
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()
}

View File

@ -13,7 +13,7 @@ bytes = "1.0.1"
form_urlencoded = "1.0.0"
itoa = "1.0.1"
js_int = { version = "0.2.0", features = ["serde"] }
ruma-serde-macros = { version = "=0.6.0", path = "../ruma-serde-macros" }
ruma-macros = { version = "=0.1.0", path = "../ruma-macros" }
serde = { version = "1.0.118", features = ["derive"] }
serde_json = { version = "1.0.61", features = ["raw_value"] }

View File

@ -87,9 +87,12 @@ pub trait Outgoing {
// -- Everything below is macro-related --
pub use ruma_serde_macros::*;
pub use ruma_macros::{
AsRefStr, DeserializeFromCowStr, DisplayAsRefStr, FromString, OrdAsRefStr, Outgoing,
PartialEqAsRefStr, PartialOrdAsRefStr, SerializeAsRefStr, StringEnum, _FakeDeriveSerde,
};
/// This module is used to support the generated code from ruma-serde-macros.
/// This module is used to support the generated code from ruma-macros.
/// It is not considered part of ruma-serde's public API.
#[doc(hidden)]
pub mod exports {