yash_env/trap/
cond.rs

1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2023 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! Items that define trap conditions
18
19#[cfg(doc)]
20use super::state::Action;
21use super::SignalSystem;
22use crate::signal;
23use std::borrow::Cow;
24
25/// Condition under which an [`Action`] is executed
26#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
27#[non_exhaustive]
28pub enum Condition {
29    /// When the shell exits
30    Exit,
31    /// When the specified signal is delivered to the shell process
32    Signal(signal::Number),
33}
34
35impl From<signal::Number> for Condition {
36    fn from(number: signal::Number) -> Self {
37        Self::Signal(number)
38    }
39}
40
41/// Conversion from raw signal number to `Condition`
42///
43/// If the number is zero, the result is [`Condition::Exit`]. Otherwise, the
44/// result is [`Condition::Signal`] with the signal number.
45impl From<signal::RawNumber> for Condition {
46    fn from(number: signal::RawNumber) -> Self {
47        if let Ok(non_zero) = number.try_into() {
48            Self::Signal(signal::Number::from_raw_unchecked(non_zero))
49        } else {
50            Self::Exit
51        }
52    }
53}
54
55impl From<Condition> for signal::RawNumber {
56    fn from(cond: Condition) -> Self {
57        match cond {
58            Condition::Exit => 0,
59            Condition::Signal(number) => number.as_raw(),
60        }
61    }
62}
63
64impl Condition {
65    /// Converts this `Condition` to a `String`.
66    ///
67    /// The result is an uppercase string representing the condition such as
68    /// `"EXIT"` and `"TERM"`. Signal names are obtained from
69    /// [`signal::Name::as_string`]. This function depends on the signal system
70    /// to convert signal numbers to names.
71    #[must_use]
72    pub fn to_string<S: SignalSystem>(&self, system: &S) -> Cow<'static, str> {
73        match self {
74            Self::Exit => Cow::Borrowed("EXIT"),
75            Self::Signal(number) => system.signal_name_from_number(*number).as_string(),
76        }
77    }
78}