1
- use std:: cmp :: Ordering ;
1
+ use std:: collections :: BTreeMap ;
2
2
3
3
use crate :: document:: Document ;
4
4
@@ -25,107 +25,52 @@ fn distribute_posts_by_categories<'a>(
25
25
for post in all_posts {
26
26
if let Some ( categories) = extract_categories ( post. as_view ( ) ) {
27
27
let categories: Vec < _ > = categories. values ( ) . collect ( ) ;
28
- parse_categories_list ( & mut root, 1 , categories. as_slice ( ) , post) ?;
28
+ parse_categories_list ( & mut root, categories. as_slice ( ) , post) ?;
29
29
}
30
30
}
31
31
Ok ( root)
32
32
}
33
33
34
34
/// construct a hierarchy of Categories with their posts from a list of categories
35
35
fn parse_categories_list < ' a > (
36
- parent : & mut Category < ' a > ,
37
- cur_idx : usize ,
38
- cur_post_categories : & [ & dyn ValueView ] ,
36
+ mut parent : & mut Category < ' a > ,
37
+ post_categories : & [ & dyn ValueView ] ,
39
38
post : & ' a liquid:: model:: Value ,
40
39
) -> Result < ( ) > {
41
- if cur_idx <= cur_post_categories. len ( ) {
42
- let cat_full_path = construct_cat_full_path ( cur_idx, cur_post_categories) ;
43
- let cur_cat = if let Ok ( idx) = parent. sub_cats . binary_search_by ( |c| {
44
- compare_category_path (
45
- c. cat_path . iter ( ) . map ( |v| v. as_view ( ) ) ,
46
- cat_full_path. iter ( ) . copied ( ) ,
47
- )
48
- } ) {
49
- & mut parent. sub_cats [ idx]
50
- } else {
51
- let last_idx = parent. sub_cats . len ( ) ;
52
- parent
53
- . sub_cats
54
- . push ( Category :: with_path ( cat_full_path. into_iter ( ) ) ) ;
55
- // need to sort for binary_search_by
56
- parent. sub_cats . sort_by ( |c1, c2| {
57
- compare_category_path (
58
- c1. cat_path . iter ( ) . map ( |v| v. as_view ( ) ) ,
59
- c2. cat_path . iter ( ) . map ( |v| v. as_view ( ) ) ,
60
- )
61
- } ) ;
62
- & mut parent. sub_cats [ last_idx]
63
- } ;
64
-
65
- if is_leaf_category ( cur_idx, cur_post_categories) {
66
- cur_cat. add_post ( post) ;
67
- } else {
68
- parse_categories_list ( cur_cat, next_category ( cur_idx) , cur_post_categories, post) ?;
69
- }
40
+ for i in 0 ..post_categories. len ( ) {
41
+ let cat_name = post_categories[ i] . to_kstr ( ) . to_string ( ) ;
42
+ parent = parent
43
+ . sub_cats
44
+ . entry ( cat_name)
45
+ . or_insert_with ( || Category :: with_path ( post_categories[ 0 ..=i] . iter ( ) . copied ( ) ) ) ;
70
46
}
47
+ parent. add_post ( post) ;
71
48
Ok ( ( ) )
72
49
}
73
50
74
- #[ derive( Debug ) ]
51
+ #[ derive( Default , Debug ) ]
75
52
struct Category < ' a > {
76
53
cat_path : liquid:: model:: Array ,
77
54
posts : Vec < & ' a liquid:: model:: Value > ,
78
- sub_cats : Vec < Category < ' a > > ,
55
+ sub_cats : BTreeMap < String , Category < ' a > > ,
79
56
}
80
57
81
58
impl < ' a > Category < ' a > {
82
59
fn new ( ) -> Self {
83
- Category {
84
- cat_path : vec ! [ ] ,
85
- posts : vec ! [ ] ,
86
- sub_cats : vec ! [ ] ,
87
- }
60
+ Default :: default ( )
88
61
}
89
62
90
63
fn with_path < ' v > ( path : impl Iterator < Item = & ' v dyn ValueView > ) -> Self {
91
- Category {
92
- cat_path : path. map ( |v| v. to_value ( ) ) . collect ( ) ,
93
- posts : vec ! [ ] ,
94
- sub_cats : vec ! [ ] ,
95
- }
64
+ let mut c = Self :: new ( ) ;
65
+ c. cat_path = path. map ( |v| v. to_value ( ) ) . collect ( ) ;
66
+ c
96
67
}
97
68
98
69
fn add_post ( & mut self , post : & ' a liquid:: model:: Value ) {
99
70
self . posts . push ( post) ;
100
71
}
101
72
}
102
73
103
- fn compare_category_path < ' a , C , S > ( cur_path : C , seek : S ) -> Ordering
104
- where
105
- C : Iterator < Item = & ' a dyn ValueView > ,
106
- S : Iterator < Item = & ' a dyn ValueView > ,
107
- {
108
- cur_path
109
- . map ( liquid:: model:: ValueViewCmp :: new)
110
- . partial_cmp ( seek. map ( liquid:: model:: ValueViewCmp :: new) )
111
- . expect ( "Arrays of same hierarchy level should be fully comparable" )
112
- }
113
-
114
- fn is_leaf_category ( cur_idx : usize , categories : & [ & dyn ValueView ] ) -> bool {
115
- cur_idx == categories. len ( )
116
- }
117
-
118
- fn construct_cat_full_path < ' v > (
119
- cur_idx : usize ,
120
- categories : & [ & ' v dyn ValueView ] ,
121
- ) -> Vec < & ' v dyn ValueView > {
122
- categories[ ..cur_idx] . to_vec ( )
123
- }
124
-
125
- fn next_category ( cur_idx : usize ) -> usize {
126
- cur_idx + 1
127
- }
128
-
129
74
// walk the categories tree and construct Paginator for each node,
130
75
// filling `pages` and `indexes` accordingly
131
76
fn walk_categories (
@@ -154,7 +99,7 @@ fn walk_categories(
154
99
} else {
155
100
cur_cat_paginators_holder. push ( Paginator :: default ( ) ) ;
156
101
}
157
- for c in & mut category. sub_cats {
102
+ for c in category. sub_cats . values_mut ( ) {
158
103
let mut sub_paginators_holder = walk_categories ( c, config, doc) ?;
159
104
160
105
if let Some ( indexes) = cur_cat_paginators_holder[ 0 ] . indexes . as_mut ( ) {
@@ -166,24 +111,3 @@ fn walk_categories(
166
111
}
167
112
Ok ( cur_cat_paginators_holder)
168
113
}
169
-
170
- #[ cfg( test) ]
171
- mod test {
172
- use super :: * ;
173
-
174
- use liquid:: model:: ArrayView ;
175
-
176
- #[ test]
177
- fn compare_category_path_test ( ) {
178
- let a = liquid:: model:: array!( [ "A" ] ) ;
179
- let b = liquid:: model:: array!( [ "B" ] ) ;
180
- assert_eq ! (
181
- Ordering :: Less ,
182
- compare_category_path( a. values( ) , b. values( ) )
183
- ) ;
184
- assert_eq ! (
185
- Ordering :: Greater ,
186
- compare_category_path( b. values( ) , a. values( ) )
187
- ) ;
188
- }
189
- }
0 commit comments