modbius_core/
bitstate.rs

1use core::{convert::TryFrom, ops::Not};
2
3use crate::ModbusSerializationError;
4
5/// Bit addressable modbus data item state helper type.
6///
7/// This enum works similiar to bool but adds some helper functionality
8#[repr(u8)]
9#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
10pub enum BitState {
11    Off = 0,
12    On = 1,
13}
14
15impl BitState {
16    pub fn is_on(self) -> bool {
17        self.into()
18    }
19}
20
21impl Default for BitState {
22    fn default() -> BitState {
23        BitState::Off
24    }
25}
26
27impl TryFrom<u16> for BitState {
28    type Error = ModbusSerializationError;
29    fn try_from(value: u16) -> Result<Self, Self::Error> {
30        match value {
31            0 => Ok(Self::Off),
32            0xFF00 => Ok(Self::On),
33            _ => Err(ModbusSerializationError::InvalidValue)
34        }
35    }
36}
37
38impl Into<u16> for BitState {
39    fn into(self) -> u16 {
40        match self { 
41            Self::Off => 0,
42            Self::On => 0xFF00,
43        }
44    }
45}
46
47impl From<bool> for BitState {
48    fn from(b: bool) -> Self {
49        if b {
50            Self::On
51        } else {
52            Self::Off
53        }
54    }
55}
56
57impl Into<bool> for BitState {
58    fn into(self) -> bool {
59        match self {
60            Self::Off => false,
61            Self::On => true,
62        }
63    }
64}
65
66impl Not for BitState {
67    type Output = Self;
68
69    fn not(self) -> Self::Output {
70        match self {
71            BitState::On => BitState::Off,
72            BitState::Off => BitState::On,
73        }
74    }
75}
76
77#[cfg(test)]
78mod bitstate_test {
79    use core::convert::TryFrom;
80
81    use crate::{BitState, ModbusSerializationError};
82
83    #[test]
84    fn from_bool_true() {
85        let state_on = BitState::from(true);
86        assert_eq!(state_on, BitState::On);
87        assert_eq!(!state_on, BitState::Off);
88        assert_eq!(true, state_on.into());
89        assert_eq!(0xFF00u16, state_on.into());
90    }
91
92
93    #[test]
94    fn from_bool_false() {
95        let state_on = BitState::from(false);
96        assert_eq!(state_on, BitState::Off);
97        assert_eq!(!state_on, BitState::On);
98        assert_eq!(false, state_on.into());
99        assert_eq!(0u16, state_on.into());
100    }
101
102    #[test]
103    fn from_u16_on() {
104        let state_on = BitState::try_from(0xFF00).unwrap();
105        assert_eq!(state_on, BitState::On);
106        assert_eq!(!state_on, BitState::Off);
107        assert_eq!(true, state_on.into());
108        assert_eq!(0xFF00u16, state_on.into());
109    }
110
111    #[test]
112    fn from_u16_off() {
113        let state_on = BitState::try_from(0).unwrap();
114        assert_eq!(state_on, BitState::Off);
115        assert_eq!(!state_on, BitState::On);
116        assert_eq!(false, state_on.into());
117        assert_eq!(0u16, state_on.into());
118    }
119
120    #[test]
121    fn from_u16_invalid0() {
122        let invalid = BitState::try_from(0xF0FF).unwrap_err();
123        assert_eq!(invalid, ModbusSerializationError::InvalidValue);
124    }
125
126    #[test]
127    fn from_u16_invalid1() {
128        let invalid = BitState::try_from(0xFFFF).unwrap_err();
129        assert_eq!(invalid, ModbusSerializationError::InvalidValue);
130    }
131
132    #[test]
133    fn from_u16_invalid2() {
134        let invalid = BitState::try_from(1).unwrap_err();
135        assert_eq!(invalid, ModbusSerializationError::InvalidValue);
136    }
137}