Skip to content

Commit

Permalink
use macro_rules to implement formats
Browse files Browse the repository at this point in the history
  • Loading branch information
luizirber committed Jan 25, 2025
1 parent 8be7824 commit 9df5d8f
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 252 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ xz_tokio = ["liblzma/tokio"]


[dependencies]
cfg-if = "1.0"
thiserror = "2.0"
bzip2 = { version = "0.4.4", optional = true }
flate2 = { version = "1.0", optional = true }
Expand Down
179 changes: 70 additions & 109 deletions src/basic/compression.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
#![allow(clippy::unnecessary_wraps)]

/* standard use */
use std::io;

/* crates use */
use cfg_if::cfg_if;

/* project use */
use crate::error::Error;

/* backward compatibility, can remove on 3.x */
pub use crate::level::Level;

/* Format detection enum */
/// `Format` represent a compression format of a file. Currently Gzip, Bzip, Lzma or No are supported.
/// `Format` represent a compression format of a file. Currently Gzip, Bzip, Lzma, Zstd or No are supported.
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Format {
Gzip,
Expand All @@ -38,110 +29,80 @@ pub(crate) fn bytes2type(bytes: [u8; 5]) -> Format {
}
}

cfg_if! {
if #[cfg(feature = "gz")] {
pub(crate) fn new_gz_encoder<'a>(out: Box<dyn io::Write + 'a>, level: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Ok(Box::new(flate2::write::GzEncoder::new(
out,
level.into(),
)))
}

pub(crate) fn new_gz_decoder<'a>(
inp: Box<dyn io::Read + 'a>,
) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Ok((
Box::new(flate2::read::MultiGzDecoder::new(inp)),
Format::Gzip,
))
}
} else {
pub(crate) fn new_gz_encoder<'a>(_: Box<dyn io::Write + 'a>, _: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Err(Error::FeatureDisabled)
}

pub(crate) fn new_gz_decoder<'a>(_: Box<dyn io::Read + 'a>) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Err(Error::FeatureDisabled)
}
}
}

cfg_if! {
if #[cfg(feature = "bz2")] {
pub(crate) fn new_bz2_encoder<'a>(out: Box<dyn io::Write + 'a>, level: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Ok(Box::new(bzip2::write::BzEncoder::new(
out,
level.into(),
)))
}

pub(crate) fn new_bz2_decoder<'a>(
inp: Box<dyn io::Read + 'a>,
) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Ok((
Box::new(bzip2::read::MultiBzDecoder::new(inp)),
Format::Bzip,
))
}
} else {
pub(crate) fn new_bz2_encoder<'a>(_: Box<dyn io::Write + 'a>, _: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Err(Error::FeatureDisabled)
}

pub(crate) fn new_bz2_decoder<'a>(_: Box<dyn io::Read + 'a>) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Err(Error::FeatureDisabled)
}
}
}

cfg_if! {
if #[cfg(feature = "lzma")] {
pub(crate) fn new_lzma_encoder<'a>(out: Box<dyn io::Write + 'a>, level: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Ok(Box::new(liblzma::write::XzEncoder::new(out, level.into())))
impl_format!(
gz,
"gz",
crate::basic::compression::Format::Gzip,
flate2::write::GzEncoder::new,
flate2::read::MultiGzDecoder::new,
std::io::Read,
std::io::Write,
crate::basic::compression::Format
);

impl_format!(
bz2,
"bz2",
crate::basic::compression::Format::Bzip,
bzip2::write::BzEncoder::new,
bzip2::read::MultiBzDecoder::new,
std::io::Read,
std::io::Write,
crate::basic::compression::Format
);

impl_format!(
lzma,
"lzma",
crate::basic::compression::Format::Lzma,
liblzma::write::XzEncoder::new,
liblzma::read::XzDecoder::new,
std::io::Read,
std::io::Write,
crate::basic::compression::Format
);

pub mod zstd {
/* standard use */
use std::io;

/* project use */
use crate::error::Error;

use super::{Format, Level};

#[cfg(feature = "zstd")]
pub(crate) fn encoder<'a>(
out: Box<dyn io::Write + 'a>,
level: Level,
) -> Result<Box<dyn io::Write + 'a>, Error> {
Ok(Box::new(
zstd::stream::write::Encoder::new(out, level.into())?.auto_finish(),
))
}

