1use alloc::{format, vec, vec::Vec};
17use core::error::Error;
18
19use serde_core::{Serialize, Serializer, ser::SerializeMap as _};
20
21use crate::{AttachmentKind, Frame, FrameKind, Report};
22
23struct SerializeAttachment<'a>(&'a Frame);
24
25impl Serialize for SerializeAttachment<'_> {
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 match frame.kind() {
33 FrameKind::Context(_) => {
34 unimplemented!()
37 }
38 FrameKind::Attachment(AttachmentKind::Opaque(_)) => {
39 unimplemented!()
42 }
43 FrameKind::Attachment(AttachmentKind::Printable(attachment)) => {
44 format!("{attachment}").serialize(serializer)
45 }
46 }
47 }
48}
49
50struct SerializeAttachmentList<'a, 'b>(&'a [&'b Frame]);
51
52impl Serialize for SerializeAttachmentList<'_, '_> {
53 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
54 where
55 S: Serializer,
56 {
57 serializer.collect_seq(
58 self.0
59 .iter()
60 .copied()
61 .filter(|attachment| {
62 !matches!(
64 attachment.kind(),
65 FrameKind::Attachment(AttachmentKind::Opaque(_))
66 )
67 })
68 .map(SerializeAttachment),
69 )
70 }
71}
72
73struct SerializeContext<'a> {
74 attachments: Vec<&'a Frame>,
75 context: &'a (dyn Error + Send + Sync + 'static),
76 sources: &'a [Frame],
77}
78
79impl Serialize for SerializeContext<'_> {
80 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
81 where
82 S: Serializer,
83 {
84 let Self {
85 context,
86 attachments,
87 sources,
88 } = self;
89
90 let mut map = serializer.serialize_map(Some(3))?;
91 map.serialize_entry("context", &format!("{context}").as_str())?;
92 map.serialize_entry("attachments", &SerializeAttachmentList(attachments))?;
93 map.serialize_entry("sources", &SerializeSources(sources))?;
94
95 map.end()
96 }
97}
98
99struct SerializeSources<'a>(&'a [Frame]);
100
101impl Serialize for SerializeSources<'_> {
102 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103 where
104 S: Serializer,
105 {
106 serializer.collect_seq(self.0.iter().flat_map(|source| find_next(&[], source)))
107 }
108}
109
110fn find_next<'a>(head: &[&'a Frame], mut current: &'a Frame) -> Vec<SerializeContext<'a>> {
112 let mut attachments = vec![];
113 attachments.extend(head);
114
115 loop {
116 match current.kind() {
117 FrameKind::Context(context) => {
118 attachments.reverse();
120
121 return vec![SerializeContext {
122 attachments,
123 context,
124 sources: current.sources(),
125 }];
126 }
127 FrameKind::Attachment(_) => match current.sources() {
128 [] => {
129 return vec![];
133 }
134 [source] => {
135 attachments.push(current);
136
137 current = source;
138 }
139 sources => {
140 attachments.push(current);
142
143 return sources
144 .iter()
145 .flat_map(|source| find_next(&attachments, source))
146 .collect();
147 }
148 },
149 }
150 }
151}
152
153impl<C: Error + Send + Sync + 'static> Serialize for Report<C> {
154 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155 where
156 S: Serializer,
157 {
158 SerializeSources(self.current_frames_unchecked()).serialize(serializer)
159 }
160}
161
162impl<C: Error + Send + Sync + 'static> Serialize for Report<[C]> {
163 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164 where
165 S: Serializer,
166 {
167 SerializeSources(self.current_frames_unchecked()).serialize(serializer)
168 }
169}