use serde_json::Value;
use super::types::ParsedRoster;
pub trait FormatAdapter {
fn format(&self) -> &'static str;
fn detect(&self, decoded: &Value) -> bool;
fn parse(&self, decoded: &Value) -> Result<ParsedRoster, ParseError>;
}
#[derive(Debug)]
pub struct ParseError(pub String);
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for ParseError {}
pub fn select_adapter<'a>(
decoded: &Value,
adapters: &'a [Box<dyn FormatAdapter>],
) -> Result<&'a dyn FormatAdapter, ParseError> {
adapters
.iter()
.map(AsRef::as_ref)
.find(|a| a.detect(decoded))
.ok_or_else(|| {
let tried: Vec<&str> = adapters.iter().map(|a| a.format()).collect();
let tried = if tried.is_empty() {
"none".to_string()
} else {
tried.join(", ")
};
ParseError(format!(
"no registered import adapter recognises this payload (tried: {tried})"
))
})
}