pub(crate) fn new_lzma_decoder<'a>(
inp: Box<dyn io::Read + 'a>,
) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Ok((
Box::new(liblzma::read::XzDecoder::new(inp)),
Format::Lzma,
))
}
} else {
pub(crate) fn new_lzma_encoder<'a>(_: Box<dyn io::Write + 'a>, _: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Err(Error::FeatureDisabled)
#[cfg(feature = "zstd")]
pub(crate) fn decoder<'a>(
inp: Box<dyn io::Read + 'a>,
) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Ok((
Box::new(zstd::stream::read::Decoder::new(inp)?),
Format::Zstd,
))
}

pub(crate) fn new_lzma_decoder<'a>(_: Box<dyn io::Read + 'a>) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Err(Error::FeatureDisabled)
#[cfg(not(feature = "zstd"))]
pub(crate) fn encoder<'a>(
_: Box<dyn io::Write + 'a>,
_: Level,
) -> Result<Box<dyn io::Write + 'a>, Error> {
Err(Error::FeatureDisabled)
}
}
}

cfg_if! {
if #[cfg(feature = "zstd")] {
pub(crate) fn new_zstd_encoder<'a>(out: Box<dyn io::Write + 'a>, level: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Ok(Box::new(zstd::stream::write::Encoder::new(
out,
level.into(),
)?.auto_finish()))
}

pub(crate) fn new_zstd_decoder<'a>(
inp: Box<dyn io::Read + 'a>,
) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Ok((Box::new(zstd::stream::read::Decoder::new(inp)?),
Format::Zstd,
))
}
} else {
pub(crate) fn new_zstd_encoder<'a>(_: Box<dyn io::Write + 'a>, _: Level) -> Result<Box<dyn io::Write + 'a>, Error> {
Err(Error::FeatureDisabled)
}

pub(crate) fn new_zstd_decoder<'a>(_: Box<dyn io::Read + 'a>) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Err(Error::FeatureDisabled)
}
#[cfg(not(feature = "zstd"))]
pub(crate) fn decoder<'a>(
_: Box<dyn io::Read + 'a>,
) -> Result<(Box<dyn io::Read + 'a>, Format), Error> {
Err(Error::FeatureDisabled)
}
}
16 changes: 8 additions & 8 deletions src/basic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ pub fn get_reader<'a>(

// return readable and compression status
match compression {
compression::Format::Gzip => compression::new_gz_decoder(in_stream),
compression::Format::Bzip => compression::new_bz2_decoder(in_stream),
compression::Format::Lzma => compression::new_lzma_decoder(in_stream),
compression::Format::Zstd => compression::new_zstd_decoder(in_stream),
compression::Format::Gzip => compression::gz::decoder(in_stream),
compression::Format::Bzip => compression::bz2::decoder(in_stream),
compression::Format::Lzma => compression::lzma::decoder(in_stream),
compression::Format::Zstd => compression::zstd::decoder(in_stream),
compression::Format::No => Ok((in_stream, compression::Format::No)),
}
}
Expand Down Expand Up @@ -124,10 +124,10 @@ pub fn get_writer<'a>(
level: Level,
) -> Result<Box<dyn io::Write + 'a>, Error> {
match format {
compression::Format::Gzip => compression::new_gz_encoder(out_stream, level),
compression::Format::Bzip => compression::new_bz2_encoder(out_stream, level),
compression::Format::Lzma => compression::new_lzma_encoder(out_stream, level),
compression::Format::Zstd => compression::new_zstd_encoder(out_stream, level),
compression::Format::Gzip => compression::gz::encoder(out_stream, level),
compression::Format::Bzip => compression::bz2::encoder(out_stream, level),
compression::Format::Lzma => compression::lzma::encoder(out_stream, level),
compression::Format::Zstd => compression::zstd::encoder(out_stream, level),
compression::Format::No => Ok(Box::new(out_stream)),
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,14 @@
//! - xz_tokio -> xz2 tokio
/* declare mod */
#[macro_use]
pub(crate) mod utils;
pub mod basic;
pub mod error;
pub mod level;
pub mod seek;
pub mod seeksend;
pub mod send;
pub(crate) mod utils;

/* reexport for convinent usage of niffler */
pub use crate::basic::compression::Format;
Expand Down
Loading

0 comments on commit 9df5d8f

Please sign in to comment.