1#[cfg_attr(feature = "std", allow(unused_imports))]
17use alloc::{format, vec, vec::Vec};
18
19use serde::{ser::SerializeMap, Serialize, Serializer};
20
21use crate::{AttachmentKind, Context, Frame, FrameKind, Report};
22
23struct SerializeAttachment<'a>(&'a Frame);
24
25impl<'a> Serialize for SerializeAttachment<'a> {
26 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
27 where
28 S: Serializer,
29 {
30 let Self(frame) = self;
31
32 #[allow(clippy::match_same_arms)]
33 match frame.kind() {
34 FrameKind::Context(_) => {
35 unimplemented!()
38 }
39 FrameKind::Attachment(AttachmentKind::Opaque(_)) => {
40 unimplemented!()
43 }
44 FrameKind::Attachment(AttachmentKind::Printable(attachment)) => {
45 format!("{attachment}").serialize(serializer)
46 }
47 }
48 }
49}
50
51struct SerializeAttachmentList<'a, 'b>(&'a [&'b Frame]);
52
53impl<'a, 'b> Serialize for SerializeAttachmentList<'a, 'b> {
54 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: Serializer,
57 {
58 serializer.collect_seq(
59 self.0
60 .iter()
61 .copied()
62 .filter(|attachment| {
63 !matches!(
65 attachment.kind(),
66 FrameKind::Attachment(AttachmentKind::Opaque(_))
67 )
68 })
69 .map(SerializeAttachment),
70 )
71 }
72}
73
74struct SerializeContext<'a> {
75 attachments: Vec<&'a Frame>,
76 context: &'a dyn Context,
77 sources: &'a [Frame],
78}
79
80impl<'a> Serialize for SerializeContext<'a> {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: Serializer,
84 {
85 let Self {
86 context,
87 attachments,
88 sources,
89 } = self;
90
91 let mut map = serializer.serialize_map(Some(3))?;
92 map.serialize_entry("context", &format!("{context}").as_str())?;
93 map.serialize_entry("attachments", &SerializeAttachmentList(attachments))?;
94 map.serialize_entry("sources", &SerializeSources(sources))?;
95
96 map.end()
97 }
98}
99
100struct SerializeSources<'a>(&'a [Frame]);
101
102impl<'a> Serialize for SerializeSources<'a> {
103 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104 where
105 S: Serializer,
106 {
107 serializer.collect_seq(self.0.iter().flat_map(|source| find_next(&[], source)))
108 }
109}
110
111fn find_next<'a>(head: &[&'a Frame], mut current: &'a Frame) -> Vec<SerializeContext<'a>> {
113 let mut attachments = vec![];
114 attachments.extend(head);
115
116 loop {
117 if let FrameKind::Context(context) = current.kind() {
118 attachments.reverse();
120
121 return vec![SerializeContext {
122 attachments,
123 context,
124 sources: current.sources(),
125 }];
126 } else if current.sources().len() > 1 {
127 attachments.push(current);
129
130 return current
131 .sources()
132 .iter()
133 .flat_map(|source| find_next(&attachments, source))
134 .collect();
135 } else if current.sources().len() == 1 {
136 attachments.push(current);
137
138 current = ¤t.sources()[0];
139 } else {
140 return vec![];
143 }
144 }
145}
146
147impl<C: Context> Serialize for Report<C> {
148 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
149 where
150 S: Serializer,
151 {
152 SerializeSources(self.current_frames()).serialize(serializer)
153 }
154}