Implement MessageEvent and AnyMessageEventContent
This commit is contained in:
		
							parent
							
								
									24f720d1f1
								
							
						
					
					
						commit
						33ac5267a9
					
				| @ -6,6 +6,20 @@ use syn::{Ident, LitStr}; | |||||||
| 
 | 
 | ||||||
| use parse::RumaCollectionInput; | use parse::RumaCollectionInput; | ||||||
| 
 | 
 | ||||||
|  | fn marker_traits(ident: &Ident) -> TokenStream { | ||||||
|  |     match ident.to_string().as_str() { | ||||||
|  |         "AnyStateEventContent" => quote! { | ||||||
|  |             impl ::ruma_events::RoomEventContent for #ident {} | ||||||
|  |             impl ::ruma_events::StateEventContent for #ident {} | ||||||
|  |         }, | ||||||
|  |         "AnyMessageEventContent" => quote! { | ||||||
|  |             impl ::ruma_events::RoomEventContent for #ident {} | ||||||
|  |             impl ::ruma_events::MessageEventContent for #ident {} | ||||||
|  |         }, | ||||||
|  |         _ => TokenStream::new(), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Create a collection from `RumaCollectionInput.
 | /// Create a collection from `RumaCollectionInput.
 | ||||||
| pub fn expand_collection(input: RumaCollectionInput) -> syn::Result<TokenStream> { | pub fn expand_collection(input: RumaCollectionInput) -> syn::Result<TokenStream> { | ||||||
|     let attrs = &input.attrs; |     let attrs = &input.attrs; | ||||||
| @ -36,7 +50,7 @@ pub fn expand_collection(input: RumaCollectionInput) -> syn::Result<TokenStream> | |||||||
|         impl ::ruma_events::EventContent for #ident { |         impl ::ruma_events::EventContent for #ident { | ||||||
|             fn event_type(&self) -> &str { |             fn event_type(&self) -> &str { | ||||||
|                 match self { |                 match self { | ||||||
|                     #( Self::#variants(content) => content.event_type()),* |                     #( Self::#variants(content) => content.event_type() ),* | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -63,6 +77,8 @@ pub fn expand_collection(input: RumaCollectionInput) -> syn::Result<TokenStream> | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     let marker_trait_impls = marker_traits(ident); | ||||||
|  | 
 | ||||||
|     let raw_mod = expand_raw_content_event(&input, &variants)?; |     let raw_mod = expand_raw_content_event(&input, &variants)?; | ||||||
| 
 | 
 | ||||||
|     Ok(quote! { |     Ok(quote! { | ||||||
| @ -72,9 +88,7 @@ pub fn expand_collection(input: RumaCollectionInput) -> syn::Result<TokenStream> | |||||||
| 
 | 
 | ||||||
|         #event_content_impl |         #event_content_impl | ||||||
| 
 | 
 | ||||||
|         impl RoomEventContent for AnyStateEventContent {} |         #marker_trait_impls | ||||||
| 
 |  | ||||||
|         impl StateEventContent for AnyStateEventContent {} |  | ||||||
| 
 | 
 | ||||||
|         #raw_mod |         #raw_mod | ||||||
|     }) |     }) | ||||||
| @ -139,17 +153,18 @@ fn to_event_content_path( | |||||||
| 
 | 
 | ||||||
|     assert_eq!(&name[..2], "m."); |     assert_eq!(&name[..2], "m."); | ||||||
| 
 | 
 | ||||||
|     let event_str = name[2..].split('.').last().unwrap(); |     let path = name[2..].split('.').collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|  |     let event_str = path.last().unwrap(); | ||||||
|     let event = event_str |     let event = event_str | ||||||
|         .split('_') |         .split('_') | ||||||
|         .map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..]) |         .map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..]) | ||||||
|         .collect::<String>(); |         .collect::<String>(); | ||||||
| 
 | 
 | ||||||
|     let module = Ident::new(event_str, span); |  | ||||||
|     let content_str = Ident::new(&format!("{}EventContent", event), span); |     let content_str = Ident::new(&format!("{}EventContent", event), span); | ||||||
|  |     let path = path.iter().map(|s| Ident::new(s, span)); | ||||||
|     syn::parse_quote! { |     syn::parse_quote! { | ||||||
|         ::ruma_events::room::#module::#content_str |         ::ruma_events::#( #path )::*::#content_str | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -161,17 +176,18 @@ fn to_raw_event_content_path( | |||||||
| 
 | 
 | ||||||
|     assert_eq!(&name[..2], "m."); |     assert_eq!(&name[..2], "m."); | ||||||
| 
 | 
 | ||||||
|     let event_str = name[2..].split('.').last().unwrap(); |     let path = name[2..].split('.').collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|  |     let event_str = path.last().unwrap(); | ||||||
|     let event = event_str |     let event = event_str | ||||||
|         .split('_') |         .split('_') | ||||||
|         .map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..]) |         .map(|s| s.chars().next().unwrap().to_uppercase().to_string() + &s[1..]) | ||||||
|         .collect::<String>(); |         .collect::<String>(); | ||||||
| 
 | 
 | ||||||
|     let module = Ident::new(event_str, span); |  | ||||||
|     let content_str = Ident::new(&format!("{}EventContent", event), span); |     let content_str = Ident::new(&format!("{}EventContent", event), span); | ||||||
|  |     let path = path.iter().map(|s| Ident::new(s, span)); | ||||||
|     syn::parse_quote! { |     syn::parse_quote! { | ||||||
|         ::ruma_events::room::#module::raw::#content_str |         ::ruma_events::#( #path )::*::raw::#content_str | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ use super::SessionDescription; | |||||||
| /// This event is sent by the callee when they wish to answer the call.
 | /// This event is sent by the callee when they wish to answer the call.
 | ||||||
| #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | #[derive(Clone, Debug, Serialize, FromRaw, MessageEventContent)] | ||||||
| #[ruma_event(type = "m.call.answer")] | #[ruma_event(type = "m.call.answer")] | ||||||
| pub struct AnswerEventContenet { | pub struct AnswerEventContent { | ||||||
|     /// The VoIP session description object. The session description type must be *answer*.
 |     /// The VoIP session description object. The session description type must be *answer*.
 | ||||||
|     pub answer: SessionDescription, |     pub answer: SessionDescription, | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -134,6 +134,7 @@ mod error; | |||||||
| mod event_type; | mod event_type; | ||||||
| mod from_raw; | mod from_raw; | ||||||
| mod json; | mod json; | ||||||
|  | mod message; | ||||||
| mod state; | mod state; | ||||||
| #[doc(hidden)] // only public for external tests
 | #[doc(hidden)] // only public for external tests
 | ||||||
| pub mod util; | pub mod util; | ||||||
|  | |||||||
							
								
								
									
										491
									
								
								src/message.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								src/message.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,491 @@ | |||||||
|  | //! An enum that represents any message event. A message event is represented by
 | ||||||
|  | //! a parameterized struct allowing more flexibility in whats being sent.
 | ||||||
|  | 
 | ||||||
|  | use std::{ | ||||||
|  |     convert::TryFrom, | ||||||
|  |     time::{SystemTime, UNIX_EPOCH}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use js_int::UInt; | ||||||
|  | use ruma_identifiers::{EventId, RoomId, UserId}; | ||||||
|  | use serde::{ | ||||||
|  |     ser::{Error, SerializeStruct}, | ||||||
|  |     Serialize, Serializer, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use crate::{MessageEventContent, RawEventContent, RoomEventContent, TryFromRaw, UnsignedData}; | ||||||
|  | use ruma_events_macros::event_content_collection; | ||||||
|  | 
 | ||||||
|  | event_content_collection! { | ||||||
|  |     /// A message event.
 | ||||||
|  |     name: AnyMessageEventContent, | ||||||
|  |     events: [ | ||||||
|  |         "m.call.answer", | ||||||
|  |         "m.call.invite", | ||||||
|  |         "m.call.hangup", | ||||||
|  |         "m.call.candidates", | ||||||
|  |         "m.sticker", | ||||||
|  |     ] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Message event.
 | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub struct MessageEvent<C: MessageEventContent> | ||||||
|  | where | ||||||
|  |     C::Raw: RawEventContent, | ||||||
|  | { | ||||||
|  |     /// Data specific to the event type.
 | ||||||
|  |     pub content: C, | ||||||
|  | 
 | ||||||
|  |     /// The globally unique event identifier for the user who sent the event.
 | ||||||
|  |     pub event_id: EventId, | ||||||
|  | 
 | ||||||
|  |     /// Contains the fully-qualified ID of the user who sent this event.
 | ||||||
|  |     pub sender: UserId, | ||||||
|  | 
 | ||||||
|  |     /// Timestamp in milliseconds on originating homeserver when this event was sent.
 | ||||||
|  |     pub origin_server_ts: SystemTime, | ||||||
|  | 
 | ||||||
|  |     /// The ID of the room associated with this event.
 | ||||||
|  |     pub room_id: RoomId, | ||||||
|  | 
 | ||||||
|  |     /// Additional key-value pairs not signed by the homeserver.
 | ||||||
|  |     pub unsigned: UnsignedData, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<C> TryFromRaw for MessageEvent<C> | ||||||
|  | where | ||||||
|  |     C: MessageEventContent + TryFromRaw, | ||||||
|  |     C::Raw: RawEventContent, | ||||||
|  | { | ||||||
|  |     type Raw = raw_message_event::MessageEvent<C::Raw>; | ||||||
|  |     type Err = C::Err; | ||||||
|  | 
 | ||||||
|  |     fn try_from_raw(raw: Self::Raw) -> Result<Self, Self::Err> { | ||||||
|  |         Ok(Self { | ||||||
|  |             content: C::try_from_raw(raw.content)?, | ||||||
|  |             event_id: raw.event_id, | ||||||
|  |             sender: raw.sender, | ||||||
|  |             origin_server_ts: raw.origin_server_ts, | ||||||
|  |             room_id: raw.room_id, | ||||||
|  |             unsigned: raw.unsigned, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<C: MessageEventContent> Serialize for MessageEvent<C> | ||||||
|  | where | ||||||
|  |     C::Raw: RawEventContent, | ||||||
|  | { | ||||||
|  |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||||||
|  |     where | ||||||
|  |         S: Serializer, | ||||||
|  |     { | ||||||
|  |         let event_type = self.content.event_type(); | ||||||
|  | 
 | ||||||
|  |         let time_since_epoch = self.origin_server_ts.duration_since(UNIX_EPOCH).unwrap(); | ||||||
|  |         let timestamp = match UInt::try_from(time_since_epoch.as_millis()) { | ||||||
|  |             Ok(uint) => uint, | ||||||
|  |             Err(err) => return Err(S::Error::custom(err)), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let mut message = serializer.serialize_struct("MessageEvent", 7)?; | ||||||
|  |         message.serialize_field("content", &self.content)?; | ||||||
|  |         message.serialize_field("event_id", &self.event_id)?; | ||||||
|  |         message.serialize_field("sender", &self.sender)?; | ||||||
|  |         message.serialize_field("origin_server_ts", ×tamp)?; | ||||||
|  |         message.serialize_field("room_id", &self.room_id)?; | ||||||
|  |         message.serialize_field("type", event_type)?; | ||||||
|  |         message.end() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | mod raw_message_event { | ||||||
|  |     use std::{ | ||||||
|  |         fmt, | ||||||
|  |         marker::PhantomData, | ||||||
|  |         time::{Duration, SystemTime, UNIX_EPOCH}, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     use js_int::UInt; | ||||||
|  |     use ruma_identifiers::{EventId, RoomId, UserId}; | ||||||
|  |     use serde::de::{self, Deserialize, Deserializer, Error as _, MapAccess, Visitor}; | ||||||
|  |     use serde_json::value::RawValue as RawJsonValue; | ||||||
|  | 
 | ||||||
|  |     use crate::{RawEventContent, UnsignedData}; | ||||||
|  | 
 | ||||||
|  |     /// The raw half of a message event.
 | ||||||
|  |     #[derive(Clone, Debug)] | ||||||
|  |     pub struct MessageEvent<C> { | ||||||
|  |         /// Data specific to the event type.
 | ||||||
|  |         pub content: C, | ||||||
|  | 
 | ||||||
|  |         /// The globally unique event identifier for the user who sent the event.
 | ||||||
|  |         pub event_id: EventId, | ||||||
|  | 
 | ||||||
|  |         /// Contains the fully-qualified ID of the user who sent this event.
 | ||||||
|  |         pub sender: UserId, | ||||||
|  | 
 | ||||||
|  |         /// Timestamp in milliseconds on originating homeserver when this event was sent.
 | ||||||
|  |         pub origin_server_ts: SystemTime, | ||||||
|  | 
 | ||||||
|  |         /// The ID of the room associated with this event.
 | ||||||
|  |         pub room_id: RoomId, | ||||||
|  | 
 | ||||||
|  |         /// Additional key-value pairs not signed by the homeserver.
 | ||||||
|  |         pub unsigned: UnsignedData, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     impl<'de, C> Deserialize<'de> for MessageEvent<C> | ||||||
|  |     where | ||||||
|  |         C: RawEventContent, | ||||||
|  |     { | ||||||
|  |         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||||||
|  |         where | ||||||
|  |             D: Deserializer<'de>, | ||||||
|  |         { | ||||||
|  |             deserializer.deserialize_map(MessageEventVisitor(std::marker::PhantomData)) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[derive(serde::Deserialize)] | ||||||
|  |     #[serde(field_identifier, rename_all = "snake_case")] | ||||||
|  |     enum Field { | ||||||
|  |         Type, | ||||||
|  |         Content, | ||||||
|  |         EventId, | ||||||
|  |         Sender, | ||||||
|  |         OriginServerTs, | ||||||
|  |         RoomId, | ||||||
|  |         Unsigned, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Visits the fields of a MessageEvent<C> to handle deserialization of
 | ||||||
|  |     /// the `content` and `prev_content` fields.
 | ||||||
|  |     struct MessageEventVisitor<C>(PhantomData<C>); | ||||||
|  | 
 | ||||||
|  |     impl<'de, C> Visitor<'de> for MessageEventVisitor<C> | ||||||
|  |     where | ||||||
|  |         C: RawEventContent, | ||||||
|  |     { | ||||||
|  |         type Value = MessageEvent<C>; | ||||||
|  | 
 | ||||||
|  |         fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|  |             write!(formatter, "struct implementing MessageEventContent") | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> | ||||||
|  |         where | ||||||
|  |             A: MapAccess<'de>, | ||||||
|  |         { | ||||||
|  |             let mut content: Option<Box<RawJsonValue>> = None; | ||||||
|  |             let mut event_type: Option<String> = None; | ||||||
|  |             let mut event_id: Option<EventId> = None; | ||||||
|  |             let mut sender: Option<UserId> = None; | ||||||
|  |             let mut origin_server_ts: Option<UInt> = None; | ||||||
|  |             let mut room_id: Option<RoomId> = None; | ||||||
|  |             let mut unsigned: Option<UnsignedData> = None; | ||||||
|  | 
 | ||||||
|  |             while let Some(key) = map.next_key()? { | ||||||
|  |                 match key { | ||||||
|  |                     Field::Content => { | ||||||
|  |                         if content.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("content")); | ||||||
|  |                         } | ||||||
|  |                         content = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                     Field::EventId => { | ||||||
|  |                         if event_id.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("event_id")); | ||||||
|  |                         } | ||||||
|  |                         event_id = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                     Field::Sender => { | ||||||
|  |                         if sender.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("sender")); | ||||||
|  |                         } | ||||||
|  |                         sender = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                     Field::OriginServerTs => { | ||||||
|  |                         if origin_server_ts.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("origin_server_ts")); | ||||||
|  |                         } | ||||||
|  |                         origin_server_ts = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                     Field::RoomId => { | ||||||
|  |                         if room_id.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("room_id")); | ||||||
|  |                         } | ||||||
|  |                         room_id = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                     Field::Type => { | ||||||
|  |                         if event_type.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("type")); | ||||||
|  |                         } | ||||||
|  |                         event_type = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                     Field::Unsigned => { | ||||||
|  |                         if unsigned.is_some() { | ||||||
|  |                             return Err(de::Error::duplicate_field("unsigned")); | ||||||
|  |                         } | ||||||
|  |                         unsigned = Some(map.next_value()?); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             let event_type = event_type.ok_or_else(|| de::Error::missing_field("type"))?; | ||||||
|  | 
 | ||||||
|  |             let raw = content.ok_or_else(|| de::Error::missing_field("content"))?; | ||||||
|  |             let content = C::from_parts(&event_type, raw).map_err(A::Error::custom)?; | ||||||
|  | 
 | ||||||
|  |             let event_id = event_id.ok_or_else(|| de::Error::missing_field("event_id"))?; | ||||||
|  |             let sender = sender.ok_or_else(|| de::Error::missing_field("sender"))?; | ||||||
|  | 
 | ||||||
|  |             let origin_server_ts = origin_server_ts | ||||||
|  |                 .map(|time| UNIX_EPOCH + Duration::from_millis(time.into())) | ||||||
|  |                 .ok_or_else(|| de::Error::missing_field("origin_server_ts"))?; | ||||||
|  | 
 | ||||||
|  |             let room_id = room_id.ok_or_else(|| de::Error::missing_field("room_id"))?; | ||||||
|  | 
 | ||||||
|  |             let unsigned = unsigned.unwrap_or_default(); | ||||||
|  | 
 | ||||||
|  |             Ok(MessageEvent { | ||||||
|  |                 content, | ||||||
|  |                 event_id, | ||||||
|  |                 sender, | ||||||
|  |                 origin_server_ts, | ||||||
|  |                 room_id, | ||||||
|  |                 unsigned, | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use std::{ | ||||||
|  |         convert::TryFrom, | ||||||
|  |         time::{Duration, UNIX_EPOCH}, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     use js_int::UInt; | ||||||
|  |     use matches::assert_matches; | ||||||
|  |     use ruma_identifiers::{EventId, RoomAliasId, RoomId, UserId}; | ||||||
|  |     use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; | ||||||
|  | 
 | ||||||
|  |     use super::{AnyMessageEventContent, MessageEvent}; | ||||||
|  |     use crate::{ | ||||||
|  |         call::{answer::AnswerEventContent, SessionDescription, SessionDescriptionType}, | ||||||
|  |         room::{ImageInfo, ThumbnailInfo}, | ||||||
|  |         sticker::StickerEventContent, | ||||||
|  |         EventJson, UnsignedData, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn message_serialize_aliases() { | ||||||
|  |         let aliases_event = MessageEvent { | ||||||
|  |             content: AnyMessageEventContent::Sticker(StickerEventContent { | ||||||
|  |                 body: "Hello".into(), | ||||||
|  |                 info: ImageInfo { | ||||||
|  |                     height: UInt::new(423), | ||||||
|  |                     width: UInt::new(1011), | ||||||
|  |                     mimetype: Some("image/png".into()), | ||||||
|  |                     size: UInt::new(84242), | ||||||
|  |                     thumbnail_info: Some(Box::new(ThumbnailInfo { | ||||||
|  |                         width: UInt::new(800), | ||||||
|  |                         height: UInt::new(334), | ||||||
|  |                         mimetype: Some("image/png".into()), | ||||||
|  |                         size: UInt::new(82595), | ||||||
|  |                     })), | ||||||
|  |                     thumbnail_url: Some("mxc://matrix.org".into()), | ||||||
|  |                     thumbnail_file: None, | ||||||
|  |                 }, | ||||||
|  |                 url: "http://www.matrix.org".into(), | ||||||
|  |             }), | ||||||
|  |             event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), | ||||||
|  |             origin_server_ts: UNIX_EPOCH + Duration::from_millis(1), | ||||||
|  |             room_id: RoomId::try_from("!roomid:room.com").unwrap(), | ||||||
|  |             sender: UserId::try_from("@carl:example.com").unwrap(), | ||||||
|  |             unsigned: UnsignedData::default(), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let actual = to_json_value(&aliases_event).unwrap(); | ||||||
|  |         let expected = json!({ | ||||||
|  |             "content": { | ||||||
|  |                 "body": "Hello", | ||||||
|  |                 "info": { | ||||||
|  |                     "h": 423, | ||||||
|  |                     "mimetype": "image/png", | ||||||
|  |                     "size": 84242, | ||||||
|  |                     "thumbnail_info": { | ||||||
|  |                       "h": 334, | ||||||
|  |                       "mimetype": "image/png", | ||||||
|  |                       "size": 82595, | ||||||
|  |                       "w": 800 | ||||||
|  |                     }, | ||||||
|  |                     "thumbnail_url": "mxc://matrix.org", | ||||||
|  |                     "w": 1011 | ||||||
|  |                   }, | ||||||
|  |                 "url": "http://www.matrix.org" | ||||||
|  |             }, | ||||||
|  |             "event_id": "$h29iv0s8:example.com", | ||||||
|  |             "origin_server_ts": 1, | ||||||
|  |             "room_id": "!roomid:room.com", | ||||||
|  |             "sender": "@carl:example.com", | ||||||
|  |             "type": "m.sticker", | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         assert_eq!(actual, expected); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn deserialize_message_aliases_content() { | ||||||
|  |         let json_data = json!({ | ||||||
|  |             "answer": { | ||||||
|  |                 "type": "answer", | ||||||
|  |                 "sdp": "Hello" | ||||||
|  |             }, | ||||||
|  |             "call_id": "foofoo", | ||||||
|  |             "version": 1 | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         assert_matches!( | ||||||
|  |             from_json_value::<EventJson<AnyMessageEventContent>>(json_data) | ||||||
|  |                 .unwrap() | ||||||
|  |                 .deserialize_content("m.call.answer") | ||||||
|  |                 .unwrap(), | ||||||
|  |             AnyMessageEventContent::CallAnswer(AnswerEventContent { | ||||||
|  |                 answer: SessionDescription { | ||||||
|  |                     session_type: SessionDescriptionType::Answer, | ||||||
|  |                     sdp, | ||||||
|  |                 }, | ||||||
|  |                 call_id, | ||||||
|  |                 version, | ||||||
|  |             }) if sdp == "Hello" && call_id == "foofoo" && version == UInt::new(1).unwrap() | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn deserialize_message_aliases() { | ||||||
|  |         let json_data = json!({ | ||||||
|  |             "content": { | ||||||
|  |                 "answer": { | ||||||
|  |                     "type": "answer", | ||||||
|  |                     "sdp": "Hello" | ||||||
|  |                 }, | ||||||
|  |                 "call_id": "foofoo", | ||||||
|  |                 "version": 1 | ||||||
|  |             }, | ||||||
|  |             "event_id": "$h29iv0s8:example.com", | ||||||
|  |             "origin_server_ts": 1, | ||||||
|  |             "room_id": "!roomid:room.com", | ||||||
|  |             "sender": "@carl:example.com", | ||||||
|  |             "type": "m.call.answer" | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         assert_matches!( | ||||||
|  |             from_json_value::<EventJson<MessageEvent<AnyMessageEventContent>>>(json_data) | ||||||
|  |                 .unwrap() | ||||||
|  |                 .deserialize() | ||||||
|  |                 .unwrap(), | ||||||
|  |             MessageEvent { | ||||||
|  |                 content: AnyMessageEventContent::CallAnswer(AnswerEventContent { | ||||||
|  |                     answer: SessionDescription { | ||||||
|  |                         session_type: SessionDescriptionType::Answer, | ||||||
|  |                         sdp, | ||||||
|  |                     }, | ||||||
|  |                     call_id, | ||||||
|  |                     version, | ||||||
|  |                 }), | ||||||
|  |                 event_id, | ||||||
|  |                 origin_server_ts, | ||||||
|  |                 room_id, | ||||||
|  |                 sender, | ||||||
|  |                 unsigned, | ||||||
|  |             } if sdp == "Hello" && call_id == "foofoo" && version == UInt::new(1).unwrap() | ||||||
|  |                 && event_id == EventId::try_from("$h29iv0s8:example.com").unwrap() | ||||||
|  |                 && origin_server_ts == UNIX_EPOCH + Duration::from_millis(1) | ||||||
|  |                 && room_id == RoomId::try_from("!roomid:room.com").unwrap() | ||||||
|  |                 && sender == UserId::try_from("@carl:example.com").unwrap() | ||||||
|  |                 && unsigned.is_empty() | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn deserialize_message_avatar() { | ||||||
|  |         let json_data = json!({ | ||||||
|  |             "content": { | ||||||
|  |                 "body": "Hello", | ||||||
|  |                 "info": { | ||||||
|  |                     "h": 423, | ||||||
|  |                     "mimetype": "image/png", | ||||||
|  |                     "size": 84242, | ||||||
|  |                     "thumbnail_info": { | ||||||
|  |                       "h": 334, | ||||||
|  |                       "mimetype": "image/png", | ||||||
|  |                       "size": 82595, | ||||||
|  |                       "w": 800 | ||||||
|  |                     }, | ||||||
|  |                     "thumbnail_url": "mxc://matrix.org", | ||||||
|  |                     "w": 1011 | ||||||
|  |                   }, | ||||||
|  |                 "url": "http://www.matrix.org" | ||||||
|  |             }, | ||||||
|  |             "event_id": "$h29iv0s8:example.com", | ||||||
|  |             "origin_server_ts": 1, | ||||||
|  |             "room_id": "!roomid:room.com", | ||||||
|  |             "sender": "@carl:example.com", | ||||||
|  |             "type": "m.sticker" | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         assert_matches!( | ||||||
|  |             from_json_value::<EventJson<MessageEvent<AnyMessageEventContent>>>(json_data) | ||||||
|  |                 .unwrap() | ||||||
|  |                 .deserialize() | ||||||
|  |                 .unwrap(), | ||||||
|  |             MessageEvent { | ||||||
|  |                 content: AnyMessageEventContent::Sticker(StickerEventContent { | ||||||
|  |                     body, | ||||||
|  |                     info: ImageInfo { | ||||||
|  |                         height, | ||||||
|  |                         width, | ||||||
|  |                         mimetype: Some(mimetype), | ||||||
|  |                         size, | ||||||
|  |                         thumbnail_info: Some(thumbnail_info), | ||||||
|  |                         thumbnail_url: Some(thumbnail_url), | ||||||
|  |                         thumbnail_file: None, | ||||||
|  |                     }, | ||||||
|  |                     url, | ||||||
|  |                 }), | ||||||
|  |                 event_id, | ||||||
|  |                 origin_server_ts, | ||||||
|  |                 room_id, | ||||||
|  |                 sender, | ||||||
|  |                 unsigned | ||||||
|  |             } if event_id == EventId::try_from("$h29iv0s8:example.com").unwrap() | ||||||
|  |                 && body == "Hello" | ||||||
|  |                 && origin_server_ts == UNIX_EPOCH + Duration::from_millis(1) | ||||||
|  |                 && room_id == RoomId::try_from("!roomid:room.com").unwrap() | ||||||
|  |                 && sender == UserId::try_from("@carl:example.com").unwrap() | ||||||
|  |                 && height == UInt::new(423) | ||||||
|  |                 && width == UInt::new(1011) | ||||||
|  |                 && mimetype == "image/png" | ||||||
|  |                 && size == UInt::new(84242) | ||||||
|  |                 && thumbnail_url == "mxc://matrix.org" | ||||||
|  |                 && matches!( | ||||||
|  |                     thumbnail_info.as_ref(), | ||||||
|  |                     ThumbnailInfo { | ||||||
|  |                         width: thumb_width, | ||||||
|  |                         height: thumb_height, | ||||||
|  |                         mimetype: thumb_mimetype, | ||||||
|  |                         size: thumb_size, | ||||||
|  |                     } if *thumb_width == UInt::new(800) | ||||||
|  |                         && *thumb_height == UInt::new(334) | ||||||
|  |                         && *thumb_mimetype == Some("image/png".to_string()) | ||||||
|  |                         && *thumb_size == UInt::new(82595) | ||||||
|  |                 ) | ||||||
|  |                 && url == "http://www.matrix.org" | ||||||
|  |                 && unsigned.is_empty() | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user