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