Skip to main content

photon_protocol/compressor/
brotli.rs

1use std::io::{Read, Write};
2
3use bytes::BytesMut;
4
5use crate::ports::compress::{CompressionError, Compressor};
6
7/// Excellent compression ratio, slower to compress but fast to decompress.
8#[derive(Clone, Debug)]
9pub struct BrotliCompressor {
10    quality: u32,
11}
12
13impl BrotliCompressor {
14    pub const NAME: &str = "brotli";
15
16    pub fn new(quality: u32) -> Self {
17        Self { quality }
18    }
19}
20
21impl Default for BrotliCompressor {
22    fn default() -> Self {
23        Self::new(4)
24    }
25}
26
27impl Compressor for BrotliCompressor {
28    fn compress(&self, input: &[u8], output: &mut BytesMut) -> Result<(), CompressionError> {
29        let mut compressed = Vec::new();
30        let mut encoder = brotli::CompressorWriter::new(
31            &mut compressed,
32            4096,
33            self.quality,
34            22, // lgwin
35        );
36
37        encoder
38            .write_all(input)
39            .map_err(|e| CompressionError::Internal(e.to_string()))?;
40        drop(encoder);
41
42        output.extend_from_slice(&compressed);
43        Ok(())
44    }
45
46    fn decompress(&self, input: &[u8], output: &mut BytesMut) -> Result<(), CompressionError> {
47        let mut decompressed = Vec::new();
48        let mut decoder = brotli::Decompressor::new(input, 4096);
49
50        decoder
51            .read_to_end(&mut decompressed)
52            .map_err(|_| CompressionError::CorruptPayload {
53                compressor_name: self.name().to_owned(),
54            })?;
55
56        output.extend_from_slice(&decompressed);
57        Ok(())
58    }
59
60    fn name(&self) -> &'static str {
61        Self::NAME
62    }
63}