1use crate::db::{InputFile, RidlDatabase};
10use crate::package::{Package, PackageOrigin};
11
12pub const RIDL_STD_SOURCE: &str = include_str!("../assets/ridl_std.typl");
14
15pub const RIDL_STD_NAME: &str = "ridl.std";
17
18pub const RESERVED_PACKAGE_NAMES: &[&str] = &[RIDL_STD_NAME];
26
27pub fn is_reserved_package_name(name: &str) -> bool {
29 RESERVED_PACKAGE_NAMES.contains(&name)
30}
31
32pub const RIDL_STD_PATH: &str = "<builtin>/ridl_std.typl";
35
36pub fn std_package(db: &mut RidlDatabase) -> Package {
42 if let Some(&package) = db.std_package_cache.get() {
43 return package;
44 }
45 let file = InputFile::new(&*db, RIDL_STD_PATH.to_string(), RIDL_STD_SOURCE.to_string());
46 let package = Package::new(
47 &*db,
48 RIDL_STD_NAME.to_string(),
49 vec![file],
50 PackageOrigin::Std,
51 std::collections::BTreeMap::new(),
52 None,
53 None,
54 );
55 let _ = db.std_package_cache.set(package);
56 package
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::db::parse_file;
63
64 #[test]
68 fn std_package_parses_clean_and_exposes_ridl_std() {
69 let mut db = RidlDatabase::default();
70 let package = std_package(&mut db);
71
72 assert_eq!(package.name(&db).as_str(), "ridl.std");
73 assert_eq!(*package.origin(&db), PackageOrigin::Std);
74 assert!(
75 package.imports(&db).is_empty(),
76 "the built-in package has no manifest and no imports",
77 );
78
79 let files = package.files(&db);
80 assert_eq!(files.len(), 1, "ridl.std is a single embedded file");
81 assert_eq!(files[0].path(&db).as_str(), RIDL_STD_PATH);
82
83 let parse = parse_file(&db, files[0]);
84 assert_eq!(
85 parse.errors(),
86 &[],
87 "the embedded Appendix A source must parse without errors",
88 );
89
90 let declared = parse.syntax().text().to_string();
91 assert_eq!(declared, RIDL_STD_SOURCE, "the parse is lossless");
92 assert!(
93 RIDL_STD_SOURCE.starts_with("package ridl.std\n"),
94 "the asset starts with the `package ridl.std` declaration",
95 );
96 }
97
98 #[test]
99 fn std_package_is_memoized_per_database() {
100 let mut db = RidlDatabase::default();
101 let first = std_package(&mut db);
102 let second = std_package(&mut db);
103 assert_eq!(first, second, "the same database returns the same package");
104 }
105
106 #[test]
114 fn the_asset_is_appendix_a_verbatim() {
115 let reference = std::fs::read_to_string(concat!(
116 env!("CARGO_MANIFEST_DIR"),
117 "/../../docs/specification/typl-language-reference.md"
118 ))
119 .expect("the typl reference is readable");
120
121 let block = reference
122 .split("```ridl\n")
123 .find(|block| block.starts_with("package ridl.std\n"))
124 .and_then(|block| block.split("\n```").next())
125 .expect("Appendix A carries a `ridl.std` fenced block");
126
127 assert_eq!(
128 format!("{block}\n"),
129 RIDL_STD_SOURCE,
130 "`crates/ridl-core/assets/ridl_std.typl` and Appendix A of \
131 `docs/specification/typl-language-reference.md` have drifted apart. \
132 They are the same normative text and are edited together.",
133 );
134 }
135}