mctp_rs/
mctp_completion_code.rs

1use bit_register::{NumBytes, TryFromBits, TryIntoBits};
2
3#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
4#[cfg_attr(feature = "defmt", derive(defmt::Format))]
5pub enum MctpCompletionCode {
6    #[default]
7    Success,
8    Error,
9    ErrorInvalidData,
10    ErrorInvalidLength,
11    ErrorNotReady,
12    ErrorUnsupportedCmd,
13    CommandSpecific(u8), // 0x80-0xFF are command specific
14}
15
16impl From<MctpCompletionCode> for u8 {
17    fn from(value: MctpCompletionCode) -> Self {
18        match value {
19            MctpCompletionCode::Success => 0x00,
20            MctpCompletionCode::Error => 0x01,
21            MctpCompletionCode::ErrorInvalidData => 0x02,
22            MctpCompletionCode::ErrorInvalidLength => 0x03,
23            MctpCompletionCode::ErrorNotReady => 0x04,
24            MctpCompletionCode::ErrorUnsupportedCmd => 0x05,
25            MctpCompletionCode::CommandSpecific(code) => code,
26        }
27    }
28}
29impl TryFrom<u8> for MctpCompletionCode {
30    type Error = &'static str;
31    fn try_from(value: u8) -> Result<Self, &'static str> {
32        Ok(match value {
33            0x00 => MctpCompletionCode::Success,
34            0x01 => MctpCompletionCode::Error,
35            0x02 => MctpCompletionCode::ErrorInvalidData,
36            0x03 => MctpCompletionCode::ErrorInvalidLength,
37            0x04 => MctpCompletionCode::ErrorNotReady,
38            0x05 => MctpCompletionCode::ErrorUnsupportedCmd,
39            0x06..=0x7F => return Err("Invalid value for MCTP completion code - reserved range"),
40            0x80..=0xFF => MctpCompletionCode::CommandSpecific(value),
41        })
42    }
43}
44
45impl TryFromBits<u32> for MctpCompletionCode {
46    fn try_from_bits(bits: u32) -> Result<Self, &'static str> {
47        if bits > 0xFF {
48            return Err("Out of range value for MCTP completion code");
49        }
50        (bits as u8).try_into()
51    }
52}
53
54impl TryIntoBits<u32> for MctpCompletionCode {
55    fn try_into_bits(self) -> Result<u32, &'static str> {
56        Ok(Into::<u8>::into(self) as u32)
57    }
58}
59
60impl NumBytes for MctpCompletionCode {
61    const NUM_BYTES: usize = 1;
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_completion_code_reserved_range() {
70        // Test that reserved range 0x06-0x7F is properly rejected
71        for code in 0x06..=0x7F {
72            let result = MctpCompletionCode::try_from(code);
73            assert!(result.is_err(), "Code 0x{:02X} should be rejected", code);
74            if let Err(msg) = result {
75                assert!(msg.contains("reserved range"));
76            }
77        }
78
79        // Test valid ranges still work
80        assert_eq!(
81            MctpCompletionCode::try_from(0x00).unwrap(),
82            MctpCompletionCode::Success
83        );
84        assert_eq!(
85            MctpCompletionCode::try_from(0x05).unwrap(),
86            MctpCompletionCode::ErrorUnsupportedCmd
87        );
88        assert_eq!(
89            MctpCompletionCode::try_from(0x80).unwrap(),
90            MctpCompletionCode::CommandSpecific(0x80)
91        );
92        assert_eq!(
93            MctpCompletionCode::try_from(0xFF).unwrap(),
94            MctpCompletionCode::CommandSpecific(0xFF)
95        );
96    }
97}