use yash_env::signal;
use yash_env::system::Signals;
use yash_env::trap::Condition;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum CondSpec {
Exit,
SignalName(signal::Name),
Number(signal::RawNumber),
}
impl From<signal::Name> for CondSpec {
fn from(name: signal::Name) -> Self {
Self::SignalName(name)
}
}
impl From<signal::RawNumber> for CondSpec {
fn from(number: signal::RawNumber) -> Self {
Self::Number(number)
}
}
impl CondSpec {
#[must_use]
pub fn to_condition<S: Signals>(&self, system: &S) -> Option<Condition> {
match self {
Self::Exit => Some(Condition::Exit),
Self::SignalName(name) => {
Some(Condition::Signal(system.signal_number_from_name(*name)?))
}
Self::Number(0) => Some(Condition::Exit),
Self::Number(number) => Some(Condition::Signal(system.validate_signal(*number)?.1)),
}
}
#[must_use]
pub fn from_condition<S: Signals>(cond: &Condition, system: &S) -> Option<Self> {
match cond {
Condition::Exit => Some(Self::Exit),
Condition::Signal(number) => {
Some(Self::SignalName(system.signal_name_from_number(*number)))
}
_ => None,
}
}
}
impl std::fmt::Display for CondSpec {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Exit => "EXIT".fmt(f),
Self::SignalName(name) => name.fmt(f),
Self::Number(number) => number.fmt(f),
}
}
}
impl std::str::FromStr for CondSpec {
type Err = signal::UnknownNameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(number) = s.parse() {
return Ok(Self::Number(number));
}
if s == "EXIT" {
Ok(Self::Exit)
} else {
Ok(Self::SignalName(s.parse()?))
}
}
}