events-macros: Reorganize event impl generation
This commit is contained in:
		
							parent
							
								
									7a4af83207
								
							
						
					
					
						commit
						9103ad74bb
					
				| @ -10,6 +10,7 @@ use syn::{ | |||||||
| use crate::{ | use crate::{ | ||||||
|     event_parse::{to_kind_variation, EventKind, EventKindVariation}, |     event_parse::{to_kind_variation, EventKind, EventKindVariation}, | ||||||
|     import_ruma_events, |     import_ruma_events, | ||||||
|  |     util::is_non_stripped_room_event, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Derive `Event` macro code generation.
 | /// Derive `Event` macro code generation.
 | ||||||
| @ -41,19 +42,26 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> { | |||||||
|         )); |         )); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     let conversion_impl = expand_from_into(&input, kind, var, &fields, &ruma_events); |     let mut res = TokenStream::new(); | ||||||
|     let serialize_impl = expand_serialize_event(&input, var, &fields, &ruma_events); |  | ||||||
|     let deserialize_impl = expand_deserialize_event(&input, kind, var, &fields, &ruma_events)?; |  | ||||||
|     let redact_impl = expand_redact_event(&input, kind, var, &fields, &ruma_events); |  | ||||||
|     let eq_impl = expand_eq_ord_event(&input, &fields); |  | ||||||
| 
 | 
 | ||||||
|     Ok(quote! { |     res.extend(expand_serialize_event(&input, var, &fields, &ruma_events)); | ||||||
|         #conversion_impl |     res.extend(expand_deserialize_event(&input, kind, var, &fields, &ruma_events)?); | ||||||
|         #serialize_impl | 
 | ||||||
|         #deserialize_impl |     if var.is_sync() { | ||||||
|         #redact_impl |         res.extend(expand_sync_from_into_full(&input, kind, var, &fields, &ruma_events)); | ||||||
|         #eq_impl |     } | ||||||
|     }) | 
 | ||||||
