@@ -7,71 +7,76 @@ use env;
7
7
use util:: errors:: { CargoResult , ChainError , internal} ;
8
8
9
9
struct Category {
10
- name : String ,
11
10
slug : String ,
11
+ name : String ,
12
12
description : String ,
13
13
}
14
14
15
15
impl Category {
16
- fn concat ( & self , child : & Category ) -> Category {
17
- Category {
18
- name : format ! ( "{}::{}" , self . name, child. name) ,
19
- slug : format ! ( "{}::{}" , self . slug, child. slug) ,
20
- description : child. description . clone ( ) ,
16
+ fn from_parent ( slug : & str , name : & str , description : & str , parent : Option < & Category > )
17
+ -> Category {
18
+ match parent {
19
+ Some ( parent) => {
20
+ Category {
21
+ slug : format ! ( "{}::{}" , parent. slug, slug) ,
22
+ name : format ! ( "{}::{}" , parent. name, name) ,
23
+ description : description. into ( ) ,
24
+ }
25
+ }
26
+ None => {
27
+ Category {
28
+ slug : slug. into ( ) ,
29
+ name : name. into ( ) ,
30
+ description : description. into ( ) ,
31
+ }
32
+ }
21
33
}
22
34
}
23
35
}
24
36
25
- fn concat_parent_and_child ( parent : Option < & Category > , child : Category )
26
- -> Category {
27
- parent. map ( |p| p. concat ( & child) ) . unwrap_or ( child)
28
- }
29
-
30
- fn required_string_from_toml ( toml : & toml:: Table , key : & str )
31
- -> CargoResult < String > {
37
+ fn required_string_from_toml < ' a > ( toml : & ' a toml:: Table , key : & str ) -> CargoResult < & ' a str > {
32
38
toml. get ( key)
33
39
. and_then ( toml:: Value :: as_str)
34
- . map ( str:: to_string)
35
40
. chain_error ( || {
36
- internal ( "Expected Category toml attribute to be a String" )
41
+ internal ( format ! ( "Expected category TOML attribute '{}' to be a String" , key ) )
37
42
} )
38
43
}
39
44
40
- fn optional_string_from_toml ( toml : & toml:: Table , key : & str )
41
- -> String {
45
+ fn optional_string_from_toml < ' a > ( toml : & ' a toml:: Table , key : & str ) -> & ' a str {
42
46
toml. get ( key)
43
47
. and_then ( toml:: Value :: as_str)
44
48
. unwrap_or ( "" )
45
- . to_string ( )
46
49
}
47
50
48
- fn category_from_toml ( toml : & toml:: Value , parent : Option < & Category > )
49
- -> CargoResult < Vec < Category > > {
50
- let toml = toml. as_table ( ) . chain_error ( || {
51
- internal ( "Category isn't a toml Table" )
52
- } ) ?;
53
-
54
- let category = Category {
55
- slug : required_string_from_toml ( & toml, "slug" ) ?,
56
- name : required_string_from_toml ( & toml, "name" ) ?,
57
- description : optional_string_from_toml ( & toml, "description" ) ,
58
- } ;
59
-
60
- let category = concat_parent_and_child ( parent, category) ;
61
-
62
- let mut children: Vec < _ > = toml. get ( "categories" )
63
- . and_then ( toml:: Value :: as_slice)
64
- . map ( |children| {
65
- children. iter ( )
66
- . flat_map ( |ref child| {
67
- category_from_toml ( child, Some ( & category) )
68
- . expect ( "Could not create child from toml" )
69
- } ) . collect ( )
70
- } ) . unwrap_or ( Vec :: new ( ) ) ;
71
-
72
- children. push ( category) ;
73
-
74
- Ok ( children)
51
+ fn categories_from_toml ( categories : & toml:: Table , parent : Option < & Category > ) -> CargoResult < Vec < Category > > {
52
+ let mut result = vec ! [ ] ;
53
+
54
+ for ( slug, details) in categories {
55
+ let details = details. as_table ( ) . chain_error ( || {
56
+ internal ( format ! ( "category {} was not a TOML table" , slug) )
57
+ } ) ?;
58
+
59
+ let category = Category :: from_parent (
60
+ slug,
61
+ required_string_from_toml ( & details, "name" ) ?,
62
+ optional_string_from_toml ( & details, "description" ) ,
63
+ parent,
64
+ ) ;
65
+
66
+ if let Some ( categories) = details. get ( "categories" ) {
67
+ let categories = categories. as_table ( ) . chain_error ( || {
68
+ internal ( format ! ( "child categories of {} were not a table" , slug) )
69
+ } ) ?;
70
+
71
+ result. extend (
72
+ categories_from_toml ( categories, Some ( & category) ) ?
73
+ ) ;
74
+ }
75
+
76
+ result. push ( category)
77
+ }
78
+
79
+ Ok ( result)
75
80
}
76
81
77
82
pub fn sync ( ) -> CargoResult < ( ) > {
@@ -84,17 +89,9 @@ pub fn sync() -> CargoResult<()> {
84
89
"Could not parse categories.toml"
85
90
) ;
86
91
87
- let categories = toml. get ( "categories" )
88
- . expect ( "No categories key found" )
89
- . as_slice ( )
90
- . expect ( "Categories isn't a toml::Array" ) ;
91
-
92
- let categories: Vec < _ > = categories
93
- . iter ( )
94
- . flat_map ( |c| {
95
- category_from_toml ( c, None )
96
- . expect ( "Categories from toml failed" )
97
- } ) . collect ( ) ;
92
+ let categories = categories_from_toml ( & toml, None ) . expect (
93
+ "Could not convert categories from TOML"
94
+ ) ;
98
95
99
96
for category in categories. iter ( ) {
100
97
tx. execute ( "\
0 commit comments