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 `Tree` where the fields are all private, the fields of `TreeReflection`
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 the sum 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        /// Children of the node.
54        children: Vec<Reflection<Name, Size>>,
55        /// Sum of size hold by children of the node.
56        children_sum: Size,
57    },
58}
59
60impl<Name, Size> Display for ConversionError<Name, Size>
61where
62    Name: AsRef<OsStr> + Debug,
63    Size: size::Size,
64{
65    fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), Error> {
66        use ConversionError::*;
67        match self {
68            ExcessiveChildren {
69                path,
70                size,
71                children_sum,
72                ..
73            } => {
74                let path = path
75                    .iter()
76                    .map(PathBuf::from)
77                    .fold(PathBuf::new(), |acc, x| acc.join(x));
78                write!(
79                    formatter,
80                    "ExcessiveChildren: {path:?}: {size:?} is less than {children_sum:?}",
81                )
82            }
83        }
84    }
85}
86
87mod convert;
88mod par_methods;