Advertisement
Guest User

Untitled

a guest
Apr 20th, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.55 KB | None | 0 0
  1. #[macro_use]
  2. extern crate rental;
  3.  
  4. use flate2::read::GzDecoder;
  5. use std::fs::File;
  6. use std::io;
  7. use std::io::Read;
  8. use tar::Archive;
  9. use tar::Entry;
  10.  
  11. type Reader = Box<dyn Read>;
  12. type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
  13.  
  14. rental! {
  15. mod rentals {
  16. use super::*;
  17.  
  18. #[rental_mut]
  19. pub struct Inner {
  20. archive: Box<Archive<Reader>>,
  21. entry: Entry<'archive, Reader>,
  22. }
  23. }
  24. }
  25.  
  26. struct ArchiveFile {
  27. inner: rentals::Inner,
  28. }
  29.  
  30. fn find_entry<'a>(archive: &'a mut Archive<Reader>, file: &str) -> Result<Entry<'a, Reader>> {
  31. for entry in archive.entries()? {
  32. let entry = entry?;
  33. if entry.path()?.to_string_lossy() == file {
  34. return Ok(entry);
  35. }
  36. }
  37.  
  38. Err(Box::new(io::Error::new(
  39. io::ErrorKind::NotFound,
  40. "File not found in archive",
  41. )))
  42. }
  43.  
  44. impl ArchiveFile {
  45. pub fn open(archive: &str, file: &str) -> Result<Self> {
  46. let reader: Reader = Box::new(GzDecoder::new(File::open(archive)?));
  47. let archive = Archive::new(reader);
  48.  
  49. let inner = rentals::Inner::try_new(Box::new(archive), |arc| find_entry(arc, file))
  50. .map_err(|e| e.0)?;
  51.  
  52. Ok(ArchiveFile { inner })
  53. }
  54. }
  55.  
  56. impl Read for ArchiveFile {
  57. fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
  58. self.inner.rent_mut(|entry| entry.read(buf))
  59. }
  60. }
  61.  
  62. fn main() {
  63. let mut file = ArchiveFile::open("a.tar.gz", "a/file1").unwrap();
  64.  
  65. let mut data = String::new();
  66. file.read_to_string(&mut data).unwrap();
  67.  
  68. dbg!(data);
  69. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement