Path: blob/main/tools/build-templated-pages/src/features.rs
6595 views
use core::cmp::Ordering;1use std::fs::File;23use serde::Serialize;4use tera::{Context, Tera};5use toml_edit::DocumentMut;67use crate::Command;89#[derive(Debug, Serialize, PartialEq, Eq)]10struct Feature {11name: String,12description: String,13is_default: bool,14}1516impl Ord for Feature {17fn cmp(&self, other: &Self) -> Ordering {18self.name.cmp(&other.name)19}20}2122impl PartialOrd for Feature {23fn partial_cmp(&self, other: &Self) -> Option<Ordering> {24Some(self.cmp(other))25}26}2728fn parse_features(panic_on_missing: bool) -> Vec<Feature> {29let manifest_file = std::fs::read_to_string("Cargo.toml").unwrap();30let manifest = manifest_file.parse::<DocumentMut>().unwrap();3132let features = manifest["features"].as_table().unwrap();33let default: Vec<_> = features34.get("default")35.unwrap()36.as_array()37.unwrap()38.iter()39.flat_map(|v| {40core::iter::once(v.as_str().unwrap().to_string()).chain(41features42.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();5152features53.get_values()54.iter()55.flat_map(|(key, _)| {56let key = key[0];5758if key == "default" {59None60} else {61let name = key62.as_repr()63.unwrap()64.as_raw()65.as_str()66.unwrap()67.to_string();68if let Some(description) = key.leaf_decor().prefix() {69let description = description.as_str().unwrap().to_string();70if !description.starts_with("\n# ") || !description.ends_with('\n') {71panic!("Missing description for feature {name}");72}73let description = description74.strip_prefix("\n# ")75.unwrap()76.strip_suffix('\n')77.unwrap()78.to_string();79Some(Feature {80is_default: default.contains(&name),81name,82description,83})84} else if panic_on_missing {85panic!("Missing description for feature {name}");86} else {87None88}89}90})91.collect()92}9394pub(crate) fn check(what_to_run: Command) {95let mut features = parse_features(what_to_run.contains(Command::CHECK_MISSING));96features.sort();9798if what_to_run.contains(Command::UPDATE) {99let mut context = Context::new();100context.insert("features", &features);101Tera::new("docs-template/*.md.tpl")102.expect("error parsing template")103.render_to(104"features.md.tpl",105&context,106File::create("docs/cargo_features.md").expect("error creating file"),107)108.expect("error rendering template");109}110}111112113