use std::collections::BTreeSet;
use std::path::Path;
fn public_names(source: &str, prefixes: &[&str]) -> BTreeSet<String> {
let mut rv = BTreeSet::new();
for line in source.lines() {
if let Some(rest) = line.trim().strip_prefix("pub mod ") {
rv.insert(rest.trim_end_matches([';', '{', ' ']).to_string());
}
}
let mut rest = source;
while let Some(start) = rest.find("pub use ") {
let stmt = &rest[start + "pub use ".len()..];
let end = stmt.find(';').unwrap();
rest = &stmt[end..];
let stmt = &stmt[..end];
if !prefixes.iter().any(|p| stmt.starts_with(&format!("{p}::"))) {
continue;
}
for path in stmt.split([',', '{', '}']) {
let name = path.trim().rsplit("::").next().unwrap();
if !name.is_empty() && name != "self" {
rv.insert(name.to_string());
}
}
}
rv.retain(|name| !name.starts_with("__"));
rv
}
#[test]
fn test_facade_reexports_core() {
if cfg!(miri) {
return;
}
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let core_dir = manifest_dir.join("../deser-core/src");
let Ok(core) = std::fs::read_to_string(core_dir.join("lib.rs")) else {
return;
};
let macros = std::fs::read_to_string(core_dir.join("macros.rs")).unwrap();
let facade = std::fs::read_to_string(manifest_dir.join("src/lib.rs")).unwrap();
let mut expected = public_names(&core, &["self"]);
let mut exported = false;
for line in macros.lines().map(str::trim) {
if line == "#[macro_export]" {
exported = true;
} else if let Some(name) = line.strip_prefix("macro_rules! ") {
if exported {
expected.insert(name.trim_end_matches([' ', '{']).to_string());
}
exported = false;
}
}
expected.retain(|name| !name.starts_with("__"));
let actual = public_names(&facade, &["deser_core", "crate"]);
let missing: Vec<_> = expected.difference(&actual).collect();
assert!(
missing.is_empty(),
"deser does not re-export these items of deser-core: {missing:?}"
);
}