1use std::{
2 borrow::Cow,
3 collections::{BTreeMap, btree_map::Entry},
4 fmt::{Formatter, Result as FmtResult},
5 iter::from_fn,
6};
7
8use ruma::{
9 MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId, UserId,
10 events::{AnySyncMessageLikeEvent, room::member::MembershipState},
11 serde::Raw,
12};
13use serde::{
14 Deserialize, Deserializer, Serialize, Serializer,
15 de::{DeserializeSeed, Error as DeError, IgnoredAny, MapAccess, Visitor},
16 ser::SerializeMap,
17};
18use serde_json::value::{RawValue as RawJsonValue, Value as JsonValue, to_raw_value};
19use tuwunel_core::{Result, err, implement, result::LogErr, utils::BoolExt, warn};
20
21use super::{Pdu, Unsigned};
22
23pub const DELAY_ID: &str = "org.matrix.msc4140.delay_id";
28
29pub const PRIVATE: [&str; 2] = ["transaction_id", DELAY_ID];
34
35type BorrowedObject<'a> = BTreeMap<Cow<'a, str>, &'a RawJsonValue>;
36type JsonEntry<'a> = (JsonString<'a>, &'a RawJsonValue);
37
38struct RelationBundle<'a> {
39 unsigned: BorrowedObject<'a>,
40 relations: BorrowedObject<'a>,
41}
42
43struct ThreadBundleFields<'a> {
44 unsigned: BorrowedObject<'a>,
45 relations: BorrowedObject<'a>,
46 thread: BorrowedObject<'a>,
47 latest_event: BorrowedObject<'a>,
48 latest_event_unsigned: BorrowedObject<'a>,
49}
50
51struct RawObjectPatch<'a, 'raw, T> {
52 object: &'a BorrowedObject<'raw>,
53 field: &'static str,
54 value: T,
55}
56
57struct RawObjectRemove<'a, 'raw> {
58 object: &'a BorrowedObject<'raw>,
59 field: &'a str,
60}
61
62struct BorrowedField<'a>(&'a str);
63
64struct UniqueObject;
65
66struct JsonString<'a>(Cow<'a, str>);
67
68struct JsonStringVisitor;
69
70#[derive(Serialize)]
71struct ReferenceBundle<'a> {
72 chunk: ReferenceChunk<'a>,
73}
74
75struct ReferenceChunk<'a>(&'a [OwnedEventId]);
76
77#[derive(Serialize)]
78struct ReferenceEvent<'a> {
79 event_id: &'a OwnedEventId,
80}
81
82#[derive(Deserialize)]
83struct Identity {
84 event_id: OwnedEventId,
85 sender: OwnedUserId,
86}
87
88#[implement(Pdu)]
93#[must_use]
94pub fn without_private_unless_sender(mut self, user_id: Option<&UserId>) -> Self {
95 self.remove_private_unless_sender(user_id);
96
97 self
98}
99
100#[implement(Pdu)]
105#[inline]
106#[must_use]
107pub fn served_to(mut self, user_id: Option<&UserId>) -> Self {
108 self.remove_private_unless_sender(user_id);
109 self.add_age().log_err().ok();
110
111 self
112}
113
114#[implement(Pdu)]
121pub fn remove_private_unless_sender(&mut self, user_id: Option<&UserId>) {
122 if user_id.is_none_or(|user_id| self.sender != *user_id) {
123 self.remove_private();
124 }
125}
126
127#[implement(Pdu)]
134pub fn remove_private(&mut self) {
135 let Some(unsigned) = &self.unsigned else {
136 return;
137 };
138
139 let raw = unsigned.json().get();
140
141 if !PRIVATE.iter().any(|key| raw.contains(key)) {
142 return;
143 }
144
145 self.unsigned = without_private(raw)
146 .inspect_err(|error| {
147 warn!(event_id = %self.event_id, %error, "Omitting unreadable unsigned data.");
150 })
151 .ok();
152}
153
154fn without_private(raw: &str) -> Result<Unsigned> {
155 let mut unsigned: BTreeMap<&str, &RawJsonValue> = serde_json::from_str(raw)?;
156
157 unsigned.retain(|key, _| !PRIVATE.contains(key));
158
159 raw_as(&unsigned)
160}
161
162#[implement(Pdu)]
166pub fn remove_prev_state(&mut self) -> Result {
167 use BTreeMap as Map;
168
169 let Some(unsigned) = &self.unsigned else {
170 return Ok(());
171 };
172
173 let raw = unsigned.json().get();
174 let prev_keys = raw.contains("\"prev_content\"") || raw.contains("\"prev_sender\"");
175 if !prev_keys && raw != "{}" {
176 return Ok(());
177 }
178
179 let mut unsigned: Map<&str, Raw<JsonValue>> = serde_json::from_str(raw)
180 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
181
182 unsigned.remove("prev_content");
183 unsigned.remove("prev_sender");
184 self.unsigned = unsigned
185 .is_empty()
186 .is_false()
187 .then(|| to_raw_value(&unsigned))
188 .transpose()?
189 .map(Into::into);
190
191 Ok(())
192}
193
194#[implement(Pdu)]
200pub fn add_age(&mut self) -> Result {
201 use BTreeMap as Map;
202
203 let mut unsigned: Map<&str, Raw<JsonValue>> = self
204 .unsigned
205 .as_ref()
206 .map(Unsigned::json)
207 .map(RawJsonValue::get)
208 .map_or_else(|| Ok(Map::new()), serde_json::from_str)
209 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
210
211 let now: i128 = MilliSecondsSinceUnixEpoch::now().get().into();
213 let then: i128 = self.origin_server_ts.into();
214 let this_age = now.saturating_sub(then);
215
216 unsigned.insert("age", raw_of(&this_age)?);
217 self.unsigned = Some(to_raw_value(&unsigned)?.into());
218
219 Ok(())
220}
221
222#[implement(Pdu)]
225pub fn add_membership(&mut self, membership: &MembershipState) -> Result {
226 use BTreeMap as Map;
227
228 let mut unsigned: Map<&str, Raw<JsonValue>> = self
229 .unsigned
230 .as_ref()
231 .map(Unsigned::json)
232 .map(RawJsonValue::get)
233 .map_or_else(|| Ok(Map::new()), serde_json::from_str)
234 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
235
236 unsigned.insert("membership", raw_of(membership)?);
237 self.unsigned = Some(to_raw_value(&unsigned)?.into());
238
239 Ok(())
240}
241
242#[implement(Pdu)]
248pub fn add_relation(&mut self, name: &str, pdu: Option<&Pdu>) -> Result {
249 use serde_json::Map;
250
251 let mut unsigned: Map<String, JsonValue> = self
252 .unsigned
253 .as_ref()
254 .map(Unsigned::json)
255 .map(RawJsonValue::get)
256 .map_or_else(|| Ok(Map::new()), serde_json::from_str)
257 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
258
259 let pdu = pdu
260 .map(serde_json::to_value)
261 .transpose()?
262 .unwrap_or_else(|| JsonValue::Object(Map::new()));
263
264 unsigned
265 .entry("m.relations")
266 .or_insert(JsonValue::Object(Map::new()))
267 .as_object_mut()
268 .map(|object| object.insert(name.to_owned(), pdu));
269
270 self.unsigned = Some(to_raw_value(&unsigned)?.into());
271
272 Ok(())
273}
274
275#[implement(Pdu)]
278pub fn set_thread_participated(&mut self, participated: bool) -> Result {
279 use serde_json::Map;
280
281 let Some(unsigned) = self.unsigned.as_ref() else {
282 return Ok(());
283 };
284
285 let mut unsigned: Map<String, JsonValue> = serde_json::from_str(unsigned.json().get())
286 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
287
288 let updated = unsigned
289 .get_mut("m.relations")
290 .and_then(JsonValue::as_object_mut)
291 .and_then(|relations| relations.get_mut("m.thread"))
292 .and_then(JsonValue::as_object_mut)
293 .map(|thread| {
294 thread.insert("current_user_participated".to_owned(), participated.into());
295 })
296 .is_some();
297
298 if updated {
299 self.unsigned = Some(to_raw_value(&unsigned)?.into());
300 }
301
302 Ok(())
303}
304
305#[implement(Pdu)]
310#[inline]
311pub fn thread_latest_event(&self) -> Result<Option<(OwnedEventId, OwnedUserId)>> {
312 self.unsigned
313 .as_ref()
314 .map(Unsigned::json)
315 .map(thread_latest)
316 .transpose()?
317 .flatten()
318 .map(thread_identity)
319 .transpose()
320}
321
322#[implement(Pdu)]
327pub fn has_thread_bundle(&self) -> Result<bool> {
328 self.unsigned
329 .as_ref()
330 .map(Unsigned::json)
331 .map(thread_bundle)
332 .transpose()
333 .map(|thread| thread.flatten().is_some())
334}
335
336#[implement(Pdu)]
340pub fn set_thread_latest_event(&mut self, latest: &Raw<AnySyncMessageLikeEvent>) -> Result {
341 use serde_json::Map;
342
343 let Some(unsigned) = self.unsigned.as_ref() else {
344 return Ok(());
345 };
346
347 let latest = serde_json::to_value(latest)?;
348
349 let mut unsigned: Map<String, JsonValue> = serde_json::from_str(unsigned.json().get())
350 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
351
352 let updated = unsigned
353 .get_mut("m.relations")
354 .and_then(JsonValue::as_object_mut)
355 .and_then(|relations| relations.get_mut("m.thread"))
356 .and_then(JsonValue::as_object_mut)
357 .map(|thread| {
358 thread.insert("latest_event".to_owned(), latest);
359 })
360 .is_some();
361
362 if updated {
363 self.unsigned = Some(to_raw_value(&unsigned)?.into());
364 }
365
366 Ok(())
367}
368
369#[implement(Pdu)]
375pub fn remove_thread_latest_transaction_id_unless_sender(&mut self, user_id: &UserId) -> Result {
376 if let Some(unsigned) = self
377 .unsigned
378 .as_ref()
379 .map(Unsigned::json)
380 .map(|raw| thread_without_transaction_id(raw, user_id))
381 .transpose()?
382 .flatten()
383 {
384 self.unsigned = Some(unsigned);
385 }
386
387 Ok(())
388}
389
390fn thread_without_transaction_id(
391 raw: &RawJsonValue,
392 user_id: &UserId,
393) -> Result<Option<Unsigned>> {
394 thread_transaction_sender(raw)?
395 .map(|sender| serde_json::from_str(sender.get()))
396 .transpose()
397 .map_err(|error| err!(Database("Invalid sender in thread latest event: {error}")))?
398 .filter(|JsonString(sender)| sender != user_id.as_str())
399 .map(|JsonString(sender)| {
400 UserId::parse(sender.as_ref())
401 .map_err(|error| err!(Database("Invalid sender in thread latest event: {error}")))
402 .and_then(|_| ThreadBundleFields::parse(raw)?.without_transaction_id())
403 })
404 .transpose()
405}
406
407fn thread_transaction_sender(raw: &RawJsonValue) -> Result<Option<&RawJsonValue>> {
408 thread_latest(raw)?
409 .map(transaction_sender)
410 .transpose()
411 .map(Option::flatten)
412}
413
414fn transaction_sender(latest_event: &RawJsonValue) -> Result<Option<&RawJsonValue>> {
415 let sender = || {
416 raw_field(latest_event, "sender", "thread latest event")?.ok_or_else(|| {
417 err!(Database("Thread latest event with transaction ID has no sender"))
418 })
419 };
420
421 raw_field(latest_event, "unsigned", "thread latest event")?
422 .map(|unsigned| raw_field(unsigned, "transaction_id", "thread latest event unsigned"))
423 .transpose()?
424 .flatten()
425 .map(|_| sender())
426 .transpose()
427}
428
429fn thread_latest(raw: &RawJsonValue) -> Result<Option<&RawJsonValue>> {
430 thread_bundle(raw)?
431 .map(|thread| raw_field(thread, "latest_event", "thread bundle"))
432 .transpose()
433 .map(Option::flatten)
434}
435
436fn thread_bundle(raw: &RawJsonValue) -> Result<Option<&RawJsonValue>> {
437 raw_field(raw, "m.relations", "unsigned")?
438 .map(|relations| raw_field(relations, "m.thread", "bundled relations"))
439 .transpose()
440 .map(Option::flatten)
441}
442
443fn thread_identity(raw: &RawJsonValue) -> Result<(OwnedEventId, OwnedUserId)> {
444 serde_json::from_str(raw.get())
445 .map(|Identity { event_id, sender }| (event_id, sender))
446 .map_err(|error| err!(Database("Invalid thread latest event in PDU event: {error}")))
447}
448
449#[implement(Pdu)]
453pub fn remove_thread_bundle(&mut self) -> Result {
454 remove_relation_bundle(self, "m.thread")
455 .or_else(|_| remove_relation_bundle_canonical(self, "m.thread"))
456}
457
458fn remove_relation_bundle_canonical(pdu: &mut Pdu, relation_type: &str) -> Result {
462 let Some(raw) = pdu.unsigned.as_ref() else {
463 return Ok(());
464 };
465
466 let mut unsigned: JsonValue = serde_json::from_str(raw.json().get())?;
467 let unsigned = unsigned
468 .as_object_mut()
469 .ok_or_else(|| err!(Database("Invalid unsigned object in PDU event")))?;
470
471 let remove_relations = match unsigned.get_mut("m.relations") {
472 | None => return Ok(()),
473 | Some(JsonValue::Object(relations)) => {
474 relations.remove(relation_type);
475 relations.is_empty()
476 },
477 | Some(_) => true,
478 };
479
480 if remove_relations {
481 unsigned.remove("m.relations");
482 }
483
484 pdu.unsigned = if unsigned.is_empty() {
485 None
486 } else {
487 Some(raw_as(unsigned)?)
488 };
489
490 Ok(())
491}
492
493fn remove_relation_bundle(pdu: &mut Pdu, relation_type: &str) -> Result {
494 if let Some(unsigned) = pdu
495 .unsigned
496 .as_ref()
497 .map(Unsigned::json)
498 .map(|raw| RelationBundle::parse(raw, relation_type))
499 .transpose()?
500 .flatten()
501 .map(|bundle| bundle.without(relation_type))
502 .transpose()?
503 {
504 pdu.unsigned = unsigned;
505 }
506
507 Ok(())
508}
509
510#[implement(RelationBundle, generics = "<'a>", params = "<'a>")]
511fn parse(raw: &'a RawJsonValue, relation_type: &str) -> Result<Option<Self>> {
512 let unsigned = raw_object(raw, "unsigned")?;
513
514 unsigned
515 .get("m.relations")
516 .copied()
517 .map(|relations| raw_object(relations, "bundled relations"))
518 .transpose()
519 .map(|relations| {
520 relations
521 .filter(|relations| relations.contains_key(relation_type))
522 .map(|relations| Self { unsigned, relations })
523 })
524}
525
526#[implement(RelationBundle, generics = "<'a>", params = "<'a>")]
527fn without(&self, relation_type: &str) -> Result<Option<Unsigned>> {
528 match self.relations.len() {
529 | 1 => self
530 .unsigned
531 .len()
532 .ne(&1)
533 .then(|| raw_as(&RawObjectRemove::new(&self.unsigned, "m.relations")))
534 .transpose(),
535 | _ => {
536 let relations = RawObjectRemove::new(&self.relations, relation_type);
537 let unsigned = RawObjectPatch::new(&self.unsigned, "m.relations", relations);
538
539 raw_as(&unsigned).map(Some)
540 },
541 }
542}
543
544#[implement(Pdu)]
548pub fn set_thread_count(&mut self, count: usize) -> Result {
549 use serde_json::Map;
550
551 let Some(unsigned) = self.unsigned.as_ref() else {
552 return Ok(());
553 };
554
555 let mut unsigned: Map<String, JsonValue> = serde_json::from_str(unsigned.json().get())
556 .map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
557
558 let updated = unsigned
559 .get_mut("m.relations")
560 .and_then(JsonValue::as_object_mut)
561 .and_then(|relations| relations.get_mut("m.thread"))
562 .and_then(JsonValue::as_object_mut)
563 .map(|thread| {
564 thread.insert("count".to_owned(), count.into());
565 })
566 .is_some();
567
568 if updated {
569 self.unsigned = Some(to_raw_value(&unsigned)?.into());
570 }
571
572 Ok(())
573}
574
575#[implement(Pdu)]
579pub fn set_replacement_bundle(&mut self, replacement: &Raw<AnySyncMessageLikeEvent>) -> Result {
580 use BTreeMap as Map;
581
582 type Object = Map<String, Raw<JsonValue>>;
583
584 let parse = |raw: &RawJsonValue| -> Result<Object> {
585 serde_json::from_str(raw.get())
586 .map_err(|e| err!(Database("Invalid object in pdu unsigned: {e}")))
587 };
588
589 let mut unsigned: Object = self
590 .unsigned
591 .as_ref()
592 .map(|unsigned| parse(unsigned.json()))
593 .transpose()?
594 .unwrap_or_default();
595
596 let mut relations: Object = unsigned
597 .get("m.relations")
598 .map(|relations| parse(relations.json()))
599 .transpose()?
600 .unwrap_or_default();
601
602 relations.insert("m.replace".to_owned(), replacement.cast_ref().clone());
603 unsigned.insert("m.relations".to_owned(), to_raw_value(&relations)?.into());
604 self.unsigned = Some(to_raw_value(&unsigned)?.into());
605
606 Ok(())
607}
608
609#[implement(Pdu)]
613pub fn remove_replacement_bundle(&mut self) -> Result {
614 remove_relation_bundle(self, "m.replace")
615}
616
617#[implement(Pdu)]
622pub fn set_reference_bundle(&mut self, event_ids: &[OwnedEventId]) -> Result {
623 let unsigned = self
624 .unsigned
625 .as_ref()
626 .map(|unsigned| raw_object(unsigned.json(), "unsigned"))
627 .transpose()?
628 .unwrap_or_default();
629
630 let relations = unsigned
631 .get("m.relations")
632 .copied()
633 .map(|relations| raw_object(relations, "bundled relations"))
634 .transpose()?
635 .unwrap_or_default();
636
637 let reference = ReferenceBundle { chunk: ReferenceChunk(event_ids) };
638 let relations = RawObjectPatch::new(&relations, "m.reference", reference);
639 let unsigned = RawObjectPatch::new(&unsigned, "m.relations", relations);
640 self.unsigned = Some(raw_as(&unsigned)?);
641
642 Ok(())
643}
644
645impl<'de> Deserialize<'de> for JsonString<'de> {
646 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
647 where
648 D: Deserializer<'de>,
649 {
650 deserializer.deserialize_str(JsonStringVisitor)
651 }
652}
653
654impl<'de> Visitor<'de> for JsonStringVisitor {
655 type Value = JsonString<'de>;
656
657 fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
658 formatter.write_str("a JSON string")
659 }
660
661 fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E> {
662 Ok(JsonString(Cow::Borrowed(value)))
663 }
664
665 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
666 where
667 E: DeError,
668 {
669 Ok(JsonString(Cow::Owned(value.to_owned())))
670 }
671
672 fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
673 Ok(JsonString(Cow::Owned(value)))
674 }
675}
676
677impl<'de> DeserializeSeed<'de> for BorrowedField<'_> {
678 type Value = Option<&'de RawJsonValue>;
679
680 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
681 where
682 D: Deserializer<'de>,
683 {
684 deserializer.deserialize_map(self)
685 }
686}
687
688impl<'de> Visitor<'de> for BorrowedField<'_> {
689 type Value = Option<&'de RawJsonValue>;
690
691 fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
692 write!(formatter, "an object containing {}", self.0)
693 }
694
695 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
696 where
697 A: MapAccess<'de>,
698 {
699 let mut value = None; while let Some(JsonString(field)) = map.next_key()? {
702 value = match field.as_ref() {
703 | field if field != self.0 => map.next_value().map(|_: IgnoredAny| value),
704 | _ if value.is_some() =>
705 Err(A::Error::custom(format_args!("duplicate field `{field}`"))),
706 | _ => map.next_value().map(Some),
707 }?;
708 }
709
710 Ok(value)
711 }
712}
713
714impl<'de> DeserializeSeed<'de> for UniqueObject {
715 type Value = BorrowedObject<'de>;
716
717 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
718 where
719 D: Deserializer<'de>,
720 {
721 deserializer.deserialize_map(self)
722 }
723}
724
725impl<'de> Visitor<'de> for UniqueObject {
726 type Value = BorrowedObject<'de>;
727
728 fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
729 formatter.write_str("an object without duplicate fields")
730 }
731
732 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
733 where
734 A: MapAccess<'de>,
735 {
736 from_fn(|| map.next_entry().transpose()).try_fold(
737 BorrowedObject::new(),
738 |mut object, entry: Result<JsonEntry<'de>, A::Error>| {
739 let (JsonString(field), value) = entry?;
740
741 match object.entry(field) {
742 | Entry::Occupied(entry) =>
743 Err(A::Error::custom(format_args!("duplicate field `{}`", entry.key()))),
744 | Entry::Vacant(entry) => {
745 entry.insert(value);
746
747 Ok(object)
748 },
749 }
750 },
751 )
752 }
753}
754
755#[implement(ThreadBundleFields, generics = "<'a>", params = "<'a>")]
756fn parse(raw: &'a RawJsonValue) -> Result<Self> {
757 let child = |object: &BorrowedObject<'a>, field, name| {
758 object
759 .get(field)
760 .ok_or_else(|| {
761 err!(Database("Thread transaction probe disagreed with bundle parser"))
762 })
763 .and_then(|raw| raw_object(raw, name))
764 };
765
766 let unsigned = raw_object(raw, "unsigned")?;
767 let relations = child(&unsigned, "m.relations", "bundled relations")?;
768 let thread = child(&relations, "m.thread", "thread bundle")?;
769 let latest_event = child(&thread, "latest_event", "thread latest event")?;
770 let latest_event_unsigned = child(&latest_event, "unsigned", "thread latest event unsigned")?;
771
772 Ok(Self {
773 unsigned,
774 relations,
775 thread,
776 latest_event,
777 latest_event_unsigned,
778 })
779}
780
781#[implement(ThreadBundleFields, generics = "<'a>", params = "<'a>")]
782fn without_transaction_id<U, const N: usize>(&self) -> Result<Raw<U, N>> {
783 let latest_event_unsigned =
784 RawObjectRemove::new(&self.latest_event_unsigned, "transaction_id");
785
786 let latest_event = RawObjectPatch::new(&self.latest_event, "unsigned", latest_event_unsigned);
787 let thread = RawObjectPatch::new(&self.thread, "latest_event", latest_event);
788 let relations = RawObjectPatch::new(&self.relations, "m.thread", thread);
789 let unsigned = RawObjectPatch::new(&self.unsigned, "m.relations", relations);
790
791 raw_as(&unsigned)
792}
793
794impl<'a, 'raw, T> RawObjectPatch<'a, 'raw, T> {
795 fn new(object: &'a BorrowedObject<'raw>, field: &'static str, value: T) -> Self {
796 Self { object, field, value }
797 }
798}
799
800impl<T: Serialize> Serialize for RawObjectPatch<'_, '_, T> {
801 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
802 where
803 S: Serializer,
804 {
805 let present = self.object.contains_key(self.field);
806 let len = self
807 .object
808 .len()
809 .saturating_add(usize::from(!present));
810
811 let map = self.object.iter().try_fold(
812 serializer.serialize_map(Some(len))?,
813 |mut map, (field, value)| {
814 match field.as_ref() == self.field {
815 | true => map.serialize_entry(field, &self.value),
816 | false => map.serialize_entry(field, value),
817 }?;
818
819 Ok(map)
820 },
821 )?;
822
823 present
824 .is_false()
825 .then_some(self.field)
826 .into_iter()
827 .try_fold(map, |mut map, field| {
828 map.serialize_entry(field, &self.value)?;
829
830 Ok(map)
831 })
832 .and_then(SerializeMap::end)
833 }
834}
835
836impl<'a, 'raw> RawObjectRemove<'a, 'raw> {
837 fn new(object: &'a BorrowedObject<'raw>, field: &'a str) -> Self { Self { object, field } }
838}
839
840impl Serialize for RawObjectRemove<'_, '_> {
841 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
842 where
843 S: Serializer,
844 {
845 self.object
846 .iter()
847 .filter(|(field, _)| field.as_ref() != self.field)
848 .try_fold(
849 serializer.serialize_map(Some(self.object.len().saturating_sub(1)))?,
850 |mut map, (field, value)| {
851 map.serialize_entry(field, value)?;
852
853 Ok(map)
854 },
855 )
856 .and_then(SerializeMap::end)
857 }
858}
859
860impl Serialize for ReferenceChunk<'_> {
861 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
862 where
863 S: Serializer,
864 {
865 serializer.collect_seq(
866 self.0
867 .iter()
868 .map(|event_id| ReferenceEvent { event_id }),
869 )
870 }
871}
872
873fn raw_object<'a>(raw: &'a RawJsonValue, name: &str) -> Result<BorrowedObject<'a>> {
874 deserialize_raw(raw, UniqueObject, name)
875}
876
877fn raw_field<'a>(
878 raw: &'a RawJsonValue,
879 field: &str,
880 name: &str,
881) -> Result<Option<&'a RawJsonValue>> {
882 deserialize_raw(raw, BorrowedField(field), name)
883}
884
885fn deserialize_raw<'a, D>(raw: &'a RawJsonValue, seed: D, name: &str) -> Result<D::Value>
886where
887 D: DeserializeSeed<'a>,
888{
889 let mut deserializer = serde_json::Deserializer::from_str(raw.get());
890
891 seed.deserialize(&mut deserializer)
892 .and_then(|value| deserializer.end().map(|()| value))
893 .map_err(|error| err!(Database("Invalid {name} object in PDU event: {error}")))
894}
895
896#[inline]
901fn raw_as<T, U, const N: usize>(value: &T) -> Result<Raw<U, N>>
902where
903 T: Serialize,
904{
905 Raw::<T, N>::new(value)
906 .map(|raw| raw.cast_ref_unchecked::<U>().clone())
907 .map_err(Into::into)
908}
909
910#[inline]
911fn raw_of<T: Serialize>(value: &T) -> Result<Raw<JsonValue>> { raw_as(value) }