use crate::commands::image::ImageState;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ImageRunState<'a> {
Stable(&'a ImageState),
Pending {
current: Option<&'a ImageState>,
next: &'a ImageState,
},
Testing {
current: &'a ImageState,
fallback: &'a ImageState,
},
Unknown(Option<&'a ImageState>),
Inconsistent,
}
pub fn analyze(image_state: &[ImageState], image_id: u32) -> ImageRunState<'_> {
fn find_unique(
image_id: u32,
image_state: &[ImageState],
predicate: impl Fn(&ImageState) -> bool,
) -> Option<Option<&'_ ImageState>> {
let mut matches = image_state
.iter()
.filter(|img| img.image == image_id)
.filter(|img| predicate(img));
let first = matches.next();
match matches.next() {
Some(_) => None, None => Some(first), }
}
let active = match find_unique(image_id, image_state, |img| img.active) {
Some(value) => value,
None => return ImageRunState::Inconsistent,
};
let confirmed = match find_unique(image_id, image_state, |img| img.confirmed) {
Some(value) => value,
None => return ImageRunState::Inconsistent,
};
let pending = match find_unique(image_id, image_state, |img| img.pending) {
Some(value) => value,
None => return ImageRunState::Inconsistent,
};
if let Some(pending) = pending {
return ImageRunState::Pending {
current: active.or(confirmed),
next: pending,
};
}
match (active, confirmed) {
(Some(active), Some(confirmed)) if active.slot == confirmed.slot => {
ImageRunState::Stable(active)
}
(Some(active), Some(confirmed)) => ImageRunState::Testing {
current: active,
fallback: confirmed,
},
(Some(active), None) => ImageRunState::Stable(active),
(None, Some(confirmed)) => ImageRunState::Stable(confirmed),
(None, None) => {
ImageRunState::Unknown(
image_state
.iter()
.filter(|img| img.image == image_id)
.find(|img| img.slot == 0),
)
}
}
}