use crate::db::{InputFile, RidlDatabase};
use crate::manifest::TimingDefaults;
use crate::package::{Package, PackageOrigin};
pub const RIDL_STD_SOURCE: &str = include_str!("../assets/ridl_std.typl");
pub const RIDL_STD_NAME: &str = "ridl.std";
pub const RESERVED_PACKAGE_NAMES: &[&str] = &[RIDL_STD_NAME];
pub fn is_reserved_package_name(name: &str) -> bool {
RESERVED_PACKAGE_NAMES.contains(&name)
}
pub const RIDL_STD_PATH: &str = "<builtin>/ridl_std.typl";
pub fn std_package(db: &mut RidlDatabase) -> Package {
if let Some(&package) = db.std_package_cache.get() {
return package;
}
let file = InputFile::new(&*db, RIDL_STD_PATH.to_string(), RIDL_STD_SOURCE.to_string());
let package = Package::new(
&*db,
RIDL_STD_NAME.to_string(),
vec![file],
PackageOrigin::Std,
std::collections::BTreeMap::new(),
TimingDefaults::default(),
None,
);
let _ = db.std_package_cache.set(package);
package
}
#[cfg(test)]
mod tests {
use super::*;
use crate::db::parse_file;
#[test]
fn std_package_parses_clean_and_exposes_ridl_std() {
let mut db = RidlDatabase::default();
let package = std_package(&mut db);
assert_eq!(package.name(&db).as_str(), "ridl.std");
assert_eq!(*package.origin(&db), PackageOrigin::Std);
assert!(
package.imports(&db).is_empty(),
"the built-in package has no manifest and no imports",
);
let files = package.files(&db);
assert_eq!(files.len(), 1, "ridl.std is a single embedded file");
assert_eq!(files[0].path(&db).as_str(), RIDL_STD_PATH);
let parse = parse_file(&db, files[0]);
assert_eq!(
parse.errors(),
&[],
"the embedded Appendix A source must parse without errors",
);
let declared = parse.syntax().text().to_string();
assert_eq!(declared, RIDL_STD_SOURCE, "the parse is lossless");
assert!(
RIDL_STD_SOURCE.starts_with("package ridl.std\n"),
"the asset starts with the `package ridl.std` declaration",
);
}
#[test]
fn std_package_is_memoized_per_database() {
let mut db = RidlDatabase::default();
let first = std_package(&mut db);
let second = std_package(&mut db);
assert_eq!(first, second, "the same database returns the same package");
}
#[test]
fn the_asset_is_appendix_a_verbatim() {
let reference = std::fs::read_to_string(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../docs/specification/typl-language-reference.md"
))
.expect("the typl reference is readable");
let block = reference
.split("```ridl\n")
.find(|block| block.starts_with("package ridl.std\n"))
.and_then(|block| block.split("\n```").next())
.expect("Appendix A carries a `ridl.std` fenced block");
assert_eq!(
format!("{block}\n"),
RIDL_STD_SOURCE,
"`crates/ridl-core/assets/ridl_std.typl` and Appendix A of \
`docs/specification/typl-language-reference.md` have drifted apart. \
They are the same normative text and are edited together.",
);
}
}