1#[derive(Clone, Debug, PartialEq)]
8enum CompressMode {
9 None(u8),
10 Repeated(u8, usize),
11 Unique(Vec<u8>),
12}
13
14pub fn compress(data: &[u8]) -> Vec<u8> {
16 let mut c = Vec::<u8>::new();
17
18 let mut state = CompressMode::None(data[0]);
19
20 for i in 1..data.len() {
22 state = match state {
23 CompressMode::None(v) if data[i] == v => CompressMode::Repeated(v, 1),
24 CompressMode::None(v) => CompressMode::Unique(vec![v, data[i]]),
25 CompressMode::Repeated(v, n) if data[i] == v => CompressMode::Repeated(v, n + 1),
26 CompressMode::Repeated(v, n) => {
27 let count = 0xFF - (n as u8 - 1);
28
29 c.push(count as u8);
30 c.push(v);
31
32 CompressMode::None(data[i])
33 }
34 CompressMode::Unique(mut v) if data[i] != v[v.len() - 1] => {
35 v.push(data[i]);
36
37 CompressMode::Unique(v)
38 }
39 CompressMode::Unique(v) => {
40 let count = v.len() - 1;
41
42 c.push(count as u8);
43 c.extend_from_slice(&v[..count]);
44
45 CompressMode::Repeated(data[i], 2)
46 }
47 };
48 }
49
50 match state {
52 CompressMode::None(v) => {
53 c.push(0x00);
54 c.push(v);
55 }
56 CompressMode::Repeated(v, n) => {
57 let count = 0xFF - (n as u8 - 1);
58
59 c.push(count as u8);
60 c.push(v);
61 }
62 CompressMode::Unique(v) => {
63 let count = v.len() - 1;
64
65 c.push(count as u8);
66 c.extend_from_slice(&v);
67 }
68 }
69
70 if c.len() > 16 {
72 c = vec![];
73 c.push(data.len() as u8);
74 c.extend_from_slice(data);
75 }
76
77 c
78}
79
80pub fn uncompress(data: &[u8]) -> Vec<u8> {
81 let mut u = vec![];
82 let mut i: usize = 0;
83
84 loop {
85 let d = data[i] as i8;
86
87 if d < 0 {
88 let mut r = vec![data[i+1]; (-d+1) as usize];
90 u.append(&mut r);
91 i += 2;
92 } else {
93 let c = d as usize;
95 u.extend_from_slice(&data[i+1..i+c+2]);
96 i += c + 2;
97 }
98
99 if i >= data.len() {
100 break;
101 }
102 }
103
104 return u
105}
106
107#[cfg(test)]
108mod test {
109 #[test]
110 fn test_raster_compression() {
111 let uncompressed = [
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x23, 0xBA, 0xBF, 0xA2, 0x22, 0x2B,
114 ];
115 let compressed = [
116 0xED, 0x00, 0xFF, 0x22, 0x05, 0x23, 0xBA, 0xBF, 0xA2, 0x22, 0x2B,
117 ];
118
119 let c = super::compress(&uncompressed);
120
121 assert_eq!(
122 c, compressed,
123 "Compressed: {:02x?} Expected: {:02x?}",
124 &c, &compressed
125 );
126
127 let d = super::uncompress(&compressed);
128
129 assert_eq!(
130 d, uncompressed,
131 "Uncompressed: {:02x?} Expected: {:02x?}",
132 &d, &uncompressed
133 );
134 }
135
136 }