diff --git a/src/lib.rs b/src/lib.rs index 2d53b77..4a57860 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,35 +1,135 @@ -use std::fs::File; -use std::io::Read; -use std::path::Path; +pub mod read { + use std::fs::File; + use std::io::{Read, Seek, SeekFrom}; + use std::path::Path; -use bzip2::read::BzDecoder; -use flate2::read::GzDecoder; + use bzip2::read::BzDecoder; + use flate2::read::GzDecoder; -pub enum FileDecompressed { - Raw(File), - Gz(GzDecoder), - Bz(BzDecoder), -} + pub enum Decoder { + Raw(File), + Gz(GzDecoder), + Bz(BzDecoder), + } -impl Read for FileDecompressed { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - match self { - FileDecompressed::Raw(file) => file.read(buf), - FileDecompressed::Gz(file) => file.read(buf), - FileDecompressed::Bz(file) => file.read(buf), + impl Decoder { + pub fn open

(path: P) -> Result + where + P: AsRef, + { + let file = File::open(&path)?; + + Ok(match mime_guess::from_path(path).first_raw() { + Some("application/x-gzip") => Decoder::Gz(GzDecoder::new(file)), + Some("application/x-bzip2") => Decoder::Bz(BzDecoder::new(file)), + _ => Decoder::Raw(file), + }) + } + + pub fn stream_len(&mut self) -> std::io::Result { + let file = match self { + Decoder::Raw(file) => file, + Decoder::Gz(file) => file.get_mut(), + Decoder::Bz(file) => file.get_mut(), + }; + + let old_pos = file.seek(SeekFrom::Current(0))?; + let len = file.seek(SeekFrom::End(0))?; + + if old_pos != len { + file.seek(SeekFrom::Start(old_pos))?; + } + + Ok(len) + } + + pub fn stream_position(&mut self) -> std::io::Result { + let file = match self { + Decoder::Raw(file) => file, + Decoder::Gz(file) => file.get_mut(), + Decoder::Bz(file) => file.get_mut(), + }; + + file.seek(SeekFrom::Current(0)) + } + } + + impl Read for Decoder { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + match self { + Decoder::Raw(file) => file.read(buf), + Decoder::Gz(file) => file.read(buf), + Decoder::Bz(file) => file.read(buf), + } } } } -pub fn open

(path: P) -> Result -where - P: AsRef, -{ - let file = File::open(&path)?; +pub mod bufread { + use std::fs::File; + use std::io::{BufReader, Read, Seek, SeekFrom}; + use std::path::Path; - Ok(match mime_guess::from_path(path).first_raw() { - Some("application/x-gzip") => FileDecompressed::Gz(GzDecoder::new(file)), - Some("application/x-bzip2") => FileDecompressed::Bz(BzDecoder::new(file)), - _ => FileDecompressed::Raw(file), - }) + use bzip2::bufread::BzDecoder; + use flate2::bufread::GzDecoder; + + pub enum BufDecoder { + Raw(BufReader), + Gz(GzDecoder>), + Bz(BzDecoder>), + } + + impl BufDecoder { + pub fn open

(path: P) -> Result + where + P: AsRef, + { + let file = File::open(&path).map(BufReader::new)?; + + Ok(match mime_guess::from_path(path).first_raw() { + Some("application/x-gzip") => BufDecoder::Gz(GzDecoder::new(file)), + Some("application/x-bzip2") => BufDecoder::Bz(BzDecoder::new(file)), + _ => BufDecoder::Raw(file), + }) + } + + pub fn stream_len(&mut self) -> std::io::Result { + let file = match self { + BufDecoder::Raw(file) => file, + BufDecoder::Gz(file) => file.get_mut(), + BufDecoder::Bz(file) => file.get_mut(), + }; + + let old_pos = file.seek(SeekFrom::Current(0))?; + let len = file.seek(SeekFrom::End(0))?; + + if old_pos != len { + file.seek(SeekFrom::Start(old_pos))?; + } + + Ok(len) + } + + pub fn stream_position(&mut self) -> std::io::Result { + let file = match self { + BufDecoder::Raw(file) => file, + BufDecoder::Gz(file) => file.get_mut(), + BufDecoder::Bz(file) => file.get_mut(), + }; + + file.seek(SeekFrom::Current(0)) + } + } + + impl Read for BufDecoder { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + match self { + BufDecoder::Raw(file) => file.read(buf), + BufDecoder::Gz(file) => file.read(buf), + BufDecoder::Bz(file) => file.read(buf), + } + } + } }