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::SerializeRef;
45use deser_core::ser::{
46 Describe, EventSink, Serialize, SerializeDriver, Variant, VariantKind, VariantRepr,
47};
48use deser_core::{Atom, Error, Event, State};
49
50pub struct ToDebug {
52 root: Node,
53}
54
55impl fmt::Display for ToDebug {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 fmt::Debug::fmt(self, f)
58 }
59}
60
61impl fmt::Debug for ToDebug {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 fmt::Debug::fmt(&Render(&self.root, &self.root.desc), f)
64 }
65}
66
67impl ToDebug {
68 pub fn new<T: Serialize + ?Sized>(value: &T) -> ToDebug {
74 let mut builder = Builder::default();
75 SerializeDriver::new(&value)
76 .drive_sink(&mut builder)
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 EventSink for Builder {
209 const DESCRIBED: bool = true;
210
211 fn event(
212 &mut self,
213 event: Event<'_>,
214 value: SerializeRef<'_>,
215 state: &mut State,
216 ) -> Result<(), Error> {
217 Builder::event(self, event, value, state.is_map_key());
218 Ok(())
219 }
220}
221
222impl Builder {
223 fn event(&mut self, event: Event<'_>, value: SerializeRef<'_>, is_key: bool) {
224 let describe = |value: SerializeRef<'_>| {
225 let mut collector = Collector::default();
227 if !is_key {
228 value.describe(&mut collector);
229 }
230 collector.0
231 };
232 match event {
233 Event::Atom(atom) => {
234 let node = Node {
235 desc: describe(value),
236 kind: NodeKind::Atom(atom.to_static()),
237 };
238 self.push(node);
239 }
240 Event::MapStart(_) => {
241 self.stack.push(Node {
242 desc: describe(value),
243 kind: NodeKind::Map(Vec::new()),
244 });
245 self.keys.push(None);
246 }
247 Event::SeqStart(_) => {
248 self.stack.push(Node {
249 desc: describe(value),
250 kind: NodeKind::Seq(Vec::new()),
251 });
252 self.keys.push(None);
253 }
254 Event::MapEnd | Event::SeqEnd => {
255 self.keys.pop();
256 let node = self.stack.pop().expect("unbalanced events");
257 self.push(node);
258 }
259 }
260 }
261
262 fn push(&mut self, node: Node) {
263 let Some(parent) = self.stack.last_mut() else {
264 self.root = Some(node);
265 return;
266 };
267 match parent.kind {
268 NodeKind::Seq(ref mut items) => items.push(node),
269 NodeKind::Map(ref mut entries) => {
270 let key = self.keys.last_mut().unwrap();
271 match key.take() {
272 Some(key) => entries.push((key, node)),
273 None => *key = Some(node),
274 }
275 }
276 NodeKind::Atom(_) => unreachable!(),
277 }
278 }
279}
280
281struct Render<'a>(&'a Node, &'a [Desc]);
283
284impl<'a> Render<'a> {
285 fn plain(node: &'a Node) -> Render<'a> {
287 Render(node, &node.desc)
288 }
289}
290
291impl fmt::Debug for Render<'_> {
292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293 let Render(node, desc) = *self;
294 let Some((first, rest)) = desc.split_first() else {
295 return render_undescribed(node, f);
296 };
297 match *first {
298 Desc::Some => f.debug_tuple("Some").field(&Render(node, rest)).finish(),
299 Desc::None => f.write_str("None"),
300 Desc::Newtype(ref name) => f.debug_tuple(name).field(&Render(node, rest)).finish(),
301 Desc::Structure(ref name) => render_struct(name, node, None, f),
302 Desc::TupleStruct(ref name) => render_tuple(name, node, f),
303 Desc::UnitStruct(ref name) => f.write_str(name),
304 Desc::Tuple => render_tuple("", node, f),
305 Desc::Set => match node.kind {
306 NodeKind::Seq(ref items) => f
307 .debug_set()
308 .entries(items.iter().map(Render::plain))
309 .finish(),
310 _ => render_undescribed(node, f),
311 },
312 Desc::Variant {
313 ref name,
314 kind,
315 ref repr,
316 } => render_variant(name, kind, repr, node, rest, f),
317 }
318 }
319}
320
321fn render_undescribed(node: &Node, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 match node.kind {
323 NodeKind::Atom(ref atom) => render_atom(atom, f),
324 NodeKind::Map(ref entries) => f
325 .debug_map()
326 .entries(
327 entries
328 .iter()
329 .map(|(k, v)| (Render::plain(k), Render::plain(v))),
330 )
331 .finish(),
332 NodeKind::Seq(ref items) => f
333 .debug_list()
334 .entries(items.iter().map(Render::plain))
335 .finish(),
336 }
337}
338
339fn render_atom(atom: &Atom, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 match *atom {
341 Atom::Null => f.write_str("()"),
342 Atom::Bool(v) => fmt::Debug::fmt(&v, f),
343 Atom::Str(ref v) | Atom::Lexical(ref v) => fmt::Debug::fmt(v, f),
344 Atom::Bytes(ref v) => fmt::Debug::fmt(v.data(), f),
345 Atom::Char(v) => fmt::Debug::fmt(&v, f),
346 Atom::U64(v) => fmt::Debug::fmt(&v, f),
347 Atom::I64(v) => fmt::Debug::fmt(&v, f),
348 Atom::F32(v) => fmt::Debug::fmt(&v, f),
349 Atom::F64(v) => fmt::Debug::fmt(&v, f),
350 Atom::Ext(ref v) => fmt::Debug::fmt(v, f),
351 Atom::Implicit(ref v) => render_atom(&v.value().to_atom(), f),
352 _ => f.write_str("?"),
353 }
354}
355
356fn render_struct(
358 name: &str,
359 node: &Node,
360 skip: Option<&str>,
361 f: &mut fmt::Formatter<'_>,
362) -> fmt::Result {
363 let NodeKind::Map(ref entries) = node.kind else {
364 return render_undescribed(node, f);
365 };
366 let mut s = f.debug_struct(name);
367 for (key, value) in entries {
368 match key.as_str() {
369 Some(key) if Some(key) == skip => {}
370 Some(key) => {
371 s.field(key, &Render::plain(value));
372 }
373 None => {
374 s.field("?", &Render::plain(value));
375 }
376 }
377 }
378 s.finish()
379}
380
381struct StructWithout<'a>(&'a str, &'a Node, &'a str);
383
384impl fmt::Debug for StructWithout<'_> {
385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386 render_struct(self.0, self.1, Some(self.2), f)
387 }
388}
389
390fn render_tuple(name: &str, node: &Node, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392 let NodeKind::Seq(ref items) = node.kind else {
393 return render_undescribed(node, f);
394 };
395 let mut t = f.debug_tuple(name);
396 for item in items {
397 t.field(&Render::plain(item));
398 }
399 t.finish()
400}
401
402fn render_content(
404 name: &str,
405 kind: VariantKind,
406 content: &Node,
407 rest: &[Desc],
408 f: &mut fmt::Formatter<'_>,
409) -> fmt::Result {
410 match kind {
411 VariantKind::Unit => f.write_str(name),
412 VariantKind::Newtype => f.debug_tuple(name).field(&Render(content, rest)).finish(),
413 VariantKind::Tuple => render_tuple(name, content, f),
414 _ => render_struct(name, content, None, f),
415 }
416}
417
418fn render_variant(
419 name: &str,
420 kind: VariantKind,
421 repr: &Repr,
422 node: &Node,
423 rest: &[Desc],
424 f: &mut fmt::Formatter<'_>,
425) -> fmt::Result {
426 if kind == VariantKind::Unit {
427 return f.write_str(name);
428 }
429 match *repr {
430 Repr::External => match node.kind {
431 NodeKind::Map(ref entries) if entries.len() == 1 => {
432 let content = &entries[0].1;
433 render_content(name, kind, content, &content.desc, f)
434 }
435 _ => render_undescribed(node, f),
436 },
437 Repr::Internal { ref tag } => match (kind, rest) {
439 (VariantKind::Newtype, [Desc::Structure(inner), ..]) => f
440 .debug_tuple(name)
441 .field(&StructWithout(inner, node, tag))
442 .finish(),
443 (VariantKind::Newtype | VariantKind::Struct, _) => {
444 render_struct(name, node, Some(tag), f)
445 }
446 _ => render_undescribed(node, f),
447 },
448 Repr::Adjacent { ref content } => match node.get(content) {
449 Some(content) => render_content(name, kind, content, &content.desc, f),
450 None => render_undescribed(node, f),
451 },
452 Repr::Untagged => render_content(name, kind, node, rest, f),
454 }
455}
456
457#[cfg(test)]
458mod tests {
459 use super::*;
460
461 #[test]
462 fn test_debug_format() {
463 let mut m = alloc::collections::BTreeMap::new();
464 m.insert(true, vec![vec![&b"x"[..], b"yyy"], vec![b"zzzz\x00\x01"]]);
465 m.insert(false, vec![]);
466 assert_eq!(ToDebug::new(&m).to_string(), format!("{:?}", m));
467 }
468
469 #[test]
470 fn test_debug_format_ext() {
471 assert_eq!(
472 ToDebug::new(&vec![u128::MAX, 1]).to_string(),
473 format!("[{}, 1]", u128::MAX)
474 );
475 }
476
477 #[test]
478 fn test_std_types() {
479 fn check<T: Serialize + fmt::Debug>(value: T) {
480 assert_eq!(ToDebug::new(&value).to_string(), format!("{:?}", value));
481 assert_eq!(
482 format!("{:#?}", ToDebug::new(&value)),
483 format!("{:#?}", value)
484 );
485 }
486 check(42u32);
487 check("hello");
488 check('x');
489 check(Some(Some(1i64)));
490 check(None::<u32>);
491 check((1, "two", Some(3.5)));
492 check(vec![Some(1), None]);
493 check(alloc::collections::BTreeSet::from([1, 2, 3]));
494 check(alloc::collections::BTreeMap::from([("a", (1, 2))]));
495 check(Box::new(Some(vec![true])));
496 check(());
497 }
498}