use std::sync::Arc;
use super::{Catalog, ModelSpec};
#[derive(Clone, Debug, Default)]
pub struct ModelFacts {
bound: Option<Arc<Bound>>,
catalog: Option<Catalog>,
}
#[derive(Debug)]
struct Bound {
id: String,
spec: Arc<ModelSpec>,
}
impl ModelFacts {
pub(crate) fn builtin() -> &'static ModelFacts {
static BUILTIN: ModelFacts = ModelFacts {
bound: None,
catalog: None,
};
&BUILTIN
}
pub fn new(spec: impl Into<Arc<ModelSpec>>) -> Self {
let spec = spec.into();
Self {
bound: Some(Arc::new(Bound {
id: spec.id.clone(),
spec,
})),
catalog: None,
}
}
pub fn with_catalog(mut self, catalog: &Catalog) -> Self {
self.catalog = Some(catalog.clone());
self
}
pub fn spec(&self) -> Option<&ModelSpec> {
self.bound.as_deref().map(|bound| &*bound.spec)
}
pub fn catalog(&self) -> &Catalog {
self.catalog.as_ref().unwrap_or_else(|| Catalog::builtin())
}
pub fn for_model(&self, vendor: &str, model: &str) -> Option<&ModelSpec> {
if let Some(bound) = self.bound.as_deref()
&& (bound.spec.provider.is_declared() || bound.spec.provider.vendor() == vendor)
&& (bound.id == model || bound.spec.id == model)
{
return Some(&bound.spec);
}
self.catalog()
.get_vendor(vendor, model)
.map(|resolved| resolved.spec)
}
pub(crate) fn reads_images_or(
&self,
vendor: &str,
model: &str,
rule: impl FnOnce(&str) -> bool,
) -> bool {
self.for_model(vendor, model)
.map_or_else(|| rule(model), |spec| spec.input.image)
}
}
impl PartialEq for ModelFacts {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl Eq for ModelFacts {}
impl Catalog {
pub fn facts(
&self,
provider: crate::providers::registry::ProviderId,
model: &str,
) -> ModelFacts {
let bound = self.get_vendor(provider.vendor(), model).map(|found| {
Arc::new(Bound {
id: model.to_owned(),
spec: found.shared(),
})
});
ModelFacts {
bound,
catalog: Some(self.clone()),
}
}
}
#[cfg(test)]
mod tests;