1#![expect(deprecated, reason = "We use `Context` to maintain compatibility")]
2
3use alloc::{format, vec, vec::Vec};
19
20use serde::{Serialize, Serializer, ser::SerializeMap as _};
21
22use crate::{AttachmentKind, Context, Frame, FrameKind, Report};
23
24struct SerializeAttachment<'a>(&'a Frame);
25
26impl Serialize for SerializeAttachment<'_> {
27 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28 where
29 S: Serializer,
30 {
31 let Self(frame) = self;
32
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 Serialize for SerializeAttachmentList<'_, '_> {
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 Serialize for SerializeContext<'_> {
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 Serialize for SerializeSources<'_> {
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 match current.kind() {
118 FrameKind::Context(context) => {
119 attachments.reverse();
121
122 return vec![SerializeContext {
123 attachments,
124 context,
125 sources: current.sources(),
126 }];
127 }
128 FrameKind::Attachment(_) => match current.sources() {
129 [] => {
130 return vec![];
134 }
135 [source] => {
136 attachments.push(current);
137
138 current = source;
139 }
140 sources => {
141 attachments.push(current);
143
144 return sources
145 .iter()
146 .flat_map(|source| find_next(&attachments, source))
147 .collect();
148 }
149 },
150 }
151 }
152}
153
154impl<C: Context> Serialize for Report<C> {
155 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
156 where
157 S: Serializer,
158 {
159 SerializeSources(self.current_frames_unchecked()).serialize(serializer)
160 }
161}
162
163impl<C: Context> Serialize for Report<[C]> {
164 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
165 where
166 S: Serializer,
167 {
168 SerializeSources(self.current_frames_unchecked()).serialize(serializer)
169 }
170}