rcobs/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3/// Write trait to use with Encoder
4pub trait Write {
5    type Error;
6
7    /// Write a single byte.
8    fn write(&mut self, byte: u8) -> Result<(), Self::Error>;
9}
10
11/// Streaming encoder
12///
13/// Allows encoding of reverse-COBS messages in a streaming fashion, with almost
14/// no memory usage (internal state is just one single byte!).
15///
16/// To encode a message, call [write](Self::write) for each byte in the message, then call [end](Self::end).
17/// 
18/// You may use the same Encoder instance to encode multiple messages. In this case, you
19/// will probably want to separate messages with a `0x00`, which you have to write manually
20/// after calling [end](Self::end), for example with `encoder.writer().write(0)`.
21pub struct Encoder<W: Write> {
22    w: W,
23    run: u8,
24}
25
26impl<W: Write> Encoder<W> {
27    /// Create a new encoder with the given writer.
28    pub fn new(w: W) -> Self {
29        Self { w, run: 0 }
30    }
31
32    /// Mutably borrow the inner writer.
33    pub fn writer(&mut self) -> &mut W {
34        &mut self.w
35    }
36
37    /// Write a message byte.
38    pub fn write(&mut self, byte: u8) -> Result<(), W::Error> {
39        self.run += 1;
40        if byte == 0 {
41            self.w.write(self.run)?;
42            self.run = 0;
43        } else {
44            self.w.write(byte)?;
45            if self.run == 254 {
46                self.w.write(0xFF)?;
47                self.run = 0;
48            }
49        }
50        Ok(())
51    }
52
53    /// Finish encoding a message.
54    ///
55    /// This does NOT write a `0x00` separator byte, you must write it yourself
56    /// if you so desire.
57    pub fn end(&mut self) -> Result<(), W::Error> {
58        self.write(0)?;
59        Ok(())
60    }
61}
62
63/// Encode a full message.
64///
65/// Encodes a single message and returns it as a `Vec`. The returned data does
66/// not include any `0x00` separator byte, you have to add it yourself.
67///
68/// This is a convenience function using [Encoder] internally. For streaming encoding, use [Encoder].
69#[cfg(feature = "std")]
70pub fn encode(data: &[u8]) -> Vec<u8> {
71    struct VecWriter<'a>(&'a mut Vec<u8>);
72
73    impl<'a> Write for VecWriter<'a> {
74        type Error = std::convert::Infallible;
75        fn write(&mut self, byte: u8) -> Result<(), Self::Error> {
76            self.0.push(byte);
77            Ok(())
78        }
79    }
80
81    let mut res = Vec::new();
82    let mut enc = Encoder::new(VecWriter(&mut res));
83    for &b in data {
84        enc.write(b).unwrap();
85    }
86    enc.end().unwrap();
87    res
88}
89
90/// Error indicating the decoded data was malformed reverse-COBS.
91#[cfg(feature = "std")]
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct MalformedError;
94
95/// Decode a full message.
96///
97/// `data` must be a full reverse-COBS encoded message. Decoding partial
98/// messages is not possible. `data` must NOT include any `0x00` separator byte.
99#[cfg(feature = "std")]
100pub fn decode(data: &[u8]) -> Result<Vec<u8>, MalformedError> {
101    let mut res = vec![0; data.len()];
102    let mut dp = res.len();
103    let mut rp = res.len();
104
105    while dp != 0 {
106        let n = data[dp - 1] as usize;
107        if n == 0 {
108            return Err(MalformedError);
109        }
110
111        if n != 255 {
112            // push a 0
113            rp -= 1;
114        }
115
116        if dp < n {
117            return Err(MalformedError);
118        }
119        res[rp + 1 - n..rp].copy_from_slice(&data[dp - n..dp - 1]);
120        rp -= n - 1;
121        dp -= n;
122    }
123
124    // Remove extra zero
125    res.pop();
126
127    // Remove unused space at the beginning
128    res.drain(0..rp);
129
130    Ok(res)
131}
132
133#[cfg(feature = "std")]
134#[cfg(test)]
135mod tests {
136    use super::*;
137    use hex_literal::hex;
138
139    #[test]
140    fn it_works() {
141        let tests: &[(&[u8], &[u8])] = &[
142            (
143                &hex!(""),
144                &hex!("01"),
145            ), (
146                &hex!("00"),
147                &hex!("0101"),
148            ), (
149                &hex!("0000"),
150                &hex!("010101"),
151            ), (
152                &hex!("11220033"),
153                &hex!("1122033302"),
154            ), (
155                &hex!("11000000"),
156                &hex!("1102010101"),
157            ), (
158                &hex!("11223344"),
159                &hex!("1122334405"),
160            ), (
161                &hex!("0011001100110011"),
162                &hex!("011102110211021102"),
163            ), (
164                &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe"),
165                &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff01"),
166            ), (
167                &hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe"),
168                &hex!("010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff01"),
169            ), (
170                &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
171                &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeffff02"),
172            ), (
173                &hex!("02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00"),
174                &hex!("02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeffff0101"),
175            ), (
176                &hex!("030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff0001"),
177                &hex!("030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfefffe0102"),
178            ),
179        ];
180
181        for (dec, enc) in tests {
182            assert_eq!(&encode(dec), enc);
183            assert_eq!(&decode(enc).unwrap(), dec);
184        }
185    }
186}