diff options
| author | Brian Anderson <banderson@mozilla.com> | 2014-06-30 13:58:53 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2014-06-30 15:40:32 -0700 |
| commit | 16a9258797436498a00726e8aea2ee8a85755e15 (patch) | |
| tree | 67dde2487c095bf2f0d87ef42b6f99f8a2b91c2b | |
| parent | 94343da1bdf4de84d0ece90d920400697ad7e143 (diff) | |
| download | rust-16a9258797436498a00726e8aea2ee8a85755e15.tar.gz rust-16a9258797436498a00726e8aea2ee8a85755e15.zip | |
core: Reorganize slice module.
This is just moving things around so they are defined in a logical order.
| -rw-r--r-- | src/libcore/slice.rs | 972 |
1 files changed, 514 insertions, 458 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index a9e7efdf05a..f1a694c974a 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -14,6 +14,25 @@ #![doc(primitive = "slice")] +// How this module is organized. +// +// The library infrastructure for slices is fairly messy. There's +// a lot of stuff defined here. Let's keep it clean. +// +// Since slices don't support inherent methods; all operations +// on them are defined on traits, which are then reexported from +// the prelude for convenience. So there are a lot of traits here. +// +// The layout of this file is thus: +// +// * Slice-specific 'extension' traits and their implementations. This +// is where most of the slice API resides. +// * Implementations of a few common traits with important slice ops. +// * Definitions of a bunch of iterators. +// * Free functions. +// * The `raw` and `bytes` submodules. +// * Boilerplate trait implementations. + use mem::transmute; use clone::Clone; use collections::Collection; @@ -30,297 +49,9 @@ use mem::size_of; use kinds::marker; use raw::{Repr, Slice}; -/** - * Converts a pointer to A into a slice of length 1 (without copying). - */ -pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { - unsafe { - transmute(Slice { data: s, len: 1 }) - } -} - -/** - * Converts a pointer to A into a slice of length 1 (without copying). - */ -pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { - unsafe { - let ptr: *const A = transmute(s); - transmute(Slice { data: ptr, len: 1 }) - } -} - -/// An iterator over the slices of a vector separated by elements that -/// match a predicate function. -pub struct Splits<'a, T> { - v: &'a [T], - pred: |t: &T|: 'a -> bool, - finished: bool -} - -impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.finished { return None; } - - match self.v.iter().position(|x| (self.pred)(x)) { - None => { - self.finished = true; - Some(self.v) - } - Some(idx) => { - let ret = Some(self.v.slice(0, idx)); - self.v = self.v.slice(idx + 1, self.v.len()); - ret - } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option<uint>) { - if self.finished { - (0, Some(0)) - } else { - (1, Some(self.v.len() + 1)) - } - } -} - -impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<&'a [T]> { - if self.finished { return None; } - - match self.v.iter().rposition(|x| (self.pred)(x)) { - None => { - self.finished = true; - Some(self.v) - } - Some(idx) => { - let ret = Some(self.v.slice(idx + 1, self.v.len())); - self.v = self.v.slice(0, idx); - ret - } - } - } -} - -/// An iterator over the slices of a vector separated by elements that -/// match a predicate function, splitting at most a fixed number of times. -pub struct SplitsN<'a, T> { - iter: Splits<'a, T>, - count: uint, - invert: bool -} - -impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.count == 0 { - if self.iter.finished { - None - } else { - self.iter.finished = true; - Some(self.iter.v) - } - } else { - self.count -= 1; - if self.invert { self.iter.next_back() } else { self.iter.next() } - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option<uint>) { - if self.iter.finished { - (0, Some(0)) - } else { - (1, Some(cmp::min(self.count, self.iter.v.len()) + 1)) - } - } -} - -// Functional utilities - -/// An iterator over the (overlapping) slices of length `size` within -/// a vector. -#[deriving(Clone)] -pub struct Windows<'a, T> { - v: &'a [T], - size: uint -} - -impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.size > self.v.len() { - None - } else { - let ret = Some(self.v.slice(0, self.size)); - self.v = self.v.slice(1, self.v.len()); - ret - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option<uint>) { - if self.size > self.v.len() { - (0, Some(0)) - } else { - let x = self.v.len() - self.size; - (x.saturating_add(1), x.checked_add(&1u)) - } - } -} - -/// An iterator over a vector in (non-overlapping) chunks (`size` -/// elements at a time). -/// -/// When the vector len is not evenly divided by the chunk size, -/// the last slice of the iteration will be the remainder. -#[deriving(Clone)] -pub struct Chunks<'a, T> { - v: &'a [T], - size: uint -} - -impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a [T]> { - if self.v.len() == 0 { - None - } else { - let chunksz = cmp::min(self.v.len(), self.size); - let (fst, snd) = (self.v.slice_to(chunksz), - self.v.slice_from(chunksz)); - self.v = snd; - Some(fst) - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option<uint>) { - if self.v.len() == 0 { - (0, Some(0)) - } else { - let (n, rem) = div_rem(self.v.len(), self.size); - let n = if rem > 0 { n+1 } else { n }; - (n, Some(n)) - } - } -} - -impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<&'a [T]> { - if self.v.len() == 0 { - None - } else { - let remainder = self.v.len() % self.size; - let chunksz = if remainder != 0 { remainder } else { self.size }; - let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz), - self.v.slice_from(self.v.len() - chunksz)); - self.v = fst; - Some(snd) - } - } -} - -impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> { - #[inline] - fn indexable(&self) -> uint { - self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 } - } - - #[inline] - fn idx(&mut self, index: uint) -> Option<&'a [T]> { - if index < self.indexable() { - let lo = index * self.size; - let mut hi = lo + self.size; - if hi < lo || hi > self.v.len() { hi = self.v.len(); } - - Some(self.v.slice(lo, hi)) - } else { - None - } - } -} - -// Equality - -#[allow(missing_doc)] -pub mod traits { - use super::*; - - use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv}; - use iter::order; - use collections::Collection; - use option::Option; - - impl<'a,T:PartialEq> PartialEq for &'a [T] { - fn eq(&self, other: & &'a [T]) -> bool { - self.len() == other.len() && - order::eq(self.iter(), other.iter()) - } - fn ne(&self, other: & &'a [T]) -> bool { - self.len() != other.len() || - order::ne(self.iter(), other.iter()) - } - } - - impl<'a,T:Eq> Eq for &'a [T] {} - - impl<'a,T:PartialEq, V: Vector<T>> Equiv<V> for &'a [T] { - #[inline] - fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } - } - - impl<'a,T:Ord> Ord for &'a [T] { - fn cmp(&self, other: & &'a [T]) -> Ordering { - order::cmp(self.iter(), other.iter()) - } - } - - impl<'a, T: PartialOrd> PartialOrd for &'a [T] { - #[inline] - fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> { - order::partial_cmp(self.iter(), other.iter()) - } - #[inline] - fn lt(&self, other: & &'a [T]) -> bool { - order::lt(self.iter(), other.iter()) - } - #[inline] - fn le(&self, other: & &'a [T]) -> bool { - order::le(self.iter(), other.iter()) - } - #[inline] - fn ge(&self, other: & &'a [T]) -> bool { - order::ge(self.iter(), other.iter()) - } - #[inline] - fn gt(&self, other: & &'a [T]) -> bool { - order::gt(self.iter(), other.iter()) - } - } -} - -/// Any vector that can be represented as a slice. -pub trait Vector<T> { - /// Work with `self` as a slice. - fn as_slice<'a>(&'a self) -> &'a [T]; -} - -impl<'a,T> Vector<T> for &'a [T] { - #[inline(always)] - fn as_slice<'a>(&'a self) -> &'a [T] { *self } -} - -impl<'a, T> Collection for &'a [T] { - /// Returns the length of a vector - #[inline] - fn len(&self) -> uint { - self.repr().len - } -} +// +// Extension traits +// /// Extension methods for vectors pub trait ImmutableVector<'a, T> { @@ -653,69 +384,6 @@ impl<'a,T> ImmutableVector<'a, T> for &'a [T] { } } -/// Extension methods for vectors contain `PartialEq` elements. -pub trait ImmutableEqVector<T:PartialEq> { - /// Find the first index containing a matching value - fn position_elem(&self, t: &T) -> Option<uint>; - - /// Find the last index containing a matching value - fn rposition_elem(&self, t: &T) -> Option<uint>; - - /// Return true if a vector contains an element with the given value - fn contains(&self, x: &T) -> bool; - - /// Returns true if `needle` is a prefix of the vector. - fn starts_with(&self, needle: &[T]) -> bool; - - /// Returns true if `needle` is a suffix of the vector. - fn ends_with(&self, needle: &[T]) -> bool; -} - -impl<'a,T:PartialEq> ImmutableEqVector<T> for &'a [T] { - #[inline] - fn position_elem(&self, x: &T) -> Option<uint> { - self.iter().position(|y| *x == *y) - } - - #[inline] - fn rposition_elem(&self, t: &T) -> Option<uint> { - self.iter().rposition(|x| *x == *t) - } - - #[inline] - fn contains(&self, x: &T) -> bool { - self.iter().any(|elt| *x == *elt) - } - - #[inline] - fn starts_with(&self, needle: &[T]) -> bool { - let n = needle.len(); - self.len() >= n && needle == self.slice_to(n) - } - - #[inline] - fn ends_with(&self, needle: &[T]) -> bool { - let (m, n) = (self.len(), needle.len()); - m >= n && needle == self.slice_from(m - n) - } -} - -/// Extension methods for vectors containing `Ord` elements. -pub trait ImmutableOrdVector<T: Ord> { - /** - * Binary search a sorted vector for a given element. - * - * Returns the index of the element or None if not found. - */ - fn bsearch_elem(&self, x: &T) -> Option<uint>; -} - -impl<'a, T: Ord> ImmutableOrdVector<T> for &'a [T] { - fn bsearch_elem(&self, x: &T) -> Option<uint> { - self.bsearch(|p| p.cmp(x)) - } -} - /// Extension methods for vectors such that their elements are /// mutable. pub trait MutableVector<'a, T> { @@ -1071,6 +739,69 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] { } } +/// Extension methods for vectors contain `PartialEq` elements. +pub trait ImmutableEqVector<T:PartialEq> { + /// Find the first index containing a matching value + fn position_elem(&self, t: &T) -> Option<uint>; + + /// Find the last index containing a matching value + fn rposition_elem(&self, t: &T) -> Option<uint>; + + /// Return true if a vector contains an element with the given value + fn contains(&self, x: &T) -> bool; + + /// Returns true if `needle` is a prefix of the vector. + fn starts_with(&self, needle: &[T]) -> bool; + + /// Returns true if `needle` is a suffix of the vector. + fn ends_with(&self, needle: &[T]) -> bool; +} + +impl<'a,T:PartialEq> ImmutableEqVector<T> for &'a [T] { + #[inline] + fn position_elem(&self, x: &T) -> Option<uint> { + self.iter().position(|y| *x == *y) + } + + #[inline] + fn rposition_elem(&self, t: &T) -> Option<uint> { + self.iter().rposition(|x| *x == *t) + } + + #[inline] + fn contains(&self, x: &T) -> bool { + self.iter().any(|elt| *x == *elt) + } + + #[inline] + fn starts_with(&self, needle: &[T]) -> bool { + let n = needle.len(); + self.len() >= n && needle == self.slice_to(n) + } + + #[inline] + fn ends_with(&self, needle: &[T]) -> bool { + let (m, n) = (self.len(), needle.len()); + m >= n && needle == self.slice_from(m - n) + } +} + +/// Extension methods for vectors containing `Ord` elements. +pub trait ImmutableOrdVector<T: Ord> { + /** + * Binary search a sorted vector for a given element. + * + * Returns the index of the element or None if not found. + */ + fn bsearch_elem(&self, x: &T) -> Option<uint>; +} + +impl<'a, T: Ord> ImmutableOrdVector<T> for &'a [T] { + fn bsearch_elem(&self, x: &T) -> Option<uint> { + self.bsearch(|p| p.cmp(x)) + } +} + /// Trait for &[T] where T is Cloneable pub trait MutableCloneableVector<T> { /// Copies as many elements from `src` as it can into `self` (the @@ -1105,117 +836,44 @@ impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] { } } -/// Unsafe operations -pub mod raw { - use mem::transmute; - use ptr::RawPtr; - use raw::Slice; - use option::{None, Option, Some}; - /** - * Form a slice from a pointer and length (as a number of units, - * not bytes). - */ - #[inline] - pub unsafe fn buf_as_slice<T,U>(p: *const T, len: uint, f: |v: &[T]| -> U) - -> U { - f(transmute(Slice { - data: p, - len: len - })) - } - /** - * Form a slice from a pointer and length (as a number of units, - * not bytes). - */ - #[inline] - pub unsafe fn mut_buf_as_slice<T, - U>( - p: *mut T, - len: uint, - f: |v: &mut [T]| -> U) - -> U { - f(transmute(Slice { - data: p as *const T, - len: len - })) - } - /** - * Returns a pointer to first element in slice and adjusts - * slice so it no longer contains that element. Returns None - * if the slice is empty. O(1). - */ - #[inline] - pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> { - if slice.len == 0 { return None; } - let head: *const T = slice.data; - slice.data = slice.data.offset(1); - slice.len -= 1; - Some(head) - } +// +// Common traits +// - /** - * Returns a pointer to last element in slice and adjusts - * slice so it no longer contains that element. Returns None - * if the slice is empty. O(1). - */ - #[inline] - pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> { - if slice.len == 0 { return None; } - let tail: *const T = slice.data.offset((slice.len - 1) as int); - slice.len -= 1; - Some(tail) - } +/// Any vector that can be represented as a slice. +pub trait Vector<T> { + /// Work with `self` as a slice. + fn as_slice<'a>(&'a self) -> &'a [T]; } -/// Operations on `[u8]`. -pub mod bytes { - use collections::Collection; - use ptr; - use slice::MutableVector; - - /// A trait for operations on mutable `[u8]`s. - pub trait MutableByteVector { - /// Sets all bytes of the receiver to the given value. - fn set_memory(self, value: u8); - } - - impl<'a> MutableByteVector for &'a mut [u8] { - #[inline] - #[allow(experimental)] - fn set_memory(self, value: u8) { - unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) }; - } - } +impl<'a,T> Vector<T> for &'a [T] { + #[inline(always)] + fn as_slice<'a>(&'a self) -> &'a [T] { *self } +} - /// Copies data from `src` to `dst` - /// - /// `src` and `dst` must not overlap. Fails if the length of `dst` - /// is less than the length of `src`. +impl<'a, T> Collection for &'a [T] { + /// Returns the length of a vector #[inline] - pub fn copy_memory(dst: &mut [u8], src: &[u8]) { - // Bound checks are done at .copy_memory. - unsafe { dst.copy_memory(src) } + fn len(&self) -> uint { + self.repr().len } } -/// Immutable slice iterator -pub struct Items<'a, T> { - ptr: *const T, - end: *const T, - marker: marker::ContravariantLifetime<'a> +impl<'a, T> Default for &'a [T] { + fn default() -> &'a [T] { &[] } } -/// Mutable slice iterator -pub struct MutItems<'a, T> { - ptr: *mut T, - end: *mut T, - marker: marker::ContravariantLifetime<'a>, - marker2: marker::NoCopy -} + + +// +// Iterators +// + +// The shared definition of the `Item` and `MutItems` iterators macro_rules! iterator { (struct $name:ident -> $ptr:ty, $elem:ty) => { impl<'a, T> Iterator<$elem> for $name<'a, T> { @@ -1272,6 +930,21 @@ macro_rules! iterator { } } +/// Immutable slice iterator +pub struct Items<'a, T> { + ptr: *const T, + end: *const T, + marker: marker::ContravariantLifetime<'a> +} + +iterator!{struct Items -> *const T, &'a T} + +impl<'a, T> ExactSize<&'a T> for Items<'a, T> {} + +impl<'a, T> Clone for Items<'a, T> { + fn clone(&self) -> Items<'a, T> { *self } +} + impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { #[inline] fn indexable(&self) -> uint { @@ -1291,16 +964,72 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { } } -iterator!{struct Items -> *const T, &'a T} +/// Mutable slice iterator +pub struct MutItems<'a, T> { + ptr: *mut T, + end: *mut T, + marker: marker::ContravariantLifetime<'a>, + marker2: marker::NoCopy +} + +iterator!{struct MutItems -> *mut T, &'a mut T} -impl<'a, T> ExactSize<&'a T> for Items<'a, T> {} impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {} -impl<'a, T> Clone for Items<'a, T> { - fn clone(&self) -> Items<'a, T> { *self } +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function. +pub struct Splits<'a, T> { + v: &'a [T], + pred: |t: &T|: 'a -> bool, + finished: bool } -iterator!{struct MutItems -> *mut T, &'a mut T} +impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.finished { return None; } + + match self.v.iter().position(|x| (self.pred)(x)) { + None => { + self.finished = true; + Some(self.v) + } + Some(idx) => { + let ret = Some(self.v.slice(0, idx)); + self.v = self.v.slice(idx + 1, self.v.len()); + ret + } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + if self.finished { + (0, Some(0)) + } else { + (1, Some(self.v.len() + 1)) + } + } +} + +impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.finished { return None; } + + match self.v.iter().rposition(|x| (self.pred)(x)) { + None => { + self.finished = true; + Some(self.v) + } + Some(idx) => { + let ret = Some(self.v.slice(idx + 1, self.v.len())); + self.v = self.v.slice(0, idx); + ret + } + } + } +} /// An iterator over the subslices of the vector which are separated /// by elements that match `pred`. @@ -1368,6 +1097,144 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> { } } +/// An iterator over the slices of a vector separated by elements that +/// match a predicate function, splitting at most a fixed number of times. +pub struct SplitsN<'a, T> { + iter: Splits<'a, T>, + count: uint, + invert: bool +} + +impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.count == 0 { + if self.iter.finished { + None + } else { + self.iter.finished = true; + Some(self.iter.v) + } + } else { + self.count -= 1; + if self.invert { self.iter.next_back() } else { self.iter.next() } + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + if self.iter.finished { + (0, Some(0)) + } else { + (1, Some(cmp::min(self.count, self.iter.v.len()) + 1)) + } + } +} + +/// An iterator over the (overlapping) slices of length `size` within +/// a vector. +#[deriving(Clone)] +pub struct Windows<'a, T> { + v: &'a [T], + size: uint +} + +impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.size > self.v.len() { + None + } else { + let ret = Some(self.v.slice(0, self.size)); + self.v = self.v.slice(1, self.v.len()); + ret + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + if self.size > self.v.len() { + (0, Some(0)) + } else { + let x = self.v.len() - self.size; + (x.saturating_add(1), x.checked_add(&1u)) + } + } +} + +/// An iterator over a vector in (non-overlapping) chunks (`size` +/// elements at a time). +/// +/// When the vector len is not evenly divided by the chunk size, +/// the last slice of the iteration will be the remainder. +#[deriving(Clone)] +pub struct Chunks<'a, T> { + v: &'a [T], + size: uint +} + +impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.v.len() == 0 { + None + } else { + let chunksz = cmp::min(self.v.len(), self.size); + let (fst, snd) = (self.v.slice_to(chunksz), + self.v.slice_from(chunksz)); + self.v = snd; + Some(fst) + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + if self.v.len() == 0 { + (0, Some(0)) + } else { + let (n, rem) = div_rem(self.v.len(), self.size); + let n = if rem > 0 { n+1 } else { n }; + (n, Some(n)) + } + } +} + +impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.v.len() == 0 { + None + } else { + let remainder = self.v.len() % self.size; + let chunksz = if remainder != 0 { remainder } else { self.size }; + let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz), + self.v.slice_from(self.v.len() - chunksz)); + self.v = fst; + Some(snd) + } + } +} + +impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> { + #[inline] + fn indexable(&self) -> uint { + self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 } + } + + #[inline] + fn idx(&mut self, index: uint) -> Option<&'a [T]> { + if index < self.indexable() { + let lo = index * self.size; + let mut hi = lo + self.size; + if hi < lo || hi > self.v.len() { hi = self.v.len(); } + + Some(self.v.slice(lo, hi)) + } else { + None + } + } +} + /// An iterator over a vector in (non-overlapping) mutable chunks (`size` elements at a time). When /// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be /// the remainder. @@ -1419,6 +1286,195 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> { } } -impl<'a, T> Default for &'a [T] { - fn default() -> &'a [T] { &[] } + + + +// +// Free functions +// + +/** + * Converts a pointer to A into a slice of length 1 (without copying). + */ +pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { + unsafe { + transmute(Slice { data: s, len: 1 }) + } +} + +/** + * Converts a pointer to A into a slice of length 1 (without copying). + */ +pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { + unsafe { + let ptr: *const A = transmute(s); + transmute(Slice { data: ptr, len: 1 }) + } +} + + + + +// +// Submodules +// + +/// Unsafe operations +pub mod raw { + use mem::transmute; + use ptr::RawPtr; + use raw::Slice; + use option::{None, Option, Some}; + + /** + * Form a slice from a pointer and length (as a number of units, + * not bytes). + */ + #[inline] + pub unsafe fn buf_as_slice<T,U>(p: *const T, len: uint, f: |v: &[T]| -> U) + -> U { + f(transmute(Slice { + data: p, + len: len + })) + } + + /** + * Form a slice from a pointer and length (as a number of units, + * not bytes). + */ + #[inline] + pub unsafe fn mut_buf_as_slice<T, + U>( + p: *mut T, + len: uint, + f: |v: &mut [T]| -> U) + -> U { + f(transmute(Slice { + data: p as *const T, + len: len + })) + } + + /** + * Returns a pointer to first element in slice and adjusts + * slice so it no longer contains that element. Returns None + * if the slice is empty. O(1). + */ + #[inline] + pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> { + if slice.len == 0 { return None; } + let head: *const T = slice.data; + slice.data = slice.data.offset(1); + slice.len -= 1; + Some(head) + } + + /** + * Returns a pointer to last element in slice and adjusts + * slice so it no longer contains that element. Returns None + * if the slice is empty. O(1). + */ + #[inline] + pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> Option<*const T> { + if slice.len == 0 { return None; } + let tail: *const T = slice.data.offset((slice.len - 1) as int); + slice.len -= 1; + Some(tail) + } +} + +/// Operations on `[u8]`. +pub mod bytes { + use collections::Collection; + use ptr; + use slice::MutableVector; + + /// A trait for operations on mutable `[u8]`s. + pub trait MutableByteVector { + /// Sets all bytes of the receiver to the given value. + fn set_memory(self, value: u8); + } + + impl<'a> MutableByteVector for &'a mut [u8] { + #[inline] + #[allow(experimental)] + fn set_memory(self, value: u8) { + unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) }; + } + } + + /// Copies data from `src` to `dst` + /// + /// `src` and `dst` must not overlap. Fails if the length of `dst` + /// is less than the length of `src`. + #[inline] + pub fn copy_memory(dst: &mut [u8], src: &[u8]) { + // Bound checks are done at .copy_memory. + unsafe { dst.copy_memory(src) } + } +} + + + + +// +// Boilerplate traits +// + +#[allow(missing_doc)] +pub mod traits { + use super::*; + + use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Equiv}; + use iter::order; + use collections::Collection; + use option::Option; + + impl<'a,T:PartialEq> PartialEq for &'a [T] { + fn eq(&self, other: & &'a [T]) -> bool { + self.len() == other.len() && + order::eq(self.iter(), other.iter()) + } + fn ne(&self, other: & &'a [T]) -> bool { + self.len() != other.len() || + order::ne(self.iter(), other.iter()) + } + } + + impl<'a,T:Eq> Eq for &'a [T] {} + + impl<'a,T:PartialEq, V: Vector<T>> Equiv<V> for &'a [T] { + #[inline] + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } + } + + impl<'a,T:Ord> Ord for &'a [T] { + fn cmp(&self, other: & &'a [T]) -> Ordering { + order::cmp(self.iter(), other.iter()) + } + } + + impl<'a, T: PartialOrd> PartialOrd for &'a [T] { + #[inline] + fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> { + order::partial_cmp(self.iter(), other.iter()) + } + #[inline] + fn lt(&self, other: & &'a [T]) -> bool { + order::lt(self.iter(), other.iter()) + } + #[inline] + fn le(&self, other: & &'a [T]) -> bool { + order::le(self.iter(), other.iter()) + } + #[inline] + fn ge(&self, other: & &'a [T]) -> bool { + order::ge(self.iter(), other.iter()) + } + #[inline] + fn gt(&self, other: & &'a [T]) -> bool { + order::gt(self.iter(), other.iter()) + } + } } |
