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;