parallel_disk_usage/data_tree/reflection/
par_methods.rs1use 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 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 excess_child = children
19 .iter()
20 .enumerate()
21 .find(|(_, child)| child.size > size);
22 if let Some((index, _)) = excess_child {
23 let path = once(name).collect();
24 let child = keep_one(children, index).expect("excess child");
25 return Err(ConversionError::ExcessiveChildren { path, size, child });
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 child,
37 }) => {
38 path.push_front(name);
39 return Err(ConversionError::ExcessiveChildren { path, size, child });
40 }
41 };
42 Ok(DataTree {
43 name,
44 size,
45 children,
46 })
47 }
48
49 pub fn par_try_map<TargetName, TargetSize, Error, Transform>(
51 self,
52 transform: Transform,
53 ) -> Result<Reflection<TargetName, TargetSize>, Error>
54 where
55 TargetName: Send,
56 TargetSize: size::Size + Send + Sync,
57 Error: Send,
58 Transform: Fn(Name, Size) -> Result<(TargetName, TargetSize), Error> + Copy + Sync,
59 {
60 let Reflection {
61 name,
62 size,
63 children,
64 } = self;
65 let children = children
66 .into_par_iter()
67 .map(|child| child.par_try_map(transform))
68 .collect::<Result<Vec<_>, _>>()?;
69 let (name, size) = transform(name, size)?;
70 Ok(Reflection {
71 name,
72 size,
73 children,
74 })
75 }
76
77 pub fn par_convert_names_to_utf8(self) -> Result<Reflection<String, Size>, Name>
79 where
80 Name: AsRef<OsStr>,
81 Size: Sync,
82 {
83 self.par_try_map(|name, size| {
84 name.as_ref()
85 .to_str()
86 .map(|name| (name.to_string(), size))
87 .ok_or(name)
88 })
89 }
90}
91
92#[inline]
94fn keep_one<Item>(vec: Vec<Item>, index: usize) -> Option<Item> {
95 vec.into_iter().nth(index)
97}