1mod builder;
8mod count;
9mod format;
10mod hashes;
11mod id;
12mod raw_id;
13#[cfg(test)]
14mod tests;
15mod unsigned;
16
17use std::cmp::Ordering;
18
19use ruma::{
20 CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId,
21 OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, UInt, UserId,
22 canonical_json::redact_in_place,
23 events::TimelineEventType,
24 room_version_rules::{RedactionRules, RoomVersionRules},
25 serde::Raw,
26};
27use serde::{Deserialize, Serialize};
28use serde_json::value::RawValue as RawJsonValue;
29use smallvec::SmallVec;
30use tuwunel_core::{Err, Result, err};
31
32pub use self::{
33 Count as PduCount, Id as PduId, Pdu as PduEvent, RawId as RawPduId,
34 builder::{Builder, Builder as PduBuilder},
35 count::Count,
36 format::{
37 check::{check_room_id, check_rules},
38 from_incoming_federation, into_outgoing_federation,
39 },
40 hashes::EventHashes as EventHash,
41 id::Id,
42 raw_id::*,
43 unsigned::{DELAY_ID, PRIVATE as PRIVATE_UNSIGNED},
44};
45use super::{Event, ShortRoomId, StateKey};
46
47#[derive(Clone, Deserialize, Serialize, Debug)]
53pub struct Pdu {
54 #[serde(rename = "type")]
58 pub kind: TimelineEventType,
59
60 pub content: Content,
64
65 pub event_id: OwnedEventId,
70
71 pub room_id: OwnedRoomId,
76
77 pub sender: OwnedUserId,
82
83 #[serde(skip_serializing_if = "Option::is_none")]
88 pub state_key: Option<StateKey>,
89
90 #[serde(skip_serializing_if = "Option::is_none")]
95 pub redacts: Option<OwnedEventId>,
96
97 pub prev_events: PrevEvents,
101
102 pub auth_events: AuthEvents,
107
108 pub origin_server_ts: UInt,
112
113 pub depth: UInt,
118
119 pub hashes: EventHash,
124
125 #[serde(skip_serializing_if = "Option::is_none")]
130 pub origin: Option<OwnedServerName>,
131
132 #[serde(default, skip_serializing_if = "Option::is_none")]
137 pub unsigned: Option<Unsigned>,
138
139 #[cfg(test)]
144 #[serde(default, skip_serializing)]
145 pub rejected: bool,
146}
147
148pub type PrevEvents = SmallVec<[OwnedEventId; 1]>;
153
154pub type AuthEvents = SmallVec<[OwnedEventId; 3]>;
159
160pub type Content = Raw<CanonicalJsonObject, 112>;
165
166pub type Unsigned = Raw<CanonicalJsonObject, 112>;
173
174pub const MAX_PDU_BYTES: usize = 65_535;
177
178pub use tuwunel_core::matrix::MAX_PREV_EVENTS;
179
180pub const MAX_AUTH_EVENTS: usize = 10;
183
184impl Pdu {
185 pub fn from_object_and_roomid_and_eventid(
190 room_id: &RoomId,
191 event_id: &EventId,
192 mut json: CanonicalJsonObject,
193 ) -> Result<Self> {
194 let room_id = CanonicalJsonValue::String(room_id.into());
195 json.insert("room_id".into(), room_id);
196 Self::from_object_and_eventid(event_id, json)
197 }
198
199 pub fn from_object_and_eventid(
204 event_id: &EventId,
205 mut json: CanonicalJsonObject,
206 ) -> Result<Self> {
207 let event_id = CanonicalJsonValue::String(event_id.into());
208 json.insert("event_id".into(), event_id);
209 Self::from_object(json)
210 }
211
212 pub fn from_object_federation(
223 room_id: &RoomId,
224 event_id: &EventId,
225 json: CanonicalJsonObject,
226 rules: &RoomVersionRules,
227 ) -> Result<(Self, CanonicalJsonObject)> {
228 let json = from_incoming_federation(room_id, event_id, json, rules);
229 let pdu = Self::from_object_checked(json.clone(), rules)?;
230 check_room_id(&pdu, room_id)?;
231
232 if rules
233 .authorization
234 .room_create_event_id_as_room_id
235 && pdu.kind == TimelineEventType::RoomCreate
236 && room_id.as_event_id().ok().as_deref() != Some(event_id)
237 {
238 return Err!(Request(InvalidParam(
239 "Create event {event_id} is not the create event of {room_id}"
240 )));
241 }
242
243 Ok((pdu, json))
244 }
245
246 pub fn from_object_checked(
251 json: CanonicalJsonObject,
252 rules: &RoomVersionRules,
253 ) -> Result<Self> {
254 check_rules(&json, &rules.event_format)?;
255 Self::from_object(json)
256 }
257
258 pub fn from_object(json: CanonicalJsonObject) -> Result<Self> {
263 let json = CanonicalJsonValue::Object(json);
264 Self::from_value(json)
265 }
266
267 pub fn from_raw_value(json: &RawJsonValue) -> Result<Self> {
278 let json: CanonicalJsonValue = json.into();
279 Self::from_value(json)
280 }
281
282 pub fn from_value(json: CanonicalJsonValue) -> Result<Self> {
287 serde_json::from_value(json.into()).map_err(Into::into)
288 }
289
290 pub fn from_raw_json(json: &RawJsonValue) -> Result<Self> {
296 Self::deserialize(json).map_err(Into::into)
297 }
298
299 pub fn redacted(&self, rules: &RedactionRules) -> Result<Self> {
303 let mut object = self.to_canonical_object();
304
305 redact_in_place(&mut object, rules, None)
306 .map_err(|e| err!("Failed to redact event: {e}"))?;
307
308 Self::from_object(object)
309 }
310}
311
312impl Event for Pdu
313where
314 Self: Send + Sync + 'static,
315{
316 #[inline]
317 fn auth_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
318 self.auth_events.iter().map(AsRef::as_ref)
319 }
320
321 #[inline]
322 fn auth_events_into(
323 self,
324 ) -> impl IntoIterator<IntoIter = impl Iterator<Item = OwnedEventId>> + Send {
325 self.auth_events.into_iter()
326 }
327
328 #[inline]
329 fn content(&self) -> &RawJsonValue { self.content.json() }
330
331 #[inline]
332 fn event_id(&self) -> &EventId { &self.event_id }
333
334 #[inline]
335 fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
336 MilliSecondsSinceUnixEpoch(self.origin_server_ts)
337 }
338
339 #[inline]
340 fn prev_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
341 self.prev_events.iter().map(AsRef::as_ref)
342 }
343
344 #[inline]
345 fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() }
346
347 #[cfg(test)]
348 #[inline]
349 fn rejected(&self) -> bool { self.rejected }
350
351 #[cfg(not(test))]
352 #[inline]
353 fn rejected(&self) -> bool { false }
354
355 #[inline]
356 fn room_id(&self) -> &RoomId { &self.room_id }
357
358 #[inline]
359 fn sender(&self) -> &UserId { &self.sender }
360
361 #[inline]
362 fn state_key(&self) -> Option<&str> { self.state_key.as_deref() }
363
364 #[inline]
365 fn kind(&self) -> &TimelineEventType { &self.kind }
366
367 #[inline]
368 fn unsigned(&self) -> Option<&RawJsonValue> { self.unsigned.as_ref().map(Unsigned::json) }
369
370 #[inline]
371 fn as_mut_pdu(&mut self) -> &mut Pdu { self }
372
373 #[inline]
374 fn as_pdu(&self) -> &Pdu { self }
375
376 #[inline]
377 fn into_pdu(self) -> Pdu { self }
378
379 #[inline]
380 fn is_owned(&self) -> bool { true }
381}
382
383impl Event for &Pdu
384where
385 Self: Send,
386{
387 #[inline]
388 fn auth_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
389 self.auth_events.iter().map(AsRef::as_ref)
390 }
391
392 #[inline]
393 fn auth_events_into(
394 self,
395 ) -> impl IntoIterator<IntoIter = impl Iterator<Item = OwnedEventId>> + Send {
396 self.auth_events.iter().map(ToOwned::to_owned)
397 }
398
399 #[inline]
400 fn content(&self) -> &RawJsonValue { self.content.json() }
401
402 #[inline]
403 fn event_id(&self) -> &EventId { &self.event_id }
404
405 #[inline]
406 fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
407 MilliSecondsSinceUnixEpoch(self.origin_server_ts)
408 }
409
410 #[inline]
411 fn prev_events(&self) -> impl DoubleEndedIterator<Item = &EventId> + Clone + Send + '_ {
412 self.prev_events.iter().map(AsRef::as_ref)
413 }
414
415 #[inline]
416 fn redacts(&self) -> Option<&EventId> { self.redacts.as_deref() }
417
418 #[cfg(test)]
419 #[inline]
420 fn rejected(&self) -> bool { self.rejected }
421
422 #[cfg(not(test))]
423 #[inline]
424 fn rejected(&self) -> bool { false }
425
426 #[inline]
427 fn room_id(&self) -> &RoomId { &self.room_id }
428
429 #[inline]
430 fn sender(&self) -> &UserId { &self.sender }
431
432 #[inline]
433 fn state_key(&self) -> Option<&str> { self.state_key.as_deref() }
434
435 #[inline]
436 fn kind(&self) -> &TimelineEventType { &self.kind }
437
438 #[inline]
439 fn unsigned(&self) -> Option<&RawJsonValue> { self.unsigned.as_ref().map(Unsigned::json) }
440
441 #[inline]
442 fn as_pdu(&self) -> &Pdu { self }
443
444 #[inline]
445 fn into_pdu(self) -> Pdu { self.clone() }
446
447 #[inline]
448 fn is_owned(&self) -> bool { false }
449}
450
451impl Eq for Pdu {}
453
454impl PartialEq for Pdu {
456 fn eq(&self, other: &Self) -> bool { self.event_id == other.event_id }
457}
458
459impl Ord for Pdu {
461 fn cmp(&self, other: &Self) -> Ordering { self.event_id.cmp(&other.event_id) }
462}
463
464impl PartialOrd for Pdu {
466 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
467}