dle_encoder/
lib.rs

1// use std::io::Read;
2
3pub const STX_CHAR: u8 = 0x02;
4pub const ETX_CHAR: u8 = 0x03;
5pub const DLE_CHAR: u8 = 0x10;
6pub const CR_CHAR: u8 = 0x0d;
7
8/// This struct is used to create a DleEncoder instance. It can also
9/// be used to configure the encoder
10#[derive(Copy, Clone)]
11pub struct DleEncoder {
12    /// Configure whether the encoder uses the escaped or non-escaped mode
13    pub escape_stx_etx: bool,
14    /// It is possible to escape CR characters as well in the escaped mode
15    pub escape_cr: bool,
16    /// Configure the encoder to not add STX and ETX characters at the start
17    /// and end when encoding
18    pub add_stx_etx: bool,
19}
20
21#[derive(Debug, PartialEq)]
22pub enum DleError {
23    StreamTooShort,
24    DecodingError,
25}
26
27impl Default for DleEncoder {
28    fn default() -> DleEncoder {
29        DleEncoder {
30            escape_stx_etx: true,
31            escape_cr: false,
32            add_stx_etx: true,
33        }
34    }
35}
36
37impl DleEncoder {
38    /// This method encodes a given byte stream with ASCII based DLE encoding.
39    /// It returns the number of encoded bytes or a DLE error code.
40    ///
41    /// # Arguments
42    ///
43    /// * `source_stream` - The stream to encode
44    /// * `dest_stream` - Encoded stream will be written here
45    ///
46    /// # Examples
47    ///
48    /// ```
49    /// use dle_encoder::DleEncoder;
50    ///
51    /// let dle_encoder = DleEncoder::default();
52    /// let mut encoding_buffer: [u8; 16] = [0; 16];
53    /// let example_array: [u8; 3] = [0, 0x02, 0x10];
54    ///
55    /// let encode_result = dle_encoder.encode(
56    ///     &example_array, &mut encoding_buffer
57    /// );
58    /// assert!(encode_result.is_ok());
59    /// let encoded_len = encode_result.unwrap();
60    /// assert_eq!(encoded_len, 7);
61    ///
62    /// println!("Source buffer: {:?}", example_array);
63    /// println!("Encoded stream: {:?}", &encoding_buffer[ .. encoded_len])
64    /// ```
65    pub fn encode(&self, source_stream: &[u8], dest_stream: &mut [u8]) -> Result<usize, DleError> {
66        if self.escape_stx_etx {
67            self.encode_escaped(source_stream, dest_stream)
68        } else {
69            self.encode_non_escaped(source_stream, dest_stream)
70        }
71    }
72
73    /// This method encodes a given byte stream with ASCII based DLE encoding.
74    /// It explicitely does so in the escaped mode, which is the default
75    /// mode.
76    ///
77    /// # Arguments
78    ///
79    /// * `source_stream` - The stream to encode
80    /// * `dest_stream` - Encoded stream will be written here
81    pub fn encode_escaped(
82        &self,
83        source_stream: &[u8],
84        dest_stream: &mut [u8],
85    ) -> Result<usize, DleError> {
86        let mut encoded_idx = 0;
87        let mut source_idx = 0;
88        let max_dest_len = dest_stream.len();
89        if self.add_stx_etx {
90            if max_dest_len < 1 {
91                return Err(DleError::StreamTooShort);
92            }
93            dest_stream[encoded_idx] = STX_CHAR;
94            encoded_idx += 1;
95        }
96        while encoded_idx < max_dest_len && source_idx < source_stream.len() {
97            let next_byte = source_stream[source_idx];
98            if next_byte == STX_CHAR
99                || next_byte == ETX_CHAR
100                || (self.escape_cr && next_byte == CR_CHAR)
101            {
102                if encoded_idx + 1 >= max_dest_len {
103                    return Err(DleError::StreamTooShort);
104                } else {
105                    dest_stream[encoded_idx] = DLE_CHAR;
106                    encoded_idx += 1;
107                    // Next byte will be the actual byte + 0x40. This prevents STX and ETX from
108                    // appearin in the encoded data stream at all, so when polling an encoded
109                    // stream, the transmission can be stopped at ETX. 0x40 was chose at random
110                    // with special requirements:
111                    // - Prevent going from one control char to another
112                    // - Prevent overflow for common characters
113                    dest_stream[encoded_idx] = next_byte + 0x40;
114                }
115            } else if next_byte == DLE_CHAR {
116                if encoded_idx + 1 >= max_dest_len {
117                    return Err(DleError::StreamTooShort);
118                } else {
119                    dest_stream[encoded_idx] = DLE_CHAR;
120                    encoded_idx += 1;
121                    dest_stream[encoded_idx] = DLE_CHAR;
122                }
123            } else {
124                dest_stream[encoded_idx] = next_byte;
125            }
126            encoded_idx += 1;
127            source_idx += 1;
128        }
129
130        if source_idx == source_stream.len() {
131            if self.add_stx_etx {
132                if encoded_idx + 1 >= max_dest_len {
133                    return Err(DleError::StreamTooShort);
134                }
135                dest_stream[encoded_idx] = ETX_CHAR;
136                encoded_idx += 1
137            }
138            Ok(encoded_idx)
139        } else {
140            Err(DleError::StreamTooShort)
141        }
142    }
143
144    /// This method encodes a given byte stream with ASCII based DLE encoding.
145    /// It explicitely does so in the non-escaped mode.
146    ///
147    /// # Arguments
148    ///
149    /// * `source_stream` - The stream to encode
150    /// * `dest_stream` - Encoded stream will be written here
151    ///
152    /// # Example
153    ///
154    /// ```
155    /// use dle_encoder::DleEncoder;
156    ///
157    /// let dle_encoder = DleEncoder::default();
158    /// let mut encoding_buffer: [u8; 16] = [0; 16];
159    /// let example_array: [u8; 3] = [0, 0x02, 0x10];
160    ///
161    /// let encode_result = dle_encoder.encode_non_escaped(
162    ///     &example_array, &mut encoding_buffer
163    /// );
164    /// assert!(encode_result.is_ok());
165    /// let encoded_len = encode_result.unwrap();
166    /// assert_eq!(encoded_len, 8);
167    ///
168    /// println!("Source buffer: {:?}", example_array);
169    /// println!("Encoded stream: {:?}", &encoding_buffer[ .. encoded_len])
170    /// ```
171    pub fn encode_non_escaped(
172        &self,
173        source_stream: &[u8],
174        dest_stream: &mut [u8],
175    ) -> Result<usize, DleError> {
176        let mut encoded_idx = 0;
177        let mut source_idx = 0;
178        let source_stream_len = source_stream.len();
179        let max_dest_len = dest_stream.len();
180        if self.add_stx_etx {
181            if max_dest_len < 2 {
182                return Err(DleError::StreamTooShort);
183            }
184            dest_stream[encoded_idx] = DLE_CHAR;
185            encoded_idx += 1;
186            dest_stream[encoded_idx] = STX_CHAR;
187            encoded_idx += 1;
188        }
189
190        while encoded_idx < max_dest_len && source_idx < source_stream_len {
191            let next_byte = source_stream[source_idx];
192            if next_byte == DLE_CHAR {
193                if encoded_idx + 1 >= max_dest_len {
194                    return Err(DleError::StreamTooShort);
195                } else {
196                    dest_stream[encoded_idx] = DLE_CHAR;
197                    encoded_idx += 1;
198                    dest_stream[encoded_idx] = DLE_CHAR;
199                }
200            } else {
201                dest_stream[encoded_idx] = next_byte;
202            }
203            encoded_idx += 1;
204            source_idx += 1;
205        }
206
207        if source_idx == source_stream_len {
208            if self.add_stx_etx {
209                if encoded_idx + 2 >= max_dest_len {
210                    return Err(DleError::StreamTooShort);
211                }
212                dest_stream[encoded_idx] = DLE_CHAR;
213                encoded_idx += 1;
214                dest_stream[encoded_idx] = ETX_CHAR;
215                encoded_idx += 1;
216            }
217            Ok(encoded_idx)
218        } else {
219            Err(DleError::StreamTooShort)
220        }
221    }
222
223    /// This method decodes a given byte stream which was encoded with a ASCII
224    /// DLE encoder. It explicitely does so in the escaped mode, which is the default
225    /// mode. It returns the length of the decoded buffer or an error code if
226    /// there is a decoder failure or the destination stream is too short.
227    ///
228    /// # Arguments
229    ///
230    /// * `source_stream` - The stream to decode
231    /// * `dest_stream` - Decoded stream will be written here
232    /// * `read_len` - The number of read bytes in the source stream will be
233    ///   assigned to this variable
234    ///
235    /// # Examples
236    ///
237    /// ```
238    /// use dle_encoder::DleEncoder;
239    ///
240    /// let dle_encoder = DleEncoder::default();
241    /// let mut decoding_buffer: [u8; 16] = [0; 16];
242    /// let encoded_array: [u8; 4] = [0x02, 0x10, 0x02 + 0x40, 0x03];
243    /// let mut read_len = 0;
244    /// let decode_result = dle_encoder.decode(
245    ///     &encoded_array, &mut decoding_buffer, &mut read_len
246    /// );
247    /// assert!(decode_result.is_ok());
248    /// let decoded_len = decode_result.unwrap();
249    /// assert_eq!(decoded_len, 1);
250    ///
251    /// println!("Source buffer: {:?}", encoded_array);
252    /// println!("Encoded stream: {:?}", &decoding_buffer[ .. decoded_len])
253    /// ```
254    pub fn decode(
255        &self,
256        source_stream: &[u8],
257        dest_stream: &mut [u8],
258        read_len: &mut usize,
259    ) -> Result<usize, DleError> {
260        if self.escape_stx_etx {
261            self.decode_escaped(source_stream, dest_stream, read_len)
262        } else {
263            self.decode_non_escaped(source_stream, dest_stream, read_len)
264        }
265    }
266
267    /// This method decodes a given byte stream which was encoded with a ASCII
268    /// DLE encoder. It explicitely does so in the escaped mode, which is the default
269    /// mode. It returns the length of the decoded buffer or an error code if
270    /// there is a decoder failure or the destination stream is too short.
271    ///
272    /// # Arguments
273    ///
274    /// * `source_stream` - The stream to decode
275    /// * `dest_stream` - Decoded stream will be written here
276    /// * `read_len` - The number of read bytes in the source stream will be
277    ///   assigned to this variable
278    pub fn decode_escaped(
279        &self,
280        source_stream: &[u8],
281        dest_stream: &mut [u8],
282        read_len: &mut usize,
283    ) -> Result<usize, DleError> {
284        let mut encoded_idx = 0;
285        let mut decoded_idx = 0;
286        let source_stream_len = source_stream.len();
287        let dest_stream_len = dest_stream.len();
288        *read_len = 0;
289        if dest_stream_len < 1 {
290            return Err(DleError::StreamTooShort);
291        }
292        if source_stream[encoded_idx] != STX_CHAR {
293            return Err(DleError::DecodingError);
294        }
295        encoded_idx += 1;
296        while encoded_idx < source_stream_len - 1
297            && decoded_idx < dest_stream_len
298            && source_stream[encoded_idx] != ETX_CHAR
299            && source_stream[encoded_idx] != STX_CHAR
300        {
301            if source_stream[encoded_idx] == DLE_CHAR {
302                if encoded_idx + 1 >= source_stream_len {
303                    *read_len = source_stream_len;
304                    return Err(DleError::DecodingError);
305                }
306                let next_byte = source_stream[encoded_idx + 1];
307                if next_byte == DLE_CHAR {
308                    dest_stream[decoded_idx] = next_byte;
309                } else if next_byte == STX_CHAR + 0x40
310                    || next_byte == ETX_CHAR + 0x40
311                    || (self.escape_cr && next_byte == CR_CHAR + 0x40)
312                {
313                    dest_stream[decoded_idx] = next_byte - 0x40;
314                } else {
315                    *read_len = encoded_idx + 2;
316                    return Err(DleError::DecodingError);
317                }
318                encoded_idx += 1
319            } else {
320                dest_stream[decoded_idx] = source_stream[encoded_idx];
321            }
322            encoded_idx += 1;
323            decoded_idx += 1
324        }
325
326        if source_stream[encoded_idx] != ETX_CHAR {
327            if decoded_idx == dest_stream_len {
328                *read_len = 0;
329                Err(DleError::StreamTooShort)
330            } else {
331                *read_len = encoded_idx + 1;
332                Err(DleError::DecodingError)
333            }
334        } else {
335            *read_len = encoded_idx + 1;
336            Ok(decoded_idx)
337        }
338    }
339
340    /// This method decodes a given byte stream which was encoded with a ASCII
341    /// DLE encoder. It explicitely does so in the non-escaped mode.
342    /// It returns the length of the decoded buffer or an error code if
343    /// there is a decoder failure or the destination stream is too short.
344    ///
345    /// # Arguments
346    ///
347    /// * `source_stream` - The stream to decode
348    /// * `dest_stream` - Decoded stream will be written here
349    /// * `read_len` - The number of read bytes in the source stream will be
350    ///   assigned to this variable
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// use dle_encoder::DleEncoder;
356    ///
357    /// let dle_encoder = DleEncoder::default();
358    /// let mut decoding_buffer: [u8; 16] = [0; 16];
359    /// let encoded_array: [u8; 6] = [0x10, 0x02, 0x02, 0x03, 0x10, 0x03];
360    /// let mut read_len = 0;
361    /// let decode_result = dle_encoder.decode_non_escaped(
362    ///     &encoded_array, &mut decoding_buffer, &mut read_len
363    /// );
364    /// assert!(decode_result.is_ok());
365    /// let decoded_len = decode_result.unwrap();
366    /// assert_eq!(decoded_len, 2);
367    ///
368    /// println!("Source buffer: {:?}", encoded_array);
369    /// println!("Encoded stream: {:?}", &decoding_buffer[ .. decoded_len])
370    /// ```
371    pub fn decode_non_escaped(
372        &self,
373        source_stream: &[u8],
374        dest_stream: &mut [u8],
375        read_len: &mut usize,
376    ) -> Result<usize, DleError> {
377        let mut encoded_idx = 0;
378        let mut decoded_idx = 0;
379        let source_stream_len = source_stream.len();
380        let dest_stream_len = dest_stream.len();
381        *read_len = 0;
382
383        if dest_stream_len < 2 {
384            return Err(DleError::StreamTooShort);
385        }
386        if source_stream[encoded_idx] != DLE_CHAR {
387            return Err(DleError::DecodingError);
388        }
389        encoded_idx += 1;
390        if source_stream[encoded_idx] != STX_CHAR {
391            *read_len = 1;
392            return Err(DleError::DecodingError);
393        }
394        encoded_idx += 1;
395        while encoded_idx < source_stream_len && decoded_idx < dest_stream_len {
396            if source_stream[encoded_idx] == DLE_CHAR {
397                if encoded_idx + 1 >= source_stream_len {
398                    *read_len = encoded_idx;
399                    return Err(DleError::DecodingError);
400                }
401                let next_byte = source_stream[encoded_idx + 1];
402                if next_byte == STX_CHAR {
403                    // Set read_len so the DLE/STX char combination is preserved
404                    // It could be the start of another frame
405                    *read_len = encoded_idx;
406                    return Err(DleError::DecodingError);
407                } else if next_byte == DLE_CHAR {
408                    dest_stream[decoded_idx] = next_byte;
409                    encoded_idx += 1;
410                } else if next_byte == ETX_CHAR {
411                    // End of stream reached
412                    *read_len = encoded_idx + 2;
413                    return Ok(decoded_idx);
414                } else {
415                    *read_len = encoded_idx;
416                    return Err(DleError::DecodingError);
417                }
418            } else {
419                dest_stream[decoded_idx] = source_stream[encoded_idx];
420            }
421            encoded_idx += 1;
422            decoded_idx += 1;
423        }
424
425        if decoded_idx == dest_stream_len {
426            // So far we did not find anything wrong here, let the user try
427            // again
428            *read_len = 0;
429            Err(DleError::StreamTooShort)
430        } else {
431            *read_len = encoded_idx;
432            Err(DleError::DecodingError)
433        }
434    }
435
436    // TODO: Implement for the generic Read Trait
437    //pub fn decode_from_reader(source: &impl std::io::Read) {}
438}
439
440#[cfg(test)]
441mod tests {
442    use super::*;
443
444    const TEST_ARRAY_0: [u8; 5] = [0, 0, 0, 0, 0];
445    const TEST_ARRAY_1: [u8; 3] = [0, DLE_CHAR, 5];
446    const TEST_ARRAY_2: [u8; 3] = [0, STX_CHAR, 5];
447    const TEST_ARRAY_3: [u8; 3] = [0, CR_CHAR, ETX_CHAR];
448    const TEST_ARRAY_4: [u8; 3] = [DLE_CHAR, ETX_CHAR, STX_CHAR];
449
450    const TEST_ARRAY_0_ENCODED_ESCPAED: &[u8] = &[STX_CHAR, 0, 0, 0, 0, 0, ETX_CHAR];
451    const TEST_ARRAY_0_ENCODED_NON_ESCPAED: &[u8] =
452        &[DLE_CHAR, STX_CHAR, 0, 0, 0, 0, 0, DLE_CHAR, ETX_CHAR];
453
454    const TEST_ARRAY_1_ENCODED_ESCPAED: [u8; 6] = [STX_CHAR, 0, DLE_CHAR, DLE_CHAR, 5, ETX_CHAR];
455    const TEST_ARRAY_1_ENCODED_NON_ESCPAED: [u8; 8] = [
456        DLE_CHAR, STX_CHAR, 0, DLE_CHAR, DLE_CHAR, 5, DLE_CHAR, ETX_CHAR,
457    ];
458
459    const TEST_ARRAY_2_ENCODED_ESCPAED: &[u8] =
460        &[STX_CHAR, 0, DLE_CHAR, STX_CHAR + 0x40, 5, ETX_CHAR];
461    const TEST_ARRAY_2_ENCODED_NON_ESCPAED: &[u8] =
462        &[DLE_CHAR, STX_CHAR, 0, STX_CHAR, 5, DLE_CHAR, ETX_CHAR];
463
464    const TEST_ARRAY_3_ENCODED_ESCPAED: &[u8] =
465        &[STX_CHAR, 0, CR_CHAR, DLE_CHAR, ETX_CHAR + 0x40, ETX_CHAR];
466    const TEST_ARRAY_3_ENCODED_NON_ESCPAED: &[u8] =
467        &[DLE_CHAR, STX_CHAR, 0, CR_CHAR, ETX_CHAR, DLE_CHAR, ETX_CHAR];
468
469    const TEST_ARRAY_4_ENCODED_ESCPAED: &[u8] = &[
470        STX_CHAR,
471        DLE_CHAR,
472        DLE_CHAR,
473        DLE_CHAR,
474        ETX_CHAR + 0x40,
475        DLE_CHAR,
476        STX_CHAR + 0x40,
477        ETX_CHAR,
478    ];
479    const TEST_ARRAY_4_ENCODED_NON_ESCPAED: [u8; 8] = [
480        DLE_CHAR, STX_CHAR, DLE_CHAR, DLE_CHAR, ETX_CHAR, STX_CHAR, DLE_CHAR, ETX_CHAR,
481    ];
482
483    #[test]
484    fn test_encoder() {
485        let mut dle_encoder = DleEncoder::default();
486        let mut buffer: [u8; 32] = [0; 32];
487        let test_encode_closure = |dle_encoder: &DleEncoder,
488                                   buf_to_encode: &[u8],
489                                   expected_buf: &[u8],
490                                   buffer: &mut [u8]| {
491            let encode_res = dle_encoder.encode(buf_to_encode, buffer);
492            assert!(encode_res.is_ok());
493            for (idx, byte) in expected_buf.iter().enumerate() {
494                assert_eq!(buffer[idx], *byte);
495            }
496            assert_eq!(encode_res.unwrap(), expected_buf.len());
497        };
498
499        let test_faulty_encoding = |dle_encoder: &DleEncoder,
500                                    buf_to_encode: &[u8],
501                                    expected_buf: &[u8],
502                                    buffer: &mut [u8]| {
503            for faulty_dest_size in 0..expected_buf.len() {
504                let encode_res =
505                    dle_encoder.encode(buf_to_encode, &mut buffer[0..faulty_dest_size]);
506                assert!(encode_res.is_err());
507                assert_eq!(encode_res.unwrap_err(), DleError::StreamTooShort);
508            }
509        };
510
511        test_encode_closure(
512            &dle_encoder,
513            &TEST_ARRAY_0,
514            TEST_ARRAY_0_ENCODED_ESCPAED,
515            &mut buffer,
516        );
517        test_encode_closure(
518            &dle_encoder,
519            &TEST_ARRAY_1,
520            &TEST_ARRAY_1_ENCODED_ESCPAED,
521            &mut buffer,
522        );
523        test_encode_closure(
524            &dle_encoder,
525            &TEST_ARRAY_2,
526            TEST_ARRAY_2_ENCODED_ESCPAED,
527            &mut buffer,
528        );
529        test_encode_closure(
530            &dle_encoder,
531            &TEST_ARRAY_3,
532            TEST_ARRAY_3_ENCODED_ESCPAED,
533            &mut buffer,
534        );
535        test_encode_closure(
536            &dle_encoder,
537            &TEST_ARRAY_4,
538            TEST_ARRAY_4_ENCODED_ESCPAED,
539            &mut buffer,
540        );
541
542        test_faulty_encoding(
543            &dle_encoder,
544            &TEST_ARRAY_0,
545            TEST_ARRAY_0_ENCODED_ESCPAED,
546            &mut buffer,
547        );
548        test_faulty_encoding(
549            &dle_encoder,
550            &TEST_ARRAY_1,
551            &TEST_ARRAY_1_ENCODED_ESCPAED,
552            &mut buffer,
553        );
554        test_faulty_encoding(
555            &dle_encoder,
556            &TEST_ARRAY_2,
557            TEST_ARRAY_2_ENCODED_ESCPAED,
558            &mut buffer,
559        );
560        test_faulty_encoding(
561            &dle_encoder,
562            &TEST_ARRAY_3,
563            TEST_ARRAY_3_ENCODED_ESCPAED,
564            &mut buffer,
565        );
566        test_faulty_encoding(
567            &dle_encoder,
568            &TEST_ARRAY_4,
569            TEST_ARRAY_4_ENCODED_ESCPAED,
570            &mut buffer,
571        );
572
573        dle_encoder.escape_stx_etx = false;
574        test_encode_closure(
575            &dle_encoder,
576            &TEST_ARRAY_0,
577            TEST_ARRAY_0_ENCODED_NON_ESCPAED,
578            &mut buffer,
579        );
580        test_encode_closure(
581            &dle_encoder,
582            &TEST_ARRAY_1,
583            &TEST_ARRAY_1_ENCODED_NON_ESCPAED,
584            &mut buffer,
585        );
586        test_encode_closure(
587            &dle_encoder,
588            &TEST_ARRAY_2,
589            TEST_ARRAY_2_ENCODED_NON_ESCPAED,
590            &mut buffer,
591        );
592        test_encode_closure(
593            &dle_encoder,
594            &TEST_ARRAY_3,
595            TEST_ARRAY_3_ENCODED_NON_ESCPAED,
596            &mut buffer,
597        );
598        test_encode_closure(
599            &dle_encoder,
600            &TEST_ARRAY_4,
601            &TEST_ARRAY_4_ENCODED_NON_ESCPAED,
602            &mut buffer,
603        );
604
605        test_faulty_encoding(
606            &dle_encoder,
607            &TEST_ARRAY_0,
608            TEST_ARRAY_0_ENCODED_ESCPAED,
609            &mut buffer,
610        );
611        test_faulty_encoding(
612            &dle_encoder,
613            &TEST_ARRAY_1,
614            &TEST_ARRAY_1_ENCODED_ESCPAED,
615            &mut buffer,
616        );
617        test_faulty_encoding(
618            &dle_encoder,
619            &TEST_ARRAY_2,
620            TEST_ARRAY_2_ENCODED_ESCPAED,
621            &mut buffer,
622        );
623        test_faulty_encoding(
624            &dle_encoder,
625            &TEST_ARRAY_3,
626            TEST_ARRAY_3_ENCODED_ESCPAED,
627            &mut buffer,
628        );
629        test_faulty_encoding(
630            &dle_encoder,
631            &TEST_ARRAY_4,
632            TEST_ARRAY_4_ENCODED_ESCPAED,
633            &mut buffer,
634        );
635    }
636
637    #[test]
638    fn test_decoder() {
639        let mut dle_encoder = DleEncoder::default();
640        let mut buffer: [u8; 32] = [0; 32];
641        let test_decode_closure = |dle_encoder: &DleEncoder,
642                                   encoded_test_vec: &[u8],
643                                   expected_buf: &[u8],
644                                   buffer: &mut [u8]| {
645            let mut read_len = 0;
646            let decode_res = dle_encoder.decode(encoded_test_vec, buffer, &mut read_len);
647            assert!(decode_res.is_ok());
648            for (idx, byte) in expected_buf.iter().enumerate() {
649                assert_eq!(buffer[idx], *byte);
650            }
651            assert_eq!(read_len, encoded_test_vec.len());
652            assert_eq!(decode_res.unwrap(), expected_buf.len());
653        };
654
655        let test_faulty_decoding =
656            |dle_encoder: &DleEncoder, faulty_encoded_buf: &[u8], buffer: &mut [u8]| {
657                let mut read_len = 0;
658                let decode_res = dle_encoder.decode(&faulty_encoded_buf, buffer, &mut read_len);
659                assert!(decode_res.is_err());
660                assert_eq!(decode_res.unwrap_err(), DleError::DecodingError);
661            };
662
663        test_decode_closure(
664            &dle_encoder,
665            TEST_ARRAY_0_ENCODED_ESCPAED,
666            &TEST_ARRAY_0,
667            &mut buffer,
668        );
669        test_decode_closure(
670            &dle_encoder,
671            &TEST_ARRAY_1_ENCODED_ESCPAED,
672            &TEST_ARRAY_1,
673            &mut buffer,
674        );
675        test_decode_closure(
676            &dle_encoder,
677            TEST_ARRAY_2_ENCODED_ESCPAED,
678            &TEST_ARRAY_2,
679            &mut buffer,
680        );
681        test_decode_closure(
682            &dle_encoder,
683            TEST_ARRAY_3_ENCODED_ESCPAED,
684            &TEST_ARRAY_3,
685            &mut buffer,
686        );
687        test_decode_closure(
688            &dle_encoder,
689            TEST_ARRAY_4_ENCODED_ESCPAED,
690            &TEST_ARRAY_4,
691            &mut buffer,
692        );
693
694        dle_encoder.escape_stx_etx = false;
695        test_decode_closure(
696            &dle_encoder,
697            TEST_ARRAY_0_ENCODED_NON_ESCPAED,
698            &TEST_ARRAY_0,
699            &mut buffer,
700        );
701        test_decode_closure(
702            &dle_encoder,
703            &TEST_ARRAY_1_ENCODED_NON_ESCPAED,
704            &TEST_ARRAY_1,
705            &mut buffer,
706        );
707        test_decode_closure(
708            &dle_encoder,
709            TEST_ARRAY_2_ENCODED_NON_ESCPAED,
710            &TEST_ARRAY_2,
711            &mut buffer,
712        );
713        test_decode_closure(
714            &dle_encoder,
715            TEST_ARRAY_3_ENCODED_NON_ESCPAED,
716            &TEST_ARRAY_3,
717            &mut buffer,
718        );
719        test_decode_closure(
720            &dle_encoder,
721            &TEST_ARRAY_4_ENCODED_NON_ESCPAED,
722            &TEST_ARRAY_4,
723            &mut buffer,
724        );
725
726        let mut test_array_1_encoded_faulty = TEST_ARRAY_1_ENCODED_NON_ESCPAED.clone();
727        let mut prev_val = test_array_1_encoded_faulty[0];
728        test_array_1_encoded_faulty[0] = 0;
729        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
730
731        test_array_1_encoded_faulty[0] = prev_val;
732        prev_val = test_array_1_encoded_faulty[1];
733        test_array_1_encoded_faulty[1] = 0;
734        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
735
736        test_array_1_encoded_faulty[1] = prev_val;
737        prev_val = test_array_1_encoded_faulty[6];
738        test_array_1_encoded_faulty[6] = 0;
739        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
740
741        test_array_1_encoded_faulty[6] = prev_val;
742        test_array_1_encoded_faulty[7] = 0;
743        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
744
745        let mut test_array_4_encoded_faulty = TEST_ARRAY_4_ENCODED_NON_ESCPAED.clone();
746        test_array_4_encoded_faulty[3] = 0;
747        test_faulty_decoding(&dle_encoder, &test_array_4_encoded_faulty, &mut buffer);
748
749        dle_encoder.escape_stx_etx = true;
750        let mut test_array_1_encoded_faulty = TEST_ARRAY_1_ENCODED_ESCPAED.clone();
751        prev_val = test_array_1_encoded_faulty[3];
752        test_array_1_encoded_faulty[3] = 0;
753        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
754
755        test_array_1_encoded_faulty[3] = prev_val;
756        prev_val = test_array_1_encoded_faulty[0];
757        test_array_1_encoded_faulty[0] = 0;
758        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
759
760        test_array_1_encoded_faulty[0] = prev_val;
761        prev_val = test_array_1_encoded_faulty[5];
762        test_array_1_encoded_faulty[5] = 0;
763        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
764
765        test_array_1_encoded_faulty[5] = prev_val;
766        test_array_1_encoded_faulty[2] = 0;
767        test_faulty_decoding(&dle_encoder, &test_array_1_encoded_faulty, &mut buffer);
768
769        let mut decoding_buffer: [u8; 16] = [0; 16];
770        let encoded_array: [u8; 4] = [0x02, 0x10, 0x02 + 0x40, 0x03];
771        let mut read_len = 0;
772        let decode_result = dle_encoder.decode(&encoded_array, &mut decoding_buffer, &mut read_len);
773        assert!(decode_result.is_ok());
774        let decoded_len = decode_result.unwrap();
775        assert_eq!(decoded_len, 1);
776    }
777}