#[cfg(doc)]
use super::state::Action;
use crate::signal;
use crate::system::Signals;
use itertools::Itertools as _;
use std::borrow::Cow;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum Condition {
Exit,
Signal(signal::Number),
}
impl From<signal::Number> for Condition {
fn from(number: signal::Number) -> Self {
Self::Signal(number)
}
}
impl From<signal::RawNumber> for Condition {
fn from(number: signal::RawNumber) -> Self {
if let Ok(non_zero) = number.try_into() {
Self::Signal(signal::Number::from_raw_unchecked(non_zero))
} else {
Self::Exit
}
}
}
impl From<Condition> for signal::RawNumber {
fn from(cond: Condition) -> Self {
match cond {
Condition::Exit => 0,
Condition::Signal(number) => number.as_raw(),
}
}
}
impl Condition {
#[must_use]
pub fn to_string<S: Signals>(&self, system: &S) -> Cow<'static, str> {
match self {
Self::Exit => Cow::Borrowed("EXIT"),
Self::Signal(number) => system.sig2str(*number).unwrap_or(Cow::Borrowed("?")),
}
}
pub fn iter<S: Signals>(system: &S) -> impl Iterator<Item = Condition> + '_ {
let non_real_time = S::NAMED_SIGNALS
.iter()
.filter_map(|&(_, number)| Some(Condition::Signal(number?)));
let non_real_time_count = S::NAMED_SIGNALS.len();
let real_time = system.iter_sigrt().map(Condition::Signal);
let real_time_count = real_time.size_hint().1.unwrap_or_default();
let mut conditions = Vec::with_capacity(1 + non_real_time_count + real_time_count);
conditions.push(Condition::Exit);
conditions.extend(non_real_time);
conditions.extend(real_time);
conditions.sort();
conditions.into_iter().dedup()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::system::r#virtual::VirtualSystem;
#[test]
fn condition_iter_is_sorted() {
let system = VirtualSystem::new();
let iter = Condition::iter(&system);
assert!(iter.is_sorted());
}
#[test]
fn condition_iter_is_unique() {
let system = VirtualSystem::new();
let iter = Condition::iter(&system);
let iter_dedup = Condition::iter(&system).dedup();
assert!(iter.eq(iter_dedup));
}
}