1use core::fmt;
4
5use crate::signal::Signal;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum ShutdownReason {
15 Signal(Signal),
17 Requested,
20 Forced,
22 Timeout,
24 Error,
26}
27
28impl ShutdownReason {
29 #[must_use]
31 pub const fn description(self) -> &'static str {
32 match self {
33 Self::Signal(_) => "signal",
34 Self::Requested => "requested",
35 Self::Forced => "forced",
36 Self::Timeout => "timeout",
37 Self::Error => "error",
38 }
39 }
40
41 #[must_use]
43 pub const fn is_signal(self) -> bool {
44 matches!(self, Self::Signal(_))
45 }
46}
47
48impl fmt::Display for ShutdownReason {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 Self::Signal(s) => write!(f, "Signal({s})"),
52 Self::Requested => f.write_str("Requested"),
53 Self::Forced => f.write_str("Forced"),
54 Self::Timeout => f.write_str("Timeout"),
55 Self::Error => f.write_str("Error"),
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn description_labels() {
66 assert_eq!(ShutdownReason::Requested.description(), "requested");
67 assert_eq!(ShutdownReason::Forced.description(), "forced");
68 assert_eq!(ShutdownReason::Timeout.description(), "timeout");
69 assert_eq!(ShutdownReason::Error.description(), "error");
70 assert_eq!(
71 ShutdownReason::Signal(Signal::Terminate).description(),
72 "signal"
73 );
74 }
75
76 #[test]
77 fn is_signal_only_for_signal_variant() {
78 assert!(ShutdownReason::Signal(Signal::Interrupt).is_signal());
79 assert!(!ShutdownReason::Requested.is_signal());
80 assert!(!ShutdownReason::Forced.is_signal());
81 }
82
83 #[test]
84 fn display_renders_signal_label() {
85 let s = format!("{}", ShutdownReason::Signal(Signal::Terminate));
86 assert!(s.starts_with("Signal("));
87 }
88}