Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,24 @@ Options:
-V, --version Print version
```

By default, all compression algorithms are enabled. To specify the specific
types of compression you want to enable, you can use the `-c` flag with the
values:
By default, the `brotli`, `gzip`, and `zstd` algorithms are enabled. To specify
the specific types of compression you want to enable, you can use the `-c` flag
with the values:

- `br` or `brotli`
- `de` or `deflate`
- `gz` or `gzip`
- `zst` or `zstd`

By default, the highest supported compression quality is used for each algorithm.
The default compression qualities used per algorithm are:

```
brotli: 10
deflate: 7
gzip: 7
zstd: 19
```

To specify a different quality, add the value after a colon like so:

```
Expand Down
65 changes: 53 additions & 12 deletions src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,62 @@ use flate2::{
};
use zstd::Encoder;

use crate::precompress::Algorithm;

#[derive(Debug, Clone, Copy)]
pub(crate) struct Quality {
pub(crate) brotli: u8,
pub(crate) deflate: u8,
pub(crate) gzip: u8,
pub(crate) zstd: u8,
pub(crate) brotli: i8,
pub(crate) deflate: i8,
pub(crate) gzip: i8,
pub(crate) zstd: i8,
}

impl Default for Quality {
fn default() -> Self {
Quality {
brotli: 11,
deflate: 9,
gzip: 9,
zstd: 21,
brotli: 10,
deflate: 7,
gzip: 7,
zstd: 19,
}
}
}

impl Quality {
pub(crate) fn set(&mut self, algorithm: Algorithm, quality: i8) -> bool {
match algorithm {
Algorithm::Brotli => {
if (0..=11).contains(&quality) {
self.brotli = quality;
true
} else {
false
}
}
Algorithm::Deflate => {
if (1..=9).contains(&quality) {
self.deflate = quality;
true
} else {
false
}
}
Algorithm::Gzip => {
if (1..=9).contains(&quality) {
self.gzip = quality;
true
} else {
false
}
}
Algorithm::Zstd => {
if (-7..=22).contains(&quality) {
self.zstd = quality;
true
} else {
false
}
}
}
}
}
Expand All @@ -45,10 +86,10 @@ impl Context {
Context {
read_buf: vec![0; buf_size],
write_buf: vec![0; buf_size],
brotli_quality: i32::from(quality.brotli),
deflate_quality: u32::from(quality.deflate),
gzip_quality: u32::from(quality.gzip),
zstd_quality: i32::from(quality.zstd),
brotli_quality: quality.brotli as i32,
deflate_quality: quality.deflate as u32,
gzip_quality: quality.gzip as u32,
zstd_quality: quality.zstd as i32,
}
}

Expand Down
34 changes: 23 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ fn parse_compression(compression: Option<Vec<String>>) -> (Algorithms, Quality)
let raw = v
.into_iter()
.flat_map(|s| s.split(',').map(|s| s.to_owned()).collect::<Vec<_>>());
let mut algs = Algorithms::default();
let mut algs = Algorithms::empty();
for s in raw {
let (c, q) = if let Some((c, q)) = s.split_once(':') {
let q: u8 = match q.parse() {
let q: i8 = match q.parse() {
Ok(q) => q,
Err(_) => {
eprintln!("Error: invalid compression quality: {q}");
Expand All @@ -104,26 +104,38 @@ fn parse_compression(compression: Option<Vec<String>>) -> (Algorithms, Quality)
match c {
"br" | "brotli" => {
algs.brotli = true;
if let Some(q) = q {
quality.brotli = q;
if let Some(q) = q
&& !quality.set(Algorithm::Brotli, q)
{
eprintln!("Error: invalid brotli compression quality: {q}");
exit(1);
}
}
"de" | "deflate" => {
algs.deflate = true;
if let Some(q) = q {
quality.deflate = q;
if let Some(q) = q
&& !quality.set(Algorithm::Deflate, q)
{
eprintln!("Error: invalid deflate compression quality: {q}");
exit(1);
}
}
"gz" | "gzip" => {
algs.gzip = true;
if let Some(q) = q {
quality.gzip = q;
if let Some(q) = q
&& !quality.set(Algorithm::Gzip, q)
{
eprintln!("Error: invalid gzip compression quality: {q}");
exit(1);
}
}
"zst" | "zstd" => {
algs.zstd = true;
if let Some(q) = q {
quality.zstd = q;
if let Some(q) = q
&& !quality.set(Algorithm::Zstd, q)
{
eprintln!("Error: invalid zstd compression quality: {q}");
exit(1);
}
}
_ => {
Expand All @@ -134,7 +146,7 @@ fn parse_compression(compression: Option<Vec<String>>) -> (Algorithms, Quality)
}
algs
})
.unwrap_or_else(Algorithms::all_enabled);
.unwrap_or_default();

(algs, quality)
}
Expand Down
19 changes: 15 additions & 4 deletions src/precompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,34 @@ impl Algorithm {
}
}

#[derive(Debug, Default, Clone, Copy)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Algorithms {
pub(crate) brotli: bool,
pub(crate) deflate: bool,
pub(crate) gzip: bool,
pub(crate) zstd: bool,
}

impl Algorithms {
pub(crate) fn all_enabled() -> Self {
impl Default for Algorithms {
fn default() -> Self {
Self {
brotli: true,
deflate: true,
deflate: false,
gzip: true,
zstd: true,
}
}
}

impl Algorithms {
pub(crate) fn empty() -> Self {
Self {
brotli: false,
deflate: false,
gzip: false,
zstd: false,
}
}

pub(crate) fn iter(self) -> impl Iterator<Item = Algorithm> {
Algorithm::iter().filter(move |algorithm| self.is_enabled(*algorithm))
Expand Down