1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::fmt;

const HARDWARE_OK: u32 = 0;
const HARDWARE_MISSING: u32 = 1;
const HARDWARE_NOTIFICATION: u32 = 2;
const HARDWARE_WARNING: u32 = 3;
const HARDWARE_ERROR: u32 = 4;

/// Represents the overall status of the CDR hardware.
#[repr(u32)]
#[derive(Clone, Copy, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum HardwareStatus {
    #[default]
    Ok = HARDWARE_OK,
    Missing = HARDWARE_MISSING,
    Notification = HARDWARE_NOTIFICATION,
    Warning = HARDWARE_WARNING,
    Error = HARDWARE_ERROR,
}

impl HardwareStatus {
    /// Creates a new [HardwareStatus].
    pub const fn new() -> Self {
        Self::Ok
    }

    /// Creates a new [HardwareStatus] from the provided parameter.
    pub const fn create(val: u32) -> Self {
        match val {
            HARDWARE_OK => Self::Ok,
            HARDWARE_MISSING => Self::Missing,
            HARDWARE_NOTIFICATION => Self::Notification,
            HARDWARE_WARNING => Self::Warning,
            HARDWARE_ERROR => Self::Error,
            _ => Self::Missing,
        }
    }
}

impl From<&[HardwareStatus]> for HardwareStatus {
    fn from(val: &[HardwareStatus]) -> Self {
        // start by checking for the "highest" priority status, i.e. status that require the most
        // attention
        if val.contains(&Self::Error) {
            Self::Error
        } else if val.contains(&Self::Warning) {
            Self::Warning
        } else if val.contains(&Self::Missing) {
            Self::Missing
        } else if val.contains(&Self::Notification) {
            Self::Notification
        } else {
            Self::Ok
        }
    }
}

impl<const N: usize> From<&[HardwareStatus; N]> for HardwareStatus {
    fn from(val: &[HardwareStatus; N]) -> Self {
        val.as_ref().into()
    }
}

impl<const N: usize> From<[HardwareStatus; N]> for HardwareStatus {
    fn from(val: [HardwareStatus; N]) -> Self {
        val.as_ref().into()
    }
}

impl From<HardwareStatus> for &'static str {
    fn from(val: HardwareStatus) -> Self {
        match val {
            HardwareStatus::Ok => "OK",
            HardwareStatus::Missing => "missing",
            HardwareStatus::Notification => "notification",
            HardwareStatus::Warning => "warning",
            HardwareStatus::Error => "error",
        }
    }
}

impl From<&HardwareStatus> for &'static str {
    fn from(val: &HardwareStatus) -> Self {
        (*val).into()
    }
}

impl fmt::Display for HardwareStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, r#""{}""#, <&str>::from(self))
    }
}

impl_xfs_enum!(HardwareStatus, "hardwareStatus");