Skip to content

Commit

Permalink
clip Compression levels for each algorithm
Browse files Browse the repository at this point in the history
to open zstd level 22 without being a breaking change or allowing to pass incorrect values to other algorithms
  • Loading branch information
Ten0 committed Apr 7, 2024
1 parent 554c795 commit 6b8907d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 14 deletions.
57 changes: 47 additions & 10 deletions serde_avro_fast/src/object_container_file_encoding/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ pub enum Compression {
/// as specified in RFC 1951. Note that this format (unlike the "zlib
/// format" in RFC 1950) does not have a checksum.
Deflate {
/// Deflate compression level to use
/// Deflate compression level to use (1-9 or
/// [`CompressionLevel::default()`])
level: CompressionLevel,
},
#[cfg(feature = "bzip2")]
/// The `BZip2` codec uses [BZip2](https://sourceware.org/bzip2/)
/// compression library.
Bzip2 {
/// BZip2 compression level to use
/// BZip2 compression level to use (1-9 or
/// [`CompressionLevel::default()`])
level: CompressionLevel,
},
#[cfg(feature = "snappy")]
Expand All @@ -44,14 +46,16 @@ pub enum Compression {
/// The `Xz` codec uses [Xz utils](https://tukaani.org/xz/)
/// compression library.
Xz {
/// Xz compression level to use
/// Xz compression level to use (1-9 or
/// [`CompressionLevel::default()`])
level: CompressionLevel,
},
#[cfg(feature = "zstandard")]
/// The `zstandard` codec uses Facebook’s [Zstandard](https://facebook.github.io/zstd/)
/// compression library
Zstandard {
/// Zstandard compression level to use
/// Zstandard compression level to use (1-22 or
/// [`CompressionLevel::default()`])
level: CompressionLevel,
},
}
Expand All @@ -68,15 +72,36 @@ impl CompressionLevel {
/// Specifies the compression level that will be used for the compression
/// algorithms
///
/// # Default value
/// All algorithms have a default compression level configured
/// that may be used by instantiating [`CompressionLevel::default()`].
///
/// Use [`CompressionLevel::new`] if you want to specify a specific
/// compression level.
///
/// # Clipping
/// Depending on the algorithm that will be used, `level` may get clipped
/// into the appropriate range (e.g. set to `9` if higher than `9`).
///
/// This is done to ensure that the compression level is always within the
/// valid range for the algorithm.
///
/// See the [`Compression`] enum for the effective ranges for each
/// algorithm.
///
/// # Panics
/// If `level` is lower than `1` or greater than `9`
/// If `level` is lower than `1`
///
/// This is because all algorithms expect compression levels between `1`
/// ("fast compression") and `9` ("take as long as you'd like").
pub const fn new(level: u8) -> Self {
/// This is because compression level 0 means "actually don't compress" for
/// most algorithms, and in that case one should just use
/// [`Compression::Null`] instead.
pub const fn new(mut level: u8) -> Self {
if level == u8::MAX {
level -= 1;
}
match NonZeroU8::new(level) {
Some(n) if n.get() < 10 => Self { repr: n },
_ => panic!("Compression level must be between 1 and 9"),
Some(n) => Self { repr: n },
None => panic!("Compression level must be greater than 0"),
}
}

Expand All @@ -90,6 +115,18 @@ impl CompressionLevel {
}
}

#[allow(unused)]
/// may be unused depending on which compression codecs features are enabled
fn clip(mut self, high: u8) -> Self {
if self.repr.get() != u8::MAX {
self.repr = self.repr.min(NonZeroU8::new(high).expect(
"Highest compression level for \
algorithm should be greater than zero",
))
}
self
}

#[allow(unused)]
/// may be unused depending on which compression codecs features are enabled
fn instantiate<T: Default, C: From<u8>, F: FnOnce(C) -> T>(self, f: F) -> T {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,33 @@ impl CompressionCodecState {
#[cfg(feature = "deflate")]
Compression::Deflate { level } => Kind::Deflate {
compress: flate2::Compress::new(
level.instantiate(flate2::Compression::new),
level.clip(9).instantiate(flate2::Compression::new),
false,
),
},
#[cfg(feature = "bzip2")]
Compression::Bzip2 { level } => Kind::Bzip2 { len: 0, level },
Compression::Bzip2 { level } => Kind::Bzip2 {
len: 0,
level: level.clip(9),
},
#[cfg(feature = "snappy")]
Compression::Snappy => Kind::Snappy {
encoder: snap::raw::Encoder::new(),
},
#[cfg(feature = "xz")]
Compression::Xz { level } => Kind::Xz { len: 0, level },
Compression::Xz { level } => Kind::Xz {
len: 0,
level: level.clip(9),
},
#[cfg(feature = "zstandard")]
Compression::Zstandard { level } => Kind::Zstandard {
compressor: None,
level,
level: level.clip(
(*zstd::compression_level_range().end())
.max(0)
.try_into()
.unwrap_or(u8::MAX - 1),
),
},
},
}
Expand Down

0 comments on commit 6b8907d

Please sign in to comment.