use std::sync::OnceLock;
use crate::host::{EMBEDDED_BLOCKS, EMBEDDED_LIBS, SEALED};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kind {
Block,
Lib,
}
impl Kind {
pub fn as_str(self) -> &'static str {
match self {
Kind::Block => "block",
Kind::Lib => "lib",
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Entry {
pub name: &'static str,
pub kind: Kind,
pub source: &'static str,
}
pub fn entries() -> &'static [Entry] {
static ENTRIES: OnceLock<Vec<Entry>> = OnceLock::new();
ENTRIES
.get_or_init(|| {
let blocks = EMBEDDED_BLOCKS.iter().map(|(name, source)| Entry {
name,
kind: Kind::Block,
source,
});
let libs = EMBEDDED_LIBS.iter().map(|(name, source)| Entry {
name,
kind: Kind::Lib,
source,
});
blocks.chain(libs).collect()
})
.as_slice()
}
pub fn find(name: &str) -> Option<&'static Entry> {
entries().iter().find(|e| e.name == name)
}
pub fn is_sealed(name: &str) -> bool {
let root = name.split('.').next().unwrap_or(name);
SEALED.iter().any(|s| *s == name || *s == root)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_entries_are_the_blocks_then_the_modules() {
let names: Vec<&str> = entries().iter().map(|e| e.name).collect();
assert_eq!(&names[..2], ["agent", "coding"]);
assert!(names.contains(&"lshape.t"), "{names:?}");
let blocks = entries().iter().filter(|e| e.kind == Kind::Block).count();
assert_eq!(blocks, EMBEDDED_BLOCKS.len());
assert_eq!(entries().len(), EMBEDDED_BLOCKS.len() + EMBEDDED_LIBS.len());
}
#[test]
fn an_entry_carries_its_source() {
let session = find("session").expect("session is embedded");
assert_eq!(session.kind, Kind::Lib);
assert!(session.source.contains("return M"), "{}", session.source);
assert!(find("no_such_module").is_none());
}
#[test]
fn the_seal_covers_a_root_and_its_parts() {
assert!(is_sealed("knl"));
assert!(is_sealed("knl_types"));
assert!(is_sealed("lshape"));
assert!(is_sealed("lshape.t"));
assert!(is_sealed("lshape.whatever_comes_next"));
assert!(!is_sealed("agent"));
assert!(!is_sealed("llm_proto.openai"));
}
}