Skip to main content

tuwunel_core/matrix/
pdu.rs

1mod builder;
2mod count;
3mod format;
4mod hashes;
5mod id;
6mod raw_id;
7#[cfg(test)]
8mod tests;
9mod unsigned;
10
11use std::cmp::Ordering;
12
13use ruma::{
14	CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId,
15	OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, UInt, UserId, events::TimelineEventType,
16	room_version_rules::RoomVersionRules, serde::Raw,
17};
18use serde::{Deserialize, Serialize};
19use serde_json::value::RawValue as RawJsonValue;
20use smallvec::SmallVec;
21
22pub use self::{
23	Count as PduCount, Id as PduId, Pdu as PduEvent, RawId as RawPduId,
24	builder::{Builder, Builder as PduBuilder},
25	count::Count,
26	format::{
27		check::{check_room_id, check_rules},
28		from_incoming_federation, into_outgoing_federation,
29	},
30	hashes::EventHashes as EventHash,
31	id::Id,
32	raw_id::*,
33};
34use super::{Event, ShortRoomId, StateKey};
35use crate::Result;
36
37/// Persistent Data Unit (Event)
38#[derive(Clone, Deserialize, Serialize, Debug)]
39pub struct Pdu {
40	#[serde(rename = "type")]
41	pub kind: TimelineEventType,
42
43	pub content: Content,
44
45	pub event_id: OwnedEventId,
46
47	pub room_id: OwnedRoomId,
48
49	pub sender: OwnedUserId,
50
51	#[serde(skip_serializing_if = "Option::is_none")]
52	pub state_key: Option<StateKey>,
53
54	#[serde(skip_serializing_if = "Option::is_none")]
55	pub redacts: Option<OwnedEventId>,
56
57	pub prev_events: PrevEvents,
58
59	pub auth_events: AuthEvents,
60
61	pub origin_server_ts: UInt,
62
63	pub depth: UInt,
64
65	pub hashes: EventHash,
66
67	#[serde(skip_serializing_if = "Option::is_none")]
68	pub origin: Option<OwnedServerName>,
69
70	#[serde(default, skip_serializing_if = "Option::is_none")]
71	pub unsigned: Option<Box<RawJsonValue>>,
72
73	// BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>
74	#[serde(default, skip_serializing_if = "Option::is_none")]
75	pub signatures: Option<Box<RawJsonValue>>,
76
77	//TODO: https://spec.matrix.org/v1.14/rooms/v11/#rejected-events
78	#[cfg(test)]
79	#[serde(default, skip_serializing)]
80	pub rejected: bool,
81}
82
83/// Tuned prev_events vector. Most events have one prev_event. Many events have
84/// more but allocations for all of those cases still beats allocations for all
85/// cases.
86pub type PrevEvents = SmallVec<[OwnedEventId; 1]>;
87
88/// Tuned auth_events vector. Average events have three auth events. It is
89/// debatable whether this could be an ArrayVec but the realistic upper-bound is
90/// too high and non-deterministic in the era of restricted-type rooms.
91pub type AuthEvents = SmallVec<[OwnedEventId; 3]>;
92
93/// Tuned content buffer. This was chosen empirically based on a significantly
94/// high-rate modality in the 96-112B size class reported by jemalloc. With two
95/// additional words (hopefully) for the SmallVec it puts us squarely at 128B.
96pub type Content = Raw<CanonicalJsonObject, 112>;
97
98/// The [maximum size allowed] for a PDU.
99/// [maximum size allowed]: <https://spec.matrix.org/latest/client-server-api/#size-limits>
100pub const MAX_PDU_BYTES: usize = 65_535;
101
102/// The [maximum length allowed] for the `prev_events` array of a PDU.
103/// [maximum length allowed]: <https://spec.matrix.org/latest/rooms/v1/#event-format>
104pub const MAX_PREV_EVENTS: usize = 20;
105
106/// The [maximum length allowed] for the `auth_events` array of a PDU.
107/// [maximum length allowed]: <https://spec.matrix.org/latest/rooms/v1/#event-format>
108pub const MAX_AUTH_EVENTS: usize = 10;
109
110impl Pdu {
111	pub fn from_object_and_roomid_and_eventid(
112		room_id: &RoomId,
113		event_id: &EventId,
114		mut json: CanonicalJsonObject,
115	) -> Result<Self> {
116		let room_id = CanonicalJsonValue::String(room_id.into());
117		json.insert("room_id".into(), room_id);
118		Self::from_object_and_eventid(event_id, json)
119	}
120
121	pub fn from_object_and_eventid(
122		event_id: &EventId,
123		mut json: CanonicalJsonObject,
124	) -> Result<Self> {
125		let event_id = CanonicalJsonValue::String(event_id.into());
126		json.insert("event_id".into(), event_id);
127		Self::from_object(json)
128	}
129
130	pub fn from_object_federation(
131		room_id: &RoomId,
132		event_id: &EventId,
133		json: CanonicalJsonObject,
134		rules: &RoomVersionRules,
135	) -> Result<(Self, CanonicalJsonObject)> {
136		let json = from_incoming_federation(room_id, event_id, json, rules);
137		let pdu = Self::from_object_checked(json.clone(), rules)?;
138		check_room_id(&pdu, room_id)?;
139		Ok((pdu, json))
140	}
141
142	pub fn from_object_checked(
143		json: CanonicalJsonObject,
144		rules: &RoomVersionRules,
145	) -> Result<Self> {
146		check_rules(&json, &rules.event_format)?;
147		Self::from_object(json)
148	}
149
150	pub fn from_object(json: CanonicalJsonObject) -> Result<Self> {
151		let json = CanonicalJsonValue::Object(json);
152		Self::from_value(json)
153	}
154
155	pub fn from_raw_value(json: &RawJsonValue) -> Result<Self> {
156		let json: CanonicalJsonValue = json.into();
157		Self::from_value(json)
158	}
159
160	pub fn from_value(json: CanonicalJsonValue) -> Result<Self> {
161		serde_json::from_value(json.into()).map_err(Into::into)
162	}
163
164	pub fn from_raw_json(json: &RawJsonValue) -> Result<Self> {
165		Self::deserialize(json).map_err(Into::into)
166	}
167}
168
169impl Event for Pdu
170where
171	Self: Send + Sync + 'static,
172{
173	#[inline]
174	fn auth_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
175		self.auth_events.iter().map(AsRef::as_ref)
176	}
177
178	#[inline]
179	fn auth_events_into(
180		self,
181	) -> impl IntoIterator<IntoIter = impl Iterator<Item = OwnedEventId>> + Send {
182		self.auth_events.into_iter()
183	}
184
185	#[inline]
186	fn content(&self) -> &RawJsonValue { self.content.json() }
187
188	#[inline]
189	fn event_id(&self) -> &EventId { &self.event_id }
190
191	#[inline]
192	fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
193		MilliSecondsSinceUnixEpoch(self.origin_server_ts)
194	}
195
196	#[inline]
197	fn prev_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
198		self.prev_events.iter().map(AsRef::as_ref)
199	}
200
201	#[inline]
202	fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() }
203
204	#[cfg(test)]
205	#[inline]
206	fn rejected(&self) -> bool { self.rejected }
207
208	#[cfg(not(test))]
209	#[inline]
210	fn rejected(&self) -> bool { false }
211
212	#[inline]
213	fn room_id(&self) -> &RoomId { &self.room_id }
214
215	#[inline]
216	fn sender(&self) -> &UserId { &self.sender }
217
218	#[inline]
219	fn state_key(&self) -> Option<&str> { self.state_key.as_deref() }
220
221	#[inline]
222	fn kind(&self) -> &TimelineEventType { &self.kind }
223
224	#[inline]
225	fn unsigned(&self) -> Option<&RawJsonValue> { self.unsigned.as_deref() }
226
227	#[inline]
228	fn as_mut_pdu(&mut self) -> &mut Pdu { self }
229
230	#[inline]
231	fn as_pdu(&self) -> &Pdu { self }
232
233	#[inline]
234	fn into_pdu(self) -> Pdu { self }
235
236	#[inline]
237	fn is_owned(&self) -> bool { true }
238}
239
240impl Event for &Pdu
241where
242	Self: Send,
243{
244	#[inline]
245	fn auth_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
246		self.auth_events.iter().map(AsRef::as_ref)
247	}
248
249	#[inline]
250	fn auth_events_into(
251		self,
252	) -> impl IntoIterator<IntoIter = impl Iterator<Item = OwnedEventId>> + Send {
253		self.auth_events.iter().map(ToOwned::to_owned)
254	}
255
256	#[inline]
257	fn content(&self) -> &RawJsonValue { self.content.json() }
258
259	#[inline]
260	fn event_id(&self) -> &EventId { &self.event_id }
261
262	#[inline]
263	fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
264		MilliSecondsSinceUnixEpoch(self.origin_server_ts)
265	}
266
267	#[inline]
268	fn prev_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
269		self.prev_events.iter().map(AsRef::as_ref)
270	}
271
272	#[inline]
273	fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() }
274
275	#[cfg(test)]
276	#[inline]
277	fn rejected(&self) -> bool { self.rejected }
278
279	#[cfg(not(test))]
280	#[inline]
281	fn rejected(&self) -> bool { false }
282
283	#[inline]
284	fn room_id(&self) -> &RoomId { &self.room_id }
285
286	#[inline]
287	fn sender(&self) -> &UserId { &self.sender }
288
289	#[inline]
290	fn state_key(&self) -> Option<&str> { self.state_key.as_deref() }
291
292	#[inline]
293	fn kind(&self) -> &TimelineEventType { &self.kind }
294
295	#[inline]
296	fn unsigned(&self) -> Option<&RawJsonValue> { self.unsigned.as_deref() }
297
298	#[inline]
299	fn as_pdu(&self) -> &Pdu { self }
300
301	#[inline]
302	fn into_pdu(self) -> Pdu { self.clone() }
303
304	#[inline]
305	fn is_owned(&self) -> bool { false }
306}
307
308/// Prevent derived equality which wouldn't limit itself to event_id
309impl Eq for Pdu {}
310
311/// Equality determined by the Pdu's ID, not the memory representations.
312impl PartialEq for Pdu {
313	fn eq(&self, other: &Self) -> bool { self.event_id == other.event_id }
314}
315
316/// Ordering determined by the Pdu's ID, not the memory representations.
317impl Ord for Pdu {
318	fn cmp(&self, other: &Self) -> Ordering { self.event_id.cmp(&other.event_id) }
319}
320
321/// Ordering determined by the Pdu's ID, not the memory representations.
322impl PartialOrd for Pdu {
323	fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
324}