pub type GeneratedFile = (&'static str, String);
const GENERATED_MANIFEST: &str = r#"[package]
name = "app"
version = "0.1.0"
edition = "2021"
"#;
pub const TOPOLOGY_WIDTH: usize = 3;
pub const TOPOLOGY_MODULES: usize = 1 << (TOPOLOGY_WIDTH * TOPOLOGY_WIDTH);
const TOPOLOGY_SUFFIXES: [&str; TOPOLOGY_WIDTH] = ["a", "b", "c"];
fn generated_library(source: String) -> Vec<GeneratedFile> {
vec![
("repo/Cargo.toml", GENERATED_MANIFEST.to_owned()),
("repo/src/lib.rs", source),
]
}
pub fn topology_states(subset: usize, from: usize, to: usize) -> bool {
subset & (1 << (from * TOPOLOGY_WIDTH + to)) != 0
}
pub fn topology_name(subset: usize, at: usize) -> String {
format!("m{subset}_{}", TOPOLOGY_SUFFIXES[at])
}
pub fn topology_corpus() -> Vec<GeneratedFile> {
generated_library((0..TOPOLOGY_MODULES).map(topology_module).collect())
}
fn topology_module(subset: usize) -> String {
let declared: String = (0..TOPOLOGY_WIDTH)
.map(|from| topology_function(subset, from))
.collect();
format!("pub mod m{subset} {{\n{declared}}}\n\n")
}
fn topology_function(subset: usize, from: usize) -> String {
let calls: String = (0..TOPOLOGY_WIDTH)
.filter(|to| topology_states(subset, from, *to))
.map(|to| format!(" {}();\n", topology_name(subset, to)))
.collect();
format!(
" pub fn {}() {{\n{calls} }}\n",
topology_name(subset, from)
)
}
pub fn diamond_corpus(multiplicity: usize) -> Vec<GeneratedFile> {
generated_library(format!(
"pub fn seed() {{\n{}{}}}\n\npub fn left() {{\n{}}}\n\npub fn right() \
{{\n{}}}\n\npub fn sink() {{}}\n",
repeated_call("left", multiplicity),
repeated_call("right", multiplicity),
repeated_call("sink", multiplicity),
repeated_call("sink", multiplicity),
))
}
fn repeated_call(target: &str, multiplicity: usize) -> String {
(0..multiplicity)
.map(|_| format!(" {target}();\n"))
.collect()
}
pub fn linear_corpus(length: usize) -> Vec<GeneratedFile> {
generated_library((0..length).map(|at| linear_function(at, length)).collect())
}
fn linear_function(at: usize, length: usize) -> String {
let call = match at + 1 < length {
true => format!(" {}();\n", linear_name(at + 1)),
false => String::new(),
};
format!("pub fn {}() {{\n{call}}}\n\n", linear_name(at))
}
pub fn linear_name(at: usize) -> String {
format!("step{at}")
}