use runtime_support::{Vec, size_of, transmute, uninitialized, slice}; use joiner::Joiner; use endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. pub trait Slicable: Sized { fn from_slice(value: &[u8]) -> Option { Self::set_as_slice(|out| if value.len() == out.len() { out.copy_from_slice(&value); true } else { false }) } fn to_vec(&self) -> Vec { self.as_slice_then(|s| s.to_vec()) } fn set_as_slice bool>(set_slice: F) -> Option; fn as_slice_then R>(&self, f: F) -> R { f(&self.to_vec()) } fn size_of(_value: &[u8]) -> Option; } pub trait NonTrivialSlicable: Slicable {} impl Slicable for T { fn set_as_slice bool>(fill_slice: F) -> Option { let size = size_of::(); let mut result: T = unsafe { uninitialized() }; let result_slice = unsafe { slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) }; if fill_slice(result_slice) { Some(result.from_le()) } else { None } } fn as_slice_then R>(&self, f: F) -> R { let size = size_of::(); self.as_le_then(|le| { let value_slice = unsafe { slice::from_raw_parts(transmute::<*const Self, *const u8>(le), size) }; f(value_slice) }) } fn size_of(_value: &[u8]) -> Option { Some(size_of::()) } } impl Slicable for Vec { fn from_slice(value: &[u8]) -> Option { Some(value[4..].to_vec()) } fn set_as_slice bool>(_fill_slice: F) -> Option { unimplemented!(); } fn to_vec(&self) -> Vec { let mut r: Vec = vec![].join(&(self.len() as u32)); r.extend_from_slice(&self); r } fn size_of(data: &[u8]) -> Option { u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) } }