Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/tools/build-templated-pages/src/features.rs
6595 views
1
use core::cmp::Ordering;
2
use std::fs::File;
3
4
use serde::Serialize;
5
use tera::{Context, Tera};
6
use toml_edit::DocumentMut;
7
8
use crate::Command;
9
10
#[derive(Debug, Serialize, PartialEq, Eq)]
11
struct Feature {
12
name: String,
13
description: String,
14
is_default: bool,
15
}
16
17
impl Ord for Feature {
18
fn cmp(&self, other: &Self) -> Ordering {
19
self.name.cmp(&other.name)
20
}
21
}
22
23
impl PartialOrd for Feature {
24
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
25
Some(self.cmp(other))
26
}
27
}
28
29
fn parse_features(panic_on_missing: bool) -> Vec<Feature> {
30
let manifest_file = std::fs::read_to_string("Cargo.toml").unwrap();
31
let manifest = manifest_file.parse::<DocumentMut>().unwrap();
32
33
let features = manifest["features"].as_table().unwrap();
34
let default: Vec<_> = features
35
.get("default")
36
.unwrap()
37
.as_array()
38
.unwrap()
39
.iter()
40
.flat_map(|v| {
41
core::iter::once(v.as_str().unwrap().to_string()).chain(
42
features
43
.get(v.as_str().unwrap())
44
.unwrap()
45
.as_array()
46
.unwrap()
47
.iter()
48
.map(|v| v.as_str().unwrap().to_string()),
49
)
50
})
51
.collect();
52
53
features
54
.get_values()
55
.iter()
56
.flat_map(|(key, _)| {
57
let key = key[0];
58
59
if key == "default" {
60
None
61
} else {
62
let name = key
63
.as_repr()
64
.unwrap()
65
.as_raw()
66
.as_str()
67
.unwrap()
68
.to_string();
69
if let Some(description) = key.leaf_decor().prefix() {
70
let description = description.as_str().unwrap().to_string();
71
if !description.starts_with("\n# ") || !description.ends_with('\n') {
72
panic!("Missing description for feature {name}");
73
}
74
let description = description
75
.strip_prefix("\n# ")
76
.unwrap()
77
.strip_suffix('\n')
78
.unwrap()
79
.to_string();
80
Some(Feature {
81
is_default: default.contains(&name),
82
name,
83
description,
84
})
85
} else if panic_on_missing {
86
panic!("Missing description for feature {name}");
87
} else {
88
None
89
}
90
}
91
})
92
.collect()
93
}
94
95
pub(crate) fn check(what_to_run: Command) {
96
let mut features = parse_features(what_to_run.contains(Command::CHECK_MISSING));
97
features.sort();
98
99
if what_to_run.contains(Command::UPDATE) {
100
let mut context = Context::new();
101
context.insert("features", &features);
102
Tera::new("docs-template/*.md.tpl")
103
.expect("error parsing template")
104
.render_to(
105
"features.md.tpl",
106
&context,
107
File::create("docs/cargo_features.md").expect("error creating file"),
108
)
109
.expect("error rendering template");
110
}
111
}
112
113