events: Implement Deserialize for encrypted::Relation

This commit is contained in:
Kévin Commaille 2023-07-04 15:17:28 +02:00 committed by Kévin Commaille
parent 4d9781e05f
commit c8e61a2ee7
3 changed files with 39 additions and 55 deletions

View File

@ -23,11 +23,7 @@ pub struct EncryptedEventContent {
pub encrypted: EncryptedContentBlock, pub encrypted: EncryptedContentBlock,
/// Information about related events. /// Information about related events.
#[serde( #[serde(rename = "m.relates_to", skip_serializing_if = "Option::is_none")]
flatten,
skip_serializing_if = "Option::is_none",
deserialize_with = "super::room::encrypted::relation_serde::deserialize_relation"
)]
pub relates_to: Option<Relation>, pub relates_to: Option<Relation>,
} }

View File

@ -26,11 +26,7 @@ pub struct RoomEncryptedEventContent {
pub scheme: EncryptedEventScheme, pub scheme: EncryptedEventScheme,
/// Information about related events. /// Information about related events.
#[serde( #[serde(rename = "m.relates_to", skip_serializing_if = "Option::is_none")]
flatten,
skip_serializing_if = "Option::is_none",
deserialize_with = "relation_serde::deserialize_relation"
)]
pub relates_to: Option<Relation>, pub relates_to: Option<Relation>,
} }

View File

@ -1,26 +1,27 @@
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use super::{Annotation, InReplyTo, Reference, Relation, Replacement, Thread}; use super::{Annotation, InReplyTo, Reference, Relation, Replacement, Thread};
use crate::OwnedEventId; use crate::OwnedEventId;
pub(crate) fn deserialize_relation<'de, D>(deserializer: D) -> Result<Option<Relation>, D::Error> impl<'de> Deserialize<'de> for Relation {
where fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let ev = EventWithRelatesToJsonRepr::deserialize(deserializer)?; let relates_to = RelatesToJsonRepr::deserialize(deserializer)?;
if let Some( if let Some(
RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back }) RelationJsonRepr::ThreadStable(ThreadStableJsonRepr { event_id, is_falling_back })
| RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }), | RelationJsonRepr::ThreadUnstable(ThreadUnstableJsonRepr { event_id, is_falling_back }),
) = ev.relates_to.relation ) = relates_to.relation
{ {
let in_reply_to = ev.relates_to.in_reply_to; let in_reply_to = relates_to.in_reply_to;
return Ok(Some(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }))); return Ok(Relation::Thread(Thread { event_id, in_reply_to, is_falling_back }));
} }
let rel = if let Some(in_reply_to) = ev.relates_to.in_reply_to { let rel = if let Some(in_reply_to) = relates_to.in_reply_to {
Some(Relation::Reply { in_reply_to }) Relation::Reply { in_reply_to }
} else { } else if let Some(relation) = relates_to.relation {
ev.relates_to.relation.map(|relation| match relation { match relation {
RelationJsonRepr::Annotation(a) => Relation::Annotation(a), RelationJsonRepr::Annotation(a) => Relation::Annotation(a),
RelationJsonRepr::Reference(r) => Relation::Reference(r), RelationJsonRepr::Reference(r) => Relation::Reference(r),
RelationJsonRepr::Replacement(Replacement { event_id }) => { RelationJsonRepr::Replacement(Replacement { event_id }) => {
@ -32,10 +33,13 @@ where
// FIXME: Maybe we should log this, though at this point we don't even have // FIXME: Maybe we should log this, though at this point we don't even have
// access to the rel_type of the unknown relation. // access to the rel_type of the unknown relation.
RelationJsonRepr::Unknown => Relation::_Custom, RelationJsonRepr::Unknown => Relation::_Custom,
}) }
} else {
return Err(de::Error::missing_field("m.in_reply_to or rel_type"));
}; };
Ok(rel) Ok(rel)
}
} }
impl Serialize for Relation { impl Serialize for Relation {
@ -71,16 +75,10 @@ impl Serialize for Relation {
Relation::_Custom => RelatesToJsonRepr::default(), Relation::_Custom => RelatesToJsonRepr::default(),
}; };
EventWithRelatesToJsonRepr { relates_to }.serialize(serializer) relates_to.serialize(serializer)
} }
} }
#[derive(Deserialize, Serialize)]
struct EventWithRelatesToJsonRepr {
#[serde(rename = "m.relates_to", default, skip_serializing_if = "RelatesToJsonRepr::is_empty")]
relates_to: RelatesToJsonRepr,
}
/// 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)]
@ -92,12 +90,6 @@ struct RelatesToJsonRepr {
relation: Option<RelationJsonRepr>, relation: Option<RelationJsonRepr>,
} }
impl RelatesToJsonRepr {
fn is_empty(&self) -> bool {
self.in_reply_to.is_none() && self.relation.is_none()
}
}
/// A thread relation without the reply fallback, with stable names. /// A thread relation without the reply fallback, with stable names.
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Deserialize, Serialize)]
struct ThreadStableJsonRepr { struct ThreadStableJsonRepr {