1#![doc(html_logo_url = "https://raw.githubusercontent.com/mitsuhiko/deser/main/artwork/logo.svg")]
36#![cfg_attr(not(test), no_std)]
37
38extern crate alloc;
39
40use alloc::string::String;
41use alloc::vec::Vec;
42use core::fmt;
43
44use deser_core::ser::{Describe, Serialize, SerializeDriver, Variant, VariantKind, VariantRepr};
45use deser_core::{Atom, Event};
46
47pub struct ToDebug {
49 root: Node,
50}
51
52impl fmt::Display for ToDebug {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 fmt::Debug::fmt(self, f)
55 }
56}
57
58impl fmt::Debug for ToDebug {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 fmt::Debug::fmt(&Render(&self.root, &self.root.desc), f)
61 }
62}
63
64impl ToDebug {
65 pub fn new(value: &dyn Serialize) -> ToDebug {
71 let mut builder = Builder::default();
72 SerializeDriver::new(value)
73 .drive_described(|event, value, state| {
74 builder.event(event, value, state.is_map_key());
75 Ok(())
76 })
77 .unwrap();
78 ToDebug {
79 root: builder.root.expect("no value was serialized"),
80 }
81 }
82}
83
84#[derive(Debug)]
86enum Desc {
87 Structure(String),
88 Newtype(String),
89 TupleStruct(String),
90 UnitStruct(String),
91 Variant {
92 name: String,
93 kind: VariantKind,
94 repr: Repr,
95 },
96 Some,
97 None,
98 Tuple,
99 Set,
100}
101
102#[derive(Debug)]
104enum Repr {
105 External,
106 Internal { tag: String },
107 Adjacent { content: String },
108 Untagged,
109}
110
111#[derive(Default)]
113struct Collector(Vec<Desc>);
114
115impl Describe for Collector {
116 fn structure(&mut self, name: &str) {
117 self.0.push(Desc::Structure(name.into()));
118 }
119
120 fn newtype(&mut self, name: &str) {
121 self.0.push(Desc::Newtype(name.into()));
122 }
123
124 fn tuple_struct(&mut self, name: &str) {
125 self.0.push(Desc::TupleStruct(name.into()));
126 }
127
128 fn unit_struct(&mut self, name: &str) {
129 self.0.push(Desc::UnitStruct(name.into()));
130 }
131
132 fn variant(&mut self, variant: &Variant<'_>) {
133 let repr = match variant.repr {
134 VariantRepr::Internal { tag } => Repr::Internal { tag: tag.into() },
135 VariantRepr::Adjacent { content, .. } => Repr::Adjacent {
136 content: content.into(),
137 },
138 VariantRepr::Untagged => Repr::Untagged,
139 _ => Repr::External,
140 };
141 self.0.push(Desc::Variant {
142 name: variant.name.into(),
143 kind: variant.kind,
144 repr,
145 });
146 }
147
148 fn some(&mut self) {
149 self.0.push(Desc::Some);
150 }
151
152 fn none(&mut self) {
153 self.0.push(Desc::None);
154 }
155
156 fn tuple(&mut self) {
157 self.0.push(Desc::Tuple);
158 }
159
160 fn set(&mut self) {
161 self.0.push(Desc::Set);
162 }
163}
164
165#[derive(Debug)]
167struct Node {
168 desc: Vec<Desc>,
169 kind: NodeKind,
170}
171
172#[derive(Debug)]
173enum NodeKind {
174 Atom(Atom<'static>),
175 Map(Vec<(Node, Node)>),
176 Seq(Vec<Node>),
177}
178
179impl Node {
180 fn get(&self, key: &str) -> Option<&Node> {
182 match self.kind {
183 NodeKind::Map(ref entries) => entries
184 .iter()
185 .find(|(k, _)| k.as_str() == Some(key))
186 .map(|(_, v)| v),
187 _ => None,
188 }
189 }
190
191 fn as_str(&self) -> Option<&str> {
192 match self.kind {
193 NodeKind::Atom(ref atom) => atom.as_str(),
194 _ => None,
195 }
196 }
197}
198
199#[derive(Default)]
201struct Builder {
202 stack: Vec<Node>,
203 keys: Vec<Option<Node>>,
205 root: Option<Node>,
206}
207
208impl Builder {
209 fn event(&mut self, event: Event<'_>, value: &dyn Serialize, is_key: bool) {
210 let describe = |value: &dyn Serialize| {
211 let mut collector = Collector::default();
213 if !is_key {
214 value.describe(&mut collector);
215 }
216 collector.0
217 };
218 match event {
219 Event::Atom(atom) => {
220 let node = Node {
221 desc: describe(value),
222 kind: NodeKind::Atom(atom.to_static()),
223 };
224 self.push(node);
225 }
226 Event::MapStart(_) => {
227 self.stack.push(Node {
228 desc: describe(value),
229 kind: NodeKind::Map(Vec::new()),
230 });
231 self.keys.push(None);
232 }
233 Event::SeqStart(_) => {
234 self.stack.push(Node {
235 desc: describe(value),
236 kind: NodeKind::Seq(Vec::new()),
237 });
238 self.keys.push(None);
239 }
240 Event::MapEnd | Event::SeqEnd => {
241 self.keys.pop();
242 let node = self.stack.pop().expect("unbalanced events");
243 self.push(node);
244 }
245 }
246 }
247
248 fn push(&mut self, node: Node) {
249 let Some(parent) = self.stack.last_mut() else {
250 self.root = Some(node);
251 return;
252 };
253 match parent.kind {
254 NodeKind::Seq(ref mut items) => items.push(node),
255 NodeKind::Map(ref mut entries) => {
256 let key = self.keys.last_mut().unwrap();
257 match key.take() {
258 Some(key) => entries.push((key, node)),
259 None => *key = Some(node),
260 }
261 }
262 NodeKind::Atom(_) => unreachable!(),
263 }
264 }
265}
266
267struct Render<'a>(&'a Node, &'a [Desc]);
269
270impl<'a> Render<'a> {
271 fn plain(node: &'a Node) -> Render<'a> {
273 Render(node, &node.desc)
274 }
275}
276
277impl fmt::Debug for Render<'_> {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 let Render(node, desc) = *self;
280 let Some((first, rest)) = desc.split_first() else {
281 return render_undescribed(node, f);
282 };
283 match *first {
284 Desc::Some => f.debug_tuple("Some").field(&Render(node, rest)).finish(),
285 Desc::None => f.write_str("None"),
286 Desc::Newtype(ref name) => f.debug_tuple(name).field(&Render(node, rest)).finish(),
287 Desc::Structure(ref name) => render_struct(name, node, None, f),
288 Desc::TupleStruct(ref name) => render_tuple(name, node, f),
289 Desc::UnitStruct(ref name) => f.write_str(name),
290 Desc::Tuple => render_tuple("", node, f),
291 Desc::Set => match node.kind {
292 NodeKind::Seq(ref items) => f
293 .debug_set()
294 .entries(items.iter().map(Render::plain))
295 .finish(),
296 _ => render_undescribed(node, f),
297 },
298 Desc::Variant {
299 ref name,
300 kind,
301 ref repr,
302 } => render_variant(name, kind, repr, node, rest, f),
303 }
304 }
305}
306
307fn render_undescribed(node: &Node, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308 match node.kind {
309 NodeKind::Atom(ref atom) => render_atom(atom, f),
310 NodeKind::Map(ref entries) => f
311 .debug_map()
312 .entries(
313 entries
314 .iter()
315 .map(|(k, v)| (Render::plain(k), Render::plain(v))),
316 )
317 .finish(),
318 NodeKind::Seq(ref items) => f
319 .debug_list()
320 .entries(items.iter().map(Render::plain))
321 .finish(),
322 }
323}
324
325fn render_atom(atom: &Atom, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 match *atom {
327 Atom::Null => f.write_str("()"),
328 Atom::Bool(v) => fmt::Debug::fmt(&v, f),
329 Atom::Str(ref v) | Atom::Lexical(ref v) => fmt::Debug::fmt(v, f),
330 Atom::Bytes(ref v) => fmt::Debug::fmt(v.data(), f),
331 Atom::Char(v) => fmt::Debug::fmt(&v, f),
332 Atom::U64(v) => fmt::Debug::fmt(&v, f),
333 Atom::I64(v) => fmt::Debug::fmt(&v, f),
334 Atom::F32(v) => fmt::Debug::fmt(&v, f),
335 Atom::F64(v) => fmt::Debug::fmt(&v, f),
336 Atom::Ext(ref v) => fmt::Debug::fmt(v, f),
337 Atom::Implicit(ref v) => render_atom(&v.value().to_atom(), f),
338 _ => f.write_str("?"),
339 }
340}
341
342fn render_struct(
344 name: &str,
345 node: &Node,
346 skip: Option<&str>,
347 f: &mut fmt::Formatter<'_>,
348) -> fmt::Result {
349 let NodeKind::Map(ref entries) = node.kind else {
350 return render_undescribed(node, f);
351 };
352 let mut s = f.debug_struct(name);
353 for (key, value) in entries {
354 match key.as_str() {
355 Some(key) if Some(key) == skip => {}
356 Some(key) => {
357 s.field(key, &Render::plain(value));
358 }
359 None => {
360 s.field("?", &Render::plain(value));
361 }
362 }
363 }
364 s.finish()
365}
366
367struct StructWithout<'a>(&'a str, &'a Node, &'a str);
369
370impl fmt::Debug for StructWithout<'_> {
371 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372 render_struct(self.0, self.1, Some(self.2), f)
373 }
374}
375
376fn render_tuple(name: &str, node: &Node, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378 let NodeKind::Seq(ref items) = node.kind else {
379 return render_undescribed(node, f);
380 };
381 let mut t = f.debug_tuple(name);
382 for item in items {
383 t.field(&Render::plain(item));
384 }
385 t.finish()
386}
387
388fn render_content(
390 name: &str,
391 kind: VariantKind,
392 content: &Node,
393 rest: &[Desc],
394 f: &mut fmt::Formatter<'_>,
395) -> fmt::Result {
396 match kind {
397 VariantKind::Unit => f.write_str(name),
398 VariantKind::Newtype => f.debug_tuple(name).field(&Render(content, rest)).finish(),
399 VariantKind::Tuple => render_tuple(name, content, f),
400 _ => render_struct(name, content, None, f),
401 }
402}
403
404fn render_variant(
405 name: &str,
406 kind: VariantKind,
407 repr: &Repr,
408 node: &Node,
409 rest: &[Desc],
410 f: &mut fmt::Formatter<'_>,
411) -> fmt::Result {
412 if kind == VariantKind::Unit {
413 return f.write_str(name);
414 }
415 match *repr {
416 Repr::External => match node.kind {
417 NodeKind::Map(ref entries) if entries.len() == 1 => {
418 let content = &entries[0].1;
419 render_content(name, kind, content, &content.desc, f)
420 }
421 _ => render_undescribed(node, f),
422 },
423 Repr::Internal { ref tag } => match (kind, rest) {
425 (VariantKind::Newtype, [Desc::Structure(inner), ..]) => f
426 .debug_tuple(name)
427 .field(&StructWithout(inner, node, tag))
428 .finish(),
429 (VariantKind::Newtype | VariantKind::Struct, _) => {
430 render_struct(name, node, Some(tag), f)
431 }
432 _ => render_undescribed(node, f),
433 },
434 Repr::Adjacent { ref content } => match node.get(content) {
435 Some(content) => render_content(name, kind, content, &content.desc, f),
436 None => render_undescribed(node, f),
437 },
438 Repr::Untagged => render_content(name, kind, node, rest, f),
440 }
441}
442
443#[cfg(test)]
444mod tests {
445 use super::*;
446
447 #[test]
448 fn test_debug_format() {
449 let mut m = alloc::collections::BTreeMap::new();
450 m.insert(true, vec![vec![&b"x"[..], b"yyy"], vec![b"zzzz\x00\x01"]]);
451 m.insert(false, vec![]);
452 assert_eq!(ToDebug::new(&m).to_string(), format!("{:?}", m));
453 }
454
455 #[test]
456 fn test_debug_format_ext() {
457 assert_eq!(
458 ToDebug::new(&vec![u128::MAX, 1]).to_string(),
459 format!("[{}, 1]", u128::MAX)
460 );
461 }
462
463 #[test]
464 fn test_std_types() {
465 fn check<T: Serialize + fmt::Debug>(value: T) {
466 assert_eq!(ToDebug::new(&value).to_string(), format!("{:?}", value));
467 assert_eq!(
468 format!("{:#?}", ToDebug::new(&value)),
469 format!("{:#?}", value)
470 );
471 }
472 check(42u32);
473 check("hello");
474 check('x');
475 check(Some(Some(1i64)));
476 check(None::<u32>);
477 check((1, "two", Some(3.5)));
478 check(vec![Some(1), None]);
479 check(alloc::collections::BTreeSet::from([1, 2, 3]));
480 check(alloc::collections::BTreeMap::from([("a", (1, 2))]));
481 check(Box::new(Some(vec![true])));
482 check(());
483 }
484}