use std::path::PathBuf;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum HostError {
#[error("database at {} is locked by another process", path.display())]
Locked {
path: PathBuf,
},
#[error("i/o on {}: {source}", path.display())]
Io {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("database at {} needs a checkpoint before a read-only open (non-empty journal)", path.display())]
NeedsCheckpoint {
path: PathBuf,
},
#[error(transparent)]
Engine(#[from] plugmem_core::Error),
#[error("embedder: {0}")]
Embed(String),
}
pub const MAX_BYTES_HINT: &str = "that ceiling is `max_bytes` (`[engine] max_bytes` in config.toml), \
and it applies to each pool separately rather than to their sum. Its default is not a capacity \
judgement — it is the figure that keeps every pool addressable where `usize` is 32 bits, so a \
database written anywhere opens anywhere. Raising it costs exactly that portability: a 32-bit \
host then refuses the file with a typed error instead of misreading it.";
impl HostError {
pub fn capacity_hint(&self) -> Option<&'static str> {
let Self::Engine(engine) = self else {
return None;
};
matches!(
engine,
plugmem_core::Error::CapacityExceeded { .. }
| plugmem_core::Error::Arena(plugmem_core::ArenaError::CapacityExceeded { .. })
)
.then_some(MAX_BYTES_HINT)
}
pub(crate) fn io(path: &std::path::Path, source: std::io::Error) -> Self {
Self::Io {
path: path.to_path_buf(),
source,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_pool_ceiling_carries_its_follow_up_and_nothing_else_does() {
for engine in [
plugmem_core::Error::CapacityExceeded { what: "vectors" },
plugmem_core::Error::Arena(plugmem_core::ArenaError::CapacityExceeded {
max_bytes: 65_536,
}),
] {
let hint = HostError::Engine(engine).capacity_hint();
assert_eq!(hint, Some(MAX_BYTES_HINT));
assert!(hint.unwrap().contains("max_bytes"));
}
assert_eq!(
HostError::Engine(plugmem_core::Error::TooLarge {
what: "text",
len: 9_000,
max: 4_096,
})
.capacity_hint(),
None
);
assert_eq!(HostError::Embed("no provider".into()).capacity_hint(), None);
assert_eq!(
HostError::Locked {
path: PathBuf::from("/tmp/m.plugmem"),
}
.capacity_hint(),
None
);
}
}