1use std::borrow::Cow;
23use ruma_common::serde::JsonObject;
45use crate::relation::{CustomRelation, InReplyTo, RelationType, Replacement, Thread};
67/// 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.
13Reply {
14/// Information about another message being replied to.
15in_reply_to: InReplyTo,
16 },
1718/// An event that replaces another event.
19Replacement(Replacement<C>),
2021/// An event that belongs to a thread.
22Thread(Thread),
2324#[doc(hidden)]
25_Custom(CustomRelation),
26}
2728impl<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.
32pub fn rel_type(&self) -> Option<RelationType> {
33match 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 }
4041/// 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.
49pub fn data(&self) -> Cow<'_, JsonObject>
50where
51C: Clone,
52 {
53if let Relation::_Custom(CustomRelation(data)) = self {
54 Cow::Borrowed(data)
55 } else {
56 Cow::Owned(self.serialize_data())
57 }
58 }
59}
6061/// 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.
67Reply {
68/// Information about another message being replied to.
69in_reply_to: InReplyTo,
70 },
7172/// An event that belongs to a thread.
73Thread(Thread),
7475#[doc(hidden)]
76_Custom(CustomRelation),
77}
7879impl RelationWithoutReplacement {
80/// The type of this `Relation`.
81 ///
82 /// Returns an `Option` because the `Reply` relation does not have a`rel_type` field.
83pub fn rel_type(&self) -> Option<RelationType> {
84match self {
85Self::Reply { .. } => None,
86Self::Thread(_) => Some(RelationType::Thread),
87Self::_Custom(c) => c.rel_type(),
88 }
89 }
9091/// 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.
99pub fn data(&self) -> Cow<'_, JsonObject> {
100if let Self::_Custom(CustomRelation(data)) = self {
101 Cow::Borrowed(data)
102 } else {
103 Cow::Owned(self.serialize_data())
104 }
105 }
106}
107108impl<C> TryFrom<Relation<C>> for RelationWithoutReplacement {
109type Error = Replacement<C>;
110111fn try_from(value: Relation<C>) -> Result<Self, Self::Error> {
112let 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 };
118119Ok(rel)
120 }
121}