ruma_events/room/message/relation.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
use std::borrow::Cow;
use ruma_common::serde::JsonObject;
use crate::relation::{CustomRelation, InReplyTo, RelationType, Replacement, Thread};
/// Message event relationship.
#[derive(Clone, Debug)]
#[allow(clippy::manual_non_exhaustive)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
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.
in_reply_to: InReplyTo,
},
/// An event that replaces another event.
Replacement(Replacement<C>),
/// An event that belongs to a thread.
Thread(Thread),
#[doc(hidden)]
_Custom(CustomRelation),
}
impl<C> Relation<C> {
/// The type of this `Relation`.
///
/// Returns an `Option` because the `Reply` relation does not have a`rel_type` field.
pub fn rel_type(&self) -> Option<RelationType> {
match self {
Relation::Reply { .. } => None,
Relation::Replacement(_) => Some(RelationType::Replacement),
Relation::Thread(_) => Some(RelationType::Thread),
Relation::_Custom(c) => c.rel_type(),
}
}
/// The associated data.
///
/// The returned JSON object holds the contents of `m.relates_to`, including `rel_type` and
/// `event_id` if present, but not things like `m.new_content` for `m.replace` relations that
/// live next to `m.relates_to`.
///
/// Prefer to use the public variants of `Relation` where possible; this method is meant to
/// be used for custom relations only.
pub fn data(&self) -> Cow<'_, JsonObject>
where
C: Clone,
{
if let Relation::_Custom(CustomRelation(data)) = self {
Cow::Borrowed(data)
} else {
Cow::Owned(self.serialize_data())
}
}
}
/// Message event relationship, except a replacement.
#[derive(Clone, Debug)]
#[allow(clippy::manual_non_exhaustive)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum RelationWithoutReplacement {
/// An `m.in_reply_to` relation indicating that the event is a reply to another event.
Reply {
/// Information about another message being replied to.
in_reply_to: InReplyTo,
},
/// An event that belongs to a thread.
Thread(Thread),
#[doc(hidden)]
_Custom(CustomRelation),
}
impl RelationWithoutReplacement {
/// The type of this `Relation`.
///
/// Returns an `Option` because the `Reply` relation does not have a`rel_type` field.
pub fn rel_type(&self) -> Option<RelationType> {
match self {
Self::Reply { .. } => None,
Self::Thread(_) => Some(RelationType::Thread),
Self::_Custom(c) => c.rel_type(),
}
}
/// The associated data.
///
/// The returned JSON object holds the contents of `m.relates_to`, including `rel_type` and
/// `event_id` if present, but not things like `m.new_content` for `m.replace` relations that
/// live next to `m.relates_to`.
///
/// Prefer to use the public variants of `Relation` where possible; this method is meant to
/// be used for custom relations only.
pub fn data(&self) -> Cow<'_, JsonObject> {
if let Self::_Custom(CustomRelation(data)) = self {
Cow::Borrowed(data)
} else {
Cow::Owned(self.serialize_data())
}
}
}
impl<C> TryFrom<Relation<C>> for RelationWithoutReplacement {
type Error = Replacement<C>;
fn try_from(value: Relation<C>) -> Result<Self, Self::Error> {
let rel = match value {
Relation::Reply { in_reply_to } => Self::Reply { in_reply_to },
Relation::Replacement(r) => return Err(r),
Relation::Thread(t) => Self::Thread(t),
Relation::_Custom(c) => Self::_Custom(c),
};
Ok(rel)
}
}