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<Unsigned>,
72
73	//TODO: https://spec.matrix.org/v1.14/rooms/v11/#rejected-events
74	#[cfg(test)]
75	#[serde(default, skip_serializing)]
76	pub rejected: bool,
77}
78
79/// Tuned prev_events vector. Most events have one prev_event. Many events have
80/// more but allocations for all of those cases still beats allocations for all
81/// cases.
82pub type PrevEvents = SmallVec<[OwnedEventId; 1]>;
83
84/// Tuned auth_events vector. Average events have three auth events. It is
85/// debatable whether this could be an ArrayVec but the realistic upper-bound is
86/// too high and non-deterministic in the era of restricted-type rooms.
87pub type AuthEvents = SmallVec<[OwnedEventId; 3]>;
88
89/// Tuned content buffer. This was chosen empirically based on a significantly
90/// high-rate modality in the 96-112B size class reported by jemalloc. With two
91/// additional words (hopefully) for the SmallVec it puts us squarely at 128B.
92pub type Content = Raw<CanonicalJsonObject, 112>;
93
94/// Tuned unsigned buffer. The stored value is `None` or small (the local-send
95/// `transaction_id` echo, or a serve-time `age`/`membership` annotation), all
96/// of which stay inline at the `Content` size class. State-event `prev_content`
97/// and bundled `m.relations` exceed it and spill to the heap, which is correct.
98pub type Unsigned = Raw<CanonicalJsonObject, 112>;
99
100/// The [maximum size allowed] for a PDU.
101/// [maximum size allowed]: <https://spec.matrix.org/latest/client-server-api/#size-limits>
102pub const MAX_PDU_BYTES: usize = 65_535;
103
104/// The [maximum length allowed] for the `prev_events` array of a PDU.
105/// [maximum length allowed]: <https://spec.matrix.org/latest/rooms/v1/#event-format>
106pub const MAX_PREV_EVENTS: usize = 20;
107
108/// The [maximum length allowed] for the `auth_events` array of a PDU.
109/// [maximum length allowed]: <https://spec.matrix.org/latest/rooms/v1/#event-format>
110pub const MAX_AUTH_EVENTS: usize = 10;
111
112impl Pdu {
113	pub fn from_object_and_roomid_and_eventid(
114		room_id: &RoomId,
115		event_id: &EventId,
116		mut json: CanonicalJsonObject,
117	) -> Result<Self> {
118		let room_id = CanonicalJsonValue::String(room_id.into());
119		json.insert("room_id".into(), room_id);
120		Self::from_object_and_eventid(event_id, json)
121	}
122
123	pub fn from_object_and_eventid(
124		event_id: &EventId,
125		mut json: CanonicalJsonObject,
126	) -> Result<Self> {
127		let event_id = CanonicalJsonValue::String(event_id.into());
128		json.insert("event_id".into(), event_id);
129		Self::from_object(json)
130	}
131
132	pub fn from_object_federation(
133		room_id: &RoomId,
134		event_id: &EventId,
135		json: CanonicalJsonObject,
136		rules: &RoomVersionRules,
137	) -> Result<(Self, CanonicalJsonObject)> {
138		let json = from_incoming_federation(room_id, event_id, json, rules);
139		let pdu = Self::from_object_checked(json.clone(), rules)?;
140		check_room_id(&pdu, room_id)?;
141		Ok((pdu, json))
142	}
143
144	pub fn from_object_checked(
145		json: CanonicalJsonObject,
146		rules: &RoomVersionRules,
147	) -> Result<Self> {
148		check_rules(&json, &rules.event_format)?;
149		Self::from_object(json)
150	}
151
152	pub fn from_object(json: CanonicalJsonObject) -> Result<Self> {
153		let json = CanonicalJsonValue::Object(json);
154		Self::from_value(json)
155	}
156
157	pub fn from_raw_value(json: &RawJsonValue) -> Result<Self> {
158		let json: CanonicalJsonValue = json.into();
159		Self::from_value(json)
160	}
161
162	pub fn from_value(json: CanonicalJsonValue) -> Result<Self> {
163		serde_json::from_value(json.into()).map_err(Into::into)
164	}
165
166	pub fn from_raw_json(json: &RawJsonValue) -> Result<Self> {
167		Self::deserialize(json).map_err(Into::into)
168	}
169}
170
171impl Event for Pdu
172where
173	Self: Send + Sync + 'static,
174{
175	#[inline]
176	fn auth_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
177		self.auth_events.iter().map(AsRef::as_ref)
178	}
179
180	#[inline]
181	fn auth_events_into(
182		self,
183	) -> impl IntoIterator<IntoIter = impl Iterator<Item = OwnedEventId>> + Send {
184		self.auth_events.into_iter()
185	}
186
187	#[inline]
188	fn content(&self) -> &RawJsonValue { self.content.json() }
189
190	#[inline]
191	fn event_id(&self) -> &EventId { &self.event_id }
192
193	#[inline]
194	fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
195		MilliSecondsSinceUnixEpoch(self.origin_server_ts)
196	}
197
198	#[inline]
199	fn prev_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
200		self.prev_events.iter().map(AsRef::as_ref)
201	}
202
203	#[inline]
204	fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() }
205
206	#[cfg(test)]
207	#[inline]
208	fn rejected(&self) -> bool { self.rejected }
209
210	#[cfg(not(test))]
211	#[inline]
212	fn rejected(&self) -> bool { false }
213
214	#[inline]
215	fn room_id(&self) -> &RoomId { &self.room_id }
216
217	#[inline]
218	fn sender(&self) -> &UserId { &self.sender }
219
220	#[inline]
221	fn state_key(&self) -> Option<&str> { self.state_key.as_deref() }
222
223	#[inline]
224	fn kind(&self) -> &TimelineEventType { &self.kind }
225
226	#[inline]
227	fn unsigned(&self) -> Option<&RawJsonValue> { self.unsigned.as_ref().map(Unsigned::json) }
228
229	#[inline]
230	fn as_mut_pdu(&mut self) -> &mut Pdu { self }
231
232	#[inline]
233	fn as_pdu(&self) -> &Pdu { self }
234
235	#[inline]
236	fn into_pdu(self) -> Pdu { self }
237
238	#[inline]
239	fn is_owned(&self) -> bool { true }
240}
241
242impl Event for &Pdu
243where
244	Self: Send,
245{
246	#[inline]
247	fn auth_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
248		self.auth_events.iter().map(AsRef::as_ref)
249	}
250
251	#[inline]
252	fn auth_events_into(
253		self,
254	) -> impl IntoIterator<IntoIter = impl Iterator<Item = OwnedEventId>> + Send {
255		self.auth_events.iter().map(ToOwned::to_owned)
256	}
257
258	#[inline]
259	fn content(&self) -> &RawJsonValue { self.content.json() }
260
261	#[inline]
262	fn event_id(&self) -> &EventId { &self.event_id }
263
264	#[inline]
265	fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
266		MilliSecondsSinceUnixEpoch(self.origin_server_ts)
267	}
268
269	#[inline]
270	fn prev_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
271		self.prev_events.iter().map(AsRef::as_ref)
272	}
273
274	#[inline]
275	fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() }
276
277	#[cfg(test)]
278	#[inline]
279	fn rejected(&self) -> bool { self.rejected }
280
281	#[cfg(not(test))]
282	#[inline]
283	fn rejected(&self) -> bool { false }
284
285	#[inline]
286	fn room_id(&self) -> &RoomId { &self.room_id }
287
288	#[inline]
289	fn sender(&self) -> &UserId { &self.sender }
290
291	#[inline]
292	fn state_key(&self) -> Option<&str> { self.state_key.as_deref() }
293
294	#[inline]
295	fn kind(&self) -> &TimelineEventType { &self.kind }
296
297	#[inline]
298	fn unsigned(&self) -> Option<&RawJsonValue> { self.unsigned.as_ref().map(Unsigned::json) }
299
300	#[inline]
301	fn as_pdu(&self) -> &Pdu { self }
302
303	#[inline]
304	fn into_pdu(self) -> Pdu { self.clone() }
305
306	#[inline]
307	fn is_owned(&self) -> bool { false }
308}
309
310/// Prevent derived equality which wouldn't limit itself to event_id
311impl Eq for Pdu {}
312
313/// Equality determined by the Pdu's ID, not the memory representations.
314impl PartialEq for Pdu {
315	fn eq(&self, other: &Self) -> bool { self.event_id == other.event_id }
316}
317
318/// Ordering determined by the Pdu's ID, not the memory representations.
319impl Ord for Pdu {
320	fn cmp(&self, other: &Self) -> Ordering { self.event_id.cmp(&other.event_id) }
321}
322
323/// Ordering determined by the Pdu's ID, not the memory representations.
324impl PartialOrd for Pdu {
325	fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
326}