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;