use crate::licensing::{crates_dir, default_sample_crates, read};
pub(crate) fn embedded_payload() -> (usize, usize, u64) {
let crates = default_sample_crates();
let mut files = 0usize;
let mut bytes = 0u64;
for krate in &crates {
let dir = crates_dir().join(krate).join("samples");
let entries = std::fs::read_dir(&dir).unwrap_or_else(|e| {
panic!(
"payload oracle cannot read {}: {e}.\n\
It derives the embedded total from the sibling asset crates, so it \
only runs inside the ferrosintesis workspace.",
dir.display()
)
});
for entry in entries {
let entry = entry.expect("readable directory entry");
if entry
.path()
.extension()
.is_some_and(|e| e == "wav" || e == "flac")
{
files += 1;
bytes += entry.metadata().expect("readable metadata").len();
}
}
}
assert!(
crates.len() > 15 && files > 500,
"payload scan collapsed to {} crates / {files} files — the oracle would pass \
vacuously. Check the `embedded-samples` feature list parse.",
crates.len()
);
(crates.len(), files, bytes)
}
#[cfg(test)]
mod tests {
use super::*;
fn spelled(n: usize) -> String {
const ONES: [&str; 20] = [
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
];
const TENS: [&str; 10] = [
"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
];
if n < 20 {
return ONES[n].to_string();
}
let (t, o) = (n / 10, n % 10);
if o == 0 {
TENS[t].to_string()
} else {
format!("{}-{}", TENS[t], ONES[o])
}
}
fn parent(file: &str) -> String {
read(&crates_dir().join("ferrosintesis").join(file))
}
fn size_claims() -> Vec<(&'static str, String, f64)> {
let mut out = Vec::new();
for file in ["README.md", "NOTICE", "src/lib.rs"] {
for line in parent(file).lines() {
let lower = line.to_lowercase();
let has_unit = lower.contains("mib") || lower.contains(" mb");
let about_embedding = lower.contains("embed") || lower.contains("compil");
if !has_unit || !about_embedding || lower.trim_start().starts_with('|') {
continue;
}
for tok in line.split(|c: char| !(c.is_ascii_digit() || c == '.')) {
let Ok(v) = tok.trim_matches('.').parse::<f64>() else {
continue;
};
if v >= 1.0 {
out.push((file, line.to_string(), v));
}
}
}
}
out
}
fn number_tokens(line: &str) -> Vec<String> {
line.split(|c: char| !(c.is_alphanumeric() || c == '-'))
.map(|t| t.trim_matches('-').to_lowercase())
.filter(|t| !t.is_empty())
.collect()
}
fn as_number(tok: &str) -> Option<usize> {
if let Ok(v) = tok.parse::<usize>() {
return Some(v);
}
(0..=40).find(|&n| spelled(n) == tok)
}
fn claimed_counts_in(line: &str) -> Vec<usize> {
const FILLER: &[&str] = &["first-party", "sample-asset", "asset", "embedded"];
const SUBSET: &[&str] = &["remaining", "other", "another", "further", "only"];
let lower = line.to_lowercase();
let mut out = Vec::new();
let toks = number_tokens(&lower);
for (i, tok) in toks.iter().enumerate() {
if tok != "crates" && tok != "banks" {
continue;
}
let mut j = i;
let mut hops = 0;
while j > 0 && hops < 4 {
j -= 1;
hops += 1;
let prev = toks[j].as_str();
if let Some(n) = as_number(prev) {
let asset_context =
tok == "banks" || toks[j..=i].iter().any(|t| FILLER.contains(&t.as_str()));
let subset = j > 0 && SUBSET.contains(&toks[j - 1].as_str());
if asset_context && !subset {
out.push(n);
}
break;
}
if !FILLER.contains(&prev) {
break;
}
}
}
out
}
fn crate_count_claims() -> Vec<(&'static str, String, usize)> {
let mut out = Vec::new();
for file in ["README.md", "NOTICE", "src/lib.rs"] {
for line in parent(file).lines() {
if line.trim_start().starts_with('|') {
continue;
}
for n in claimed_counts_in(line) {
out.push((file, line.to_string(), n));
}
}
}
out
}
const NUMBER_WORDS: &[&str] = &[
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen",
"twenty",
"twenty-one",
"twenty-two",
"twenty-three",
"twenty-four",
"twenty-five",
"twenty-six",
"twenty-seven",
"twenty-eight",
"twenty-nine",
"thirty",
];
#[test]
fn no_document_states_a_stale_asset_crate_count() {
let (crates, _, _) = embedded_payload();
let claims = crate_count_claims();
assert!(
!claims.is_empty(),
"no document quotes an asset-crate count at all — either the wording changed \
and this oracle now scans nothing, or the figure was dropped."
);
let mut stated_correctly = false;
for (file, line, claimed) in &claims {
assert_eq!(
*claimed,
crates,
"{file} states {claimed} asset crates, but a default build embeds \
{crates} ({}), in:\n {line}\n\
If you just added or split a crate, this is the oracle doing its job.",
spelled(crates),
);
stated_correctly = true;
}
assert!(
stated_correctly,
"no document states the asset-crate count ({crates} / {})",
spelled(crates),
);
}
#[test]
fn documented_payload_size_is_within_ten_percent() {
let (_, _, bytes) = embedded_payload();
let real_mib = bytes as f64 / (1024.0 * 1024.0);
let claims = size_claims();
assert!(
!claims.is_empty(),
"no embedded-size claim found in any of the three documents — either the \
wording changed and this oracle now scans nothing, or the size claim was \
dropped. Both need a human."
);
for (file, line, v) in &claims {
let err = (v - real_mib).abs() / real_mib;
assert!(
err <= 0.10,
"{file} claims {v} MiB of embedded audio but the default feature embeds \
{real_mib:.1} MiB ({:.0}% off), in:\n {line}",
err * 100.0,
);
}
}
#[test]
fn the_oracles_reject_the_prose_they_were_written_to_catch() {
let real = 24usize;
let stale_counts = [
"sample-asset crates into the binary. Eleven are CC0 1.0 and require nothing.",
"A build with default features embeds all twenty-one banks.",
"16.68 MiB of CC0 attack transients (two first-party asset crates) into",
];
for text in stale_counts {
let lower = text.to_lowercase();
let toks = number_tokens(&lower);
let has_stale = toks
.iter()
.any(|t| NUMBER_WORDS.contains(&t.as_str()) && *t != spelled(real));
assert!(
has_stale,
"the count predicate does NOT flag a known-stale line: {text:?}\n\
It would have passed the drift it exists to catch."
);
}
for benign in [
"`embedded-samples` (default) compiles the asset crates into the binary.",
"sample-asset crates into the binary. Fourteen are CC0 1.0 and require nothing. The ten below are not,",
"ten of the twenty-four crates carry an attribution obligation",
"The remaining fourteen banks are CC0 and require nothing.",
] {
for got in claimed_counts_in(benign) {
assert_eq!(
got, real,
"the extractor invented a count {got} from benign prose {benign:?}"
);
}
}
let real_mib = embedded_payload().2 as f64 / (1024.0 * 1024.0);
for stale in [22.0_f64, 16.68] {
assert!(
(stale - real_mib).abs() / real_mib > 0.10,
"the size bound would ACCEPT the stale claim {stale} MiB against the real \
{real_mib:.1} MiB — the tolerance is too loose to catch real drift."
);
}
assert!(
(real_mib * 1.05 - real_mib).abs() / real_mib <= 0.10,
"the size bound rejects a figure only 5% out; it is too tight for routine \
re-cutting and will produce docs churn."
);
}
#[test]
fn payload_scan_covers_every_default_sample_crate() {
let (crates, files, bytes) = embedded_payload();
let members = read(&crates_dir().parent().unwrap().join("Cargo.toml"));
let declared = members
.lines()
.filter(|l| l.contains("crates/ferrosintesis-samples-"))
.count();
assert_eq!(
crates, declared,
"the `embedded-samples` feature lists {crates} sample crates but the \
workspace declares {declared} members. A crate in the workspace but not in \
the default feature is embedded by nobody; add it to the feature list, or \
mark it optional-by-design here."
);
assert!(
files > 1000 && bytes > 48 * 1024 * 1024,
"payload scan found only {files} files / {bytes} bytes"
);
}
#[test]
fn no_two_asset_crates_ship_the_same_wav_basename() {
let mut owner: std::collections::HashMap<String, String> = std::collections::HashMap::new();
let mut clashes: Vec<String> = Vec::new();
let mut scanned = 0usize;
let mut crate_dirs: Vec<_> = std::fs::read_dir(crates_dir())
.expect("readable crates/ directory")
.map(|e| e.expect("readable entry").path())
.filter(|p| {
p.file_name()
.and_then(|n| n.to_str())
.is_some_and(|n| n.starts_with("ferrosintesis-samples-"))
})
.collect();
crate_dirs.sort();
for dir in &crate_dirs {
let krate = dir
.file_name()
.and_then(|n| n.to_str())
.expect("crate dir name")
.to_owned();
let samples = dir.join("samples");
let Ok(entries) = std::fs::read_dir(&samples) else {
continue;
};
for entry in entries {
let path = entry.expect("readable directory entry").path();
if path.extension().is_some_and(|e| e == "wav" || e == "flac") {
let name = path
.file_name()
.and_then(|n| n.to_str())
.expect("wav file name")
.to_owned();
scanned += 1;
if let Some(first) = owner.insert(name.clone(), krate.clone()) {
clashes.push(format!("{name} is in both {first} and {krate}"));
}
}
}
if let Ok(aliases) = std::fs::read_to_string(dir.join("ALIASES")) {
for line in aliases.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let Some(alias) = line.split_whitespace().next() else {
continue;
};
scanned += 1;
if let Some(first) = owner.insert(alias.to_owned(), krate.clone()) {
clashes.push(format!(
"{alias} is an alias in {krate} and a name in {first}"
));
}
}
}
}
assert!(
crate_dirs.len() > 15 && scanned > 500,
"basename scan collapsed to {} crates / {scanned} WAVs — it would pass \
vacuously. Check that crates/ still holds the asset crates.",
crate_dirs.len()
);
assert!(
clashes.is_empty(),
"{} duplicate WAV basename(s) across asset crates; `embedded_wav` resolves by \
bare filename, first match wins, so the later crate's copy is unreachable and \
a voice would silently play the wrong recording:\n {}",
clashes.len(),
clashes.join("\n ")
);
}
}