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