diff --git a/src/bin/extract.rs b/src/bin/extract.rs index 7dddcbb2..69b12cb4 100644 --- a/src/bin/extract.rs +++ b/src/bin/extract.rs @@ -7,9 +7,9 @@ fn main() let file = std::io::File::open(&fname); let mut zipcontainer = zip::reader::ZipContainer::new(file).unwrap(); - for mut i in zipcontainer.files() + for i in zipcontainer.files() { - println!("File: {}", i.name); + println!("File: {}", String::from_utf8_lossy(i.name.as_slice())); if i.size == 0 { continue } @@ -19,7 +19,8 @@ fn main() std::io::fs::mkdir_recursive(&dirname, std::io::UserDir).unwrap(); let mut outfile = std::io::File::create(&outpath); - copy(&mut i.reader, &mut outfile).unwrap(); + let mut reader = zipcontainer.read_file(&i); + copy(&mut reader, &mut outfile).unwrap(); } } diff --git a/src/reader.rs b/src/reader.rs index 1c7b7d50..9fad5796 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -19,15 +19,15 @@ struct ZipFile pub struct ZipFileItems<'a, T:'a> { - container: &'a mut ZipContainer, + container: &'a ZipContainer, pos: uint, } -pub struct ZipFileItem<'a> +pub struct ZipFileItem { - pub name: String, + pub name: Vec, pub size: uint, - pub reader: Box, + index: uint, } fn unsupported_zip_error(detail: String) -> IoResult @@ -73,10 +73,28 @@ impl ZipContainer result } - pub fn files<'a>(&'a mut self) -> ZipFileItems<'a, T> + pub fn files(&mut self) -> ZipFileItems { ZipFileItems { container: self, pos: 0 } } + + pub fn read_file(&mut self, item: &ZipFileItem) -> IoResult> + { + let file = self.files.get_mut(item.index); + let reader = &mut self.inner; + let pos = file.local_header.header_end as i64; + + try!(reader.seek(pos, io::SeekSet)); + let lreader = io::util::LimitReader::new(reader.by_ref(), file.central_header.compressed_size as uint); + + let reader = match file.central_header.compression_method + { + spec::Stored => box Crc32Reader::new_with_check(lreader, file.central_header.crc32) as Box, + spec::Deflated => box Crc32Reader::new_with_check(lreader.deflate_decode(), file.central_header.crc32) as Box, + _ => return unsupported_zip_error("Compression method not supported".to_string()), + }; + Ok(reader) + } } impl ZipFile @@ -97,31 +115,21 @@ impl ZipFile } } -impl<'a> ZipFileItem<'a> +impl ZipFileItem { - fn new(reader: &mut S, file: &ZipFile) -> IoResult> + fn new(container: &ZipContainer, index: uint) -> IoResult { - let fname = file.central_header.file_name.clone(); - let name = String::from_utf8(fname).unwrap_or("???".to_string()); - let pos = file.local_header.header_end as i64; + let file = &container.files[index]; - try!(reader.seek(pos, io::SeekSet)); - let lreader = io::util::LimitReader::new(reader.by_ref(), file.central_header.compressed_size as uint); + let name = file.central_header.file_name.clone(); - let reader = match file.central_header.compression_method - { - spec::Stored => box Crc32Reader::new_with_check(lreader, file.central_header.crc32) as Box, - spec::Deflated => box Crc32Reader::new_with_check(lreader.deflate_decode(), file.central_header.crc32) as Box, - _ => return unsupported_zip_error("Compression method not supported".to_string()), - }; - - Ok(ZipFileItem { name: name, reader: reader, size: file.central_header.uncompressed_size as uint }) + Ok(ZipFileItem { name: name, size: file.central_header.uncompressed_size as uint, index: index }) } } -impl<'a, T: Reader+Seek> Iterator> for ZipFileItems<'a, T> +impl<'a, T: Reader+Seek> Iterator for ZipFileItems<'a, T> { - fn next(&mut self) -> Option> + fn next(&mut self) -> Option { self.pos += 1; if self.pos - 1 >= self.container.files.len() @@ -130,8 +138,7 @@ impl<'a, T: Reader+Seek> Iterator> for ZipFileItems<'a, T> } else { - let result = ZipFileItem::new(&mut self.container.inner, &self.container.files[self.pos - 1]); - result.ok() + ZipFileItem::new(self.container, self.pos - 1).ok() } } }