#![allow(
clippy::same_name_method,
reason = "rust-embed derive generates conflicting method names"
)]
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "install/"]
struct InstallAssets;
#[derive(RustEmbed)]
#[folder = "publication/"]
struct PublicationAssets;
pub(crate) fn read_bytes(key: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
InstallAssets::get(key).map(|f| f.data)
}
pub(crate) fn exists(key: &str) -> bool {
iter().any(|name| name == key)
}
pub(crate) fn read_text(key: &str) -> anyhow::Result<String> {
use anyhow::Context;
let file =
InstallAssets::get(key).with_context(|| format!("Embedded asset '{key}' is missing"))?;
let text = std::str::from_utf8(&file.data)
.with_context(|| format!("Embedded asset '{key}' is not valid UTF-8"))?;
Ok(text.to_string())
}
pub(crate) fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
InstallAssets::iter()
}
pub(crate) fn publication_manifest_bytes() -> Option<std::borrow::Cow<'static, [u8]>> {
PublicationAssets::get("manifest.toml").map(|f| f.data)
}
#[cfg(test)]
pub(crate) fn install_asset_keys_from_disk() -> Vec<String> {
let root = crate::test_support::repo_root().join("install");
let mut names: Vec<String> = walkdir::WalkDir::new(&root)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.file_type().is_file())
.filter_map(|e| {
e.path()
.strip_prefix(&root)
.ok()
.map(|p| p.to_string_lossy().replace('\\', "/"))
})
.filter(|n| n != "manifest.toml")
.collect();
names.sort();
names
}
#[cfg(test)]
pub(crate) fn publication_manifest_bytes_from_disk() -> Vec<u8> {
let path = crate::test_support::repo_root().join("publication/manifest.toml");
std::fs::read(&path).expect("shipped publication/manifest.toml on disk")
}
#[cfg(test)]
pub(crate) fn base_backings_from_disk() -> Vec<String> {
#[derive(serde::Deserialize)]
struct BaseOnly {
base: Base,
}
#[derive(serde::Deserialize)]
struct Base {
backings: Vec<String>,
}
let path = crate::test_support::repo_root().join("install/manifest.toml");
let bytes = std::fs::read(&path).expect("shipped install/manifest.toml on disk");
let text = std::str::from_utf8(&bytes).expect("install manifest is UTF-8");
let parsed: BaseOnly = toml::from_str(text).expect("install manifest [base] parses");
parsed.base.backings
}
#[cfg(test)]
pub(crate) fn assert_unprojected_install_assets_are_published() {
let published =
crate::publication::PublicationManifest::admit(&publication_manifest_bytes_from_disk())
.expect("shipped publication manifest admits from disk");
let base: std::collections::BTreeSet<String> = base_backings_from_disk().into_iter().collect();
let mut checked = 0usize;
for key in install_asset_keys_from_disk() {
if base.contains(&key) {
continue;
}
assert!(
published.declares_backing(&key),
"install asset {key:?} is neither a base backing nor published — the \
minimal-projection flip would strand it (disk-source reachability gate)"
);
checked += 1;
}
assert!(
checked > 0,
"the disk enumerator must yield non-base install assets to check"
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_bytes_and_read_text_agree_on_text_asset() {
let key = "manifest.toml";
let bytes = read_bytes(key).expect("install/manifest.toml is embedded");
assert!(!bytes.is_empty(), "manifest.toml should not be empty");
let text = read_text(key).expect("install/manifest.toml is valid UTF-8");
assert_eq!(
text.as_bytes(),
bytes.as_ref(),
"read_text must reproduce read_bytes byte-for-byte on a UTF-8 asset"
);
}
#[test]
fn exists_true_for_embedded_asset_false_for_absent() {
assert!(exists("manifest.toml"), "embedded install asset exists");
assert!(
!exists("no/such/asset.xyz"),
"absent asset key does not exist"
);
}
#[test]
fn iter_enumerates_install_assets() {
assert!(
iter().any(|name| name == "manifest.toml"),
"iter() should enumerate the InstallAssets embed"
);
}
}