@@ -2,7 +2,7 @@ use std::{cmp::Ordering, fs::File};
2
2
3
3
use serde:: Serialize ;
4
4
use tera:: { Context , Tera } ;
5
- use toml_edit:: Document ;
5
+ use toml_edit:: { Document , Key , RawString , Table , Value } ;
6
6
7
7
use crate :: Command ;
8
8
@@ -25,29 +25,9 @@ impl PartialOrd for Feature {
25
25
}
26
26
}
27
27
28
- fn parse_features ( panic_on_missing : bool ) -> Vec < Feature > {
29
- let manifest_file = std:: fs:: read_to_string ( "Cargo.toml" ) . unwrap ( ) ;
30
- let manifest = manifest_file. parse :: < Document > ( ) . unwrap ( ) ;
31
-
32
- let features = manifest[ "features" ] . as_table ( ) . unwrap ( ) ;
33
- let default: Vec < _ > = features
34
- . get ( "default" )
35
- . unwrap ( )
36
- . as_array ( )
37
- . unwrap ( )
38
- . iter ( )
39
- . flat_map ( |v| {
40
- std:: iter:: once ( v. as_str ( ) . unwrap ( ) . to_string ( ) ) . chain (
41
- features
42
- . get ( v. as_str ( ) . unwrap ( ) )
43
- . unwrap ( )
44
- . as_array ( )
45
- . unwrap ( )
46
- . iter ( )
47
- . map ( |v| v. as_str ( ) . unwrap ( ) . to_string ( ) ) ,
48
- )
49
- } )
50
- . collect ( ) ;
28
+ fn parse_features ( what_to_run : Command ) -> Vec < Feature > {
29
+ let features = get_manifest_features ( ) ;
30
+ let default = get_default_features ( & features) ;
51
31
52
32
features
53
33
. get_values ( )
@@ -58,53 +38,88 @@ fn parse_features(panic_on_missing: bool) -> Vec<Feature> {
58
38
if key == "default" {
59
39
None
60
40
} else {
61
- let name = key
62
- . as_repr ( )
63
- . unwrap ( )
64
- . as_raw ( )
65
- . as_str ( )
66
- . unwrap ( )
67
- . to_string ( ) ;
68
- if let Some ( description) = key. leaf_decor ( ) . prefix ( ) {
69
- let description = description. as_str ( ) . unwrap ( ) . to_string ( ) ;
70
- if !description. starts_with ( "\n # " ) || !description. ends_with ( '\n' ) {
71
- panic ! ( "Missing description for feature {name}" ) ;
41
+ let key_name = get_key_name ( key) ;
42
+ let key_prefix = key. leaf_decor ( ) . prefix ( ) ;
43
+ if what_to_run. contains ( Command :: CHECK_MISSING ) {
44
+ if let Some ( description) = key_prefix {
45
+ create_feature ( & default, key_name, description)
46
+ } else {
47
+ panic ! ( "Missing description for feature {key_name}" ) ;
72
48
}
73
- let description = description
74
- . strip_prefix ( "\n # " )
75
- . unwrap ( )
76
- . strip_suffix ( '\n' )
77
- . unwrap ( )
78
- . to_string ( ) ;
79
- Some ( Feature {
80
- is_default : default. contains ( & name) ,
81
- name,
82
- description,
83
- } )
84
- } else if panic_on_missing {
85
- panic ! ( "Missing description for feature {name}" ) ;
86
49
} else {
87
- None
50
+ let feature = |description| create_feature ( & default, key_name, description) ;
51
+ key_prefix. map ( feature) . unwrap ( )
88
52
}
89
53
}
90
54
} )
91
55
. collect ( )
92
56
}
93
57
94
- pub ( crate ) fn check ( what_to_run : Command ) {
95
- let mut features = parse_features ( what_to_run. contains ( Command :: CHECK_MISSING ) ) ;
58
+ fn get_manifest_features ( ) -> Table {
59
+ let manifest_file = std:: fs:: read_to_string ( "Cargo.toml" ) . unwrap ( ) ;
60
+ let manifest = manifest_file. parse :: < Document > ( ) . unwrap ( ) ;
61
+ let features = manifest[ "features" ] . as_table ( ) . unwrap ( ) . clone ( ) ;
62
+ features
63
+ }
64
+
65
+ fn create_feature ( default : & [ String ] , name : String , description : & RawString ) -> Option < Feature > {
66
+ let description = description. as_str ( ) . unwrap ( ) . to_string ( ) ;
67
+ if let Some ( stripped_description) = description
68
+ . strip_prefix ( "\n # " )
69
+ . and_then ( |d| d. strip_suffix ( '\n' ) )
70
+ {
71
+ let is_default = default. contains ( & name) ;
72
+ let description = get_description ( stripped_description. to_string ( ) , & name) ;
73
+ Some ( Feature {
74
+ is_default,
75
+ name,
76
+ description,
77
+ } )
78
+ } else {
79
+ panic ! ( "Missing description for feature {name}" ) ;
80
+ }
81
+ }
82
+
83
+ fn get_description ( description : String , name : & String ) -> String {
84
+ let description = description. to_string ( ) ;
85
+ if !description. starts_with ( "\n # " ) || !description. ends_with ( '\n' ) {
86
+ panic ! ( "Missing description for feature {name}" ) ;
87
+ }
88
+ let stripped_description = description. strip_prefix ( "\n # " ) . unwrap ( ) . strip_suffix ( '\n' ) ;
89
+ stripped_description. unwrap ( ) . to_string ( )
90
+ }
91
+
92
+ fn get_key_name ( key : & Key ) -> String {
93
+ let key_repr = key. as_repr ( ) . unwrap ( ) ;
94
+ key_repr. as_raw ( ) . as_str ( ) . unwrap ( ) . to_string ( )
95
+ }
96
+
97
+ fn get_default_features ( features : & Table ) -> Vec < String > {
98
+ let value = |v : & Value | {
99
+ let feature_name = v. as_str ( ) . unwrap ( ) ;
100
+ let feature = |v : & Value | v. as_str ( ) . unwrap ( ) . to_string ( ) ;
101
+ let features_to_array = |name| features. get ( name) . unwrap ( ) . as_array ( ) . unwrap ( ) ;
102
+ let map = features_to_array ( feature_name) . iter ( ) . map ( feature) ;
103
+ std:: iter:: once ( feature_name. to_string ( ) ) . chain ( map)
104
+ } ;
105
+ let features_to_array = |name| features. get ( name) . unwrap ( ) . as_array ( ) . unwrap ( ) ;
106
+ features_to_array ( "default" )
107
+ . iter ( )
108
+ . flat_map ( value)
109
+ . collect ( )
110
+ }
111
+
112
+ pub ( crate ) fn check ( command : Command ) {
113
+ let mut features = parse_features ( command) ;
96
114
features. sort ( ) ;
97
115
98
- if what_to_run . contains ( Command :: UPDATE ) {
116
+ if command . contains ( Command :: UPDATE ) {
99
117
let mut context = Context :: new ( ) ;
100
118
context. insert ( "features" , & features) ;
119
+ let file = File :: create ( "docs/cargo_features.md" ) . expect ( "error creating file" ) ;
101
120
Tera :: new ( "docs-template/*.md.tpl" )
102
121
. expect ( "error parsing template" )
103
- . render_to (
104
- "features.md.tpl" ,
105
- & context,
106
- File :: create ( "docs/cargo_features.md" ) . expect ( "error creating file" ) ,
107
- )
122
+ . render_to ( "features.md.tpl" , & context, file)
108
123
. expect ( "error rendering template" ) ;
109
124
}
110
125
}
0 commit comments