Skip to main content

compression_codecs/mbrotli/
params.rs

1//! This module contains mbrotli-specific types for async-compression.
2
3use compression_core::Level;
4use mbrotli::{
5    BlockBits, BlockSize, CompressionMode, EncoderConfig, InputSize, Quality, StreamConfig, Window,
6};
7use std::convert::TryFrom;
8
9/// Brotli compression parameters builder for the `mbrotli` backend. This is a stable wrapper
10/// around mbrotli's own encoder configuration, to abstract over different versions of the mbrotli
11/// library.
12///
13/// The builder methods mirror `brotli::params::EncoderParams` where the two backends overlap, so
14/// switching between them only needs a type change.
15///
16/// See the [Brotli documentation](https://www.brotli.org/encode.html#a9a8) for more information on
17/// these parameters.
18///
19/// # Examples
20///
21/// ```
22/// use compression_codecs::mbrotli;
23///
24/// let params = mbrotli::params::EncoderParams::default()
25///     .window_size(12)
26///     .text_mode();
27/// ```
28#[derive(Debug, Clone, Copy, Default)]
29pub struct EncoderParams {
30    config: EncoderConfig,
31    input_size: InputSize,
32}
33
34impl EncoderParams {
35    pub(crate) fn config(&self) -> EncoderConfig {
36        self.config
37    }
38
39    pub(crate) fn stream(&self) -> StreamConfig {
40        StreamConfig::from(self.input_size)
41    }
42
43    pub fn quality(mut self, level: Level) -> Self {
44        let quality = match level {
45            Level::Fastest => Quality::MIN,
46            Level::Best => Quality::MAX,
47            Level::Precise(quality) => {
48                let quality = quality.clamp(Quality::MIN.get().into(), Quality::MAX.get().into());
49                // The clamp above keeps `quality` inside `0..=11`, which both conversions accept.
50                Quality::try_from(quality as u8).unwrap()
51            }
52            _ => Quality::default(),
53        };
54        self.config = self.config.with_quality(quality);
55        self
56    }
57
58    /// Sets window size in bytes (as a power of two).
59    ///
60    /// Used as Brotli's `lgwin` parameter.
61    ///
62    /// `window_size` is clamped to `10 <= window_size <= 24`, except `0` which selects the default
63    /// window, as the `brotli` backend does.
64    pub fn window_size(mut self, window_size: i32) -> Self {
65        let window = if window_size == 0 {
66            Window::DEFAULT
67        } else {
68            let bits = window_size.clamp(Window::MIN_BITS.into(), Window::MAX_STANDARD_BITS.into());
69            // The clamp above keeps `bits` inside the standard window range.
70            Window::standard(bits as u8).unwrap()
71        };
72        self.config = self.config.with_window(window);
73        self
74    }
75
76    /// Sets input block size in bytes (as a power of two).
77    ///
78    /// Used as Brotli's `lgblock` parameter.
79    ///
80    /// `block_size` is clamped to `16 <= block_size <= 24`.
81    pub fn block_size(mut self, block_size: i32) -> Self {
82        let bits = block_size.clamp(BlockBits::MIN.get().into(), BlockBits::MAX.get().into());
83        // The clamp above keeps `bits` inside the range `BlockBits` accepts.
84        let bits = BlockBits::try_from(bits as u8).unwrap();
85        self.config = self.config.with_block_size(BlockSize::Bits(bits));
86        self
87    }
88
89    /// Sets hint for size of data to be compressed.
90    pub fn size_hint(mut self, size_hint: usize) -> Self {
91        self.input_size = InputSize::Exact(size_hint as u64);
92        self
93    }
94
95    /// Sets encoder to text mode.
96    ///
97    /// If input data is known to be UTF-8 text, this allows the compressor to make assumptions and
98    /// optimizations.
99    ///
100    /// Used as Brotli's `mode` parameter.
101    pub fn text_mode(mut self) -> Self {
102        self.config = self.config.with_mode(CompressionMode::Text);
103        self
104    }
105
106    /// Sets encoder to font mode.
107    ///
108    /// Tunes the compressor for WOFF 2.0 font data.
109    ///
110    /// Used as Brotli's `mode` parameter.
111    pub fn font_mode(mut self) -> Self {
112        self.config = self.config.with_mode(CompressionMode::Font);
113        self
114    }
115}