events: Split EventMeta between struct and field attributes

This commit is contained in:
Kévin Commaille 2022-05-16 17:08:36 +02:00 committed by GitHub
parent 6939c048b0
commit 74423b7a4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 29 deletions

View File

@ -6,7 +6,7 @@ error: no event type attribute found, add `#[ruma_event(type = "any.room.event",
| |
= note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the derive macro `EventContent` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected one of: `type`, `kind`, `skip_redaction`, `custom_redacted`, `type_fragment`, `state_key_type`, `alias` error: expected one of: `type`, `kind`, `custom_redacted`, `state_key_type`, `alias`
--> tests/events/ui/03-invalid-event-type.rs:11:14 --> tests/events/ui/03-invalid-event-type.rs:11:14
| |
11 | #[ruma_event(event = "m.macro.test", kind = State)] 11 | #[ruma_event(event = "m.macro.test", kind = State)]

View File

@ -27,34 +27,26 @@ mod kw {
syn::custom_keyword!(alias); syn::custom_keyword!(alias);
} }
/// Parses attributes for `*EventContent` derives. /// Parses struct attributes for `*EventContent` derives.
/// ///
/// `#[ruma_event(type = "m.room.alias")]` /// `#[ruma_event(type = "m.room.alias")]`
enum EventMeta { enum EventStructMeta {
/// Variant holds the "m.whatever" event type. /// Variant holds the "m.whatever" event type.
Type(LitStr), Type(LitStr),
Kind(EventKind), Kind(EventKind),
/// Fields marked with `#[ruma_event(skip_redaction)]` are kept when the event is
/// redacted.
SkipRedaction,
/// This attribute signals that the events redacted form is manually implemented and should not /// This attribute signals that the events redacted form is manually implemented and should not
/// be generated. /// be generated.
CustomRedacted, CustomRedacted,
/// The given field holds a part of the event type (replaces the `*` in a `m.foo.*` event
/// type).
TypeFragment,
StateKeyType(Box<Type>), StateKeyType(Box<Type>),
/// Variant that holds alternate event type accepted for deserialization. /// Variant that holds alternate event type accepted for deserialization.
Alias(LitStr), Alias(LitStr),
} }
impl EventMeta { impl EventStructMeta {
fn get_event_type(&self) -> Option<&LitStr> { fn get_event_type(&self) -> Option<&LitStr> {
match self { match self {
Self::Type(t) => Some(t), Self::Type(t) => Some(t),
@ -84,45 +76,67 @@ impl EventMeta {
} }
} }
impl Parse for EventMeta { impl Parse for EventStructMeta {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> { fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let lookahead = input.lookahead1(); let lookahead = input.lookahead1();
if lookahead.peek(Token![type]) { if lookahead.peek(Token![type]) {
let _: Token![type] = input.parse()?; let _: Token![type] = input.parse()?;
let _: Token![=] = input.parse()?; let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::Type) input.parse().map(EventStructMeta::Type)
} else if lookahead.peek(kw::kind) { } else if lookahead.peek(kw::kind) {
let _: kw::kind = input.parse()?; let _: kw::kind = input.parse()?;
let _: Token![=] = input.parse()?; let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::Kind) input.parse().map(EventStructMeta::Kind)
} else if lookahead.peek(kw::skip_redaction) {
let _: kw::skip_redaction = input.parse()?;
Ok(EventMeta::SkipRedaction)
} else if lookahead.peek(kw::custom_redacted) { } else if lookahead.peek(kw::custom_redacted) {
let _: kw::custom_redacted = input.parse()?; let _: kw::custom_redacted = input.parse()?;
Ok(EventMeta::CustomRedacted) Ok(EventStructMeta::CustomRedacted)
} else if lookahead.peek(kw::type_fragment) {
let _: kw::type_fragment = input.parse()?;
Ok(EventMeta::TypeFragment)
} else if lookahead.peek(kw::state_key_type) { } else if lookahead.peek(kw::state_key_type) {
let _: kw::state_key_type = input.parse()?; let _: kw::state_key_type = input.parse()?;
let _: Token![=] = input.parse()?; let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::StateKeyType) input.parse().map(EventStructMeta::StateKeyType)
} else if lookahead.peek(kw::alias) { } else if lookahead.peek(kw::alias) {
let _: kw::alias = input.parse()?; let _: kw::alias = input.parse()?;
let _: Token![=] = input.parse()?; let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::Alias) input.parse().map(EventStructMeta::Alias)
} else { } else {
Err(lookahead.error()) Err(lookahead.error())
} }
} }
} }
struct MetaAttrs(Vec<EventMeta>); /// Parses field attributes for `*EventContent` derives.
///
/// `#[ruma_event(skip_redaction)]`
enum EventFieldMeta {
/// Fields marked with `#[ruma_event(skip_redaction)]` are kept when the event is
/// redacted.
SkipRedaction,
/// The given field holds a part of the event type (replaces the `*` in a `m.foo.*` event
/// type).
TypeFragment,
}
impl Parse for EventFieldMeta {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(kw::skip_redaction) {
let _: kw::skip_redaction = input.parse()?;
Ok(EventFieldMeta::SkipRedaction)
} else if lookahead.peek(kw::type_fragment) {
let _: kw::type_fragment = input.parse()?;
Ok(EventFieldMeta::TypeFragment)
} else {
Err(lookahead.error())
}
}
}
struct MetaAttrs(Vec<EventStructMeta>);
impl MetaAttrs { impl MetaAttrs {
fn is_custom(&self) -> bool { fn is_custom(&self) -> bool {
self.0.iter().any(|a| matches!(a, &EventMeta::CustomRedacted)) self.0.iter().any(|a| matches!(a, &EventStructMeta::CustomRedacted))
} }
fn get_event_type(&self) -> Option<&LitStr> { fn get_event_type(&self) -> Option<&LitStr> {
@ -144,7 +158,8 @@ impl MetaAttrs {
impl Parse for MetaAttrs { impl Parse for MetaAttrs {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> { fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let attrs = syn::punctuated::Punctuated::<EventMeta, Token![,]>::parse_terminated(input)?; let attrs =
syn::punctuated::Punctuated::<EventStructMeta, Token![,]>::parse_terminated(input)?;
Ok(Self(attrs.into_iter().collect())) Ok(Self(attrs.into_iter().collect()))
} }
} }
@ -324,7 +339,7 @@ fn generate_redacted_event_content<'a>(
.iter() .iter()
.map(|a| -> syn::Result<_> { .map(|a| -> syn::Result<_> {
if a.path.is_ident("ruma_event") { if a.path.is_ident("ruma_event") {
if let EventMeta::SkipRedaction = a.parse_args()? { if let EventFieldMeta::SkipRedaction = a.parse_args()? {
keep_field = true; keep_field = true;
} }
@ -532,7 +547,7 @@ fn generate_event_content_impl<'a>(
.find_map(|f| { .find_map(|f| {
f.attrs.iter().filter(|a| a.path.is_ident("ruma_event")).find_map(|a| { f.attrs.iter().filter(|a| a.path.is_ident("ruma_event")).find_map(|a| {
match a.parse_args() { match a.parse_args() {
Ok(EventMeta::TypeFragment) => Some(Ok(f)), Ok(EventFieldMeta::TypeFragment) => Some(Ok(f)),
Ok(_) => None, Ok(_) => None,
Err(e) => Some(Err(e)), Err(e) => Some(Err(e)),
} }