diff --git a/workspace/compress/Cargo.toml b/workspace/compress/Cargo.toml index 7b27ff9..51f3262 100644 --- a/workspace/compress/Cargo.toml +++ b/workspace/compress/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "compress" +name = "substratum-compress" version.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/workspace/compress/src/decode/decoder.rs b/workspace/compress/src/decode/decoder.rs index 82c49a8..6d5a43b 100644 --- a/workspace/compress/src/decode/decoder.rs +++ b/workspace/compress/src/decode/decoder.rs @@ -3,6 +3,7 @@ use super::decode::{ DecodeBufReadIntoBufRead, DecodeBufReadIntoRead, DecodeReadIntoBufRead, DecodeReadIntoRead, }; use std::io::{BufRead, Error, Read}; +use std::path::Path; #[cfg_attr(feature = "bitcode", derive(::bitcode::Encode, ::bitcode::Decode))] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -74,3 +75,12 @@ impl_decompression_trait!( DecodeBufReadIntoBufRead, decode_bufread_into_bufread ); + +impl Decoder { + pub fn from_extension(ext: &str, uncompressed_exts: &[&str]) -> std::io::Result { + crate::Format::from_extension(ext, uncompressed_exts).map(|x| x.decoder()) + } + pub fn from_path(path: impl AsRef, uncompressed_exts: &[&str]) -> std::io::Result { + crate::Format::from_path(path, uncompressed_exts).map(|x| x.decoder()) + } +} diff --git a/workspace/compress/src/encode/encoder.rs b/workspace/compress/src/encode/encoder.rs index 40fafe0..9fe69ba 100644 --- a/workspace/compress/src/encode/encoder.rs +++ b/workspace/compress/src/encode/encoder.rs @@ -1,6 +1,7 @@ use super::adapter::Adapter; use super::encode::Encode; use std::io::{Error, Write}; +use std::path::Path; #[cfg_attr(feature = "bitcode", derive(::bitcode::Encode, ::bitcode::Decode))] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -48,3 +49,12 @@ where } } } + +impl Encoder { + pub fn from_extension(ext: &str, uncompressed_exts: &[&str]) -> std::io::Result { + crate::Format::from_extension(ext, uncompressed_exts).map(|x| x.encoder()) + } + pub fn from_path(path: impl AsRef, uncompressed_exts: &[&str]) -> std::io::Result { + crate::Format::from_path(path, uncompressed_exts).map(|x| x.encoder()) + } +} diff --git a/workspace/compress/src/format.rs b/workspace/compress/src/format.rs index 4e9832e..6e39c3a 100644 --- a/workspace/compress/src/format.rs +++ b/workspace/compress/src/format.rs @@ -1,4 +1,5 @@ use crate::{decode, encode}; +use std::io::{Error, ErrorKind, Result}; use std::path::Path; const DEFLATE: &[&str] = &[]; @@ -18,32 +19,42 @@ pub enum Format { } impl Format { - pub fn from_extension(ext: &str, uncompressed_exts: &[&str]) -> Option { + pub fn from_extension(ext: &str, uncompressed_exts: &[&str]) -> Result { match ext { // Empty extension can't be used to infer format - ext if ext.is_empty() => None, + ext if ext.is_empty() => Err(Error::new( + ErrorKind::InvalidInput, + "Can't infer format from empty extension", + )), // Uncompressed files - ext if uncompressed_exts.contains(&ext) => Some(Self::Uncompressed), + ext if uncompressed_exts.contains(&ext) => Ok(Self::Uncompressed), // DEFLATE compressed files #[cfg(any(feature = "decode-deflate", feature = "encode-deflate"))] - ext if DEFLATE.contains(&ext) => Some(Self::Deflate), + ext if DEFLATE.contains(&ext) => Ok(Self::Deflate), // GZIP compressed files #[cfg(any(feature = "decode-gzip", feature = "encode-gzip"))] - ext if GZIP.contains(&ext) => Some(Self::Gzip), + ext if GZIP.contains(&ext) => Ok(Self::Gzip), // BGZF compressed files #[cfg(any(feature = "decode-bgzf", feature = "encode-bgzf"))] - ext if BGZF.contains(&ext) => Some(Self::Bgzf), + ext if BGZF.contains(&ext) => Ok(Self::Bgzf), - _ => None, + _ => Err(Error::new( + ErrorKind::InvalidInput, + format!("Unknown format '{}'", ext), + )), } } - pub fn from_path(path: impl AsRef, uncompressed_exts: &[&str]) -> Option { - let path = path.as_ref().extension()?.to_str()?; + pub fn from_path(path: impl AsRef, uncompressed_exts: &[&str]) -> Result { + let path = path + .as_ref() + .extension() + .and_then(|ext| ext.to_str()) + .unwrap_or(""); Self::from_extension(path, uncompressed_exts) } @@ -81,25 +92,25 @@ mod tests { // Uncompressed extensions assert_eq!( - Format::from_extension("txt", uncompressed_exts), - Some(Format::Uncompressed) + Format::from_extension("txt", uncompressed_exts).unwrap(), + Format::Uncompressed ); // Known compressed extensions #[cfg(feature = "decode-gzip")] assert_eq!( - Format::from_extension("gz", uncompressed_exts), - Some(Format::Gzip) + Format::from_extension("gz", uncompressed_exts).unwrap(), + Format::Gzip ); #[cfg(feature = "decode-bgzf")] assert_eq!( - Format::from_extension("bgzf", uncompressed_exts), - Some(Format::Bgzf) + Format::from_extension("bgzf", uncompressed_exts).unwrap(), + Format::Bgzf ); // Unknown or empty extensions - assert_eq!(Format::from_extension("unknown", uncompressed_exts), None); - assert_eq!(Format::from_extension("", uncompressed_exts), None); + assert!(Format::from_extension("unknown", uncompressed_exts).is_err()); + assert!(Format::from_extension("", uncompressed_exts).is_err()); } } diff --git a/workspace/compress/src/lib.rs b/workspace/compress/src/lib.rs index a92cfe6..d829cbd 100644 --- a/workspace/compress/src/lib.rs +++ b/workspace/compress/src/lib.rs @@ -9,7 +9,7 @@ //! compress data into a memory buffer, and then decompress it back to verify integrity. //! //! ```rust -//! use compress::{adapter::BoxedSync, decode::DecodeReadIntoRead, encode::Encode, Format}; +//! use substratum_compress::{adapter::BoxedSync, decode::DecodeReadIntoRead, encode::Encode, Format}; //! use std::io::{Read, Write}; //! //! fn main() -> std::io::Result<()> { @@ -19,9 +19,8 @@ //! // 1. Setup & Inference //! // ---------------------------------------------------------------------- //! // Detect format from extension (e.g., "gz" -> Format::Gzip) -//! let format = Format::from_extension("gz", &[]); -//! assert_eq!(format, Some(Format::Gzip), "Should infer Gzip format"); -//! let format = format.unwrap(); +//! let format = Format::from_extension("gz", &[]).unwrap(); +//! assert_eq!(format, Format::Gzip, "Should infer Gzip format"); //! //! // ---------------------------------------------------------------------- //! // 2. Encode (Write) @@ -71,4 +70,6 @@ pub mod decode; pub mod encode; mod format; +pub use decode::Decoder; +pub use encode::Encoder; pub use format::Format;