use std::sync::Arc;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProviderError(pub String);
impl std::fmt::Display for ProviderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for ProviderError {}
pub trait SourceProvider {
fn discover_features(&self) -> Result<Vec<String>, ProviderError>;
fn discover_packs(&self) -> Result<Vec<String>, ProviderError>;
fn read(&self, name: &str) -> Result<Arc<str>, ProviderError>;
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
struct Fake;
impl SourceProvider for Fake {
fn discover_features(&self) -> Result<Vec<String>, ProviderError> {
Ok(vec!["a.feature".to_owned()])
}
fn discover_packs(&self) -> Result<Vec<String>, ProviderError> {
Ok(vec!["packs/p.yaml".to_owned()])
}
fn read(&self, name: &str) -> Result<Arc<str>, ProviderError> {
match name {
"a.feature" => Ok(Arc::from("Feature: X\n")),
_ => Err(ProviderError(format!("no such source: {name}"))),
}
}
}
#[test]
fn trait_is_object_safe_and_usable_as_dyn() {
let p: &dyn SourceProvider = &Fake;
assert_eq!(p.discover_features().unwrap(), vec!["a.feature".to_owned()]);
assert_eq!(&*p.read("a.feature").unwrap(), "Feature: X\n");
assert!(p.read("missing").is_err());
}
}