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
mod bindings;
use std::io::{self, Write};
use std::slice;
use bindings::{
ZopfliOptions,
ZopfliCompress,
ZopfliFormat_ZOPFLI_FORMAT_DEFLATE,
ZopfliFormat_ZOPFLI_FORMAT_GZIP,
ZopfliFormat_ZOPFLI_FORMAT_ZLIB,
};
#[derive(Copy, Clone, Debug)]
pub struct Options {
pub verbose: bool,
pub verbose_more: bool,
pub iterations: i32,
pub block_splitting: bool,
pub block_splitting_max: i32,
}
impl Default for Options {
fn default() -> Self {
Self {
verbose: false,
verbose_more: false,
iterations: 15,
block_splitting: true,
block_splitting_max: 15,
}
}
}
trait ToZopfliOptions {
fn to_zopfli_options(self: &Self) -> ZopfliOptions;
}
impl ToZopfliOptions for Options {
fn to_zopfli_options(self: &Self) -> ZopfliOptions {
ZopfliOptions {
verbose: self.verbose as i32,
verbose_more: self.verbose_more as i32,
numiterations: self.iterations,
blocksplitting: self.block_splitting as i32,
blocksplittinglast: 0,
blocksplittingmax: self.block_splitting_max,
}
}
}
#[derive(Clone, Debug)]
pub enum Format {
Deflate,
Gzip,
Zlib,
}
pub fn compress<W: Write>(options: &Options, format: &Format, input: &[u8], mut output: W) -> io::Result<()> {
let input_ptr = input.as_ptr();
let input_size = input.len();
let mut out: Vec<u8> = Vec::with_capacity(input_size);
let mut out_ptr = out.as_mut_ptr();
let mut out_size: usize = 0;
unsafe {
ZopfliCompress(
&options.to_zopfli_options(),
match *format {
Format::Deflate => ZopfliFormat_ZOPFLI_FORMAT_DEFLATE,
Format::Gzip => ZopfliFormat_ZOPFLI_FORMAT_GZIP,
Format::Zlib => ZopfliFormat_ZOPFLI_FORMAT_ZLIB,
},
input_ptr,
input_size,
&mut out_ptr,
&mut out_size,
);
output.by_ref().write_all(slice::from_raw_parts(out_ptr, out_size))
}
}