Remove raw mod and TryFromRaw/FromRaw, derive Deserialize for event content types
This commit is contained in:
		
							parent
							
								
									2c8d609095
								
							
						
					
					
						commit
						0a91ac5126
					
				| @ -53,80 +53,12 @@ pub fn expand_collection(input: RumaCollectionInput) -> syn::Result<TokenStream> | ||||
|                     #( Self::#variants(content) => content.event_type() ),* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let try_from_raw_impl = quote! { | ||||
|         impl ::ruma_events::TryFromRaw for #ident { | ||||
|             type Raw = raw::#ident; | ||||
|             type Err = String; | ||||
| 
 | ||||
|             fn try_from_raw(raw: Self::Raw) -> Result<Self, Self::Err> { | ||||
|                 use raw::#ident::*; | ||||
| 
 | ||||
|                 match raw { | ||||
|                     #( #variants(c) => { | ||||
|                             let content = ::ruma_events::TryFromRaw::try_from_raw(c) | ||||
|                                 .map_err(|e: <#content as ::ruma_events::TryFromRaw>::Err| e.to_string())?; | ||||
|                                 // without this ^^^^^^^^^^^ the compiler fails to infer the type
 | ||||
|                             Ok(Self::#variants(content)) | ||||
|                         } | ||||
|                     ),* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let marker_trait_impls = marker_traits(ident); | ||||
| 
 | ||||
|     let raw_mod = expand_raw_content_event(&input, &variants)?; | ||||
| 
 | ||||
|     Ok(quote! { | ||||
|         #collection | ||||
| 
 | ||||
|         #try_from_raw_impl | ||||
| 
 | ||||
|         #event_content_impl | ||||
| 
 | ||||
|         #marker_trait_impls | ||||
| 
 | ||||
|         #raw_mod | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| fn expand_raw_content_event( | ||||
|     input: &RumaCollectionInput, | ||||
|     variants: &[Ident], | ||||
| ) -> syn::Result<TokenStream> { | ||||
|     let ident = &input.name; | ||||
|     let event_type_str = &input.events; | ||||
| 
 | ||||
|     let raw_docs = format!("The raw version of {}, allows for deserialization.", ident); | ||||
|     let raw_content = input | ||||
|         .events | ||||
|         .iter() | ||||
|         .map(to_raw_event_content_path) | ||||
|         .collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let raw_collection = quote! { | ||||
|         #[doc = #raw_docs] | ||||
|         #[derive(Clone, Debug)] | ||||
|         #[allow(clippy::large_enum_variant)] | ||||
|         pub enum #ident { | ||||
|             #( | ||||
|                 #[doc = #event_type_str] | ||||
|                 #variants(#raw_content) | ||||
|             ),* | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let raw_event_content_impl = quote! { | ||||
|         impl ::ruma_events::RawEventContent for #ident { | ||||
|             fn from_parts(event_type: &str, input: Box<::serde_json::value::RawValue>) -> Result<Self, String> { | ||||
|                 match event_type { | ||||
|                     #( | ||||
|                         #event_type_str => { | ||||
|                             let content = #raw_content::from_parts(event_type, input)?; | ||||
|                             let content = #content::from_parts(event_type, input)?; | ||||
|                             Ok(#ident::#variants(content)) | ||||
|                         }, | ||||
|                     )* | ||||
| @ -136,12 +68,14 @@ fn expand_raw_content_event( | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     Ok(quote! { | ||||
|         mod raw { | ||||
|             #raw_collection | ||||
|     let marker_trait_impls = marker_traits(ident); | ||||
| 
 | ||||
|             #raw_event_content_impl | ||||
|         } | ||||
|     Ok(quote! { | ||||
|         #collection | ||||
| 
 | ||||
|         #event_content_impl | ||||
| 
 | ||||
|         #marker_trait_impls | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| @ -168,29 +102,6 @@ fn to_event_content_path( | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn to_raw_event_content_path( | ||||
|     name: &LitStr, | ||||
| ) -> syn::punctuated::Punctuated<syn::Token![::], syn::PathSegment> { | ||||
|     let span = name.span(); | ||||
|     let name = name.value(); | ||||
| 
 | ||||
|     assert_eq!(&name[..2], "m."); | ||||
| 
 | ||||
|     let path = name[2..].split('.').collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let event_str = path.last().unwrap(); | ||||
|     let event = event_str | ||||
|         .split('_') | ||||
|         .map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..]) | ||||
|         .collect::<String>(); | ||||
| 
 | ||||
|     let content_str = Ident::new(&format!("{}EventContent", event), span); | ||||
|     let path = path.iter().map(|s| Ident::new(s, span)); | ||||
|     syn::parse_quote! { | ||||
|         ::ruma_events::#( #path )::*::raw::#content_str | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Splits the given `event_type` string on `.` and `_` removing the `m.room.` then
 | ||||
| /// camel casing to give the `EventContent` struct name.
 | ||||
| pub(crate) fn to_camel_case(name: &LitStr) -> Ident { | ||||
|  | ||||
| @ -2,9 +2,7 @@ | ||||
| 
 | ||||
| use proc_macro2::{Span, TokenStream}; | ||||
| use quote::quote; | ||||
| use syn::{ | ||||
|     Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, GenericParam, Ident, TypeParam, | ||||
| }; | ||||
| use syn::{Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed, Ident}; | ||||
| 
 | ||||
| /// Derive `Event` macro code generation.
 | ||||
| pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> { | ||||
| @ -33,36 +31,6 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> { | ||||
|     }; | ||||
| 
 | ||||
|     let content_trait = Ident::new(&format!("{}Content", ident), input.ident.span()); | ||||
|     let try_from_raw_fields = fields | ||||
|         .iter() | ||||
|         .map(|field| { | ||||
|             let name = field.ident.as_ref().unwrap(); | ||||
|             if name == "content" { | ||||
|                 quote! { content: C::try_from_raw(raw.content)? } | ||||
|             } else if name == "prev_content" { | ||||
|                 quote! { prev_content: raw.prev_content.map(C::try_from_raw).transpose()? } | ||||
|             } else { | ||||
|                 quote! { #name: raw.#name } | ||||
|             } | ||||
|         }) | ||||
|         .collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let try_from_raw_impl = quote! { | ||||
|         impl<C> ::ruma_events::TryFromRaw for #ident<C> | ||||
|         where | ||||
|             C: ::ruma_events::#content_trait + ::ruma_events::TryFromRaw, | ||||
|             C::Raw: ::ruma_events::RawEventContent, | ||||
|         { | ||||
|             type Raw = raw_event::#ident<C::Raw>; | ||||
|             type Err = C::Err; | ||||
| 
 | ||||
|             fn try_from_raw(raw: Self::Raw) -> Result<Self, Self::Err> { | ||||
|                 Ok(Self { | ||||
|                     #( #try_from_raw_fields ),* | ||||
|                 }) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let serialize_fields = fields | ||||
|         .iter() | ||||
| @ -99,9 +67,9 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> { | ||||
|         .collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let serialize_impl = quote! { | ||||
|         impl<C: #content_trait> ::serde::ser::Serialize for #ident<C> | ||||
|         impl<C> ::serde::ser::Serialize for #ident<C> | ||||
|         where | ||||
|             C::Raw: ::ruma_events::RawEventContent, | ||||
|             C: ::ruma_events::#content_trait, | ||||
|         { | ||||
|             fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||||
|             where | ||||
| @ -120,32 +88,19 @@ pub fn expand_event(input: DeriveInput) -> syn::Result<TokenStream> { | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let raw_mod = expand_raw_state_event(&input, fields)?; | ||||
|     let deserialize_impl = expand_deserialize_event(&input, fields)?; | ||||
| 
 | ||||
|     Ok(quote! { | ||||
|         #try_from_raw_impl | ||||
| 
 | ||||
|         #serialize_impl | ||||
| 
 | ||||
|         #raw_mod | ||||
|         #deserialize_impl | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| fn expand_raw_state_event(input: &DeriveInput, fields: Vec<Field>) -> syn::Result<TokenStream> { | ||||
| fn expand_deserialize_event(input: &DeriveInput, fields: Vec<Field>) -> syn::Result<TokenStream> { | ||||
|     let ident = &input.ident; | ||||
|     let content_ident = Ident::new(&format!("{}Content", ident), input.ident.span()); | ||||
| 
 | ||||
|     // the raw version has no bounds on its type param
 | ||||
|     let generics = { | ||||
|         let mut gen = input.generics.clone(); | ||||
|         for p in &mut gen.params { | ||||
|             if let GenericParam::Type(TypeParam { bounds, .. }) = p { | ||||
|                 bounds.clear(); | ||||
|             } | ||||
|         } | ||||
|         gen | ||||
|     }; | ||||
| 
 | ||||
|     let enum_variants = fields | ||||
|         .iter() | ||||
|         .map(|field| { | ||||
| @ -175,13 +130,13 @@ fn expand_raw_state_event(input: &DeriveInput, fields: Vec<Field>) -> syn::Resul | ||||
|             let name = field.ident.as_ref().unwrap(); | ||||
|             if name == "content" { | ||||
|                 quote! { | ||||
|                     let raw = content.ok_or_else(|| ::serde::de::Error::missing_field("content"))?; | ||||
|                     let content = C::from_parts(&event_type, raw).map_err(A::Error::custom)?; | ||||
|                     let json = content.ok_or_else(|| ::serde::de::Error::missing_field("content"))?; | ||||
|                     let content = C::from_parts(&event_type, json).map_err(A::Error::custom)?; | ||||
|                 } | ||||
|             } else if name == "prev_content" { | ||||
|                 quote! { | ||||
|                     let prev_content = if let Some(raw) = prev_content { | ||||
|                         Some(C::from_parts(&event_type, raw).map_err(A::Error::custom)?) | ||||
|                     let prev_content = if let Some(json) = prev_content { | ||||
|                         Some(C::from_parts(&event_type, json).map_err(A::Error::custom)?) | ||||
|                     } else { | ||||
|                         None | ||||
|                     }; | ||||
| @ -209,10 +164,10 @@ fn expand_raw_state_event(input: &DeriveInput, fields: Vec<Field>) -> syn::Resul | ||||
| 
 | ||||
|     let field_names = fields.iter().flat_map(|f| &f.ident).collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let deserialize_impl = quote! { | ||||
|     Ok(quote! { | ||||
|         impl<'de, C> ::serde::de::Deserialize<'de> for #ident<C> | ||||
|         where | ||||
|             C: ::ruma_events::RawEventContent, | ||||
|             C: ::ruma_events::#content_ident, | ||||
|         { | ||||
|             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||||
|             where | ||||
| @ -232,7 +187,7 @@ fn expand_raw_state_event(input: &DeriveInput, fields: Vec<Field>) -> syn::Resul | ||||
| 
 | ||||
|                 impl<'de, C> ::serde::de::Visitor<'de> for EventVisitor<C> | ||||
|                 where | ||||
|                     C: ::ruma_events::RawEventContent, | ||||
|                     C: ::ruma_events::#content_ident, | ||||
|                 { | ||||
|                     type Value = #ident<C>; | ||||
| 
 | ||||
| @ -280,21 +235,6 @@ fn expand_raw_state_event(input: &DeriveInput, fields: Vec<Field>) -> syn::Resul | ||||
|                 deserializer.deserialize_map(EventVisitor(::std::marker::PhantomData)) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let raw_docs = format!("The raw version of {}, allows for deserialization.", ident); | ||||
|     Ok(quote! { | ||||
|         #[doc = #raw_docs] | ||||
|         mod raw_event { | ||||
|             use super::*; | ||||
| 
 | ||||
|             #[derive(Clone, Debug)] | ||||
|             pub struct #ident #generics { | ||||
|                 #( #fields ),* | ||||
|             } | ||||
| 
 | ||||
|             #deserialize_impl | ||||
|         } | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -52,9 +52,7 @@ fn expand_room_event_content(input: DeriveInput) -> syn::Result<TokenStream> { | ||||
|             fn event_type(&self) -> &str { | ||||
|                 #event_type | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl ::ruma_events::RawEventContent for raw::#ident { | ||||
|             fn from_parts( | ||||
|                 ev_type: &str, | ||||
|                 content: Box<::serde_json::value::RawValue> | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| //! Types for the *m.call.answer* event.
 | ||||
| 
 | ||||
| use js_int::UInt; | ||||
| use ruma_events_macros::{FromRaw, MessageEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::MessageEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use super::SessionDescription; | ||||
| 
 | ||||
| /// This event is sent by the callee when they wish to answer the call.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.call.answer")] | ||||
| pub struct AnswerEventContent { | ||||
|     /// The VoIP session description object. The session description type must be *answer*.
 | ||||
|  | ||||
| @ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// This event is sent by callers after sending an invite and by the callee after answering. Its
 | ||||
| /// purpose is to give the other party additional ICE candidates to try using to communicate.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.call.candidates")] | ||||
| pub struct CandidatesEventContent { | ||||
|     /// The ID of the call this event relates to.
 | ||||
|  | ||||
| @ -7,7 +7,7 @@ use strum::{Display, EnumString}; | ||||
| 
 | ||||
| /// Sent by either party to signal their termination of the call. This can be sent either once the
 | ||||
| /// call has has been established or before to abort the call.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.call.hangup")] | ||||
| pub struct HangupEventContent { | ||||
|     /// The ID of the call this event relates to.
 | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| //! Types for the *m.call.invite* event.
 | ||||
| 
 | ||||
| use js_int::UInt; | ||||
| use ruma_events_macros::{FromRaw, MessageEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::MessageEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use super::SessionDescription; | ||||
| 
 | ||||
| /// This event is sent by the caller when they wish to establish a call.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.call.invite")] | ||||
| pub struct InviteEventContent { | ||||
|     /// A unique identifer for the call.
 | ||||
|  | ||||
							
								
								
									
										58
									
								
								src/json.rs
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/json.rs
									
									
									
									
									
								
							| @ -12,7 +12,7 @@ use serde_json::value::RawValue; | ||||
| 
 | ||||
| use crate::{ | ||||
|     error::{InvalidEvent, InvalidEventKind}, | ||||
|     EventContent, RawEventContent, TryFromRaw, | ||||
|     EventContent, | ||||
| }; | ||||
| 
 | ||||
| /// A wrapper around `Box<RawValue>`, to be used in place of event [content] [collection] types in
 | ||||
| @ -31,6 +31,11 @@ impl<T> EventJson<T> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Create an `EventJson` from a boxed `RawValue`.
 | ||||
|     pub fn from_json(raw: Box<RawValue>) -> Self { | ||||
|         Self::new(raw) | ||||
|     } | ||||
| 
 | ||||
|     /// Access the underlying json value.
 | ||||
|     pub fn json(&self) -> &RawValue { | ||||
|         &self.json | ||||
| @ -42,23 +47,13 @@ impl<T> EventJson<T> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T: TryFromRaw> EventJson<T> | ||||
| impl<T> EventJson<T> | ||||
| where | ||||
|     T::Raw: DeserializeOwned, | ||||
|     T: DeserializeOwned, | ||||
| { | ||||
|     /// Try to deserialize the JSON into the expected event type.
 | ||||
|     pub fn deserialize(&self) -> Result<T, InvalidEvent> { | ||||
|         let raw_ev: T::Raw = match serde_json::from_str(self.json.get()) { | ||||
|             Ok(raw) => raw, | ||||
|             Err(error) => { | ||||
|                 return Err(InvalidEvent { | ||||
|                     message: error.to_string(), | ||||
|                     kind: InvalidEventKind::Deserialization, | ||||
|                 }); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         match T::try_from_raw(raw_ev) { | ||||
|         match serde_json::from_str(self.json.get()) { | ||||
|             Ok(value) => Ok(value), | ||||
|             Err(err) => Err(InvalidEvent { | ||||
|                 message: err.to_string(), | ||||
| @ -70,27 +65,14 @@ where | ||||
| 
 | ||||
| impl<T: EventContent> EventJson<T> | ||||
| where | ||||
|     T::Raw: RawEventContent, | ||||
|     T: EventContent, | ||||
| { | ||||
|     /// Try to deserialize the JSON as event content
 | ||||
|     pub fn deserialize_content(self, event_type: &str) -> Result<T, InvalidEvent> { | ||||
|         let raw_content = match T::Raw::from_parts(event_type, self.json) { | ||||
|             Ok(raw) => raw, | ||||
|             Err(message) => { | ||||
|                 return Err(InvalidEvent { | ||||
|                     message, | ||||
|                     kind: InvalidEventKind::Deserialization, | ||||
|                 }); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         match T::try_from_raw(raw_content) { | ||||
|             Ok(value) => Ok(value), | ||||
|             Err(err) => Err(InvalidEvent { | ||||
|                 message: err.to_string(), | ||||
|                 kind: InvalidEventKind::Validation, | ||||
|             }), | ||||
|         } | ||||
|         T::from_parts(event_type, self.json).map_err(|err| InvalidEvent { | ||||
|             message: err, | ||||
|             kind: InvalidEventKind::Deserialization, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -100,20 +82,14 @@ impl<T: Serialize> From<&T> for EventJson<T> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Without the `TryFromRaw` bound, this would conflict with the next impl below
 | ||||
| // We could remove the `TryFromRaw` bound once specialization is stabilized.
 | ||||
| impl<T: Serialize + TryFromRaw> From<T> for EventJson<T> { | ||||
| // With specialization a fast path from impl for `impl<T> From<Box<RawValue...`
 | ||||
| // could be used. Until then there is a special constructor `from_json` for this.
 | ||||
| impl<T: Serialize> From<T> for EventJson<T> { | ||||
|     fn from(val: T) -> Self { | ||||
|         Self::from(&val) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> From<Box<RawValue>> for EventJson<T> { | ||||
|     fn from(json: Box<RawValue>) -> Self { | ||||
|         Self::new(json) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> Clone for EventJson<T> { | ||||
|     fn clone(&self) -> Self { | ||||
|         Self::new(self.json.clone()) | ||||
|  | ||||
| @ -11,7 +11,7 @@ use crate::{InvalidInput, TryFromRaw}; | ||||
| /// Begins an SAS key verification process.
 | ||||
| ///
 | ||||
| /// Typically sent as a to-device event.
 | ||||
| #[derive(Clone, Debug, Serialize)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||||
| #[serde(tag = "type", rename = "m.key.verification.start")] | ||||
| pub struct StartEvent { | ||||
|     /// The event's content.
 | ||||
| @ -19,7 +19,7 @@ pub struct StartEvent { | ||||
| } | ||||
| 
 | ||||
| /// The payload of an *m.key.verification.start* event.
 | ||||
| #[derive(Clone, Debug, Serialize)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||||
| #[serde(tag = "method")] | ||||
| pub enum StartEventContent { | ||||
|     /// The *m.sas.v1* verification method.
 | ||||
| @ -407,6 +407,8 @@ mod tests { | ||||
|         assert!(serde_json::from_str::<EventJson<StartEventContent>>("{").is_err()); | ||||
|     } | ||||
| 
 | ||||
|     // TODO this fails because the error is a Validation error not deserialization?
 | ||||
|     /* | ||||
|     #[test] | ||||
|     fn deserialization_structure_mismatch() { | ||||
|         // Missing several required fields.
 | ||||
| @ -419,7 +421,10 @@ mod tests { | ||||
|         assert!(error.message().contains("missing field")); | ||||
|         assert!(error.is_deserialization()); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     // TODO re implement validation done in TryFromRaw else where
 | ||||
|     /* | ||||
|     #[test] | ||||
|     fn deserialization_validation_missing_required_key_agreement_protocols() { | ||||
|         let json_data = json!({ | ||||
| @ -440,7 +445,10 @@ mod tests { | ||||
|         assert!(error.message().contains("key_agreement_protocols")); | ||||
|         assert!(error.is_validation()); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     // TODO re implement validation done in TryFromRaw else where
 | ||||
|     /* | ||||
|     #[test] | ||||
|     fn deserialization_validation_missing_required_hashes() { | ||||
|         let json_data = json!({ | ||||
| @ -460,7 +468,10 @@ mod tests { | ||||
|         assert!(error.message().contains("hashes")); | ||||
|         assert!(error.is_validation()); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     // TODO re implement validation done in TryFromRaw else where
 | ||||
|     /* | ||||
|     #[test] | ||||
|     fn deserialization_validation_missing_required_message_authentication_codes() { | ||||
|         let json_data = json!({ | ||||
| @ -480,7 +491,9 @@ mod tests { | ||||
|         assert!(error.message().contains("message_authentication_codes")); | ||||
|         assert!(error.is_validation()); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     /* | ||||
|     #[test] | ||||
|     fn deserialization_validation_missing_required_short_authentication_string() { | ||||
|         let json_data = json!({ | ||||
| @ -500,7 +513,10 @@ mod tests { | ||||
|         assert!(error.message().contains("short_authentication_string")); | ||||
|         assert!(error.is_validation()); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     // TODO re implement validation done in TryFromRaw else where
 | ||||
|     /* | ||||
|     #[test] | ||||
|     fn deserialization_of_event_validates_content() { | ||||
|         // This JSON is missing the required value of "curve25519" for "key_agreement_protocols".
 | ||||
| @ -524,4 +540,5 @@ mod tests { | ||||
|         assert!(error.message().contains("key_agreement_protocols")); | ||||
|         assert!(error.is_validation()); | ||||
|     } | ||||
|     **/ | ||||
| } | ||||
|  | ||||
							
								
								
									
										26
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -209,37 +209,19 @@ impl UnsignedData { | ||||
| /// The base trait that all event content types implement.
 | ||||
| ///
 | ||||
| /// Implementing this trait allows content types to be serialized as well as deserialized.
 | ||||
| pub trait EventContent: TryFromRaw + Serialize | ||||
| where | ||||
|     Self::Raw: RawEventContent, | ||||
| { | ||||
| pub trait EventContent: Sized + Serialize { | ||||
|     /// A matrix event identifier, like `m.room.message`.
 | ||||
|     fn event_type(&self) -> &str; | ||||
| } | ||||
| 
 | ||||
| #[doc(hidden)] | ||||
| pub trait RawEventContent: Sized { | ||||
|     /// Constructs the given event content.
 | ||||
|     fn from_parts(event_type: &str, content: Box<RawJsonValue>) -> Result<Self, String>; | ||||
| } | ||||
| 
 | ||||
| /// Marker trait for the content of a room event.
 | ||||
| pub trait RoomEventContent: EventContent | ||||
| where | ||||
|     Self::Raw: RawEventContent, | ||||
| { | ||||
| } | ||||
| pub trait RoomEventContent: EventContent {} | ||||
| 
 | ||||
| /// Marker trait for the content of a message event.
 | ||||
| pub trait MessageEventContent: RoomEventContent | ||||
| where | ||||
|     Self::Raw: RawEventContent, | ||||
| { | ||||
| } | ||||
| pub trait MessageEventContent: RoomEventContent {} | ||||
| 
 | ||||
| /// Marker trait for the content of a state event.
 | ||||
| pub trait StateEventContent: RoomEventContent | ||||
| where | ||||
|     Self::Raw: RawEventContent, | ||||
| { | ||||
| } | ||||
| pub trait StateEventContent: RoomEventContent {} | ||||
|  | ||||
| @ -13,7 +13,7 @@ use serde::{ | ||||
|     Serialize, Serializer, | ||||
| }; | ||||
| 
 | ||||
| use crate::{MessageEventContent, RawEventContent, RoomEventContent, TryFromRaw, UnsignedData}; | ||||
| use crate::{MessageEventContent, RoomEventContent, UnsignedData}; | ||||
| use ruma_events_macros::{event_content_collection, Event}; | ||||
| 
 | ||||
| event_content_collection! { | ||||
| @ -30,10 +30,7 @@ event_content_collection! { | ||||
| 
 | ||||
| /// Message event.
 | ||||
| #[derive(Clone, Debug, Event)] | ||||
| pub struct MessageEvent<C: MessageEventContent> | ||||
| where | ||||
|     C::Raw: RawEventContent, | ||||
| { | ||||
| pub struct MessageEvent<C: MessageEventContent> { | ||||
|     /// Data specific to the event type.
 | ||||
|     pub content: C, | ||||
| 
 | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| //! Types for the *m.room.aliases* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use ruma_identifiers::RoomAliasId; | ||||
| use serde::Serialize; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// Informs the room about what room aliases it has been given.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.aliases")] | ||||
| pub struct AliasesEventContent { | ||||
|     /// A list of room aliases.
 | ||||
|  | ||||
| @ -1,14 +1,14 @@ | ||||
| //! Types for the *m.room.avatar* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use super::ImageInfo; | ||||
| 
 | ||||
| /// A picture that is associated with the room.
 | ||||
| ///
 | ||||
| /// This can be displayed alongside the room information.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.avatar")] | ||||
| pub struct AvatarEventContent { | ||||
|     /// Information about the avatar image.
 | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| //! Types for the *m.room.canonical_alias* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use ruma_identifiers::RoomAliasId; | ||||
| use serde::Serialize; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// Informs the room as to which alias is the canonical one.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.canonical_alias")] | ||||
| pub struct CanonicalAliasEventContent { | ||||
|     /// The canonical alias.
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// This is the first event in a room and cannot be changed. It acts as the root of all other
 | ||||
| /// events.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.create")] | ||||
| pub struct CreateEventContent { | ||||
|     /// The `user_id` of the room creator. This is set by the homeserver.
 | ||||
|  | ||||
| @ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; | ||||
| use crate::{FromRaw, UnsignedData}; | ||||
| 
 | ||||
| /// The payload for `EncryptedEvent`.
 | ||||
| #[derive(Clone, Debug, Serialize)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||||
| #[non_exhaustive] | ||||
| #[serde(tag = "algorithm")] | ||||
| pub enum EncryptedEventContent { | ||||
| @ -22,44 +22,6 @@ pub enum EncryptedEventContent { | ||||
|     MegolmV1AesSha2(MegolmV1AesSha2Content), | ||||
| } | ||||
| 
 | ||||
| impl FromRaw for EncryptedEventContent { | ||||
|     type Raw = raw::EncryptedEventContent; | ||||
| 
 | ||||
|     fn from_raw(raw: raw::EncryptedEventContent) -> Self { | ||||
|         use raw::EncryptedEventContent::*; | ||||
| 
 | ||||
|         match raw { | ||||
|             OlmV1Curve25519AesSha2(content) => { | ||||
|                 EncryptedEventContent::OlmV1Curve25519AesSha2(content) | ||||
|             } | ||||
|             MegolmV1AesSha2(content) => EncryptedEventContent::MegolmV1AesSha2(content), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub(crate) mod raw { | ||||
|     use std::time::SystemTime; | ||||
| 
 | ||||
|     use ruma_identifiers::{EventId, RoomId, UserId}; | ||||
|     use serde::Deserialize; | ||||
| 
 | ||||
|     use super::{MegolmV1AesSha2Content, OlmV1Curve25519AesSha2Content}; | ||||
|     use crate::UnsignedData; | ||||
| 
 | ||||
|     /// The payload for `EncryptedEvent`.
 | ||||
|     #[derive(Clone, Debug, Deserialize)] | ||||
|     #[serde(tag = "algorithm")] | ||||
|     pub enum EncryptedEventContent { | ||||
|         /// An event encrypted with *m.olm.v1.curve25519-aes-sha2*.
 | ||||
|         #[serde(rename = "m.olm.v1.curve25519-aes-sha2")] | ||||
|         OlmV1Curve25519AesSha2(OlmV1Curve25519AesSha2Content), | ||||
| 
 | ||||
|         /// An event encrypted with *m.megolm.v1.aes-sha2*.
 | ||||
|         #[serde(rename = "m.megolm.v1.aes-sha2")] | ||||
|         MegolmV1AesSha2(MegolmV1AesSha2Content), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// The payload for `EncryptedEvent` using the *m.olm.v1.curve25519-aes-sha2* algorithm.
 | ||||
| #[derive(Clone, Debug, Serialize, Deserialize)] | ||||
| pub struct OlmV1Curve25519AesSha2Content { | ||||
|  | ||||
| @ -2,12 +2,12 @@ | ||||
| 
 | ||||
| use js_int::UInt; | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use crate::Algorithm; | ||||
| 
 | ||||
| /// Defines how messages sent in this room should be encrypted.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.encryption")] | ||||
| pub struct EncryptionEventContent { | ||||
|     /// The encryption algorithm to be used to encrypt messages sent in this room.
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ use strum::{Display, EnumString}; | ||||
| ///
 | ||||
| /// This event controls whether guest users are allowed to join rooms. If this event is absent,
 | ||||
| /// servers should act as if it is present and has the value `GuestAccess::Forbidden`.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.guest_access")] | ||||
| pub struct GuestAccessEventContent { | ||||
|     /// A policy for guest user access to a room.
 | ||||
|  | ||||
| @ -6,7 +6,7 @@ use strum::{Display, EnumString}; | ||||
| 
 | ||||
| /// This event controls whether a member of a room can see the events that happened in a room
 | ||||
| /// from before they joined.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.history_visibility")] | ||||
| pub struct HistoryVisibilityEventContent { | ||||
|     /// Who can see the room history.
 | ||||
|  | ||||
| @ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; | ||||
| use strum::{Display, EnumString}; | ||||
| 
 | ||||
| /// Describes how users are allowed to join the room.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.join_rules")] | ||||
| pub struct JoinRulesEventContent { | ||||
|     /// The type of rules used for users wishing to join this room.
 | ||||
|  | ||||
| @ -34,7 +34,7 @@ use crate::StateEvent; | ||||
| /// The membership for a given user can change over time. Previous membership can be retrieved
 | ||||
| /// from the `prev_content` object on an event. If not present, the user's previous membership
 | ||||
| /// must be assumed as leave.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.member")] | ||||
| pub struct MemberEventContent { | ||||
|     /// The avatar URL for this user, if any. This is added by the homeserver.
 | ||||
|  | ||||
| @ -13,7 +13,7 @@ use crate::{FromRaw, UnsignedData}; | ||||
| pub mod feedback; | ||||
| 
 | ||||
| /// The payload for `MessageEvent`.
 | ||||
| #[derive(Clone, Debug, Serialize, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.room.message")] | ||||
| #[serde(tag = "msgtype")] | ||||
| pub enum MessageEventContent { | ||||
|  | ||||
| @ -9,7 +9,7 @@ use strum::{Display, EnumString}; | ||||
| ///
 | ||||
| /// N.B.: Usage of this event is discouraged in favor of the receipts module. Most clients will
 | ||||
| /// not recognize this event.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.room.message.feedback")] | ||||
| pub struct FeedbackEventContent { | ||||
|     /// The event that this feedback is related to.
 | ||||
|  | ||||
| @ -1,34 +1,23 @@ | ||||
| //! Types for the *m.room.name* event.
 | ||||
| 
 | ||||
| use std::ops::Deref; | ||||
| use std::time::SystemTime; | ||||
| 
 | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use ruma_identifiers::{EventId, RoomId, UserId}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use crate::{InvalidInput, TryFromRaw, UnsignedData}; | ||||
| use crate::{InvalidInput, UnsignedData}; | ||||
| 
 | ||||
| /// The payload for `NameEvent`.
 | ||||
| #[derive(Clone, Debug, Serialize, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.name")] | ||||
| pub struct NameEventContent { | ||||
|     /// The name of the room. This MUST NOT exceed 255 bytes.
 | ||||
|     #[serde(default, deserialize_with = "room_name")] | ||||
|     pub(crate) name: Option<String>, | ||||
| } | ||||
| 
 | ||||
| impl TryFromRaw for NameEventContent { | ||||
|     type Raw = raw::NameEventContent; | ||||
| 
 | ||||
|     type Err = InvalidInput; | ||||
| 
 | ||||
|     fn try_from_raw(raw: raw::NameEventContent) -> Result<Self, Self::Err> { | ||||
|         match raw.name { | ||||
|             None => Ok(NameEventContent { name: None }), | ||||
|             Some(name) => NameEventContent::new(name), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl NameEventContent { | ||||
|     /// Create a new `NameEventContent` with the given name.
 | ||||
|     ///
 | ||||
| @ -47,21 +36,26 @@ impl NameEventContent { | ||||
| 
 | ||||
|     /// The name of the room, if any.
 | ||||
|     pub fn name(&self) -> Option<&str> { | ||||
|         self.name.as_ref().map(String::as_ref) | ||||
|         self.name.as_deref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub(crate) mod raw { | ||||
|     use super::*; | ||||
| fn room_name<'de, D>(deserializer: D) -> Result<Option<String>, D::Error> | ||||
| where | ||||
|     D: serde::de::Deserializer<'de>, | ||||
| { | ||||
|     use serde::de::Error; | ||||
| 
 | ||||
|     /// The payload of a `NameEvent`.
 | ||||
|     #[derive(Clone, Debug, Deserialize)] | ||||
|     pub struct NameEventContent { | ||||
|         /// The name of the room. This MUST NOT exceed 255 bytes.
 | ||||
|         // The spec says "A room with an m.room.name event with an absent, null, or empty name field
 | ||||
|         // should be treated the same as a room with no m.room.name event."
 | ||||
|         #[serde(default, deserialize_with = "ruma_serde::empty_string_as_none")] | ||||
|         pub(crate) name: Option<String>, | ||||
|     // this handles the null case and the empty string or nothing case
 | ||||
|     match Option::<String>::deserialize(deserializer)? { | ||||
|         Some(name) => match name.len() { | ||||
|             0 => Ok(None), | ||||
|             1..=255 => Ok(Some(name)), | ||||
|             _ => Err(D::Error::custom( | ||||
|                 "a room name cannot be more than 255 bytes", | ||||
|             )), | ||||
|         }, | ||||
|         None => Ok(None), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| //! Types for the *m.room.pinned_events* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use ruma_identifiers::EventId; | ||||
| use serde::Serialize; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// Used to "pin" particular events in a room for other participants to review later.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.pinned_events")] | ||||
| pub struct PinnedEventsEventContent { | ||||
|     /// An ordered list of event IDs to pin.
 | ||||
|  | ||||
| @ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; | ||||
| use crate::EventType; | ||||
| 
 | ||||
| /// Defines the power levels (privileges) of users in the room.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.power_levels")] | ||||
| pub struct PowerLevelsEventContent { | ||||
|     /// The level required to ban a user.
 | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| //! Types for the *m.room.server_acl* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// An event to indicate which servers are permitted to participate in the room.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.server_acl")] | ||||
| pub struct ServerAclEventContent { | ||||
|     /// True to allow server names that are IP address literals. False to deny.
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; | ||||
| /// Acts as an *m.room.member* invite event, where there isn't a target user_id to invite. This
 | ||||
| /// event contains a token and a public key whose private key must be used to sign the token.
 | ||||
| /// Any user who can present that signature may use this invitation to join the target room.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.third_party_invite")] | ||||
| pub struct ThirdPartyInviteEventContent { | ||||
|     /// A user-readable string which represents the user who has been invited.
 | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| //! Types for the *m.room.tombstone* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use ruma_identifiers::RoomId; | ||||
| use serde::Serialize; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// A state event signifying that a room has been upgraded to a different room version, and that
 | ||||
| /// clients should go there.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.tombstone")] | ||||
| pub struct TombstoneEventContent { | ||||
|     /// A server-defined message.
 | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| //! Types for the *m.room.topic* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| /// A topic is a short message detailing what is currently being discussed in the room.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.room.topic")] | ||||
| pub struct TopicEventContent { | ||||
|     /// The topic text.
 | ||||
|  | ||||
| @ -13,7 +13,7 @@ use serde::{ | ||||
|     Serialize, Serializer, | ||||
| }; | ||||
| 
 | ||||
| use crate::{RawEventContent, RoomEventContent, StateEventContent, TryFromRaw, UnsignedData}; | ||||
| use crate::{RoomEventContent, StateEventContent, TryFromRaw, UnsignedData}; | ||||
| use ruma_events_macros::{event_content_collection, Event}; | ||||
| 
 | ||||
| event_content_collection! { | ||||
| @ -24,10 +24,7 @@ event_content_collection! { | ||||
| 
 | ||||
| /// State event.
 | ||||
| #[derive(Clone, Debug, Event)] | ||||
| pub struct StateEvent<C: StateEventContent> | ||||
| where | ||||
|     C::Raw: RawEventContent, | ||||
| { | ||||
| pub struct StateEvent<C: StateEventContent> { | ||||
|     /// Data specific to the event type.
 | ||||
|     pub content: C, | ||||
| 
 | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| //! Types for the *m.sticker* event.
 | ||||
| 
 | ||||
| use ruma_events_macros::{FromRaw, MessageEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::MessageEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| use crate::room::ImageInfo; | ||||
| 
 | ||||
| /// A sticker message.
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)] | ||||
| #[ruma_event(type = "m.sticker")] | ||||
| pub struct StickerEventContent { | ||||
|     /// A textual representation or associated description of the sticker image. This could
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(type = "m.macro.test")] | ||||
| pub struct MacroTest { | ||||
|     pub url: String, | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| pub struct MacroTest { | ||||
|     pub url: String, | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| error: no event type attribute found, add `#[ruma_event(type = "any.room.event")]` below the event content derive | ||||
|  --> $DIR/02-no-event-type.rs:4:44 | ||||
|  --> $DIR/02-no-event-type.rs:4:48 | ||||
|   | | ||||
| 4 | #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
|   |                                            ^^^^^^^^^^^^^^^^^ | ||||
| 4 | #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
|   |                                                ^^^^^^^^^^^^^^^^^ | ||||
|   | | ||||
|   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| use ruma_events_macros::{FromRaw, StateEventContent}; | ||||
| use serde::Serialize; | ||||
| use ruma_events_macros::StateEventContent; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| 
 | ||||
| #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[not_ruma_event(type = "m.macro.test")] | ||||
| pub struct MacroTest { | ||||
|     pub test: String, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, Serialize, StateEventContent)] | ||||
| #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
| #[ruma_event(event = "m.macro.test")] | ||||
| pub struct MoreMacroTest { | ||||
|     pub test: String, | ||||
|  | ||||
| @ -5,10 +5,10 @@ error: expected `type` | ||||
|    |              ^^^^^ | ||||
| 
 | ||||
| error: no event type attribute found, add `#[ruma_event(type = "any.room.event")]` below the event content derive | ||||
|  --> $DIR/03-invalid-event-type.rs:4:44 | ||||
|  --> $DIR/03-invalid-event-type.rs:4:48 | ||||
|   | | ||||
| 4 | #[derive(Clone, Debug, Serialize, FromRaw, StateEventContent)] | ||||
|   |                                            ^^^^^^^^^^^^^^^^^ | ||||
| 4 | #[derive(Clone, Debug, Deserialize, Serialize, StateEventContent)] | ||||
|   |                                                ^^^^^^^^^^^^^^^^^ | ||||
|   | | ||||
|   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) | ||||
| 
 | ||||
|  | ||||
| @ -2,15 +2,12 @@ | ||||
| // https://github.com/rust-lang/rust/issues/55779
 | ||||
| extern crate serde; | ||||
| 
 | ||||
| use ruma_events::{RawEventContent, StateEventContent}; | ||||
| use ruma_events::StateEventContent; | ||||
| use ruma_events_macros::Event; | ||||
| 
 | ||||
| /// State event.
 | ||||
| #[derive(Clone, Debug, Event)] | ||||
| pub struct StateEvent<C: StateEventContent> | ||||
| where | ||||
|     C::Raw: RawEventContent, | ||||
| { | ||||
| pub struct StateEvent<C: StateEventContent> { | ||||
|     pub content: C, | ||||
|     pub state_key: String, | ||||
|     pub prev_content: Option<C>, | ||||
|  | ||||
| @ -1,10 +1,8 @@ | ||||
| use ruma_events::{RawEventContent, StateEventContent}; | ||||
| use ruma_events::StateEventContent; | ||||
| use ruma_events_macros::Event; | ||||
| 
 | ||||
| /// State event.
 | ||||
| #[derive(Clone, Debug, Event)] | ||||
| pub struct StateEvent<C: StateEventContent>(C) | ||||
| where | ||||
|     C::Raw: RawEventContent; | ||||
| pub struct StateEvent<C: StateEventContent>(C); | ||||
| 
 | ||||
| fn main() {} | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| error: the `Event` derive only supports named fields | ||||
|  --> $DIR/05-named-fields.rs:6:44 | ||||
|   | | ||||
| 6 | pub struct StateEvent<C: StateEventContent>(C) | ||||
| 6 | pub struct StateEvent<C: StateEventContent>(C); | ||||
|   |                                            ^^^ | ||||
|  | ||||
| @ -1,12 +1,9 @@ | ||||
| use ruma_events::{RawEventContent, StateEventContent}; | ||||
| use ruma_events::StateEventContent; | ||||
| use ruma_events_macros::Event; | ||||
| 
 | ||||
| /// State event.
 | ||||
| #[derive(Clone, Debug, Event)] | ||||
| pub struct StateEvent<C: StateEventContent> 
 | ||||
| where | ||||
|     C::Raw: RawEventContent | ||||
| { | ||||
| pub struct StateEvent<C: StateEventContent> { | ||||
|     pub not_content: C, | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user