use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use xtalforge_ff::{EngineKind, EngineStatus, probe};
use crate::verbs;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EngineAvailability {
pub name: String,
pub available: bool,
pub detail: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BundleAvailability {
pub name: String,
pub available: bool,
pub detail: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Capabilities {
pub version: String,
pub features: BTreeMap<String, bool>,
pub engines: Vec<EngineAvailability>,
pub bundles: Vec<BundleAvailability>,
pub verbs: Vec<String>,
pub formats: Vec<FormatAvailability>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FormatAvailability {
pub name: String,
pub extensions: Vec<String>,
pub readable: bool,
pub writable: bool,
}
fn engine(kind: EngineKind) -> EngineAvailability {
let status = probe(kind);
match status {
EngineStatus::Available { path, version } => EngineAvailability {
name: kind.binary().to_owned(),
available: true,
detail: format!("{path} ({version})"),
},
EngineStatus::Missing { reason } => EngineAvailability {
name: kind.binary().to_owned(),
available: false,
detail: reason,
},
}
}
fn rcsr_bundle() -> BundleAvailability {
match xtalforge_analysis::RcsrIndex::from_embedded() {
Ok(index) => BundleAvailability {
name: "rcsr".to_owned(),
available: true,
detail: format!("{} RCSR nets, release 2019-06-01", index.len()),
},
Err(error) => BundleAvailability {
name: "rcsr".to_owned(),
available: false,
detail: error.to_string(),
},
}
}
#[must_use]
pub fn capability_report() -> Capabilities {
let mut features = BTreeMap::new();
features.insert("parallel".to_owned(), cfg!(feature = "parallel"));
features.insert("sci-form".to_owned(), cfg!(feature = "sci-form"));
features.insert("ml".to_owned(), cfg!(feature = "ml"));
features.insert("external".to_owned(), cfg!(feature = "external"));
let formats = xtalforge_io::registry::FORMATS
.iter()
.map(|format| FormatAvailability {
name: format.name.to_owned(),
extensions: format
.extensions
.iter()
.map(|extension| (*extension).to_owned())
.collect(),
readable: format.read.is_some(),
writable: format.write.is_some(),
})
.collect();
Capabilities {
version: xtalforge_core::version().to_owned(),
features,
engines: vec![
engine(EngineKind::DftbPlus),
engine(EngineKind::Xtb),
engine(EngineKind::Orca),
],
bundles: vec![rcsr_bundle()],
verbs: verbs::names()
.iter()
.map(|name| (*name).to_owned())
.collect(),
formats,
}
}