dstar_gateway_core/codec/dcs/
error.rs1use crate::error::EncodeError;
4
5#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum DcsError {
9 #[error("DCS packet length {got} not valid for any known type")]
11 UnknownPacketLength {
12 got: usize,
14 },
15
16 #[error("DCS voice magic missing at offset 0..4, got {got:02X?}")]
18 VoiceMagicMissing {
19 got: [u8; 4],
21 },
22
23 #[error("DCS stream id is zero (reserved)")]
25 StreamIdZero,
26
27 #[error("DCS connect reply has unknown tag {tag:02X?}")]
29 UnknownConnectTag {
30 tag: [u8; 3],
32 },
33
34 #[error("DCS UNLINK has invalid module byte 0x{byte:02X} at offset 9 (expected 0x20)")]
36 UnlinkModuleByteInvalid {
37 byte: u8,
39 },
40
41 #[error("DCS connect packet has invalid module byte 0x{byte:02X} at offset {offset}")]
43 InvalidModuleByte {
44 offset: usize,
46 byte: u8,
48 },
49
50 #[error("DCS encode buffer too small: need {need}, have {have}")]
56 EncodeBufferTooSmall {
57 need: usize,
59 have: usize,
61 },
62
63 #[error("DCS send_voice called before send_header cached the TX header")]
70 NoTxHeader,
71}
72
73impl From<EncodeError> for DcsError {
74 fn from(value: EncodeError) -> Self {
75 match value {
76 EncodeError::BufferTooSmall { need, have } => Self::EncodeBufferTooSmall { need, have },
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn unknown_length_display() {
87 let err = DcsError::UnknownPacketLength { got: 42 };
88 assert!(err.to_string().contains("42"));
89 }
90
91 #[test]
92 fn voice_magic_missing_display() {
93 let err = DcsError::VoiceMagicMissing {
94 got: [b'X', b'X', b'X', b'X'],
95 };
96 let s = err.to_string();
97 assert!(s.contains("58"), "display should contain hex of 'X' (0x58)");
98 }
99
100 #[test]
101 fn stream_id_zero_display() {
102 let err = DcsError::StreamIdZero;
103 assert_eq!(err.to_string(), "DCS stream id is zero (reserved)");
104 }
105
106 #[test]
107 fn unknown_connect_tag_display() {
108 let err = DcsError::UnknownConnectTag {
109 tag: [b'F', b'O', b'O'],
110 };
111 assert!(
112 err.to_string().contains("46"),
113 "display should contain hex of 'F'"
114 );
115 }
116
117 #[test]
118 fn unlink_module_byte_invalid_display() {
119 let err = DcsError::UnlinkModuleByteInvalid { byte: 0x41 };
120 let s = err.to_string();
121 assert!(s.contains("41"));
122 assert!(s.contains('9'));
123 }
124
125 #[test]
126 fn invalid_module_byte_display() {
127 let err = DcsError::InvalidModuleByte {
128 offset: 8,
129 byte: 0x40,
130 };
131 let s = err.to_string();
132 assert!(s.contains('8'));
133 assert!(s.contains("40"));
134 }
135
136 #[test]
137 fn no_tx_header_display_mentions_send_header() {
138 let err = DcsError::NoTxHeader;
139 let s = err.to_string();
140 assert!(s.contains("send_header"));
141 }
142}