parallel_disk_usage/data_tree/reflection.rs
1use crate::size;
2use std::{
3 collections::VecDeque,
4 ffi::OsStr,
5 fmt::{Debug, Display, Error, Formatter},
6 path::PathBuf,
7};
8
9#[cfg(feature = "json")]
10use serde::{Deserialize, Serialize};
11
12/// Intermediate format used for construction and inspection of
13/// [`DataTree`](crate::data_tree::DataTree)'s internal content.
14///
15/// Unlike `DataTree` where the fields are all private, the fields of `Reflection`
16/// are all public to allow construction in tests.
17///
18/// **Conversion between `DataTree` and `Reflection`:**
19/// * Any `DataTree` can be safely [transmuted](std::mem::transmute) to a valid `Reflection`.
20/// * Any `Reflection` can be safely transmuted to a potentially invalid `DataTree`.
21/// * To safely convert a `DataTree` into a `Reflection` without the `unsafe` keyword, use
22/// [`DataTree::into_reflection`](crate::data_tree::DataTree::into_reflection)
23/// (it would be slower than using `transmute`).
24/// * To safely convert a `Reflection` into a valid `DataTree`,
25/// use [`par_try_into_tree`](Self::par_try_into_tree).
26///
27/// **Serialization and deserialization:** _(feature: `json`)_ `Reflection` implements
28/// `Serialize` and `Deserialize` traits, this allows functions in `serde_json` to convert
29/// a `Reflection` into/from JSON.
30#[derive(Debug, Clone, PartialEq, Eq)]
31#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
32#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]
33pub struct Reflection<Name, Size: size::Size> {
34 /// Name of the tree.
35 pub name: Name,
36 /// Disk usage of a file or total disk usage of a folder.
37 pub size: Size,
38 /// Data of children filesystem subtrees.
39 pub children: Vec<Self>,
40}
41
42/// Error that occurs when an attempt to convert a [`Reflection`] into a
43/// [`DataTree`](crate::data_tree::DataTree) fails.
44#[derive(Debug, Clone, PartialEq, Eq)]
45#[non_exhaustive]
46pub enum ConversionError<Name, Size: size::Size> {
47 /// When a node's size is less than one of its children.
48 ExcessiveChildren {
49 /// Path from root to the node.
50 path: VecDeque<Name>,
51 /// Size hold by the node.
52 size: Size,
53 /// The child whose size was greater than that of the node.
54 child: Reflection<Name, Size>,
55 },
56}
57
58impl<Name, Size> Display for ConversionError<Name, Size>
59where
60 Name: AsRef<OsStr> + Debug,
61 Size: size::Size,
62{
63 fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), Error> {
64 use ConversionError::*;
65 match self {
66 ExcessiveChildren { path, size, child } => {
67 let path = path
68 .iter()
69 .map(PathBuf::from)
70 .fold(PathBuf::new(), |acc, x| acc.join(x));
71 write!(
72 formatter,
73 "ExcessiveChildren: {path:?} ({size:?}) is less than a child named {child_name:?} ({child_size:?})",
74 child_name = child.name,
75 child_size = child.size,
76 )
77 }
78 }
79 }
80}
81
82mod convert;
83mod par_methods;