use std::sync::OnceLock;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StdlibSource {
pub module: &'static str,
pub source: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StdlibPromptAsset {
pub path: &'static str,
pub source: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StdlibCliScript {
pub name: &'static str,
pub source: &'static str,
}
#[derive(Debug)]
pub struct StdlibCatalog {
pub sources: &'static [StdlibSource],
pub prompt_assets: &'static [StdlibPromptAsset],
pub cli_scripts: &'static [StdlibCliScript],
}
impl StdlibCatalog {
pub fn source(&self, module: &str) -> Option<&'static str> {
self.sources
.iter()
.find_map(|entry| (entry.module == module).then_some(entry.source))
}
pub fn prompt_asset(&self, path: &str) -> Option<&'static str> {
let path = path.strip_prefix("std/").unwrap_or(path);
self.prompt_assets
.iter()
.find_map(|entry| (entry.path == path).then_some(entry.source))
}
pub fn cli_script(&self, name: &str) -> Option<&'static str> {
self.cli_scripts
.iter()
.find_map(|entry| (entry.name == name).then_some(entry.source))
}
}
static INSTALLED: OnceLock<&'static StdlibCatalog> = OnceLock::new();
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CatalogNotInstalled;
impl std::fmt::Display for CatalogNotInstalled {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(
"no Harn standard library is installed: the host must link harn-stdlib and call \
harn_stdlib::install() before running Harn code",
)
}
}
impl std::error::Error for CatalogNotInstalled {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CatalogAlreadyInstalled;
impl std::fmt::Display for CatalogAlreadyInstalled {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a different Harn standard library is already installed")
}
}
impl std::error::Error for CatalogAlreadyInstalled {}
pub fn install(catalog: &'static StdlibCatalog) -> Result<(), CatalogAlreadyInstalled> {
let installed = INSTALLED.get_or_init(|| catalog);
if std::ptr::eq(*installed, catalog) {
Ok(())
} else {
Err(CatalogAlreadyInstalled)
}
}
pub fn installed() -> Result<&'static StdlibCatalog, CatalogNotInstalled> {
INSTALLED.get().copied().ok_or(CatalogNotInstalled)
}
pub fn builtin_reexports(module: &str) -> &'static [&'static str] {
match module {
"testing" => &[
"assert",
"assert_approx",
"assert_eq",
"assert_matches",
"assert_ne",
"skip",
"value_diff",
],
_ => &[],
}
}
#[cfg(test)]
mod tests {
use super::*;
static ONE: StdlibCatalog = StdlibCatalog {
sources: &[StdlibSource {
module: "text",
source: "pub fn shout() {}",
}],
prompt_assets: &[StdlibPromptAsset {
path: "agent/prompts/x.harn.prompt",
source: "hello",
}],
cli_scripts: &[],
};
static OTHER: StdlibCatalog = StdlibCatalog {
sources: &[],
prompt_assets: &[],
cli_scripts: &[],
};
#[test]
fn lookups_answer_by_module_and_by_prefixed_path() {
assert_eq!(ONE.source("text"), Some("pub fn shout() {}"));
assert_eq!(ONE.source("missing"), None);
assert_eq!(
ONE.prompt_asset("std/agent/prompts/x.harn.prompt"),
Some("hello")
);
}
#[test]
fn a_reader_before_install_gets_a_typed_error_then_the_one_catalog() {
assert_eq!(installed().err(), Some(CatalogNotInstalled));
install(&ONE).expect("first install");
install(&ONE).expect("same catalog again");
assert_eq!(install(&OTHER), Err(CatalogAlreadyInstalled));
assert!(std::ptr::eq(
installed().expect("installed"),
&raw const ONE
));
}
}