rscompress_transformation/
runlength.rs1use crate::{Transform, TransformError};
6use log::info;
7
8const RUN_BYTE_CODE: u8 = 0;
9
10#[derive(Debug)]
12pub struct RunLength {
13 current: Option<u8>,
14 reverse_started: bool,
15}
16
17impl RunLength {
18 pub fn new() -> Self {
19 RunLength {
20 current: None,
21 reverse_started: false,
22 }
23 }
24}
25
26impl Default for RunLength {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl Transform for RunLength {
34 fn transform(&mut self, source: &[u8]) -> Result<Vec<u8>, TransformError> {
35 if source.is_empty() {
36 return Err(TransformError::EmptyBufferError);
37 }
38 let mut result: Vec<u8> = Vec::with_capacity(source.len());
39 for byte in source.iter() {
40 info!("Transform: {} | {:?}", byte, self);
41 if self.current.is_some() && self.current.unwrap() == *byte {
42 result.push(RUN_BYTE_CODE);
43 } else if self.current.is_some() && RUN_BYTE_CODE == *byte {
44 result.push(self.current.unwrap());
45 self.current = Some(*byte);
46 } else {
47 result.push(*byte);
48 self.current = Some(*byte);
49 }
50 }
51 self.reverse_started = false;
52 Ok(result)
53 }
54
55 fn reverse(&mut self, source: &[u8]) -> Result<Vec<u8>, TransformError> {
56 if source.is_empty() {
57 return Err(TransformError::EmptyBufferError);
58 }
59 let mut result: Vec<u8> = Vec::with_capacity(source.len());
60 for byte in source.iter() {
61 info!("Reverse: {} | {:?}", byte, self);
62 if self.current.is_some() && *byte == RUN_BYTE_CODE && self.reverse_started {
63 result.push(self.current.unwrap());
64 self.reverse_started = true;
65 } else if self.current.is_some()
66 && *byte == self.current.unwrap()
67 && self.reverse_started
68 {
69 result.push(RUN_BYTE_CODE);
70 self.current = Some(RUN_BYTE_CODE);
71 self.reverse_started = true;
72 } else {
73 result.push(*byte);
74 self.current = Some(*byte);
75 self.reverse_started = true;
76 }
77 }
78 Ok(result)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use crate::tests::{random_roundtrip, reverse, roundtrip, transform};
86
87 #[test]
88 fn test_easy_transforms() {
89 transform::<RunLength>(
90 &[8, 2, 2, 2, 24, 32, 32, 1, 24],
91 &[
92 8,
93 2,
94 RUN_BYTE_CODE,
95 RUN_BYTE_CODE,
96 24,
97 32,
98 RUN_BYTE_CODE,
99 1,
100 24,
101 ],
102 );
103 }
104 #[test]
105 fn test_easy_reverses() {
106 reverse::<RunLength>(
107 &[
108 8,
109 2,
110 RUN_BYTE_CODE,
111 RUN_BYTE_CODE,
112 24,
113 32,
114 RUN_BYTE_CODE,
115 1,
116 24,
117 ],
118 &[8, 2, 2, 2, 24, 32, 32, 1, 24],
119 );
120 reverse::<RunLength>(
121 &[8, RUN_BYTE_CODE, RUN_BYTE_CODE, 8],
122 &[8, 8, 8, RUN_BYTE_CODE],
123 );
124 }
125
126 #[test]
127 fn test_roundtrip() {
128 roundtrip::<RunLength>(&[8, 2, 2, 2, 24, 32, 32, 1, 24]);
129 roundtrip::<RunLength>(&[8, 8, 8, 8, 2]);
130 roundtrip::<RunLength>(&[8, 8, 1, 2, 2]);
131 roundtrip::<RunLength>(&[8, 8, 8, 8]);
132 roundtrip::<RunLength>(&[RUN_BYTE_CODE, 8, 8, 8]);
133 roundtrip::<RunLength>(&[8, 1, 5, 8]);
134 }
135
136 #[test]
137 fn test_random_roundtrip() {
138 random_roundtrip::<RunLength>(100, 10_000);
139 random_roundtrip::<RunLength>(100, 10_000);
140 random_roundtrip::<RunLength>(100, 10_000);
141 random_roundtrip::<RunLength>(100, 10_000);
142 random_roundtrip::<RunLength>(100, 10_000);
143 }
144}