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