Rework read_sized_string(): truncate null bytes

This commit is contained in:
Matteo Cypriani 2016-12-07 17:51:59 -05:00
parent 4b92eb0239
commit 00c88153b2
3 changed files with 35 additions and 7 deletions

View File

@ -23,6 +23,7 @@
//! Error type for NRGrip. //! Error type for NRGrip.
use std::error::Error; use std::error::Error;
use std::ffi;
use std::fmt; use std::fmt;
use std::io; use std::io;
@ -30,6 +31,7 @@ use std::io;
#[derive(Debug)] #[derive(Debug)]
pub enum NrgError { pub enum NrgError {
Io(io::Error), Io(io::Error),
String(ffi::IntoStringError),
NrgFormat, NrgFormat,
NrgFormatV1, NrgFormatV1,
NrgChunkId, NrgChunkId,
@ -43,6 +45,7 @@ impl fmt::Display for NrgError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
NrgError::Io(ref err) => err.fmt(f), NrgError::Io(ref err) => err.fmt(f),
NrgError::String(ref err) => err.fmt(f),
NrgError::NrgFormat => write!(f, "NRG format unknown."), NrgError::NrgFormat => write!(f, "NRG format unknown."),
NrgError::NrgFormatV1 => write!(f, "NRG v1 format is not handled."), NrgError::NrgFormatV1 => write!(f, "NRG v1 format is not handled."),
NrgError::NrgChunkId => write!(f, "NRG chunk ID unknown."), NrgError::NrgChunkId => write!(f, "NRG chunk ID unknown."),
@ -58,6 +61,7 @@ impl Error for NrgError {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
NrgError::Io(ref err) => err.description(), NrgError::Io(ref err) => err.description(),
NrgError::String(ref err) => err.description(),
NrgError::NrgFormat => "NRG format", NrgError::NrgFormat => "NRG format",
NrgError::NrgFormatV1 => "NRG format v1", NrgError::NrgFormatV1 => "NRG format v1",
NrgError::NrgChunkId => "NRG chunk ID", NrgError::NrgChunkId => "NRG chunk ID",
@ -71,6 +75,7 @@ impl Error for NrgError {
fn cause(&self) -> Option<&Error> { fn cause(&self) -> Option<&Error> {
match *self { match *self {
NrgError::Io(ref err) => Some(err), NrgError::Io(ref err) => Some(err),
NrgError::String(ref err) => Some(err),
NrgError::NrgFormat => None, NrgError::NrgFormat => None,
NrgError::NrgFormatV1 => None, NrgError::NrgFormatV1 => None,
NrgError::NrgChunkId => None, NrgError::NrgChunkId => None,
@ -87,3 +92,9 @@ impl From<io::Error> for NrgError {
NrgError::Io(err) NrgError::Io(err)
} }
} }
impl From<ffi::IntoStringError> for NrgError {
fn from(err: ffi::IntoStringError) -> NrgError {
NrgError::String(err)
}
}

View File

@ -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`. /// Reads an NRG chunk ID (i.e. a 4-byte string) from `fd`.
fn read_nrg_chunk_id(fd: &File) -> Result<String, NrgError> { fn read_nrg_chunk_id(fd: &mut File) -> Result<String, NrgError> {
read_sized_string(fd, 4) read_sized_string(fd, 4)
} }

View File

@ -22,6 +22,7 @@
//! Miscellaneous functions to read fixed-size data from a file. //! Miscellaneous functions to read fixed-size data from a file.
use std::ffi::CString;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::mem; use std::mem;
@ -29,12 +30,28 @@ use std::mem;
use ::error::NrgError; use ::error::NrgError;
/// Reads a String of size `size` from `fd`. /// Reads a String of `size` bytes from `fd`.
pub fn read_sized_string(fd: &File, size: u64) -> Result<String, NrgError> { ///
let mut handle = fd.take(size); /// The string will be truncated at the first null byte encountered; therefore,
let mut string = String::new(); /// its length may be less than `size` characters.
try!(handle.read_to_string(&mut string)); pub fn read_sized_string(fd: &mut File, size: usize)
Ok(string) -> Result<String, NrgError> {
// 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)
} }