From 00c88153b2230387771df7902830f67979dc6cc3 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 7 Dec 2016 17:51:59 -0500 Subject: [PATCH] Rework read_sized_string(): truncate null bytes --- src/error.rs | 11 +++++++++++ src/metadata/mod.rs | 2 +- src/metadata/readers.rs | 29 +++++++++++++++++++++++------ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/error.rs b/src/error.rs index b248934..c6360b2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -23,6 +23,7 @@ //! Error type for NRGrip. use std::error::Error; +use std::ffi; use std::fmt; use std::io; @@ -30,6 +31,7 @@ use std::io; #[derive(Debug)] pub enum NrgError { Io(io::Error), + String(ffi::IntoStringError), NrgFormat, NrgFormatV1, NrgChunkId, @@ -43,6 +45,7 @@ impl fmt::Display for NrgError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { NrgError::Io(ref err) => err.fmt(f), + NrgError::String(ref err) => err.fmt(f), NrgError::NrgFormat => write!(f, "NRG format unknown."), NrgError::NrgFormatV1 => write!(f, "NRG v1 format is not handled."), NrgError::NrgChunkId => write!(f, "NRG chunk ID unknown."), @@ -58,6 +61,7 @@ impl Error for NrgError { fn description(&self) -> &str { match *self { NrgError::Io(ref err) => err.description(), + NrgError::String(ref err) => err.description(), NrgError::NrgFormat => "NRG format", NrgError::NrgFormatV1 => "NRG format v1", NrgError::NrgChunkId => "NRG chunk ID", @@ -71,6 +75,7 @@ impl Error for NrgError { fn cause(&self) -> Option<&Error> { match *self { NrgError::Io(ref err) => Some(err), + NrgError::String(ref err) => Some(err), NrgError::NrgFormat => None, NrgError::NrgFormatV1 => None, NrgError::NrgChunkId => None, @@ -87,3 +92,9 @@ impl From for NrgError { NrgError::Io(err) } } + +impl From for NrgError { + fn from(err: ffi::IntoStringError) -> NrgError { + NrgError::String(err) + } +} diff --git a/src/metadata/mod.rs b/src/metadata/mod.rs index 098bde4..1791b56 100644 --- a/src/metadata/mod.rs +++ b/src/metadata/mod.rs @@ -139,7 +139,7 @@ fn read_nrg_chunks(fd: &mut File, nm: &mut NrgMetadata) -> Result<(), NrgError> /// Reads an NRG chunk ID (i.e. a 4-byte string) from `fd`. -fn read_nrg_chunk_id(fd: &File) -> Result { +fn read_nrg_chunk_id(fd: &mut File) -> Result { read_sized_string(fd, 4) } diff --git a/src/metadata/readers.rs b/src/metadata/readers.rs index 9883727..45bc410 100644 --- a/src/metadata/readers.rs +++ b/src/metadata/readers.rs @@ -22,6 +22,7 @@ //! Miscellaneous functions to read fixed-size data from a file. +use std::ffi::CString; use std::fs::File; use std::io::Read; use std::mem; @@ -29,12 +30,28 @@ use std::mem; use ::error::NrgError; -/// Reads a String of size `size` from `fd`. -pub fn read_sized_string(fd: &File, size: u64) -> Result { - let mut handle = fd.take(size); - let mut string = String::new(); - try!(handle.read_to_string(&mut string)); - Ok(string) +/// Reads a String of `size` bytes from `fd`. +/// +/// The string will be truncated at the first null byte encountered; therefore, +/// its length may be less than `size` characters. +pub fn read_sized_string(fd: &mut File, size: usize) + -> Result { + // Read size bytes + let mut bytes = vec!(0u8; size); + try!(fd.read_exact(&mut bytes)); + + // Truncate the vector at the first null byte + let mut i: usize = 0; + for b in bytes.iter() { + if *b == 0 { break; } + i += 1; + } + bytes.truncate(i); + + let cstring = CString::new(bytes) + .expect("This Vec wasn't supposed to contain any null byte!"); + + cstring.into_string().map_err(NrgError::String) }