Skip to content

core: add {Imm,M}utablePrimitiveSlice trait #19241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
50 changes: 50 additions & 0 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<T: Primitive> 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::<T>() * 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<T: Primitive> MutablePrimitiveSlice for [T] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unsafe, because Primitive is just a trait, and can be implemented for new types (e.g. new enums that you create). Also note that Primitive has been deprecated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same above I believe as well)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also exposing the underlying endian-ness of the system (not portable), which may want to at least be mentioned in the documentation if we move forward with this.

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::<T>() * self.len()
})
}
}
}