polars_utils/
compression.rs

1use polars_error::{PolarsResult, polars_bail};
2
3/// Defines valid compression levels.
4pub trait CompressionLevel<T: std::fmt::Display + std::cmp::PartialOrd> {
5    const MINIMUM_LEVEL: T;
6    const MAXIMUM_LEVEL: T;
7
8    /// Tests if the provided compression level is valid.
9    fn is_valid_level(level: T) -> PolarsResult<()> {
10        let compression_range = Self::MINIMUM_LEVEL..=Self::MAXIMUM_LEVEL;
11        if compression_range.contains(&level) {
12            Ok(())
13        } else {
14            polars_bail!(InvalidOperation: "valid compression range {}..={} exceeded.",
15                compression_range.start(),
16                compression_range.end()
17            )
18        }
19    }
20}
21
22/// Represents a valid brotli compression level.
23#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
24pub struct BrotliLevel(u32);
25
26impl Default for BrotliLevel {
27    fn default() -> Self {
28        Self(1)
29    }
30}
31
32impl CompressionLevel<u32> for BrotliLevel {
33    const MINIMUM_LEVEL: u32 = 0;
34    const MAXIMUM_LEVEL: u32 = 11;
35}
36
37impl BrotliLevel {
38    /// Attempts to create a brotli compression level.
39    ///
40    /// Compression levels must be valid.
41    pub fn try_new(level: u32) -> PolarsResult<Self> {
42        Self::is_valid_level(level).map(|_| Self(level))
43    }
44
45    /// Returns the compression level.
46    pub fn compression_level(&self) -> u32 {
47        self.0
48    }
49}
50
51/// Represents a valid gzip compression level.
52#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
53pub struct GzipLevel(u8);
54
55impl Default for GzipLevel {
56    fn default() -> Self {
57        // The default as of miniz_oxide 0.5.1 is 6 for compression level
58        // (miniz_oxide::deflate::CompressionLevel::DefaultLevel)
59        Self(6)
60    }
61}
62
63impl CompressionLevel<u8> for GzipLevel {
64    const MINIMUM_LEVEL: u8 = 0;
65    const MAXIMUM_LEVEL: u8 = 9;
66}
67
68impl GzipLevel {
69    /// Attempts to create a gzip compression level.
70    ///
71    /// Compression levels must be valid (i.e. be acceptable for `flate2::Compression`).
72    pub fn try_new(level: u8) -> PolarsResult<Self> {
73        Self::is_valid_level(level).map(|_| Self(level))
74    }
75
76    /// Returns the compression level.
77    pub fn compression_level(&self) -> u8 {
78        self.0
79    }
80}
81
82/// Represents a valid zstd compression level.
83#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
84pub struct ZstdLevel(i32);
85
86impl CompressionLevel<i32> for ZstdLevel {
87    // zstd binds to C, and hence zstd::compression_level_range() is not const as this calls the
88    // underlying C library.
89    const MINIMUM_LEVEL: i32 = 1;
90    const MAXIMUM_LEVEL: i32 = 22;
91}
92
93impl ZstdLevel {
94    /// Attempts to create a zstd compression level from a given compression level.
95    ///
96    /// Compression levels must be valid (i.e. be acceptable for `zstd::compression_level_range`).
97    pub fn try_new(level: i32) -> PolarsResult<Self> {
98        Self::is_valid_level(level).map(|_| Self(level))
99    }
100
101    /// Returns the compression level.
102    pub fn compression_level(&self) -> i32 {
103        self.0
104    }
105}
106
107impl Default for ZstdLevel {
108    fn default() -> Self {
109        Self(3)
110    }
111}