Skip to main content

tree_display/
support.rs

1//! Implementations of `TreeDisplay` for common Rust types.
2//!
3//! This module provides `TreeDisplay` implementations for:
4//! - Primitive types (bool, char, integers, floats, etc.)
5//! - Standard library collections (Vec, HashMap, HashSet, etc.)
6//! - Smart pointers (Box, Rc, Arc, RefCell, etc.)
7//! - Common types (Option, Result, tuples, ranges, etc.)
8//! - Path and time types
9//!
10//! ## Feature Flags
11//! - `chumsky`: Enables support for `chumsky::span::SimpleSpan`
12
13use crate::{
14  context::Context,
15  format::{Content, Index, Keyword, Member, TypeName},
16  Tree, TreeDisplay,
17};
18
19mod support {
20  use super::*;
21
22  /// Implements `TreeDisplay` for primitive types by rendering them as leaf nodes.
23  macro_rules! impl_tree_display_for_primitive {
24    ($($ty:ty),* $(,)?) => {
25      $(
26        impl TreeDisplay for $ty {
27          fn tree(&self, _: &Context) -> Tree {
28            Tree::leaf(self.clone())
29          }
30        }
31      )*
32    };
33  }
34
35  impl_tree_display_for_primitive!(
36    bool,
37    char,
38    String,
39    i8,
40    i16,
41    i32,
42    i64,
43    i128,
44    isize,
45    u8,
46    u16,
47    u32,
48    u64,
49    u128,
50    usize,
51    f32,
52    f64,
53    std::num::NonZeroU8,
54    std::num::NonZeroU16,
55    std::num::NonZeroU32,
56    std::num::NonZeroU64,
57    std::num::NonZeroU128,
58    std::num::NonZeroUsize,
59    std::num::NonZeroI8,
60    std::num::NonZeroI16,
61    std::num::NonZeroI32,
62    std::num::NonZeroI64,
63    std::num::NonZeroI128,
64    std::num::NonZeroIsize,
65  );
66
67  /// Implements `TreeDisplay` for tuples up to 12 elements.
68  ///
69  /// Each tuple element is displayed as a labeled child with an index.
70  macro_rules! impl_tuple_tree_display {
71    ($($ty:ident $idx:tt),*) => {
72      impl<$($ty: TreeDisplay),*> TreeDisplay for ($($ty,)*) {
73        #[allow(unused_variables)] // supress erroneous warning
74        fn tree(&self, context: &Context) -> Tree {
75          #[allow(unused_mut)] // supress erroneous warning
76          let mut tree = Tree::leaf(TypeName::new("tuple"));
77          $(
78            let node = self.$idx.tree(context).labeled(Member(format!(".{}", $idx)));
79            tree.subtrees.push(node);
80          )*
81          tree
82        }
83      }
84  };
85  }
86
87  // Manual expansion for each tuple size
88  impl_tuple_tree_display!();
89  impl_tuple_tree_display!(T0 0);
90  impl_tuple_tree_display!(T0 0, T1 1);
91  impl_tuple_tree_display!(T0 0, T1 1, T2 2);
92  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3);
93  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4);
94  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5);
95  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6);
96  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7);
97  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8);
98  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9);
99  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9, T10 10);
100  impl_tuple_tree_display!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5, T6 6, T7 7, T8 8, T9 9, T10 10, T11 11);
101
102  /// `&str` is displayed as a string leaf, not a tree of characters.
103  impl TreeDisplay for &str {
104    fn tree(&self, _: &Context) -> Tree {
105      Tree::leaf(ToString::to_string(&self))
106    }
107  }
108
109  // ──── Smart pointers ──────────────────────────────────────────────────────────────────────────
110
111  impl<T: TreeDisplay + ?Sized> TreeDisplay for &T {
112    fn tree(&self, context: &Context) -> Tree {
113      (**self).tree(context)
114    }
115  }
116
117  impl<T: TreeDisplay + ?Sized> TreeDisplay for &mut T {
118    fn tree(&self, context: &Context) -> Tree {
119      (**self).tree(context)
120    }
121  }
122
123  impl<T: TreeDisplay + ?Sized> TreeDisplay for Box<T> {
124    fn tree(&self, context: &Context) -> Tree {
125      (**self).tree(context)
126    }
127  }
128
129  impl<T: TreeDisplay + ?Sized> TreeDisplay for std::rc::Rc<T> {
130    fn tree(&self, context: &Context) -> Tree {
131      (**self).tree(context)
132    }
133  }
134
135  impl<T: TreeDisplay + ?Sized> TreeDisplay for std::sync::Arc<T> {
136    fn tree(&self, context: &Context) -> Tree {
137      (**self).tree(context)
138    }
139  }
140
141  impl<T: TreeDisplay> TreeDisplay for std::cell::RefCell<T> {
142    fn tree(&self, context: &Context) -> Tree {
143      self.borrow().tree(context)
144    }
145  }
146
147  impl<T: TreeDisplay> TreeDisplay for std::sync::Mutex<T> {
148    fn tree(&self, context: &Context) -> Tree {
149      self.lock().unwrap().tree(context)
150    }
151  }
152
153  impl<T: TreeDisplay> TreeDisplay for std::sync::RwLock<T> {
154    fn tree(&self, context: &Context) -> Tree {
155      self.read().unwrap().tree(context)
156    }
157  }
158
159  // ──── Option and Result ───────────────────────────────────────────────────────────────────────
160
161  impl<T: TreeDisplay> TreeDisplay for Option<T> {
162    fn tree(&self, context: &Context) -> Tree {
163      match self {
164        Some(value) => value.tree(context),
165        None => Tree::leaf(Keyword::new("None")),
166      }
167    }
168  }
169
170  impl<T: TreeDisplay, E: TreeDisplay> TreeDisplay for Result<T, E> {
171    fn tree(&self, context: &Context) -> Tree {
172      match self {
173        Ok(value) => value.tree(context),
174        Err(err) => err.tree(context),
175      }
176    }
177  }
178
179  // ──── Collections ─────────────────────────────────────────────────────────────────────────────
180
181  impl<T: TreeDisplay, const N: usize> TreeDisplay for [T; N] {
182    fn tree(&self, context: &Context) -> Tree {
183      let mut children: Vec<Tree> = self
184        .iter()
185        .enumerate()
186        .map(|(i, item)| item.tree(context).labeled(Index::new(i)))
187        .collect();
188      let len_node = Tree::leaf(N).labeled(Member::new("len"));
189      children.insert(0, len_node);
190      Tree::new(TypeName::new("Array"), children)
191    }
192  }
193
194  impl<T: TreeDisplay> TreeDisplay for [T] {
195    fn tree(&self, context: &Context) -> Tree {
196      let mut children: Vec<Tree> = self
197        .iter()
198        .enumerate()
199        .map(|(i, item)| item.tree(context).labeled(Index::new(i)))
200        .collect();
201      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
202      children.insert(0, len_node);
203      Tree::new(TypeName::new("Slice"), children)
204    }
205  }
206
207  impl<T: TreeDisplay> TreeDisplay for Vec<T> {
208    fn tree(&self, context: &Context) -> Tree {
209      let mut children: Vec<Tree> = self
210        .iter()
211        .enumerate()
212        .map(|(i, item)| item.tree(context).labeled(Index::new(i)))
213        .collect();
214      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
215      children.insert(0, len_node);
216      Tree::new(TypeName::new("Vec"), children)
217    }
218  }
219
220  impl<T: TreeDisplay> TreeDisplay for std::collections::VecDeque<T> {
221    fn tree(&self, context: &Context) -> Tree {
222      let mut children: Vec<Tree> = self
223        .iter()
224        .enumerate()
225        .map(|(i, item)| item.tree(context).labeled(Index::new(i)))
226        .collect();
227      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
228      children.insert(0, len_node);
229      Tree::new(TypeName::new("VecDeque"), children)
230    }
231  }
232
233  impl<T: TreeDisplay> TreeDisplay for std::collections::LinkedList<T> {
234    fn tree(&self, context: &Context) -> Tree {
235      let mut children: Vec<Tree> = self
236        .iter()
237        .enumerate()
238        .map(|(i, item)| item.tree(context).labeled(Index::new(i)))
239        .collect();
240      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
241      children.insert(0, len_node);
242      Tree::new(TypeName::new("LinkedList"), children)
243    }
244  }
245
246  impl<K: Clone + Content, V: TreeDisplay, S> TreeDisplay for std::collections::HashMap<K, V, S> {
247    fn tree(&self, context: &Context) -> Tree {
248      let mut children: Vec<Tree> = self
249        .iter()
250        .map(|(key, value)| value.tree(context).labeled(Index::new(key.clone())))
251        .collect();
252      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
253      children.insert(0, len_node);
254      Tree::new(TypeName::new("HashMap"), children)
255    }
256  }
257
258  impl<K: Clone + Content, V: TreeDisplay> TreeDisplay for std::collections::BTreeMap<K, V> {
259    fn tree(&self, context: &Context) -> Tree {
260      let mut children: Vec<Tree> = self
261        .iter()
262        .map(|(key, value)| value.tree(context).labeled(Index::new(key.clone())))
263        .collect();
264      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
265      children.insert(0, len_node);
266      Tree::new(TypeName::new("BTreeMap"), children)
267    }
268  }
269
270  impl<T: TreeDisplay, S> TreeDisplay for std::collections::HashSet<T, S> {
271    fn tree(&self, context: &Context) -> Tree {
272      let mut children: Vec<Tree> = self.iter().map(|item| item.tree(context)).collect();
273      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
274      children.insert(0, len_node);
275      Tree::new(TypeName::new("HashSet"), children)
276    }
277  }
278
279  impl<T: TreeDisplay> TreeDisplay for std::collections::BTreeSet<T> {
280    fn tree(&self, context: &Context) -> Tree {
281      let mut children: Vec<Tree> = self.iter().map(|item| item.tree(context)).collect();
282      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
283      children.insert(0, len_node);
284      Tree::new(TypeName::new("BTreeSet"), children)
285    }
286  }
287
288  impl<T: TreeDisplay> TreeDisplay for std::collections::BinaryHeap<T> {
289    fn tree(&self, context: &Context) -> Tree {
290      let mut children: Vec<Tree> = self.iter().map(|item| item.tree(context)).collect();
291      let len_node = Tree::leaf(self.len()).labeled(Member::new("len"));
292      children.insert(0, len_node);
293      Tree::new(TypeName::new("BinaryHeap"), children)
294    }
295  }
296
297  // ──── Path and file types ─────────────────────────────────────────────────────────────────────
298
299  impl TreeDisplay for std::path::Path {
300    fn tree(&self, _: &Context) -> Tree {
301      Tree::leaf(format!("{:?}", self))
302    }
303  }
304
305  impl TreeDisplay for std::path::PathBuf {
306    fn tree(&self, _: &Context) -> Tree {
307      Tree::leaf(format!("{:?}", self))
308    }
309  }
310
311  impl TreeDisplay for std::ffi::OsString {
312    fn tree(&self, _: &Context) -> Tree {
313      Tree::leaf(format!("{:?}", self))
314    }
315  }
316
317  impl TreeDisplay for std::ffi::OsStr {
318    fn tree(&self, _: &Context) -> Tree {
319      Tree::leaf(format!("{:?}", self))
320    }
321  }
322
323  // ──── Time types ──────────────────────────────────────────────────────────────────────────────
324
325  impl TreeDisplay for std::time::Duration {
326    fn tree(&self, _: &Context) -> Tree {
327      Tree::leaf(format!("{}s", self.as_secs_f64()))
328    }
329  }
330
331  impl TreeDisplay for std::time::Instant {
332    fn tree(&self, _: &Context) -> Tree {
333      Tree::leaf(format!("{:?}", self))
334    }
335  }
336
337  impl TreeDisplay for std::time::SystemTime {
338    fn tree(&self, _: &Context) -> Tree {
339      Tree::leaf(format!("{:?}", self))
340    }
341  }
342
343  // ──── Range types ─────────────────────────────────────────────────────────────────────────
344
345  impl<T: TreeDisplay + std::fmt::Debug + Clone + 'static> TreeDisplay for std::ops::Range<T> {
346    fn tree(&self, _: &Context) -> Tree {
347      let children = vec![
348        Tree::leaf(self.start.clone()).labeled(Member::new("start")),
349        Tree::leaf(self.end.clone()).labeled(Member::new("end")),
350      ];
351      Tree::new(TypeName::new("Range"), children)
352    }
353  }
354
355  impl<T: TreeDisplay + std::fmt::Debug + Clone + 'static> TreeDisplay
356    for std::ops::RangeInclusive<T>
357  {
358    fn tree(&self, _: &Context) -> Tree {
359      let children = vec![
360        Tree::leaf(self.start().clone()).labeled(Member::new("start")),
361        Tree::leaf(self.end().clone()).labeled(Member::new("end")),
362      ];
363      Tree::new(TypeName::new("RangeInclusive"), children)
364    }
365  }
366
367  impl<T: TreeDisplay + std::fmt::Debug + Clone + 'static> TreeDisplay for std::ops::RangeFrom<T> {
368    fn tree(&self, _: &Context) -> Tree {
369      let children = vec![Tree::leaf(self.start.clone()).labeled(Member::new("start"))];
370      Tree::new(TypeName::new("RangeFrom"), children)
371    }
372  }
373
374  impl<T: TreeDisplay + std::fmt::Debug + Clone + 'static> TreeDisplay for std::ops::RangeTo<T> {
375    fn tree(&self, _: &Context) -> Tree {
376      let children = vec![Tree::leaf(self.end.clone()).labeled(Member::new("end"))];
377      Tree::new(TypeName::new("RangeTo"), children)
378    }
379  }
380
381  impl<T: TreeDisplay + std::fmt::Debug + Clone + 'static> TreeDisplay
382    for std::ops::RangeToInclusive<T>
383  {
384    fn tree(&self, _: &Context) -> Tree {
385      let children = vec![Tree::leaf(self.end.clone()).labeled(Member::new("end"))];
386      Tree::new(TypeName::new("RangeToInclusive"), children)
387    }
388  }
389
390  impl TreeDisplay for std::ops::RangeFull {
391    fn tree(&self, _: &Context) -> Tree {
392      Tree::leaf(TypeName::new("RangeFull"))
393    }
394  }
395
396  // ──── Marker types ────────────────────────────────────────────────────────────────────────────
397
398  impl<T> TreeDisplay for std::marker::PhantomData<T> {
399    fn tree(&self, _: &Context) -> Tree {
400      Tree::leaf(TypeName::new("PhantomData"))
401    }
402  }
403}
404
405#[cfg(feature = "chumsky")]
406mod chumsky_support {
407  use super::*;
408  use chumsky::span::SimpleSpan;
409
410  impl TreeDisplay for SimpleSpan {
411    fn tree(&self, _: &Context) -> Tree {
412      let children = vec![
413        Tree::leaf(self.start).labeled(Member::new("start")),
414        Tree::leaf(self.end).labeled(Member::new("end")),
415      ];
416      Tree::new(TypeName::new("SimpleSpan"), children)
417    }
418  }
419}