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)
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
|
11 | #[ruma_event(event = "m.macro.test", kind = State)]

View File

@ -27,34 +27,26 @@ mod kw {
syn::custom_keyword!(alias);
}
/// Parses attributes for `*EventContent` derives.
/// Parses struct attributes for `*EventContent` derives.
///
/// `#[ruma_event(type = "m.room.alias")]`
enum EventMeta {
enum EventStructMeta {
/// Variant holds the "m.whatever" event type.
Type(LitStr),
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
/// be generated.
CustomRedacted,
/// The given field holds a part of the event type (replaces the `*` in a `m.foo.*` event
/// type).
TypeFragment,
StateKeyType(Box<Type>),
/// Variant that holds alternate event type accepted for deserialization.
Alias(LitStr),
}
impl EventMeta {
impl EventStructMeta {
fn get_event_type(&self) -> Option<&LitStr> {
match self {
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> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![type]) {
let _: Token![type] = input.parse()?;
let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::Type)
input.parse().map(EventStructMeta::Type)
} else if lookahead.peek(kw::kind) {
let _: kw::kind = input.parse()?;
let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::Kind)
} else if lookahead.peek(kw::skip_redaction) {
let _: kw::skip_redaction = input.parse()?;
Ok(EventMeta::SkipRedaction)
input.parse().map(EventStructMeta::Kind)
} else if lookahead.peek(kw::custom_redacted) {
let _: kw::custom_redacted = input.parse()?;
Ok(EventMeta::CustomRedacted)
} else if lookahead.peek(kw::type_fragment) {
let _: kw::type_fragment = input.parse()?;
Ok(EventMeta::TypeFragment)
Ok(EventStructMeta::CustomRedacted)
} else if lookahead.peek(kw::state_key_type) {
let _: kw::state_key_type = input.parse()?;
let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::StateKeyType)
input.parse().map(EventStructMeta::StateKeyType)
} else if lookahead.peek(kw::alias) {
let _: kw::alias = input.parse()?;
let _: Token![=] = input.parse()?;
input.parse().map(EventMeta::Alias)
input.parse().map(EventStructMeta::Alias)
} else {
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 {
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> {
@ -144,7 +158,8 @@ impl MetaAttrs {
impl Parse for MetaAttrs {
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()))
}
}
@ -324,7 +339,7 @@ fn generate_redacted_event_content<'a>(
.iter()
.map(|a| -> syn::Result<_> {
if a.path.is_ident("ruma_event") {
if let EventMeta::SkipRedaction = a.parse_args()? {
if let EventFieldMeta::SkipRedaction = a.parse_args()? {
keep_field = true;
}
@ -532,7 +547,7 @@ fn generate_event_content_impl<'a>(
.find_map(|f| {
f.attrs.iter().filter(|a| a.path.is_ident("ruma_event")).find_map(|a| {
match a.parse_args() {
Ok(EventMeta::TypeFragment) => Some(Ok(f)),
Ok(EventFieldMeta::TypeFragment) => Some(Ok(f)),
Ok(_) => None,
Err(e) => Some(Err(e)),
}