parallel_disk_usage/data_tree/reflection/
par_methods.rs

1use super::{ConversionError, Reflection};
2use crate::{data_tree::DataTree, size};
3use rayon::prelude::*;
4use std::{ffi::OsStr, iter::once};
5
6impl<Name, Size> Reflection<Name, Size>
7where
8    Name: Send,
9    Size: size::Size + Send,
10{
11    /// Attempting to convert a [`Reflection`] into a valid [`DataTree`].
12    pub fn par_try_into_tree(self) -> Result<DataTree<Name, Size>, ConversionError<Name, Size>> {
13        let Reflection {
14            name,
15            size,
16            children,
17        } = self;
18        let children_sum = children.iter().map(|child| child.size).sum();
19        if size < children_sum {
20            return Err(ConversionError::ExcessiveChildren {
21                path: once(name).collect(),
22                size,
23                children,
24                children_sum,
25            });
26        }
27        let children: Result<Vec<_>, _> = children
28            .into_par_iter()
29            .map(Self::par_try_into_tree)
30            .collect();
31        let children = match children {
32            Ok(children) => children,
33            Err(ConversionError::ExcessiveChildren {
34                mut path,
35                size,
36                children,
37                children_sum,
38            }) => {
39                path.push_front(name);
40                return Err(ConversionError::ExcessiveChildren {
41                    path,
42                    size,
43                    children,
44                    children_sum,
45                });
46            }
47        };
48        Ok(DataTree {
49            name,
50            size,
51            children,
52        })
53    }
54
55    /// Attempt to transform names and sizes.
56    pub fn par_try_map<TargetName, TargetSize, Error, Transform>(
57        self,
58        transform: Transform,
59    ) -> Result<Reflection<TargetName, TargetSize>, Error>
60    where
61        TargetName: Send,
62        TargetSize: size::Size + Send + Sync,
63        Error: Send,
64        Transform: Fn(Name, Size) -> Result<(TargetName, TargetSize), Error> + Copy + Sync,
65    {
66        let Reflection {
67            name,
68            size,
69            children,
70        } = self;
71        let children = children
72            .into_par_iter()
73            .map(|child| child.par_try_map(transform))
74            .collect::<Result<Vec<_>, _>>()?;
75        let (name, size) = transform(name, size)?;
76        Ok(Reflection {
77            name,
78            size,
79            children,
80        })
81    }
82
83    /// Attempt to convert all names from `OsString` to `String`.
84    pub fn par_convert_names_to_utf8(self) -> Result<Reflection<String, Size>, Name>
85    where
86        Name: AsRef<OsStr>,
87        Size: Sync,
88    {
89        self.par_try_map(|name, size| {
90            name.as_ref()
91                .to_str()
92                .map(|name| (name.to_string(), size))
93                .ok_or(name)
94        })
95    }
96}