For some reason zip::read::ZipArchive
is having trouble reading back a file written using zip::write::ZipWriter
.
Here's how I create the zip buffer:
fn create_zipped_test_file(contents: &'static str) -> Cursor<Vec<u8>> {
let file = Vec::new();
let cur = Cursor::new(file);
let mut zip = ZipWriter::new(cur);
let options = SimpleFileOptions::default();
zip.start_file("gamestate", options).unwrap();
if zip.write(contents.as_bytes()).unwrap() != contents.len() {
panic!("Failed to write the entire file");
}
let mut cur = zip.finish().unwrap();
cur.seek(SeekFrom::Start(0)).unwrap();
return cur;
}
And here's where I try to read it back:
pub fn read<F: Read>(file: &mut F) -> Result<SaveFile, SaveFileError> {
let mut contents = vec![];
let contents_size = file.read_to_end(&mut contents)?;
if contents_size < ARCHIVE_HEADER.len() {
return Err(SaveFileError::ParseError("Save file is too small"));
}
let mut compressed = false;
let mut binary = false;
// find if ARCHIVE_HEADER is in the file
for i in 0..contents_size - ARCHIVE_HEADER.len() {
if contents[i..i + ARCHIVE_HEADER.len()] == *ARCHIVE_HEADER {
compressed = true;
break;
} else if contents[i..i + BINARY_HEADER.len()] == *BINARY_HEADER {
binary = true;
}
}
if compressed {
let mut archive = ZipArchive::new(Cursor::new(contents))?;
let mut gamestate = archive.by_index(0)?;
if gamestate.is_dir() {
return Err(SaveFileError::ParseError("Save file is a directory"));
}
if gamestate.name() != "gamestate" {
return Err(SaveFileError::ParseError("Unexpected file name"));
}
let gamestate_size = gamestate.size() as usize;
let mut contents = Vec::with_capacity(gamestate_size);
if gamestate.read(&mut contents)? != gamestate_size {
return Err(SaveFileError::ParseError("Failed to read the entire file"));
}
return Ok(SaveFile { contents, binary });
} else {
return Ok(SaveFile { contents, binary });
}
}
It keeps failing at the gamestate.read(&mut contents)? != gamestate_size
check.
I know that the correct number of bytes is being written, and it's not an issue with the cursor's position within the stream because I reset that.
What am I doing wrong?
What am I doing wrong?
read
doesn't take a vector to append to, it takes a slice of size n
:
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
and reads at most n
bytes from the source overwriting the slice, but may read less (which is why it returns the number of bytes it has read).
Since you're giving it an empty slice (because you're giving it a slice created from an empty vec) it reads nothing, and returns successfully with a read amount of 0, probably.
If you want to read the entire file into a vector, use read_to_end
, that's what it's for. That'll read()
repeatedly with some internally guessed buffer size until it reaches the end of the readable or a fatal error.