1use crate::buf::WriteBuf;
40use crate::error::{Error, Result};
41
42const MAX_RUN: usize = 254;
44
45#[inline]
59#[must_use]
60pub const fn max_encoded_len(len: usize) -> usize {
61 let overhead = if len == 0 { 1 } else { len.div_ceil(MAX_RUN) };
62 len.saturating_add(overhead)
63}
64
65pub fn encode(src: &[u8], out: &mut WriteBuf<'_>) -> Result<()> {
89 let dst = out.spare_mut();
90 if dst.len() < max_encoded_len(src.len()) && dst.len() < encoded_len(src) {
93 return Err(Error::BufferFull);
94 }
95 let mut code_at = 0;
97 let mut write = 1;
98 let mut code: u8 = 1;
99 for (i, &byte) in src.iter().enumerate() {
100 if byte != 0 {
101 dst[write] = byte;
102 write += 1;
103 code += 1;
104 }
105 if byte == 0 || (code == 0xFF && i + 1 < src.len()) {
106 dst[code_at] = code;
108 code_at = write;
109 write += 1;
110 code = 1;
111 }
112 }
113 dst[code_at] = code;
114 out.commit(write);
115 Ok(())
116}
117
118fn encoded_len(src: &[u8]) -> usize {
120 let mut len = 1;
121 let mut code: u8 = 1;
122 for (i, &byte) in src.iter().enumerate() {
123 if byte != 0 {
124 len += 1;
125 code += 1;
126 }
127 if byte == 0 || (code == 0xFF && i + 1 < src.len()) {
128 len += 1;
129 code = 1;
130 }
131 }
132 len
133}
134
135pub fn decode(src: &[u8], out: &mut WriteBuf<'_>) -> Result<()> {
164 let mut len = 0;
166 for_each_run(src, |run, zero_follows| {
167 len += run.len() + usize::from(zero_follows);
168 Ok(())
169 })?;
170 let Some(dst) = out.spare_mut().get_mut(..len) else {
171 return Err(Error::BufferFull);
172 };
173 let mut write = 0;
174 for_each_run(src, |run, zero_follows| {
175 dst[write..write + run.len()].copy_from_slice(run);
176 write += run.len();
177 if zero_follows {
178 dst[write] = 0;
179 write += 1;
180 }
181 Ok(())
182 })?;
183 out.commit(len);
184 Ok(())
185}
186
187pub fn decode_in_place(buf: &mut [u8]) -> Result<usize> {
209 validate(buf)?;
210 let mut read = 0;
211 let mut write = 0;
212 while read < buf.len() {
213 let code = usize::from(buf[read]);
214 let run_start = read + 1;
215 let run_end = read + code;
216 buf.copy_within(run_start..run_end, write);
217 write += code - 1;
218 read = run_end;
219 if code != 0xFF && read < buf.len() {
220 buf[write] = 0;
221 write += 1;
222 }
223 }
224 Ok(write)
225}
226
227fn validate(src: &[u8]) -> Result<()> {
229 for_each_run(src, |_, _| Ok(()))
230}
231
232fn for_each_run<'a>(
234 src: &'a [u8],
235 mut emit: impl FnMut(&'a [u8], bool) -> Result<()>,
236) -> Result<()> {
237 if src.is_empty() {
238 return Err(Error::InvalidEncoding);
239 }
240 let mut read = 0;
241 while read < src.len() {
242 let code = usize::from(src[read]);
243 if code == 0 {
244 return Err(Error::InvalidEncoding);
245 }
246 let run = src
247 .get(read + 1..read + code)
248 .ok_or(Error::InvalidEncoding)?;
249 if run.contains(&0) {
250 return Err(Error::InvalidEncoding);
251 }
252 read += code;
253 emit(run, code != 0xFF && read < src.len())?;
254 }
255 Ok(())
256}
257
258#[cfg(test)]
259mod tests {
260 use super::*;
261
262 fn encode_vec(src: &[u8]) -> Vec<u8> {
263 let mut out = vec![0u8; max_encoded_len(src.len())];
264 let mut buf = WriteBuf::new(&mut out);
265 encode(src, &mut buf).unwrap();
266 let n = buf.position();
267 out.truncate(n);
268 out
269 }
270
271 fn decode_vec(src: &[u8]) -> Result<Vec<u8>> {
272 let mut out = vec![0u8; src.len()];
273 let mut buf = WriteBuf::new(&mut out);
274 decode(src, &mut buf)?;
275 let n = buf.position();
276 out.truncate(n);
277 Ok(out)
278 }
279
280 #[test]
281 fn wikipedia_vectors() {
282 let cases: [(&[u8], &[u8]); 6] = [
283 (&[], &[0x01]),
284 (&[0x00], &[0x01, 0x01]),
285 (&[0x00, 0x00], &[0x01, 0x01, 0x01]),
286 (&[0x00, 0x11, 0x00], &[0x01, 0x02, 0x11, 0x01]),
287 (&[0x11, 0x22, 0x00, 0x33], &[0x03, 0x11, 0x22, 0x02, 0x33]),
288 (&[0x11, 0x22, 0x33, 0x44], &[0x05, 0x11, 0x22, 0x33, 0x44]),
289 ];
290 for (raw, encoded) in cases {
291 assert_eq!(encode_vec(raw), encoded, "encode {raw:?}");
292 assert_eq!(decode_vec(encoded).unwrap(), raw, "decode {encoded:?}");
293 let mut block = encoded.to_vec();
294 let len = decode_in_place(&mut block).unwrap();
295 assert_eq!(&block[..len], raw);
296 }
297 }
298
299 #[test]
300 fn long_runs() {
301 let raw: Vec<u8> = (1..=254).map(|i| i as u8).collect();
303 let encoded = encode_vec(&raw);
304 assert_eq!(encoded.len(), 255);
305 assert_eq!(encoded[0], 0xFF);
306 assert_eq!(decode_vec(&encoded).unwrap(), raw);
307
308 let raw: Vec<u8> = (0..255).map(|i| (i % 255) as u8 + 1).collect();
310 let encoded = encode_vec(&raw);
311 assert_eq!(encoded.len(), max_encoded_len(255));
312 assert_eq!(&encoded[255..], &[0x02, raw[254]]);
313 assert_eq!(decode_vec(&encoded).unwrap(), raw);
314
315 let mut raw: Vec<u8> = vec![0x7F; 254];
317 raw.push(0);
318 let encoded = encode_vec(&raw);
319 assert_eq!(decode_vec(&encoded).unwrap(), raw);
320 }
321
322 #[test]
323 fn round_trip_mixed_lengths() {
324 for len in [0usize, 1, 253, 254, 255, 508, 509, 1000] {
325 let raw: Vec<u8> = (0..len).map(|i| (i * 7 % 5) as u8).collect();
326 let encoded = encode_vec(&raw);
327 assert!(encoded.len() <= max_encoded_len(len));
328 assert!(!encoded.contains(&0));
329 assert_eq!(decode_vec(&encoded).unwrap(), raw);
330 }
331 }
332
333 #[test]
334 fn malformed_blocks() {
335 let cases: [&[u8]; 5] = [
336 &[],
337 &[0x00],
338 &[0x03, 0x11],
339 &[0x02, 0x00],
340 &[0x02, 0x11, 0x00, 0x01],
341 ];
342 for bad in cases {
343 assert_eq!(decode_vec(bad), Err(Error::InvalidEncoding), "{bad:?}");
344 let mut block = bad.to_vec();
345 assert_eq!(decode_in_place(&mut block), Err(Error::InvalidEncoding));
346 }
347 }
348
349 #[test]
350 fn encode_is_atomic_on_buffer_full() {
351 for (src, room) in [
352 (&[0x11u8, 0x22][..], 2usize),
353 (&[0x00, 0x00], 2),
354 (&[0x11], 0),
355 ] {
356 let mut out = vec![0xEEu8; room];
357 let mut buf = WriteBuf::new(&mut out);
358 assert_eq!(encode(src, &mut buf), Err(Error::BufferFull), "{src:?}");
359 assert_eq!(buf.position(), 0);
360 assert!(
361 out.iter().all(|&b| b == 0xEE),
362 "nothing written for {src:?}"
363 );
364 }
365 let raw: Vec<u8> = vec![0x00; 300];
367 let mut out = vec![0u8; encoded_len(&raw)];
368 assert!(out.len() < max_encoded_len(raw.len()) || raw.is_empty());
369 encode(&raw, &mut WriteBuf::new(&mut out)).unwrap();
370 }
371
372 #[test]
373 fn encoded_len_matches_encode() {
374 for len in [0usize, 1, 253, 254, 255, 508, 600] {
375 for zero_every in [1usize, 2, 7, 1000] {
376 let raw: Vec<u8> = (0..len).map(|i| u8::from(i % zero_every != 0)).collect();
377 let written = encode_vec(&raw).len();
378 assert_eq!(encoded_len(&raw), written, "len={len} every={zero_every}");
379 }
380 }
381 }
382
383 #[test]
384 fn non_canonical_trailing_block_is_accepted() {
385 let mut long = vec![0xFFu8];
387 long.extend(core::iter::repeat_n(0x07u8, 254));
388 let mut with_empty = long.clone();
389 with_empty.push(0x01);
390 assert_eq!(decode_vec(&long).unwrap(), decode_vec(&with_empty).unwrap());
391 assert_eq!(encode_vec(&decode_vec(&with_empty).unwrap()), long);
392 }
393
394 #[test]
395 fn decode_is_atomic_on_error() {
396 let mut out = [0xEEu8; 2];
397 let mut buf = WriteBuf::new(&mut out);
398 assert_eq!(decode(&[0x04, 1, 2, 3], &mut buf), Err(Error::BufferFull));
399 assert_eq!(
400 decode(&[0x02, 1, 0x02, 2], &mut buf),
401 Err(Error::BufferFull)
402 );
403 assert_eq!(
405 decode(&[0x02, 1, 0x05], &mut buf),
406 Err(Error::InvalidEncoding)
407 );
408 assert_eq!(buf.position(), 0);
409 assert_eq!(out, [0xEE, 0xEE], "nothing is written on error");
410
411 let mut block = [0x02, 0x11, 0x03, 0x22];
412 assert_eq!(decode_in_place(&mut block), Err(Error::InvalidEncoding));
413 assert_eq!(
414 block,
415 [0x02, 0x11, 0x03, 0x22],
416 "in-place input unchanged on error"
417 );
418 }
419
420 #[test]
421 fn max_encoded_len_saturates() {
422 assert_eq!(max_encoded_len(usize::MAX), usize::MAX);
423 }
424}