1mod ffi;
6
7pub fn compress<T>(data: &[u8], metadata: T, quality: usize, transform: bool) -> Option<Vec<u8>>
9where
10 T: Into<Vec<u8>>,
11{
12 let metadata = match std::ffi::CString::new(metadata) {
13 Ok(metadata) => metadata,
14 _ => return None,
15 };
16 let metadata_size = metadata.count_bytes();
17 let size = unsafe {
18 ffi::ComputeTTFToWOFF2Size(
19 data.as_ptr() as *const _,
20 data.len(),
21 metadata.as_ptr() as *const _,
22 metadata_size,
23 )
24 };
25 let mut buffer = vec![0; size];
26 let mut size = buffer.len();
27 let status = unsafe {
28 ffi::ConvertTTFToWOFF2(
29 data.as_ptr() as *const _,
30 data.len(),
31 buffer.as_mut_ptr() as *mut _,
32 &mut size as *mut _,
33 metadata.as_ptr() as *const _,
34 metadata_size,
35 quality as core::ffi::c_int,
36 transform as core::ffi::c_int,
37 )
38 };
39 debug_assert_ne!(status, 0);
40 if status == 0 {
41 return None;
42 }
43 buffer.truncate(size);
44 buffer.into()
45}
46
47pub fn decompress(data: &[u8]) -> Option<Vec<u8>> {
49 let size = unsafe { ffi::ComputeWOFF2ToTTFSize(data.as_ptr() as *const _, data.len()) };
50 let mut buffer = vec![0; size];
51 let status = unsafe {
52 ffi::ConvertWOFF2ToTTF(
53 buffer.as_mut_ptr() as *mut _,
54 size,
55 data.as_ptr() as *const _,
56 data.len(),
57 )
58 };
59 debug_assert_ne!(status, 0);
60 if status == 0 {
61 return None;
62 }
63 buffer.into()
64}
65
66#[cfg(test)]
67mod tests {
68 use std::fs::{read, write};
69
70 const DEFAULT_METADATA: &str = "";
71 const DEFAULT_QUALITY: usize = 8;
72 const DEFAULT_TRANSFORM: bool = true;
73
74 macro_rules! ok(($result:expr) => ($result.unwrap()));
75
76 #[test]
77 fn otf() {
78 ok!(write(
79 "tests/fixtures/Roboto-Regular.otf.woff2",
80 ok!(super::compress(
81 &ok!(read("tests/fixtures/Roboto-Regular.otf")),
82 DEFAULT_METADATA,
83 DEFAULT_QUALITY,
84 DEFAULT_TRANSFORM,
85 )),
86 ));
87 ok!(write(
88 "tests/fixtures/Roboto-Regular.otf",
89 ok!(super::decompress(&ok!(read(
90 "tests/fixtures/Roboto-Regular.otf.woff2"
91 )))),
92 ));
93 }
94
95 #[test]
96 fn ttf() {
97 ok!(write(
98 "tests/fixtures/Roboto-Regular.ttf.woff2",
99 ok!(super::compress(
100 &ok!(read("tests/fixtures/Roboto-Regular.ttf")),
101 DEFAULT_METADATA,
102 DEFAULT_QUALITY,
103 DEFAULT_TRANSFORM,
104 )),
105 ));
106 ok!(write(
107 "tests/fixtures/Roboto-Regular.ttf",
108 ok!(super::decompress(&ok!(read(
109 "tests/fixtures/Roboto-Regular.ttf.woff2"
110 )))),
111 ));
112 }
113}