1#![cfg_attr(not(feature = "std"), no_std)]
2
3pub trait Write {
5 type Error;
6
7 fn write(&mut self, byte: u8) -> Result<(), Self::Error>;
9}
10
11pub struct Encoder<W> {
22 w: W,
23 run: u8,
24 zeros: u8,
25}
26
27impl<W> Encoder<W> {
39 pub const fn new(w: W) -> Self {
41 Self {
42 w,
43 run: 0,
44 zeros: 0,
45 }
46 }
47
48 pub fn writer(&mut self) -> &mut W {
50 &mut self.w
51 }
52}
53
54impl<W: Write> Encoder<W> {
55
56 pub fn write(&mut self, byte: u8) -> Result<(), W::Error> {
58 if self.run < 7 {
59 if byte == 0 {
60 self.zeros |= 1 << self.run;
61 } else {
62 self.w.write(byte)?;
63 }
64
65 self.run += 1;
66 if self.run == 7 && self.zeros != 0x00 {
67 self.w.write(self.zeros)?;
68 self.run = 0;
69 self.zeros = 0;
70 }
71 } else if byte == 0 {
72 self.w.write((self.run - 7) | 0x80)?;
73 self.run = 0;
74 self.zeros = 0;
75 } else {
76 self.w.write(byte)?;
77 self.run += 1;
78 if self.run == 134 {
79 self.w.write(0xFF)?;
80 self.run = 0;
81 self.zeros = 0;
82 }
83 }
84 Ok(())
85 }
86
87 pub fn end(&mut self) -> Result<(), W::Error> {
92 match self.run {
93 0 => {},
94 1..=6 => self.w.write((self.zeros | (0xFF << self.run)) & 0x7F)?,
95 _ => self.w.write((self.run - 7) | 0x80)?,
96 }
97 self.run = 0;
98 self.zeros = 0;
99 Ok(())
100 }
101}
102
103#[cfg(feature = "std")]
110pub fn encode(data: &[u8]) -> Vec<u8> {
111 struct VecWriter<'a>(&'a mut Vec<u8>);
112
113 impl<'a> Write for VecWriter<'a> {
114 type Error = std::convert::Infallible;
115 fn write(&mut self, byte: u8) -> Result<(), Self::Error> {
116 self.0.push(byte);
117 Ok(())
118 }
119 }
120
121 let mut res = Vec::new();
122 let mut enc = Encoder::new(VecWriter(&mut res));
123 for &b in data {
124 enc.write(b).unwrap();
125 }
126 enc.end().unwrap();
127 res
128}
129
130#[cfg(feature = "std")]
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub struct MalformedError;
134
135#[cfg(feature = "std")]
140pub fn decode(data: &[u8]) -> Result<Vec<u8>, MalformedError> {
141 let mut res = vec![];
142 let mut data = data.iter().rev().cloned();
143 while let Some(x) = data.next() {
144 match x {
145 0 => return Err(MalformedError),
146 0x01..=0x7f => {
147 for i in 0..7 {
148 if x & (1 << (6-i)) == 0 {
149 res.push(data.next().ok_or(MalformedError)?);
150 } else {
151 res.push(0);
152 }
153 }
154 }
155 0x80..=0xfe => {
156 let n = (x & 0x7f) + 7;
157 res.push(0);
158 for _ in 0..n {
159 res.push(data.next().ok_or(MalformedError)?);
160 }
161 }
162 0xff => {
163 for _ in 0..134 {
164 res.push(data.next().ok_or(MalformedError)?);
165 }
166 }
167 }
168 }
169
170 res.reverse();
171 Ok(res)
172}
173
174#[cfg(feature = "std")]
175#[cfg(test)]
176mod tests {
177 use super::*;
178 use hex_literal::hex;
179
180 #[test]
181 fn it_works() {
182 let tests: &[(&[u8], &[u8])] = &[
183 (
184 &hex!(""),
185 &hex!(""),
186 ), (
187 &hex!("00"),
188 &hex!("7f"),
189 ), (
190 &hex!("0000"),
191 &hex!("7f"),
192 ), (
193 &hex!("00000000000000"),
194 &hex!("7f"),
195 ), (
196 &hex!("0000000000000000"),
197 &hex!("7f7f"),
198 ), (
199 &hex!("01"),
200 &hex!("017e"),
201 ), (
202 &hex!("0100"),
203 &hex!("017e"),
204 ), (
205 &hex!("0001"),
206 &hex!("017d"),
207 ), (
208 &hex!("0102"),
209 &hex!("01027c"),
210 ), (
211 &hex!("11223344556600"),
212 &hex!("11223344556640"),
213 ), (
214 &hex!("11223344556677"),
215 &hex!("1122334455667780"),
216 ), (
217 &hex!("1122334455667700"),
218 &hex!("1122334455667780"),
219 ), (
220 &hex!("1122334455667788"),
221 &hex!("112233445566778881"),
222 ), (
223 &hex!("00000000000000 000000000000ff"),
224 &hex!("7f ff3f"),
225 ), (
226 &hex!("00000000004400 000000000000ff"),
227 &hex!("445f ff3f"),
228 ), (
229 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485"),
230 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485fe"),
231 ), (
232 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848500"),
233 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485fe"),
234 ), (
235 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586"),
236 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586ff"),
237 ), (
238 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858600"),
239 &hex!("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283848586ff7f"),
240 ),
241 ];
242
243 for (dec, enc) in tests {
244 assert_eq!(&encode(dec), enc);
245
246 let got = decode(enc).unwrap();
247 assert_eq!(&got[..dec.len()], *dec);
248 assert!(&got[dec.len()..].iter().all(|&x| x == 0));
249 }
250 }
251}