ruma_events/room/message/
relation.rs

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