From 7aaec16b53c4b7a68ae655e6e936a01ec5cafc52 Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Wed, 9 Sep 2020 07:34:22 +0200 Subject: [PATCH] Added memmap version. --- Cargo.toml | 1 + src/lib.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 7194b92..3ab5279 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,6 @@ edition = "2018" [dependencies] bzip2 = "0.4" flate2 = "1.0" +memmap = "0.7" mime = "0.3" mime_guess = "2.0" diff --git a/src/lib.rs b/src/lib.rs index 568dee3..834793b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,3 +150,76 @@ pub mod bufread { } } } + +pub mod memmap { + use std::fs::File; + use std::io::{Cursor, Read, Seek, SeekFrom}; + use std::path::Path; + + use bzip2::read::BzDecoder; + use flate2::read::GzDecoder; + use memmap::{Mmap, MmapOptions}; + + pub enum MmapDecoder { + Raw(Cursor), + Gz(GzDecoder>), + Bz(BzDecoder>), + } + + impl MmapDecoder { + pub fn open

(path: P) -> Result + where + P: AsRef, + { + let file = File::open(&path)?; + let mmap = unsafe { MmapOptions::new().map(&file)? }; + let cursor = Cursor::new(mmap); + + Ok(match mime_guess::from_path(path).first_raw() { + Some("application/x-gzip") => MmapDecoder::Gz(GzDecoder::new(cursor)), + Some("application/x-bzip2") => MmapDecoder::Bz(BzDecoder::new(cursor)), + _ => MmapDecoder::Raw(cursor), + }) + } + + #[inline] + pub fn stream_len(&mut self) -> std::io::Result { + let file = match self { + MmapDecoder::Raw(file) => file, + MmapDecoder::Gz(file) => file.get_mut(), + MmapDecoder::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) + } + + #[inline] + pub fn stream_position(&mut self) -> std::io::Result { + let file = match self { + MmapDecoder::Raw(file) => file, + MmapDecoder::Gz(file) => file.get_mut(), + MmapDecoder::Bz(file) => file.get_mut(), + }; + + file.seek(SeekFrom::Current(0)) + } + } + + impl Read for MmapDecoder { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + match self { + MmapDecoder::Raw(file) => file.read(buf), + MmapDecoder::Gz(file) => file.read(buf), + MmapDecoder::Bz(file) => file.read(buf), + } + } + } +}