Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #[macro_use]
- extern crate rental;
- use flate2::read::GzDecoder;
- use std::fs::File;
- use std::io;
- use std::io::Read;
- use tar::Archive;
- use tar::Entry;
- type Reader = Box<dyn Read>;
- type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
- rental! {
- mod rentals {
- use super::*;
- #[rental_mut]
- pub struct Inner {
- archive: Box<Archive<Reader>>,
- entry: Entry<'archive, Reader>,
- }
- }
- }
- struct ArchiveFile {
- inner: rentals::Inner,
- }
- fn find_entry<'a>(archive: &'a mut Archive<Reader>, file: &str) -> Result<Entry<'a, Reader>> {
- for entry in archive.entries()? {
- let entry = entry?;
- if entry.path()?.to_string_lossy() == file {
- return Ok(entry);
- }
- }
- Err(Box::new(io::Error::new(
- io::ErrorKind::NotFound,
- "File not found in archive",
- )))
- }
- impl ArchiveFile {
- pub fn open(archive: &str, file: &str) -> Result<Self> {
- let reader: Reader = Box::new(GzDecoder::new(File::open(archive)?));
- let archive = Archive::new(reader);
- let inner = rentals::Inner::try_new(Box::new(archive), |arc| find_entry(arc, file))
- .map_err(|e| e.0)?;
- Ok(ArchiveFile { inner })
- }
- }
- impl Read for ArchiveFile {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- self.inner.rent_mut(|entry| entry.read(buf))
- }
- }
- fn main() {
- let mut file = ArchiveFile::open("a.tar.gz", "a/file1").unwrap();
- let mut data = String::new();
- file.read_to_string(&mut data).unwrap();
- dbg!(data);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement