use super::{DeviceGateState, DevicePlanningSession, NativePlanAvailability, NativePlanSummary};
use crate::compile::CompilerError;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub(crate) struct NativePlanCatalog {
availability: HashMap<DeviceGateState, NativePlanAvailability>,
}
impl NativePlanCatalog {
pub(crate) fn build_with_session(
session: &DevicePlanningSession,
roots: impl IntoIterator<Item = DeviceGateState>,
) -> Result<Self, CompilerError> {
let mut roots = roots.into_iter().collect::<Vec<_>>();
roots.sort();
roots.dedup();
let snapshot = session.prepare(roots.iter().cloned())?;
let mut availability = HashMap::with_capacity(roots.len());
for root in roots {
let planned = snapshot.availability(&root).ok_or_else(|| {
CompilerError::InvariantViolation(format!(
"device planning session did not retain requested root {root:?}"
))
})?;
availability.insert(root, planned);
}
Ok(Self { availability })
}
pub(crate) fn availability(&self, state: &DeviceGateState) -> Option<&NativePlanAvailability> {
self.availability.get(state)
}
pub(crate) fn summary(&self, state: &DeviceGateState) -> Option<&NativePlanSummary> {
match self.availability(state) {
Some(NativePlanAvailability::Feasible(summary)) => Some(summary.as_ref()),
Some(NativePlanAvailability::Unsupported(_)) | None => None,
}
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (&DeviceGateState, &NativePlanSummary)> {
self.availability
.iter()
.filter_map(|(state, availability)| {
let NativePlanAvailability::Feasible(summary) = availability else {
return None;
};
Some((state, summary.as_ref()))
})
}
pub(crate) fn iter_availability(
&self,
) -> impl Iterator<Item = (&DeviceGateState, &NativePlanAvailability)> {
self.availability.iter()
}
}