diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ab5ac5bf9e146..ab184ae518920 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -107,6 +107,7 @@ pub use core::slice::{ImmutableIntSlice, MutableIntSlice}; pub use core::slice::{MutSplits, MutChunks, Splits}; pub use core::slice::{bytes, mut_ref_slice, ref_slice, CloneSlicePrelude}; pub use core::slice::{Found, NotFound, from_raw_buf, from_raw_mut_buf}; +pub use core::slice::{ImmutablePrimitiveSlice, MutablePrimitiveSlice}; // Functional utilities diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 754da272c2481..545c5b49a2f41 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -43,6 +43,7 @@ use cmp; use default::Default; use iter::*; use num::Int; +use num::Primitive; use ops; use option::{None, Option, Some}; use ptr; @@ -1832,3 +1833,52 @@ impl_int_slice!(u16, i16) impl_int_slice!(u32, i32) impl_int_slice!(u64, i64) impl_int_slice!(uint, int) + +#[experimental] +/// Extension methods for working with immutable slices of primitive types. +pub trait ImmutablePrimitiveSlice for Sized? { + /// Convert this slice to a slice of bytes. + /// + /// For structures with padding, care needs to be taken to avoid + /// inter-field and trailing padding, as the contents of structure + /// padding are unspecified. + fn as_bytes<'a>(&'a self) -> &'a [u8]; +} + +/// This conservatively uses `Primitive` instead of `Copy` because a `Copy` type +/// could conceivably have uninitialized private fields that would be unsafe to +/// read. +impl ImmutablePrimitiveSlice for [T] { + fn as_bytes<'a>(&'a self) -> &'a [u8] { + unsafe { + // This cannot overflow, because otherwise the slice would + // not be able to fit in the address space. + transmute(RawSlice{ + data: self.as_ptr(), + len: size_of::() * self.len() + }) + } + } +} + +#[experimental] +/// Extension methods for working with mutable slices of primitive types. +pub trait MutablePrimitiveSlice for Sized? { + /// Convert this slice to a mutable slice of bytes. + fn as_mut_bytes<'a>(&'a mut self) -> &'a mut [u8]; +} + +/// This uses `Primitive` instead of `Copy` because otherwise one would be +/// able to write invalid enum discriminants or bools, which is unsafe. +impl MutablePrimitiveSlice for [T] { + fn as_mut_bytes<'a>(&'a mut self) -> &'a mut [u8] { + unsafe { + // This cannot overflow, because otherwise the slice would + // not be able to fit in the address space. + transmute(RawSlice{ + data: self.as_ptr(), + len: size_of::() * self.len() + }) + } + } +}