1use crate::lz77::{buffer_full, ProcessStatus};
2use crate::output_writer::{BufferStatus, DynamicWriter};
3
4use std::cmp;
5use std::ops::Range;
6
7const MIN_MATCH: usize = crate::huffman_table::MIN_MATCH as usize;
8const MAX_MATCH: usize = crate::huffman_table::MAX_MATCH as usize;
9
10fn get_match_length_rle(data: &[u8], prev: u8) -> usize {
14 data.iter()
15 .take(MAX_MATCH)
16 .take_while(|&&b| b == prev)
17 .count()
18}
19
20pub fn process_chunk_greedy_rle(
24 data: &[u8],
25 iterated_data: &Range<usize>,
26 writer: &mut DynamicWriter,
27) -> (usize, ProcessStatus) {
28 if data.is_empty() {
29 return (0, ProcessStatus::Ok);
30 };
31
32 let end = cmp::min(data.len(), iterated_data.end);
33 let start = cmp::max(iterated_data.start, 1);
35 let mut prev = data[start - 1];
37 let current_chunk = &data[cmp::min(start, end)..end];
39 let mut insert_it = current_chunk.iter().enumerate();
40 let mut overlap = 0;
41 if iterated_data.start == 0 && !data.is_empty() {
43 write_literal!(writer, data[0], 1);
44 }
45
46 while let Some((n, &b)) = insert_it.next() {
47 let position = n + start;
48 let match_len = if prev == b {
49 get_match_length_rle(&data[position..], prev)
52 } else {
53 0
54 };
55 if match_len >= MIN_MATCH {
56 if position + match_len > end {
57 overlap = position + match_len - end;
58 };
59 let b_status = writer.write_length_rle(match_len as u16);
60 if b_status == BufferStatus::Full {
61 return (overlap, buffer_full(position + match_len));
62 }
63 insert_it.nth(match_len - 2);
64 } else {
65 write_literal!(writer, b, position + 1);
66 }
67 prev = b;
68 }
69
70 (overlap, ProcessStatus::Ok)
71}
72
73#[cfg(test)]
74mod test {
75 use super::*;
76 use crate::lzvalue::{ld, lit, LZValue};
77
78 fn l(c: char) -> LZValue {
79 lit(c as u8)
80 }
81
82 #[test]
83 fn rle_compress() {
84 let input = b"textaaaaaaaaatext";
85 let mut w = DynamicWriter::new();
86 let r = 0..input.len();
87 let (overlap, _) = process_chunk_greedy_rle(input, &r, &mut w);
88 let expected = [
89 l('t'),
90 l('e'),
91 l('x'),
92 l('t'),
93 l('a'),
94 ld(8, 1),
95 l('t'),
96 l('e'),
97 l('x'),
98 l('t'),
99 ];
100 assert!(w.get_buffer() == expected);
103 assert_eq!(overlap, 0);
104 }
105}