Skip to main content

idm_frame/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3use core::iter::{Iterator, FusedIterator};
4use core::error::Error;
5use core::fmt::Display;
6
7/// Size of a Version 1 IDM Frame
8pub const IDMV1_FRAME_SIZE: usize = 6;
9/// Size of a Version 2 IDM Frame
10pub const IDMV2_FRAME_SIZE: usize = 8;
11/// Absolute smallest valid IDM frame
12pub const MIN_FRAME_SIZE: usize = IDMV1_FRAME_SIZE;
13
14/// Values of the IDM `version` field
15pub type IDMVersion = u8;
16/// IDM Protocol Version 1
17pub const IDM_VERSION_1: IDMVersion = 1;
18/// IDM Protocol Version 2
19pub const IDM_VERSION_2: IDMVersion = 2;
20
21/// Values of the IDM `final` field
22pub type IDMFinality = u8;
23/// Not a final frame relaying the last bytes of a complete IDM-PDU
24pub const IDM_NOT_FINAL: IDMFinality = 0;
25/// A final frame relaying the last bytes of a complete IDM-PDU
26pub const IDM_FINAL: IDMFinality = 1;
27
28/// Mask for the `encoding` field of a version 2 IDM frame.
29pub type EncodingMask = u16;
30/// Distinguished Encoding Rules (DER) as described in ITU-T Recommendation X.690.
31pub const IDM_ENCODING_DER: EncodingMask = 0b1000_0000_0000_0000;
32/// Basic Aligned variant of Packed Encoding Rules (PER) as described in ITU-T Recommendation X.691.
33pub const IDM_ENCODING_PER_ALIGNED: EncodingMask = 0b0100_0000_0000_0000;
34/// Basic Unaligned variant of Packed Encoding Rules (PER) as described in ITU-T Recommendation X.691.
35pub const IDM_ENCODING_PER_UNALIGNED: EncodingMask = 0b0010_0000_0000_0000;
36/// XML Encoding Rules (XER) as described in ITU-T Recommendation X.693.
37pub const IDM_ENCODING_XER: EncodingMask = 0b0001_0000_0000_0000;
38
39/// An error pertaining to IDM frame decoding
40#[derive(Debug, Clone, Eq, PartialEq)]
41pub enum IdmError {
42    /// Unsupported version
43    UnsupportedVersion(u8),
44}
45
46impl Display for IdmError {
47
48    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49        match self {
50            IdmError::UnsupportedVersion(v) => write!(f, "unrecognized idm version ({})", v),
51        }
52    }
53
54}
55
56impl Error for IdmError {}
57
58/// An IDM Frame
59#[derive(Debug)]
60pub struct IdmFrame <'a> {
61    /// The version field. Only version 1 or 2 are currently defined, which are
62    /// encoded as the values 1 and 2, respectively.
63    pub version: u8,
64    /// The final field. This frame is the final frame containing the complete
65    /// IDM PDU if this is set to 1. It is not the final frame if this is set
66    /// to 0. All other values are unspecified, but you should probably close
67    /// the connection if anything else is used.
68    pub final_: u8,
69    /// The encoding field of a version 2 IDM frame. This is always set to zero
70    /// for version 1 IDM frames.
71    pub encoding: u16,
72    /// The data fragment carried by the IDM frame.
73    pub data: &'a [u8],
74}
75
76/// Iterator that reads IDM frames from a buffer, such as a buffer of bytes read
77/// in from a TCP socket.
78pub struct IdmFrameIter <'a> {
79    buffer: &'a [u8],
80}
81
82impl <'a> IdmFrameIter<'a> {
83
84    /// Create a new IDM frame iterator
85    pub fn new(buffer: &'a [u8]) -> IdmFrameIter<'a> {
86        IdmFrameIter { buffer }
87    }
88
89    /// Bytes in the buffer not yet read
90    pub fn bytes_unread(&self) -> usize {
91        self.buffer.len()
92    }
93
94}
95
96impl <'a> Iterator for IdmFrameIter<'a> {
97    type Item = Result<IdmFrame<'a>, IdmError>;
98
99    fn next(&mut self) -> Option<Self::Item> {
100        if self.buffer.len() < MIN_FRAME_SIZE {
101            return None;
102        }
103        let version: u8 = self.buffer[0];
104        let final_: u8 = self.buffer[1];
105        let mut encoding: u16 = 0;
106        match version {
107            1 => {
108                let len: usize = u32::from_be_bytes([
109                    self.buffer[2],
110                    self.buffer[3],
111                    self.buffer[4],
112                    self.buffer[5],
113                ]) as usize;
114                let data = self.buffer.get(IDMV1_FRAME_SIZE..IDMV1_FRAME_SIZE + len)?;
115                self.buffer = &self.buffer[IDMV1_FRAME_SIZE + len..];
116                Some(Ok(IdmFrame {
117                    version,
118                    final_,
119                    encoding,
120                    data,
121                }))
122            },
123            2 => {
124                if self.buffer.len() < IDMV2_FRAME_SIZE {
125                    return None;
126                }
127                encoding = u16::from_be_bytes([
128                    self.buffer[2],
129                    self.buffer[3],
130                ]);
131                let len: usize = u32::from_be_bytes([
132                    self.buffer[4],
133                    self.buffer[5],
134                    self.buffer[6],
135                    self.buffer[7],
136                ]) as usize;
137                let data = self.buffer.get(IDMV2_FRAME_SIZE..IDMV2_FRAME_SIZE + len)?;
138                self.buffer = &self.buffer[IDMV2_FRAME_SIZE + len..];
139                Some(Ok(IdmFrame {
140                    version,
141                    final_,
142                    encoding,
143                    data,
144                }))
145            },
146            _ => {
147                self.buffer = &self.buffer[0..0];
148                Some(Err(IdmError::UnsupportedVersion(version)))
149            },
150        }
151    }
152
153}
154
155impl <'a> FusedIterator for IdmFrameIter<'a> {}
156
157/// Write an IDM version 1 frame header to `header`
158pub fn write_idm_v1_frame_header(
159    header: &mut [u8; IDMV1_FRAME_SIZE],
160    final_: bool,
161    data_len: u32,
162) {
163    header[0] = IDM_VERSION_1;
164    header[1] = if final_ { IDM_FINAL } else { IDM_NOT_FINAL };
165    let [l1, l2, l3, l4] = data_len.to_be_bytes();
166    header[2] = l1;
167    header[3] = l2;
168    header[4] = l3;
169    header[5] = l4;
170}
171
172/// Write an IDM version 2 frame header to `header`
173pub fn write_idm_v2_frame_header(
174    header: &mut [u8; IDMV2_FRAME_SIZE],
175    final_: bool,
176    encoding: EncodingMask,
177    data_len: u32,
178) {
179    header[0] = IDM_VERSION_2;
180    header[1] = if final_ { IDM_FINAL } else { IDM_NOT_FINAL };
181    let [e1, e2] = encoding.to_be_bytes();
182    header[2] = e1;
183    header[3] = e2;
184    let [l1, l2, l3, l4] = data_len.to_be_bytes();
185    header[4] = l1;
186    header[5] = l2;
187    header[6] = l3;
188    header[7] = l4;
189}
190
191#[cfg(test)]
192mod tests {
193
194    extern crate alloc;
195    use alloc::vec::Vec;
196
197    use super::{
198        IdmFrameIter,
199        write_idm_v1_frame_header,
200        write_idm_v2_frame_header,
201        IDM_ENCODING_XER,
202        IDMV1_FRAME_SIZE,
203        IDMV2_FRAME_SIZE,
204    };
205
206    #[test]
207    fn iter_idm_v1_frames_1() {
208        let buffer: Vec<u8> = Vec::from([
209            1, 1, 0, 0, 0, 5, 1, 2, 3, 4, 5,
210        ].as_slice());
211        let mut frames = IdmFrameIter::new(buffer.as_slice());
212        let frame = frames.next().unwrap().unwrap();
213        assert_eq!(frame.version, 1);
214        assert_eq!(frame.final_, 1);
215        assert_eq!(frame.encoding, 0);
216        assert_eq!(frame.data, [1,2,3,4,5].as_slice());
217        let frame = frames.next();
218        assert!(frame.is_none());
219        let frame = frames.next();
220        assert!(frame.is_none());
221    }
222
223    #[test]
224    fn iter_idm_v1_frames_2() {
225        let buffer: Vec<u8> = Vec::from([
226            1, 1, 0, 0, 0, 5, 1, 2, 3, 4, 5, 1
227        ].as_slice());
228        let mut frames = IdmFrameIter::new(buffer.as_slice());
229        let frame = frames.next().unwrap().unwrap();
230        assert_eq!(frame.version, 1);
231        assert_eq!(frame.final_, 1);
232        assert_eq!(frame.encoding, 0);
233        assert_eq!(frame.data, [1,2,3,4,5].as_slice());
234        let frame = frames.next();
235        assert!(frame.is_none());
236        let frame = frames.next();
237        assert!(frame.is_none());
238    }
239
240    #[test]
241    fn iter_idm_v1_frames_3() {
242        let buffer: Vec<u8> = Vec::from([ 1, 1, 0, 0, 0, 0 ].as_slice());
243        let mut frames = IdmFrameIter::new(buffer.as_slice());
244        let frame = frames.next().unwrap().unwrap();
245        assert_eq!(frame.version, 1);
246        assert_eq!(frame.final_, 1);
247        assert_eq!(frame.encoding, 0);
248        assert_eq!(frame.data, [].as_slice());
249        let frame = frames.next();
250        assert!(frame.is_none());
251        let frame = frames.next();
252        assert!(frame.is_none());
253    }
254
255    #[test]
256    fn iter_idm_v1_frames_4() {
257        let buffer: Vec<u8> = Vec::from([
258            1, 0, 0, 0, 0, 5, 1, 2, 3, 4, 5,
259            1, 1, 0, 0, 0, 4, 5, 6, 7, 8, 9,
260        ].as_slice());
261        let mut frames = IdmFrameIter::new(buffer.as_slice());
262        let frame = frames.next().unwrap().unwrap();
263        assert_eq!(frame.version, 1);
264        assert_eq!(frame.final_, 0);
265        assert_eq!(frame.encoding, 0);
266        assert_eq!(frame.data, [1,2,3,4,5].as_slice());
267        let frame = frames.next().unwrap().unwrap();
268        assert_eq!(frame.version, 1);
269        assert_eq!(frame.final_, 1);
270        assert_eq!(frame.encoding, 0);
271        assert_eq!(frame.data, [5,6,7,8].as_slice());
272
273        let frame = frames.next();
274        assert!(frame.is_none());
275        let frame = frames.next();
276        assert!(frame.is_none());
277    }
278
279    #[test]
280    fn iter_idm_v2_frames_1() {
281        let buffer: Vec<u8> = Vec::from([
282            2, 1, 8, 8, 0, 0, 0, 5, 1, 2, 3, 4, 5,
283        ].as_slice());
284        let mut frames = IdmFrameIter::new(buffer.as_slice());
285        let frame = frames.next().unwrap().unwrap();
286        assert_eq!(frame.version, 2);
287        assert_eq!(frame.final_, 1);
288        assert_eq!(frame.encoding, 0x0808);
289        assert_eq!(frame.data, [1,2,3,4,5].as_slice());
290        let frame = frames.next();
291        assert!(frame.is_none());
292        let frame = frames.next();
293        assert!(frame.is_none());
294    }
295
296    #[test]
297    fn iter_idm_v2_frames_2() {
298        let buffer: Vec<u8> = Vec::from([
299            2, 1, 8, 8, 0, 0, 0, 5, 1, 2, 3, 4, 5, 1
300        ].as_slice());
301        let mut frames = IdmFrameIter::new(buffer.as_slice());
302        let frame = frames.next().unwrap().unwrap();
303        assert_eq!(frame.version, 2);
304        assert_eq!(frame.final_, 1);
305        assert_eq!(frame.encoding, 0x0808);
306        assert_eq!(frame.data, [1,2,3,4,5].as_slice());
307        let frame = frames.next();
308        assert!(frame.is_none());
309        let frame = frames.next();
310        assert!(frame.is_none());
311    }
312
313    #[test]
314    fn iter_idm_v2_frames_3() {
315        let buffer: Vec<u8> = Vec::from([ 2, 1, 8, 8, 0, 0, 0, 0 ].as_slice());
316        let mut frames = IdmFrameIter::new(buffer.as_slice());
317        let frame = frames.next().unwrap().unwrap();
318        assert_eq!(frame.version, 2);
319        assert_eq!(frame.final_, 1);
320        assert_eq!(frame.encoding, 0x0808);
321        assert_eq!(frame.data, [].as_slice());
322        let frame = frames.next();
323        assert!(frame.is_none());
324        let frame = frames.next();
325        assert!(frame.is_none());
326    }
327
328    #[test]
329    fn iter_idm_v2_frames_4() {
330        let buffer: Vec<u8> = Vec::from([
331            2, 0, 8, 8, 0, 0, 0, 5, 1, 2, 3, 4, 5,
332            2, 1, 8, 8, 0, 0, 0, 4, 5, 6, 7, 8, 9,
333        ].as_slice());
334        let mut frames = IdmFrameIter::new(buffer.as_slice());
335        let frame = frames.next().unwrap().unwrap();
336        assert_eq!(frame.version, 2);
337        assert_eq!(frame.final_, 0);
338        assert_eq!(frame.encoding, 0x0808);
339        assert_eq!(frame.data, [1,2,3,4,5].as_slice());
340        let frame = frames.next().unwrap().unwrap();
341        assert_eq!(frame.version, 2);
342        assert_eq!(frame.final_, 1);
343        assert_eq!(frame.encoding, 0x0808);
344        assert_eq!(frame.data, [5,6,7,8].as_slice());
345
346        let frame = frames.next();
347        assert!(frame.is_none());
348        let frame = frames.next();
349        assert!(frame.is_none());
350    }
351
352    #[test]
353    fn iter_idm_unrecognized_version() {
354        let buffer: Vec<u8> = Vec::from([
355            3, 1, 8, 8, 0, 0, 0, 4, 5, 6, 7, 8, 9,
356        ].as_slice());
357        let mut frames = IdmFrameIter::new(buffer.as_slice());
358        let frame = frames.next().unwrap();
359        assert!(frame.is_err());
360
361        let frame = frames.next();
362        assert!(frame.is_none());
363        let frame = frames.next();
364        assert!(frame.is_none());
365    }
366
367    #[test]
368    fn test_write_idm_v1_frame_header_1() {
369        let mut buf: [u8; IDMV1_FRAME_SIZE] = [0, 0, 0, 0, 0, 0];
370        write_idm_v1_frame_header(&mut buf, true, 1024);
371        assert_eq!(buf, [1, 1, 0, 0, 4, 0]);
372    }
373
374    #[test]
375    fn test_write_idm_v2_frame_header_1() {
376        let mut buf: [u8; IDMV2_FRAME_SIZE] = [0, 0, 0, 0, 0, 0, 0, 0];
377        write_idm_v2_frame_header(&mut buf, true, IDM_ENCODING_XER, 1024);
378        assert_eq!(buf, [2, 1, 0x10, 0, 0, 0, 4, 0]);
379    }
380
381}