|  |     if matches!(kind, EventKind::Message | EventKind::State) | ||||||
|  |         && matches!(var, EventKindVariation::Full | EventKindVariation::Sync) | ||||||
|  |     { | ||||||
|  |         res.extend(expand_redact_event(&input, kind, var, &fields, &ruma_events)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if is_non_stripped_room_event(kind, var) { | ||||||
|  |         res.extend(expand_eq_ord_event(&input)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Ok(res) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn expand_serialize_event( | fn expand_serialize_event( | ||||||
| @ -405,17 +413,17 @@ fn expand_redact_event( | |||||||
|     var: EventKindVariation, |     var: EventKindVariation, | ||||||
|     fields: &[Field], |     fields: &[Field], | ||||||
|     ruma_events: &TokenStream, |     ruma_events: &TokenStream, | ||||||
| ) -> Option<TokenStream> { | ) -> TokenStream { | ||||||
|     let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers }; |     let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers }; | ||||||
| 
 | 
 | ||||||
|     let redacted_type = kind.to_event_ident(var.to_redacted()?)?; |     let redacted_type = kind.to_event_ident(var.to_redacted().unwrap()).unwrap(); | ||||||
|     let redacted_content_trait = |     let redacted_content_trait = | ||||||
|         format_ident!("{}Content", kind.to_event_ident(EventKindVariation::Redacted).unwrap()); |         format_ident!("{}Content", kind.to_event_ident(EventKindVariation::Redacted).unwrap()); | ||||||
|     let ident = &input.ident; |     let ident = &input.ident; | ||||||
| 
 | 
 | ||||||
|     let mut generics = input.generics.clone(); |     let mut generics = input.generics.clone(); | ||||||
|     if generics.params.is_empty() { |     if generics.params.is_empty() { | ||||||
|         return None; |         return TokenStream::new(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     assert_eq!(generics.params.len(), 1, "expected one generic parameter"); |     assert_eq!(generics.params.len(), 1, "expected one generic parameter"); | ||||||
| @ -450,7 +458,7 @@ fn expand_redact_event( | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     Some(quote! { |     quote! { | ||||||
|         #[automatically_derived] |         #[automatically_derived] | ||||||
|         impl #impl_generics #ruma_events::Redact for #ident #ty_gen #where_clause { |         impl #impl_generics #ruma_events::Redact for #ident #ty_gen #where_clause { | ||||||
|             type Redacted = |             type Redacted = | ||||||
| @ -468,91 +476,83 @@ fn expand_redact_event( | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }) |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn expand_from_into( | fn expand_sync_from_into_full( | ||||||
|     input: &DeriveInput, |     input: &DeriveInput, | ||||||
|     kind: EventKind, |     kind: EventKind, | ||||||
|     var: EventKindVariation, |     var: EventKindVariation, | ||||||
|     fields: &[Field], |     fields: &[Field], | ||||||
|     ruma_events: &TokenStream, |     ruma_events: &TokenStream, | ||||||
| ) -> Option<TokenStream> { | ) -> TokenStream { | ||||||
|     let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers }; |     let ruma_identifiers = quote! { #ruma_events::exports::ruma_identifiers }; | ||||||
| 
 | 
 | ||||||
|     let ident = &input.ident; |     let ident = &input.ident; | ||||||
| 
 |     let full_struct = kind.to_event_ident(var.to_full().unwrap()).unwrap(); | ||||||
|     let (impl_generics, ty_gen, where_clause) = input.generics.split_for_impl(); |     let (impl_generics, ty_gen, where_clause) = input.generics.split_for_impl(); | ||||||
| 
 |  | ||||||
|     let fields: Vec<_> = fields.iter().flat_map(|f| &f.ident).collect(); |     let fields: Vec<_> = fields.iter().flat_map(|f| &f.ident).collect(); | ||||||
| 
 | 
 | ||||||
|     if let EventKindVariation::Sync | EventKindVariation::RedactedSync = var { |     quote! { | ||||||
|         let full_struct = kind.to_event_ident(var.to_full().unwrap()).unwrap(); |         #[automatically_derived] | ||||||
|         Some(quote! { |         impl #impl_generics ::std::convert::From<#full_struct #ty_gen> | ||||||
|             #[automatically_derived] |             for #ident #ty_gen #where_clause | ||||||
|             impl #impl_generics ::std::convert::From<#full_struct #ty_gen> |         { | ||||||
|                 for #ident #ty_gen #where_clause |             fn from(event: #full_struct #ty_gen) -> Self { | ||||||
|             { |                 let #full_struct { #( #fields, )* .. } = event; | ||||||
|                 fn from(event: #full_struct #ty_gen) -> Self { |                 Self { #( #fields, )* } | ||||||
|                     let #full_struct { #( #fields, )* .. } = event; |  | ||||||
|                     Self { #( #fields, )* } |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             #[automatically_derived] |         #[automatically_derived] | ||||||
|             impl #impl_generics #ident #ty_gen #where_clause { |         impl #impl_generics #ident #ty_gen #where_clause { | ||||||
|                 /// Convert this sync event into a full event, one with a room_id field.
 |             /// Convert this sync event into a full event, one with a room_id field.
 | ||||||
|                 pub fn into_full_event( |             pub fn into_full_event( | ||||||
|                     self, |                 self, | ||||||
|                     room_id: #ruma_identifiers::RoomId, |                 room_id: #ruma_identifiers::RoomId, | ||||||
|                 ) -> #full_struct #ty_gen { |             ) -> #full_struct #ty_gen { | ||||||
|                     let Self { #( #fields, )* } = self; |                 let Self { #( #fields, )* } = self; | ||||||
|                     #full_struct { |                 #full_struct { | ||||||
|                         #( #fields, )* |                     #( #fields, )* | ||||||
|                         room_id, |                     room_id, | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     } else { |  | ||||||
|         None |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn expand_eq_ord_event(input: &DeriveInput, fields: &[Field]) -> Option<TokenStream> { |  | ||||||
|     fields.iter().flat_map(|f| f.ident.as_ref()).any(|f| f == "event_id").then(|| { |  | ||||||
|         let ident = &input.ident; |  | ||||||
|         let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl(); |  | ||||||
| 
 |  | ||||||
|         quote! { |  | ||||||
|             #[automatically_derived] |  | ||||||
|             impl #impl_gen ::std::cmp::PartialEq for #ident #ty_gen #where_clause { |  | ||||||
|                 /// Checks if two `EventId`s are equal.
 |  | ||||||
|                 fn eq(&self, other: &Self) -> ::std::primitive::bool { |  | ||||||
|                     self.event_id == other.event_id |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             #[automatically_derived] |  | ||||||
|             impl #impl_gen ::std::cmp::Eq for #ident #ty_gen #where_clause {} |  | ||||||
| 
 |  | ||||||
|             #[automatically_derived] |  | ||||||
|             impl #impl_gen ::std::cmp::PartialOrd for #ident #ty_gen #where_clause { |  | ||||||
|                 /// Compares `EventId`s and orders them lexicographically.
 |  | ||||||
|                 fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> { |  | ||||||
|                     self.event_id.partial_cmp(&other.event_id) |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             #[automatically_derived] |  | ||||||
|             impl #impl_gen ::std::cmp::Ord for #ident #ty_gen #where_clause { |  | ||||||
|                 /// Compares `EventId`s and orders them lexicographically.
 |  | ||||||
|                 fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { |  | ||||||
|                     self.event_id.cmp(&other.event_id) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }) |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn expand_eq_ord_event(input: &DeriveInput) -> TokenStream { | ||||||
|  |     let ident = &input.ident; | ||||||
|  |     let (impl_gen, ty_gen, where_clause) = input.generics.split_for_impl(); | ||||||
|  | 
 | ||||||
|  |     quote! { | ||||||
|  |         #[automatically_derived] | ||||||
|  |         impl #impl_gen ::std::cmp::PartialEq for #ident #ty_gen #where_clause { | ||||||
|  |             /// Checks if two `EventId`s are equal.
 | ||||||
|  |             fn eq(&self, other: &Self) -> ::std::primitive::bool { | ||||||
|  |                 self.event_id == other.event_id | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #[automatically_derived] | ||||||
|  |         impl #impl_gen ::std::cmp::Eq for #ident #ty_gen #where_clause {} | ||||||
|  | 
 | ||||||
|  |         #[automatically_derived] | ||||||
|  |         impl #impl_gen ::std::cmp::PartialOrd for #ident #ty_gen #where_clause { | ||||||
|  |             /// Compares `EventId`s and orders them lexicographically.
 | ||||||
|  |             fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> { | ||||||
|  |                 self.event_id.partial_cmp(&other.event_id) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #[automatically_derived] | ||||||
|  |         impl #impl_gen ::std::cmp::Ord for #ident #ty_gen #where_clause { | ||||||
|  |             /// Compares `EventId`s and orders them lexicographically.
 | ||||||
|  |             fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { | ||||||
|  |                 self.event_id.cmp(&other.event_id) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// CamelCase's a field ident like "foo_bar" to "FooBar".
 | /// CamelCase's a field ident like "foo_bar" to "FooBar".
 | ||||||
|  | |||||||
| @ -4,43 +4,10 @@ use proc_macro2::{Span, TokenStream}; | |||||||
| use quote::{format_ident, quote, ToTokens}; | use quote::{format_ident, quote, ToTokens}; | ||||||
| use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr}; | use syn::{Attribute, Data, DataEnum, DeriveInput, Ident, LitStr}; | ||||||
| 
 | 
 | ||||||
| use crate::event_parse::{EventEnumDecl, EventEnumEntry, EventKind, EventKindVariation}; | use crate::{ | ||||||
| 
 |     event_parse::{EventEnumDecl, EventEnumEntry, EventKind, EventKindVariation}, | ||||||
| fn is_non_stripped_room_event(kind: EventKind, var: EventKindVariation) -> bool { |     util::{has_prev_content_field, EVENT_FIELDS}, | ||||||
|     matches!(kind, EventKind::Message | EventKind::State) | }; | ||||||
|         && matches!( |  | ||||||
|             var, |  | ||||||
|             EventKindVariation::Full |  | ||||||
|                 | EventKindVariation::Sync |  | ||||||
|                 | EventKindVariation::Redacted |  | ||||||
|                 | EventKindVariation::RedactedSync |  | ||||||
|         ) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn has_prev_content_field(kind: EventKind, var: EventKindVariation) -> bool { |  | ||||||
|     matches!(kind, EventKind::State) |  | ||||||
|         && matches!(var, EventKindVariation::Full | EventKindVariation::Sync) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type EventKindFn = fn(EventKind, EventKindVariation) -> bool; |  | ||||||
| 
 |  | ||||||
| /// This const is used to generate the accessor methods for the `Any*Event` enums.
 |  | ||||||
| ///
 |  | ||||||
| /// DO NOT alter the field names unless the structs in `ruma_events::event_kinds` have changed.
 |  | ||||||
| const EVENT_FIELDS: &[(&str, EventKindFn)] = &[ |  | ||||||
|     ("origin_server_ts", is_non_stripped_room_event), |  | ||||||
|     ("room_id", |kind, var| { |  | ||||||
|         matches!(kind, EventKind::Message | EventKind::State | EventKind::Ephemeral) |  | ||||||
|             && matches!(var, EventKindVariation::Full | EventKindVariation::Redacted) |  | ||||||
|     }), |  | ||||||
|     ("event_id", is_non_stripped_room_event), |  | ||||||
|     ("sender", |kind, var| { |  | ||||||
|         matches!(kind, EventKind::Message | EventKind::State | EventKind::ToDevice) |  | ||||||
|             && var != EventKindVariation::Initial |  | ||||||
|     }), |  | ||||||
|     ("state_key", |kind, _| matches!(kind, EventKind::State)), |  | ||||||
|     ("unsigned", is_non_stripped_room_event), |  | ||||||
| ]; |  | ||||||
| 
 | 
 | ||||||
| /// Create a content enum from `EventEnumInput`.
 | /// Create a content enum from `EventEnumInput`.
 | ||||||
| pub fn expand_event_enums(input: &EventEnumDecl) -> syn::Result<TokenStream> { | pub fn expand_event_enums(input: &EventEnumDecl) -> syn::Result<TokenStream> { | ||||||
|  | |||||||
| @ -45,6 +45,10 @@ impl EventKindVariation { | |||||||
|         matches!(self, Self::Redacted | Self::RedactedSync) |         matches!(self, Self::Redacted | Self::RedactedSync) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn is_sync(self) -> bool { | ||||||
|  |         matches!(self, Self::Sync | Self::RedactedSync) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn to_redacted(self) -> Option<Self> { |     pub fn to_redacted(self) -> Option<Self> { | ||||||
|         match self { |         match self { | ||||||
|             EventKindVariation::Full => Some(EventKindVariation::Redacted), |             EventKindVariation::Full => Some(EventKindVariation::Redacted), | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ mod event_content; | |||||||
| mod event_enum; | mod event_enum; | ||||||
| mod event_parse; | mod event_parse; | ||||||
| mod event_type; | mod event_type; | ||||||
|  | mod util; | ||||||
| 
 | 
 | ||||||
| /// Generates an enum to represent the various Matrix event types.
 | /// Generates an enum to represent the various Matrix event types.
 | ||||||
| ///
 | ///
 | ||||||
|  | |||||||
							
								
								
									
										37
									
								
								crates/ruma-events-macros/src/util.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								crates/ruma-events-macros/src/util.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | use crate::event_parse::{EventKind, EventKindVariation}; | ||||||
|  | 
 | ||||||
|  | pub(crate) fn is_non_stripped_room_event(kind: EventKind, var: EventKindVariation) -> bool { | ||||||
|  |     matches!(kind, EventKind::Message | EventKind::State) | ||||||
|  |         && matches!( | ||||||
|  |             var, | ||||||
|  |             EventKindVariation::Full | ||||||
|  |                 | EventKindVariation::Sync | ||||||
|  |                 | EventKindVariation::Redacted | ||||||
|  |                 | EventKindVariation::RedactedSync | ||||||
|  |         ) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub(crate) fn has_prev_content_field(kind: EventKind, var: EventKindVariation) -> bool { | ||||||
|  |     matches!(kind, EventKind::State) | ||||||
|  |         && matches!(var, EventKindVariation::Full | EventKindVariation::Sync) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub(crate) type EventKindFn = fn(EventKind, EventKindVariation) -> bool; | ||||||
|  | 
 | ||||||
|  | /// This const is used to generate the accessor methods for the `Any*Event` enums.
 | ||||||
|  | ///
 | ||||||
|  | /// DO NOT alter the field names unless the structs in `ruma_events::event_kinds` have changed.
 | ||||||
|  | pub(crate) const EVENT_FIELDS: &[(&str, EventKindFn)] = &[ | ||||||
|  |     ("origin_server_ts", is_non_stripped_room_event), | ||||||
|  |     ("room_id", |kind, var| { | ||||||
|  |         matches!(kind, EventKind::Message | EventKind::State | EventKind::Ephemeral) | ||||||
|  |             && matches!(var, EventKindVariation::Full | EventKindVariation::Redacted) | ||||||
|  |     }), | ||||||
|  |     ("event_id", is_non_stripped_room_event), | ||||||
|  |     ("sender", |kind, var| { | ||||||
|  |         matches!(kind, EventKind::Message | EventKind::State | EventKind::ToDevice) | ||||||
|  |             && var != EventKindVariation::Initial | ||||||
|  |     }), | ||||||
|  |     ("state_key", |kind, _| matches!(kind, EventKind::State)), | ||||||
|  |     ("unsigned", is_non_stripped_room_event), | ||||||
|  | ]; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user