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}