events: Make Replacement generic over the parent type
Because the new content must be of the same type.
This commit is contained in:
parent
7c802c89ca
commit
7c0f7ba5f1
@ -40,7 +40,7 @@ pub struct AudioEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<AudioEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl AudioEventContent {
|
||||
|
@ -24,7 +24,7 @@ pub struct EmoteEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<EmoteEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl EmoteEventContent {
|
||||
|
@ -35,7 +35,7 @@ pub struct FileEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<FileEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl FileEventContent {
|
||||
|
@ -51,7 +51,7 @@ pub struct ImageEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<ImageEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl ImageEventContent {
|
||||
|
@ -40,7 +40,7 @@ pub struct LocationEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<LocationEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl LocationEventContent {
|
||||
|
@ -73,7 +73,7 @@ pub struct MessageEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<MessageEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl MessageEventContent {
|
||||
|
@ -24,7 +24,7 @@ pub struct NoticeEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<NoticeEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl NoticeEventContent {
|
||||
|
@ -107,8 +107,8 @@ pub enum Relation {
|
||||
_Custom,
|
||||
}
|
||||
|
||||
impl From<message::Relation> for Relation {
|
||||
fn from(rel: message::Relation) -> Self {
|
||||
impl<C> From<message::Relation<C>> for Relation {
|
||||
fn from(rel: message::Relation<C>) -> Self {
|
||||
match rel {
|
||||
message::Relation::Reply { in_reply_to } => Self::Reply { in_reply_to },
|
||||
message::Relation::Replacement(re) => {
|
||||
|
@ -62,7 +62,7 @@ pub struct RoomMessageEventContent {
|
||||
///
|
||||
/// [rich replies]: https://spec.matrix.org/v1.2/client-server-api/#rich-replies
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<MessageType>>,
|
||||
}
|
||||
|
||||
impl RoomMessageEventContent {
|
||||
@ -467,7 +467,7 @@ impl From<RoomMessageEventContent> for MessageType {
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(clippy::manual_non_exhaustive)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub enum Relation {
|
||||
pub enum Relation<C> {
|
||||
/// An `m.in_reply_to` relation indicating that the event is a reply to another event.
|
||||
Reply {
|
||||
/// Information about another message being replied to.
|
||||
@ -475,7 +475,7 @@ pub enum Relation {
|
||||
},
|
||||
|
||||
/// An event that replaces another event.
|
||||
Replacement(Replacement),
|
||||
Replacement(Replacement<C>),
|
||||
|
||||
/// An event that belongs to a thread.
|
||||
Thread(Thread),
|
||||
@ -504,17 +504,17 @@ impl InReplyTo {
|
||||
/// [replaces another event]: https://spec.matrix.org/v1.4/client-server-api/#event-replacements
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
pub struct Replacement {
|
||||
pub struct Replacement<C> {
|
||||
/// The ID of the event being replaced.
|
||||
pub event_id: OwnedEventId,
|
||||
|
||||
/// New content.
|
||||
pub new_content: Box<RoomMessageEventContent>,
|
||||
pub new_content: C,
|
||||
}
|
||||
|
||||
impl Replacement {
|
||||
impl<C> Replacement<C> {
|
||||
/// Creates a new `Replacement` with the given event ID and new content.
|
||||
pub fn new(event_id: OwnedEventId, new_content: Box<RoomMessageEventContent>) -> Self {
|
||||
pub fn new(event_id: OwnedEventId, new_content: C) -> Self {
|
||||
Self { event_id, new_content }
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ impl<'de> Deserialize<'de> for RoomMessageEventContent {
|
||||
{
|
||||
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
||||
let mut deserializer = serde_json::Deserializer::from_str(json.get());
|
||||
let relates_to =
|
||||
Option::<Relation>::deserialize(&mut deserializer).map_err(de::Error::custom)?;
|
||||
let relates_to = Option::<Relation<MessageType>>::deserialize(&mut deserializer)
|
||||
.map_err(de::Error::custom)?;
|
||||
|
||||
Ok(Self { msgtype: from_raw_json_value(&json)?, relates_to })
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use super::{InReplyTo, Relation, Replacement, RoomMessageEventContent, Thread};
|
||||
use super::{InReplyTo, Relation, Replacement, Thread};
|
||||
use crate::OwnedEventId;
|
||||
|
||||
impl<'de> Deserialize<'de> for Relation {
|
||||
impl<'de, C> Deserialize<'de> for Relation<C>
|
||||
where
|
||||
C: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
@ -47,17 +50,22 @@ impl<'de> Deserialize<'de> for Relation {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Relation {
|
||||
impl<C> Serialize for Relation<C>
|
||||
where
|
||||
C: Clone + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
#[allow(clippy::needless_update)]
|
||||
let json_repr = match self {
|
||||
Relation::Reply { in_reply_to } => EventWithRelatesToJsonRepr::new(RelatesToJsonRepr {
|
||||
Relation::Reply { in_reply_to } => {
|
||||
EventWithRelatesToJsonRepr::<C>::new(RelatesToJsonRepr {
|
||||
in_reply_to: Some(in_reply_to.clone()),
|
||||
..Default::default()
|
||||
}),
|
||||
})
|
||||
}
|
||||
Relation::Replacement(Replacement { event_id, new_content }) => {
|
||||
EventWithRelatesToJsonRepr {
|
||||
relates_to: RelatesToJsonRepr {
|
||||
@ -79,28 +87,34 @@ impl Serialize for Relation {
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
Relation::_Custom => EventWithRelatesToJsonRepr::default(),
|
||||
Relation::_Custom => EventWithRelatesToJsonRepr::<C>::default(),
|
||||
};
|
||||
|
||||
json_repr.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
struct EventWithRelatesToJsonRepr {
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct EventWithRelatesToJsonRepr<C> {
|
||||
#[serde(rename = "m.relates_to", default, skip_serializing_if = "RelatesToJsonRepr::is_empty")]
|
||||
relates_to: RelatesToJsonRepr,
|
||||
|
||||
#[serde(rename = "m.new_content", skip_serializing_if = "Option::is_none")]
|
||||
new_content: Option<Box<RoomMessageEventContent>>,
|
||||
new_content: Option<C>,
|
||||
}
|
||||
|
||||
impl EventWithRelatesToJsonRepr {
|
||||
impl<C> EventWithRelatesToJsonRepr<C> {
|
||||
fn new(relates_to: RelatesToJsonRepr) -> Self {
|
||||
Self { relates_to, new_content: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Default for EventWithRelatesToJsonRepr<C> {
|
||||
fn default() -> Self {
|
||||
Self { relates_to: RelatesToJsonRepr::default(), new_content: None }
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct modeling the different ways relationships can be expressed in a `m.relates_to` field of
|
||||
/// an event.
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
|
@ -50,7 +50,7 @@ pub struct VideoEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<VideoEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl VideoEventContent {
|
||||
|
@ -38,7 +38,7 @@ pub struct VoiceEventContent {
|
||||
|
||||
/// Information about related messages.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub relates_to: Option<Relation>,
|
||||
pub relates_to: Option<Relation<VoiceEventContentWithoutRelation>>,
|
||||
}
|
||||
|
||||
impl VoiceEventContent {
|
||||
|
@ -75,7 +75,7 @@ fn replacement_serialize() {
|
||||
relates_to: Some(Relation::Replacement(
|
||||
Replacement::new(
|
||||
event_id!("$1598361704261elfgc").to_owned(),
|
||||
Box::new(RoomMessageEventContent::text_plain("This is the new content.")),
|
||||
RoomMessageEventContent::text_plain("This is the new content.").into(),
|
||||
)
|
||||
))
|
||||
}
|
||||
@ -142,7 +142,7 @@ fn replacement_deserialize() {
|
||||
}) => replacement
|
||||
);
|
||||
assert_eq!(replacement.event_id, "$1598361704261elfgc");
|
||||
let text = assert_matches!(replacement.new_content.msgtype, MessageType::Text(text) => text);
|
||||
let text = assert_matches!(replacement.new_content, MessageType::Text(text) => text);
|
||||
assert_eq!(text.body, "Hello! My name is bar");
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
use assert_matches::assert_matches;
|
||||
use ruma_common::{
|
||||
event_id,
|
||||
events::room::message::{
|
||||
InReplyTo, MessageType, Relation, RoomMessageEventContent,
|
||||
RoomMessageEventContentWithoutRelation,
|
||||
},
|
||||
events::room::message::{InReplyTo, MessageType, Relation, RoomMessageEventContent},
|
||||
};
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
@ -13,7 +10,7 @@ fn serialize_room_message_content_without_relation() {
|
||||
let mut content = RoomMessageEventContent::text_plain("Hello, world!");
|
||||
content.relates_to =
|
||||
Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$eventId").to_owned()) });
|
||||
let without_relation = RoomMessageEventContentWithoutRelation::from(content);
|
||||
let without_relation = MessageType::from(content);
|
||||
|
||||
#[cfg(not(feature = "unstable-msc3246"))]
|
||||
assert_eq!(
|
||||
@ -43,8 +40,8 @@ fn deserialize_room_message_content_without_relation() {
|
||||
});
|
||||
|
||||
let text = assert_matches!(
|
||||
from_json_value::<RoomMessageEventContentWithoutRelation>(json_data),
|
||||
Ok(RoomMessageEventContentWithoutRelation::Text(text)) => text
|
||||
from_json_value::<MessageType>(json_data),
|
||||
Ok(MessageType::Text(text)) => text
|
||||
);
|
||||
assert_eq!(text.body, "Hello, world!");
|
||||
}
|
||||
@ -54,8 +51,7 @@ fn convert_room_message_content_without_relation_to_full() {
|
||||
let mut content = RoomMessageEventContent::text_plain("Hello, world!");
|
||||
content.relates_to =
|
||||
Some(Relation::Reply { in_reply_to: InReplyTo::new(event_id!("$eventId").to_owned()) });
|
||||
let new_content =
|
||||
RoomMessageEventContent::from(RoomMessageEventContentWithoutRelation::from(content));
|
||||
let new_content = RoomMessageEventContent::from(MessageType::from(content));
|
||||
|
||||
let (text, relates_to) = assert_matches!(
|
||||
new_content,
|
||||
|
Loading…
x
Reference in New Issue
Block a user