Skip to main content

sark_core/http/
compress.rs

1//! ```no_run
2//! use sark_core::http::compress::Gzip;
3//! let body: &[u8] = b"hello";
4//! let zipped = Gzip::new().encode(body).unwrap();
5//! ```
6
7use libdeflater::{CompressionLvl, Compressor};
8use o3::buffer::{InitializedSharedPool, Pooled};
9
10const GZIP_SLOTS: usize = 32;
11const GZIP_CAPACITY: usize = 256 * 1024;
12
13pub struct Gzip {
14    encoder: Compressor,
15    pool: InitializedSharedPool,
16}
17
18impl Gzip {
19    const LEVEL: i32 = 3;
20
21    pub fn new() -> Self {
22        Self::with_pool(GZIP_SLOTS, GZIP_CAPACITY)
23    }
24
25    pub fn with_pool(slots: usize, capacity: usize) -> Self {
26        let level = CompressionLvl::new(Self::LEVEL).expect("valid libdeflate compression level");
27        Self {
28            encoder: Compressor::new(level),
29            pool: InitializedSharedPool::new(slots, capacity),
30        }
31    }
32
33    pub fn encode(&mut self, src: &[u8]) -> Option<Pooled> {
34        let cap = self.encoder.gzip_compress_bound(src.len());
35        if cap > self.pool.capacity() {
36            return None;
37        }
38        let mut lease = self.pool.try_acquire()?;
39        let n = self
40            .encoder
41            .gzip_compress(src, lease.spare_mut())
42            .expect("gzip_compress_bound undersized");
43        lease
44            .try_advance(n)
45            .expect("gzip_compress_bound undersized");
46        Some(lease.freeze())
47    }
48}
49
50impl Default for Gzip {
51    fn default() -> Self {
52        Self::new()
53    }
54}