1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::adler32::Adler32;
use crate::prelude::{deflate, inflate, inflate_to, BlockType, Cache};
use std::convert::TryInto;
const ERROR_ADLER32: &str = "Zlib checksum error";
const ERROR_DEFLATE: &str = "Zlib only supports deflate compression algorithm";
const ERROR_DICT: &str = "Zlib dictionaries is not implemented";
const ERROR_FCHECK: &str = "Fcheck must be multiple of 31";
const ERROR_LENGTH: &str = "Zlib's header is missing";
const HEADER_LEN: usize = 2;
const ADLER_LEN: usize = 4;
const METHOD_DEFLATE: u8 = 8;
pub fn zlib_encode(v_in: &[u8], btype: BlockType, cache: &mut Cache) -> Vec<u8> {
let cmf = 0x78;
let flevel = 2;
let fcheck = 28;
let flg = flevel << 6 | fcheck;
let mut adler32 = Adler32::new();
let mut data = deflate(v_in, btype, cache);
adler32.update(&v_in);
let mut v_out = Vec::with_capacity(data.len() + 2 + 4);
v_out.extend(&[cmf, flg]);
v_out.append(&mut data);
v_out.extend(&adler32.checksum());
v_out
}
pub fn zlib_decode(v_in: &[u8], cache: &mut Cache) -> Result<Vec<u8>, String> {
if v_in.len() < HEADER_LEN + ADLER_LEN {
return Err(ERROR_LENGTH.into());
}
let cmf = v_in[0];
let flg = v_in[1];
if (cmf & 0x0F) != METHOD_DEFLATE {
return Err(ERROR_DEFLATE.into());
}
if ((cmf as u16) << 8 | flg as u16) % 31 != 0 {
return Err(ERROR_FCHECK.into());
}
if (flg & 0b100_000) > 0 {
return Err(ERROR_DICT.into());
}
let mut adler32 = Adler32::new();
let v_out = inflate(&v_in[HEADER_LEN..v_in.len() - ADLER_LEN], cache)?;
adler32.update(&v_out);
let _adler32: [u8; 4] = v_in[v_in.len() - ADLER_LEN..].try_into().unwrap();
if adler32.checksum() != _adler32 {
return Err(ERROR_ADLER32.into());
}
Ok(v_out)
}
pub fn zlib_decode_to(v_in: &[u8], cache: &mut Cache, v_out: &mut [u8]) -> Result<(), String> {
if v_in.len() < HEADER_LEN + ADLER_LEN {
return Err(ERROR_LENGTH.into());
}
let cmf = v_in[0];
let flg = v_in[1];
if (cmf & 0x0F) != METHOD_DEFLATE {
return Err(ERROR_DEFLATE.into());
}
if ((cmf as u16) << 8 | flg as u16) % 31 != 0 {
return Err(ERROR_FCHECK.into());
}
if (flg & 0b100_000) > 0 {
return Err(ERROR_DICT.into());
}
let mut adler32 = Adler32::new();
inflate_to(&v_in[HEADER_LEN..v_in.len() - ADLER_LEN], cache, v_out)?;
adler32.update(v_out);
let _adler32: [u8; 4] = v_in[v_in.len() - ADLER_LEN..].try_into().unwrap();
if adler32.checksum() != _adler32 {
return Err(ERROR_ADLER32.into());
}
Ok(())
}