more tables

This commit is contained in:
nora 2024-02-07 21:12:08 +01:00
parent f4493e17b2
commit 09ee1f7a33
3 changed files with 123 additions and 39 deletions

View file

@ -8,7 +8,7 @@ use std::{
};
use eyre::{bail, Context, OptionExt, Result};
use parse::ParsedTargetInfoFile;
use parse::{ParsedTargetInfoFile, Tier, TriStateBool};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
/// Information about a target obtained from `target_info.toml``.
@ -16,7 +16,7 @@ struct TargetDocs {
name: String,
maintainers: Vec<String>,
sections: Vec<(String, String)>,
tier: String,
tier: Option<Tier>,
// TODO: Make this mandatory.
metadata: Option<TargetMetadata>,
}
@ -24,8 +24,8 @@ struct TargetDocs {
/// Metadata for the table
struct TargetMetadata {
notes: String,
std: String,
host: String,
std: TriStateBool,
host: TriStateBool,
}
const SECTIONS: &[&str] = &[
@ -182,8 +182,7 @@ fn target_doc_info(info_patterns: &mut [TargetPatternEntry], target: &str) -> Ta
TargetDocs {
name: target.to_owned(),
maintainers,
// tier: tier.expect(&format!("no tier found for target {target}")),
tier: tier.unwrap_or("UNKNOWN".to_owned()),
tier,
sections,
metadata,
}

View file

@ -1,34 +1,53 @@
//! Suboptimal half-markdown parser that's just good-enough for this.
use eyre::{bail, OptionExt, Result, WrapErr};
use serde::Deserialize;
use std::{fs::DirEntry, path::Path};
#[derive(Debug, PartialEq, Clone, Deserialize)]
pub enum Tier {
#[serde(rename = "1")]
One,
#[serde(rename = "2")]
Two,
#[serde(rename = "3")]
Three,
}
#[derive(Debug)]
pub struct ParsedTargetInfoFile {
pub pattern: String,
pub tier: Option<String>,
pub tier: Option<Tier>,
pub maintainers: Vec<String>,
pub sections: Vec<(String, String)>,
pub metadata: Vec<ParsedTargetMetadata>,
}
#[derive(serde::Deserialize)]
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct Frontmatter {
tier: Option<String>,
tier: Option<Tier>,
#[serde(default)]
maintainers: Vec<String>,
#[serde(default)]
metadata: Vec<ParsedTargetMetadata>,
}
#[derive(Debug, Clone, serde::Deserialize)]
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ParsedTargetMetadata {
pub pattern: String,
pub notes: String,
pub std: String,
pub host: String,
pub std: TriStateBool,
pub host: TriStateBool,
}
#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TriStateBool {
True,
False,
Unknown,
}
pub fn load_target_infos(directory: &Path) -> Result<Vec<ParsedTargetInfoFile>> {
@ -112,6 +131,8 @@ fn parse_file(name: &str, content: &str) -> Result<ParsedTargetInfoFile> {
#[cfg(test)]
mod tests {
use crate::parse::Tier;
#[test]
fn no_frontmatter() {
let name = "archlinux-unknown-linux-gnu.md"; // arch linux is an arch, right?
@ -171,7 +192,7 @@ But it should be possible.
assert_eq!(info.maintainers, vec!["who maintains the cat?"]);
assert_eq!(info.pattern, name);
assert_eq!(info.tier, Some("1".to_owned()));
assert_eq!(info.tier, Some(Tier::One));
assert_eq!(
info.sections,
vec![

View file

@ -1,11 +1,32 @@
use eyre::{bail, Context, OptionExt, Result};
use eyre::{Context, OptionExt, Result};
use std::{fs, path::Path};
use crate::{is_in_rust_lang_rust, RustcTargetInfo, TargetDocs};
use crate::{
is_in_rust_lang_rust,
parse::{Tier, TriStateBool},
RustcTargetInfo, TargetDocs,
};
impl TargetDocs {
fn has_host_tools(&self) -> bool {
self.metadata
.as_ref()
.map_or(false, |meta| meta.host == TriStateBool::True)
}
}
/// Renders a single target markdown file from the information obtained.
pub fn render_target_md(target: &TargetDocs, rustc_info: &RustcTargetInfo) -> String {
let mut doc = format!("# {}\n\n**Tier: {}**\n\n", target.name, target.tier);
let mut doc = format!(
"# {}\n\n**Tier: {}**\n\n",
target.name,
match target.tier {
Some(Tier::One) => "1",
Some(Tier::Two) => "2",
Some(Tier::Three) => "3",
None => "UNKNOWN",
}
);
let mut section = |name: &str, content: &str| {
doc.push_str("## ");
@ -123,7 +144,7 @@ pub fn render_static(src_output: &Path, targets: &[(TargetDocs, RustcTargetInfo)
But as you might notice, all targets are actually present with a stub :3.
",
)
.unwrap();
.wrap_err("writing front page information about experiment")?;
}
// TODO: Render the nice table showing off all targets and their tier.
@ -131,20 +152,50 @@ pub fn render_static(src_output: &Path, targets: &[(TargetDocs, RustcTargetInfo)
let platform_support_main_old =
fs::read_to_string(&platform_support_main).wrap_err("reading platform-support.md")?;
let tier3_table =
render_table_with_host(targets.into_iter().filter(|target| target.0.tier == "3"))
.wrap_err("rendering tier 3 table")?;
// needs footnotes...
//let tier1host_table = render_table(
// targets
// .into_iter()
// .filter(|target| target.0.tier == Some(Tier::One)),
//)?;
// Tier 2 without host doesn't exist right now
// they all support std, obviously
//let tier2host_table = render_table_without_std this needs a better scheme??(
// targets
// .into_iter()
// .filter(|target| target.0.tier == Some(Tier::Two) && target.0.has_host_tools()),
//)
//.wrap_err("rendering tier 2 table")?;
let tier2_table = render_table(
targets
.into_iter()
.filter(|target| target.0.tier == Some(Tier::Two) && !target.0.has_host_tools()),
)?;
let tier3_table = render_table_with_host(
targets
.into_iter()
.filter(|target| target.0.tier == Some(Tier::Three)),
)?;
let platform_support_main_new =
replace_section(&platform_support_main_old, "TIER3", &tier3_table)
.wrap_err("replacing platform support.md")?;
let content = platform_support_main_old;
let content = replace_section(&content, "TIER2", &tier2_table)
.wrap_err("replacing platform support.md")?;
let content = replace_section(&content, "TIER3", &tier3_table)
.wrap_err("replacing platform support.md")?;
fs::write(platform_support_main, platform_support_main_new)
.wrap_err("writing platform-support.md")?;
fs::write(platform_support_main, content).wrap_err("writing platform-support.md")?;
Ok(())
}
fn render_table_tri_state_bool(bool: TriStateBool) -> &'static str {
match bool {
TriStateBool::True => "",
TriStateBool::False => " ",
TriStateBool::Unknown => "?",
}
}
fn render_table_with_host<'a>(
targets: impl IntoIterator<Item = &'a (TargetDocs, RustcTargetInfo)>,
) -> Result<String> {
@ -152,20 +203,13 @@ fn render_table_with_host<'a>(
for (target, _) in targets {
let meta = target.metadata.as_ref();
let std = match meta.map(|meta| meta.std.as_str()) {
Some("true") => "",
Some("unknown") => "?",
Some("false") => " ",
None => "?",
_ => bail!("invalid value for std todo parse early"),
};
let host = match meta.map(|meta| meta.host.as_str()) {
Some("true") => "",
Some("unknown") => "?",
Some("false") => " ",
None => "?",
_ => bail!("invalid value for host todo parse early"),
};
let std = meta
.map(|meta| render_table_tri_state_bool(meta.std))
.unwrap_or("?");
let host = meta
.map(|meta| render_table_tri_state_bool(meta.host))
.unwrap_or("?");
let notes = meta.map(|meta| meta.notes.as_str()).unwrap_or("unknown");
rows.push(format!(
"[`{0}`](platform-support/targets/{0}.md) | {std} | {host} | {notes}",
@ -175,3 +219,23 @@ fn render_table_with_host<'a>(
Ok(rows.join("\n"))
}
fn render_table<'a>(
targets: impl IntoIterator<Item = &'a (TargetDocs, RustcTargetInfo)>,
) -> Result<String> {
let mut rows = Vec::new();
for (target, _) in targets {
let meta = target.metadata.as_ref();
let std = meta
.map(|meta| render_table_tri_state_bool(meta.std))
.unwrap_or("?");
let notes = meta.map(|meta| meta.notes.as_str()).unwrap_or("unknown");
rows.push(format!(
"[`{0}`](platform-support/targets/{0}.md) | {std} | {notes}",
target.name
));
}
Ok(rows.join("\n"))
}