Merge a patch from kpcyrd to remove some unsafe blocks.

A part of the patch involves copying or initializing arrays, but the
performance impact should be negligible.  TryFrom will eliminate copying
when stabilized.
This commit is contained in:
KAMADA Ken'ichi 2019-03-26 23:17:31 +09:00
commit 46510fef82
4 changed files with 27 additions and 31 deletions

View File

@ -46,44 +46,40 @@ pub struct LittleEndian;
macro_rules! generate_load {
($name:ident, $int_type:ident, $from_func:ident) => (
fn $name(buf: &[u8], offset: usize) -> $int_type {
// Check if the specified range of the slice is valid
// before transmute(). This will also detect the
// wrap-around of (offset + size_of) in the release mode.
let buf = &buf[offset .. offset + mem::size_of::<$int_type>()];
let ptr = buf.as_ptr() as *const $int_type;
let num = unsafe { mem::transmute(*ptr) };
let mut num = [0u8; mem::size_of::<$int_type>()];
num.copy_from_slice(
&buf[offset .. offset + mem::size_of::<$int_type>()]);
$int_type::$from_func(num)
}
)
}
macro_rules! generate_write {
($name:ident, $int_type:ident, $type_size:expr, $to_func:ident) => (
($name:ident, $int_type:ident, $to_func:ident) => (
fn $name<W>(w: &mut W, num: $int_type)
-> io::Result<()> where W: io::Write {
let buf: [u8; $type_size] =
unsafe { mem::transmute(num.$to_func()) };
let buf = num.$to_func();
w.write_all(&buf)
}
)
}
impl Endian for BigEndian {
generate_load!(loadu16, u16, from_be);
generate_load!(loadu32, u32, from_be);
generate_load!(loadu64, u64, from_be);
generate_write!(writeu16, u16, 2, to_be);
generate_write!(writeu32, u32, 4, to_be);
generate_write!(writeu64, u64, 8, to_be);
generate_load!(loadu16, u16, from_be_bytes);
generate_load!(loadu32, u32, from_be_bytes);
generate_load!(loadu64, u64, from_be_bytes);
generate_write!(writeu16, u16, to_be_bytes);
generate_write!(writeu32, u32, to_be_bytes);
generate_write!(writeu64, u64, to_be_bytes);
}
impl Endian for LittleEndian {
generate_load!(loadu16, u16, from_le);
generate_load!(loadu32, u32, from_le);
generate_load!(loadu64, u64, from_le);
generate_write!(writeu16, u16, 2, to_le);
generate_write!(writeu32, u32, 4, to_le);
generate_write!(writeu64, u64, 8, to_le);
generate_load!(loadu16, u16, from_le_bytes);
generate_load!(loadu32, u32, from_le_bytes);
generate_load!(loadu64, u64, from_le_bytes);
generate_write!(writeu16, u16, to_le_bytes);
generate_write!(writeu32, u32, to_le_bytes);
generate_write!(writeu64, u64, to_le_bytes);
}
#[cfg(test)]

View File

@ -34,12 +34,12 @@ const ASCII_A: u8 = 0x41;
const ASCII_Z: u8 = 0x5a;
pub fn read8<R>(reader: &mut R) -> Result<u8, io::Error> where R: io::Read {
let mut buf: [u8; 1] = unsafe { ::std::mem::uninitialized() };
let mut buf = [0u8; 1];
reader.read_exact(&mut buf).and(Ok(buf[0]))
}
pub fn read16<R>(reader: &mut R) -> Result<u16, io::Error> where R: io::Read {
let mut buf: [u8; 2] = unsafe { ::std::mem::uninitialized() };
let mut buf = [0u8; 2];
reader.read_exact(&mut buf)?;
Ok(((buf[0] as u16) << 8) + buf[1] as u16)
}

View File

@ -357,10 +357,10 @@ fn parse_rational<'a, E>(data: &'a [u8], offset: usize, count: usize)
fn parse_sbyte<'a>(data: &'a [u8], offset: usize, count: usize)
-> Value<'a> {
let uslice = &data[offset .. offset + count];
let islice = unsafe { ::std::slice::from_raw_parts(
uslice.as_ptr() as *const i8, count) };
Value::SByte(islice.to_vec())
let bytes = data[offset .. offset + count].into_iter()
.map(|x| *x as i8)
.collect();
Value::SByte(bytes)
}
fn parse_undefined<'a>(data: &'a [u8], offset: usize, count: usize)

View File

@ -26,7 +26,6 @@
use std::io;
use std::io::{Seek, SeekFrom, Write};
use std::slice;
use endian::{Endian, BigEndian, LittleEndian};
use error::Error;
@ -527,9 +526,10 @@ fn compose_value<E>(value: &Value)
Ok((5, vec.len(), buf))
},
Value::SByte(ref vec) => {
let uslice = unsafe { slice::from_raw_parts(
vec.as_ptr() as *const u8, vec.len()) };
Ok((6, vec.len(), uslice.to_vec()))
let bytes = vec.into_iter()
.map(|x| *x as u8)
.collect();
Ok((6, vec.len(), bytes))
},
Value::Undefined(ref s, _) =>
Ok((7, s.len(), s.to_vec())),