use std::fmt;
use std::str::FromStr;
use crate::dense_cache::WarmError;
use crate::embedding::EmbedderError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OnArtifactMiss {
Error,
Embed,
}
impl OnArtifactMiss {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
OnArtifactMiss::Error => "error",
OnArtifactMiss::Embed => "embed",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseOnArtifactMissError(pub String);
impl fmt::Display for ParseOnArtifactMissError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"unknown on-artifact-miss policy {:?} (expected \"error\" or \"embed\")",
self.0
)
}
}
impl std::error::Error for ParseOnArtifactMissError {}
impl FromStr for OnArtifactMiss {
type Err = ParseOnArtifactMissError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"error" => Ok(OnArtifactMiss::Error),
"embed" => Ok(OnArtifactMiss::Embed),
other => Err(ParseOnArtifactMissError(other.to_string())),
}
}
}
#[derive(Debug, Clone)]
pub enum ArtifactWarmError {
Warm(WarmError),
Incomplete {
missing: Vec<String>,
},
Embedder(EmbedderError),
}
impl fmt::Display for ArtifactWarmError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ArtifactWarmError::Warm(e) => write!(f, "{e}"),
ArtifactWarmError::Incomplete { missing } => write!(
f,
"embedding artifact incomplete for the current corpus: {} id(s) missing ({})",
missing.len(),
missing.join(", ")
),
ArtifactWarmError::Embedder(e) => write!(f, "{e}"),
}
}
}
impl std::error::Error for ArtifactWarmError {}
impl From<WarmError> for ArtifactWarmError {
fn from(value: WarmError) -> Self {
Self::Warm(value)
}
}
impl From<EmbedderError> for ArtifactWarmError {
fn from(value: EmbedderError) -> Self {
Self::Embedder(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn on_artifact_miss_round_trips_through_str() {
for policy in [OnArtifactMiss::Error, OnArtifactMiss::Embed] {
assert_eq!(policy.as_str().parse::<OnArtifactMiss>().unwrap(), policy);
}
}
#[test]
fn on_artifact_miss_rejects_unknown() {
assert!("reuse".parse::<OnArtifactMiss>().is_err());
}
#[test]
fn incomplete_display_lists_missing_ids() {
let incomplete = ArtifactWarmError::Incomplete {
missing: vec!["a".into(), "b".into()],
};
let message = incomplete.to_string();
assert!(message.contains("embedding artifact incomplete for the current corpus"));
assert!(message.contains("a, b"));
}
}