@@ -3,22 +3,26 @@ pub mod info;
33pub use info:: Info ;
44
55use super :: { data_tree:: DataTree , size} ;
6+ use pipe_trait:: Pipe ;
67use rayon:: prelude:: * ;
8+ use std:: { marker:: PhantomData , ops:: Not } ;
79
810/// Collection of functions and starting points in order to build a [`DataTree`] with [`From`] or [`Into`].
911#[ derive( Debug ) ]
10- pub struct TreeBuilder < Path , Name , Size , GetInfo , JoinPath >
12+ pub struct TreeBuilder < Path , NameIter , Size , GetInfo , JoinPath >
1113where
1214 Path : Send + Sync ,
13- Name : Send + Sync ,
14- GetInfo : Fn ( & Path ) -> Info < Name , Size > + Copy + Send + Sync ,
15- JoinPath : Fn ( & Path , & Name ) -> Path + Copy + Send + Sync ,
15+ NameIter : IntoIterator ,
16+ NameIter :: IntoIter : Send ,
17+ NameIter :: Item : Send ,
18+ GetInfo : Fn ( & Path ) -> Info < NameIter , Size > + Copy + Send + Sync ,
19+ JoinPath : Fn ( & Path , & NameIter :: Item ) -> Path + Copy + Send + Sync ,
1620 Size : size:: Size + Send ,
1721{
1822 /// Path to the root.
1923 pub path : Path ,
2024 /// Name of the root.
21- pub name : Name ,
25+ pub name : NameIter :: Item ,
2226 /// Function to extract necessary information from `path` (`size` and `children`).
2327 pub get_info : GetInfo ,
2428 /// Function to join parent's `path` with a child's name to make the child's `name`.
@@ -27,17 +31,19 @@ where
2731 pub max_depth : u64 ,
2832}
2933
30- impl < Path , Name , Size , GetInfo , JoinPath > From < TreeBuilder < Path , Name , Size , GetInfo , JoinPath > >
31- for DataTree < Name , Size >
34+ impl < Path , NameIter , Size , GetInfo , JoinPath >
35+ From < TreeBuilder < Path , NameIter , Size , GetInfo , JoinPath > > for DataTree < NameIter :: Item , Size >
3236where
3337 Path : Send + Sync ,
34- Name : Send + Sync ,
35- GetInfo : Fn ( & Path ) -> Info < Name , Size > + Copy + Send + Sync ,
36- JoinPath : Fn ( & Path , & Name ) -> Path + Copy + Send + Sync ,
38+ NameIter : IntoIterator ,
39+ NameIter :: IntoIter : Send ,
40+ NameIter :: Item : Send ,
41+ GetInfo : Fn ( & Path ) -> Info < NameIter , Size > + Copy + Send + Sync ,
42+ JoinPath : Fn ( & Path , & NameIter :: Item ) -> Path + Copy + Send + Sync ,
3743 Size : size:: Size + Send ,
3844{
3945 /// Create a [`DataTree`] from a [`TreeBuilder`].
40- fn from ( builder : TreeBuilder < Path , Name , Size , GetInfo , JoinPath > ) -> Self {
46+ fn from ( builder : TreeBuilder < Path , NameIter , Size , GetInfo , JoinPath > ) -> Self {
4147 let TreeBuilder {
4248 path,
4349 name,
@@ -50,21 +56,68 @@ where
5056 let max_depth = max_depth. saturating_sub ( 1 ) ;
5157
5258 let children = children
53- . into_par_iter ( )
54- . map ( |name| TreeBuilder {
55- path : join_path ( & path, & name) ,
56- name,
57- get_info,
58- join_path,
59- max_depth,
59+ . into_iter ( )
60+ . pipe ( Chunks :: < 64 , _ > :: new)
61+ . par_bridge ( )
62+ . map ( |names : Vec < _ > | -> Vec < _ > {
63+ names
64+ . into_par_iter ( )
65+ . map ( |name| TreeBuilder {
66+ path : join_path ( & path, & name) ,
67+ name,
68+ get_info,
69+ join_path,
70+ max_depth,
71+ } )
72+ . map ( Self :: from)
73+ . collect ( )
6074 } )
61- . map ( Self :: from ) ;
75+ . reduce ( Vec :: new , add_short_vec_to_long ) ;
6276
6377 if max_depth > 0 {
64- DataTree :: dir ( name, size, children. collect ( ) )
78+ DataTree :: dir ( name, size, children)
6579 } else {
66- let size = size + children. map ( |child| child. size ( ) ) . sum ( ) ;
80+ let size = size + children. into_iter ( ) . map ( |child| child. size ( ) ) . sum ( ) ;
6781 DataTree :: dir ( name, size, Vec :: new ( ) )
6882 }
6983 }
7084}
85+
86+ /// Concat 2 `Vec`s in any order with minimal copying.
87+ fn add_short_vec_to_long < Item > ( mut a : Vec < Item > , mut b : Vec < Item > ) -> Vec < Item > {
88+ if a. len ( ) > b. len ( ) {
89+ a. extend ( b) ;
90+ a
91+ } else {
92+ b. extend ( a) ;
93+ b
94+ }
95+ }
96+
97+ /// Utility type to iterate over each `Vec` of at most `LEN` items.
98+ #[ derive( Debug , Clone , Copy ) ]
99+ struct Chunks < const LEN : usize , Iter > {
100+ iter : Iter ,
101+ _phantom : PhantomData < [ ( ) ; LEN ] > ,
102+ }
103+
104+ impl < const LEN : usize , Iter > Chunks < LEN , Iter > {
105+ /// Start iterating chunks.
106+ fn new ( iter : Iter ) -> Self {
107+ Chunks {
108+ iter,
109+ _phantom : PhantomData ,
110+ }
111+ }
112+ }
113+
114+ impl < const LEN : usize , Iter > Iterator for Chunks < LEN , Iter >
115+ where
116+ Iter : Iterator ,
117+ {
118+ type Item = Vec < Iter :: Item > ;
119+ fn next ( & mut self ) -> Option < Self :: Item > {
120+ let chunk: Vec < _ > = self . iter . by_ref ( ) . take ( LEN ) . collect ( ) ;
121+ chunk. is_empty ( ) . not ( ) . then_some ( chunk)
122+ }
123+ }
0 commit comments