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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::mem::transmute;

#[repr(u16)]
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq)]
pub enum AlarmSeverity {
    #[default]
    None = 0,
    Minor,
    Major,
    Invalid,
}

impl AlarmSeverity {
    pub fn try_from_raw(raw: u16) -> Option<Self> {
        if !(0..(sys::epicsAlarmSeverity::ALARM_NSEV as u16)).contains(&raw) {
            return None;
        }
        let sev = unsafe { transmute::<u32, sys::epicsAlarmSeverity>(raw as _) };
        Some(match sev {
            sys::epicsAlarmSeverity::epicsSevNone => AlarmSeverity::None,
            sys::epicsAlarmSeverity::epicsSevMinor => AlarmSeverity::Minor,
            sys::epicsAlarmSeverity::epicsSevMajor => AlarmSeverity::Major,
            sys::epicsAlarmSeverity::epicsSevInvalid => AlarmSeverity::Invalid,
            _ => unreachable!(),
        })
    }

    pub fn raw(&self) -> sys::epicsAlarmSeverity {
        match self {
            AlarmSeverity::None => sys::epicsAlarmSeverity::epicsSevNone,
            AlarmSeverity::Minor => sys::epicsAlarmSeverity::epicsSevMinor,
            AlarmSeverity::Major => sys::epicsAlarmSeverity::epicsSevMajor,
            AlarmSeverity::Invalid => sys::epicsAlarmSeverity::epicsSevInvalid,
        }
    }
}

#[repr(u16)]
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq)]
pub enum AlarmCondition {
    #[default]
    None = 0,
    Read,
    Write,
    HiHi,
    High,
    LoLo,
    Low,
    State,
    Cos,
    Comm,
    Timeout,
    HwLimit,
    Calc,
    Scan,
    Link,
    Soft,
    BadSub,
    Udf,
    Disable,
    Simm,
    ReadAccess,
    WriteAccess,
}

impl AlarmCondition {
    pub fn try_from_raw(raw: u16) -> Option<Self> {
        if !(0..(sys::epicsAlarmCondition::ALARM_NSTATUS as u16)).contains(&raw) {
            return None;
        }
        let sev = unsafe { transmute::<u32, sys::epicsAlarmCondition>(raw as _) };
        Some(match sev {
            sys::epicsAlarmCondition::epicsAlarmNone => AlarmCondition::None,
            sys::epicsAlarmCondition::epicsAlarmRead => AlarmCondition::Read,
            sys::epicsAlarmCondition::epicsAlarmWrite => AlarmCondition::Write,
            sys::epicsAlarmCondition::epicsAlarmHiHi => AlarmCondition::HiHi,
            sys::epicsAlarmCondition::epicsAlarmHigh => AlarmCondition::High,
            sys::epicsAlarmCondition::epicsAlarmLoLo => AlarmCondition::LoLo,
            sys::epicsAlarmCondition::epicsAlarmLow => AlarmCondition::Low,
            sys::epicsAlarmCondition::epicsAlarmState => AlarmCondition::State,
            sys::epicsAlarmCondition::epicsAlarmCos => AlarmCondition::Cos,
            sys::epicsAlarmCondition::epicsAlarmComm => AlarmCondition::Comm,
            sys::epicsAlarmCondition::epicsAlarmTimeout => AlarmCondition::Timeout,
            sys::epicsAlarmCondition::epicsAlarmHwLimit => AlarmCondition::HwLimit,
            sys::epicsAlarmCondition::epicsAlarmCalc => AlarmCondition::Calc,
            sys::epicsAlarmCondition::epicsAlarmScan => AlarmCondition::Scan,
            sys::epicsAlarmCondition::epicsAlarmLink => AlarmCondition::Link,
            sys::epicsAlarmCondition::epicsAlarmSoft => AlarmCondition::Soft,
            sys::epicsAlarmCondition::epicsAlarmBadSub => AlarmCondition::BadSub,
            sys::epicsAlarmCondition::epicsAlarmUDF => AlarmCondition::Udf,
            sys::epicsAlarmCondition::epicsAlarmDisable => AlarmCondition::Disable,
            sys::epicsAlarmCondition::epicsAlarmSimm => AlarmCondition::Simm,
            sys::epicsAlarmCondition::epicsAlarmReadAccess => AlarmCondition::ReadAccess,
            sys::epicsAlarmCondition::epicsAlarmWriteAccess => AlarmCondition::WriteAccess,
            _ => unreachable!(),
        })
    }

    pub fn raw(&self) -> sys::epicsAlarmCondition {
        match self {
            AlarmCondition::None => sys::epicsAlarmCondition::epicsAlarmNone,
            AlarmCondition::Read => sys::epicsAlarmCondition::epicsAlarmRead,
            AlarmCondition::Write => sys::epicsAlarmCondition::epicsAlarmWrite,
            AlarmCondition::HiHi => sys::epicsAlarmCondition::epicsAlarmHiHi,
            AlarmCondition::High => sys::epicsAlarmCondition::epicsAlarmHigh,
            AlarmCondition::LoLo => sys::epicsAlarmCondition::epicsAlarmLoLo,
            AlarmCondition::Low => sys::epicsAlarmCondition::epicsAlarmLow,
            AlarmCondition::State => sys::epicsAlarmCondition::epicsAlarmState,
            AlarmCondition::Cos => sys::epicsAlarmCondition::epicsAlarmCos,
            AlarmCondition::Comm => sys::epicsAlarmCondition::epicsAlarmComm,
            AlarmCondition::Timeout => sys::epicsAlarmCondition::epicsAlarmTimeout,
            AlarmCondition::HwLimit => sys::epicsAlarmCondition::epicsAlarmHwLimit,
            AlarmCondition::Calc => sys::epicsAlarmCondition::epicsAlarmCalc,
            AlarmCondition::Scan => sys::epicsAlarmCondition::epicsAlarmScan,
            AlarmCondition::Link => sys::epicsAlarmCondition::epicsAlarmLink,
            AlarmCondition::Soft => sys::epicsAlarmCondition::epicsAlarmSoft,
            AlarmCondition::BadSub => sys::epicsAlarmCondition::epicsAlarmBadSub,
            AlarmCondition::Udf => sys::epicsAlarmCondition::epicsAlarmUDF,
            AlarmCondition::Disable => sys::epicsAlarmCondition::epicsAlarmDisable,
            AlarmCondition::Simm => sys::epicsAlarmCondition::epicsAlarmSimm,
            AlarmCondition::ReadAccess => sys::epicsAlarmCondition::epicsAlarmReadAccess,
            AlarmCondition::WriteAccess => sys::epicsAlarmCondition::epicsAlarmWriteAccess,
        }
    }
}

/// EPICS channel alarm.
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq)]
pub struct Alarm {
    pub condition: AlarmCondition,
    pub severity: AlarmSeverity,
}