1use byteorder::{BigEndian, ByteOrder};
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum AtpError {
6 #[error("invalid size - expected at least {expected} bytes but found {found}")]
7 InvalidSize { expected: usize, found: usize },
8 #[error("unknown function code {code}")]
9 UnknownFunction { code: u8 },
10}
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13pub enum AtpFunction {
14 Request = 1,
15 Response = 2,
16 Release = 3,
17}
18
19impl TryFrom<u8> for AtpFunction {
20 type Error = AtpError;
21
22 fn try_from(value: u8) -> Result<Self, Self::Error> {
23 match value {
24 1 => Ok(AtpFunction::Request),
25 2 => Ok(AtpFunction::Response),
26 3 => Ok(AtpFunction::Release),
27 _ => Err(AtpError::UnknownFunction { code: value }),
28 }
29 }
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct AtpPacket {
34 pub function: AtpFunction,
35 pub xo: bool,
36 pub eom: bool,
37 pub sts: bool,
38 pub bitmap_seq_num: u8,
39 pub tid: u16,
40 pub user_bytes: [u8; 4],
41}
42
43impl AtpPacket {
44 pub const HEADER_LEN: usize = 8;
45
46 pub fn parse(buf: &[u8]) -> Result<Self, AtpError> {
47 if buf.len() < Self::HEADER_LEN {
48 return Err(AtpError::InvalidSize {
49 expected: Self::HEADER_LEN,
50 found: buf.len(),
51 });
52 }
53
54 let control = buf[0];
55 let function_code = (control >> 6) & 0x03;
57 let function = AtpFunction::try_from(function_code)?;
58
59 let xo = (control & 0x20) != 0;
61 let eom = (control & 0x10) != 0;
63 let sts = (control & 0x08) != 0;
65
66 let bitmap_seq_num = buf[1];
67 let tid = BigEndian::read_u16(&buf[2..4]);
68 let mut user_bytes = [0u8; 4];
69 user_bytes.copy_from_slice(&buf[4..8]);
70
71 Ok(Self {
72 function,
73 xo,
74 eom,
75 sts,
76 bitmap_seq_num,
77 tid,
78 user_bytes,
79 })
80 }
81
82 pub fn to_bytes(&self, buf: &mut [u8]) -> Result<usize, AtpError> {
83 let total_len = Self::HEADER_LEN;
84 if buf.len() < total_len {
85 return Err(AtpError::InvalidSize {
86 expected: total_len,
87 found: buf.len(),
88 });
89 }
90
91 let mut control = (self.function as u8) << 6;
92 if self.xo {
93 control |= 0x20;
94 }
95 if self.eom {
96 control |= 0x10;
97 }
98 if self.sts {
99 control |= 0x08;
100 }
101
102 buf[0] = control;
103 buf[1] = self.bitmap_seq_num;
104 BigEndian::write_u16(&mut buf[2..4], self.tid);
105 buf[4..8].copy_from_slice(&self.user_bytes);
106
107 Ok(total_len)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_parse_atp_request() {
117 let data: &[u8] = &[0x60, 0xFF, 0x12, 0x34, 0x01, 0x02, 0x03, 0x04, 0xAA, 0xBB];
124
125 let packet = AtpPacket::parse(data).expect("failed to parse");
126
127 assert_eq!(packet.function, AtpFunction::Request);
128 assert!(packet.xo);
129 assert!(!packet.eom);
130 assert!(!packet.sts);
131 assert_eq!(packet.bitmap_seq_num, 0xFF);
132 assert_eq!(packet.tid, 0x1234);
133 assert_eq!(packet.user_bytes, [1, 2, 3, 4]);
134 }
135
136 #[test]
137 fn test_encode_atp_response() {
138 let packet = AtpPacket {
139 function: AtpFunction::Response,
140 xo: false,
141 eom: true,
142 sts: false,
143 bitmap_seq_num: 1, tid: 0x5678,
145 user_bytes: [0xDE, 0xAD, 0xBE, 0xEF],
146 };
147
148 let expected: &[u8] = &[0x90, 0x01, 0x56, 0x78, 0xDE, 0xAD, 0xBE, 0xEF];
151
152 let mut buf = [0u8; 8];
153 let len = packet.to_bytes(&mut buf).expect("failed to encode");
154
155 assert_eq!(len, 8);
156 assert_eq!(&buf, expected);
157 }
158
159 #[test]
160 fn test_round_trip() {
161 let original = AtpPacket {
162 function: AtpFunction::Release,
163 xo: false, eom: false,
165 sts: true,
166 bitmap_seq_num: 0,
167 tid: 9999,
168 user_bytes: [5, 6, 7, 8],
169 };
170
171 let mut buf = [0u8; 8];
172 let len = original.to_bytes(&mut buf).expect("failed to encode");
173 assert_eq!(len, 8);
174
175 let parsed = AtpPacket::parse(&buf).expect("failed to parse");
176 assert_eq!(original, parsed);
177 }
178}