diff options
| author | bors <bors@rust-lang.org> | 2014-10-08 08:27:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-10-08 08:27:10 +0000 |
| commit | bc649ba8f803913a23c767d57be01c693cd03d8a (patch) | |
| tree | ebe322af4897bcc8e99a243435af8aec48f367bd /src | |
| parent | 57af34b9ad2a4a5a8932ccb06d022d5f8c5807bc (diff) | |
| parent | f744479562aa69a8c8cd95900b548fea250236a4 (diff) | |
| download | rust-bc649ba8f803913a23c767d57be01c693cd03d8a.tar.gz rust-bc649ba8f803913a23c767d57be01c693cd03d8a.zip | |
auto merge of #17447 : thestinger/rust/silly_string, r=aturon
This provides a way to pass `&[T]` to functions taking `&U` where `U` is a `Vec<T>`. This is useful in many cases not covered by the Equiv trait or methods like `find_with` on TreeMap.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcollections/string.rs | 28 | ||||
| -rw-r--r-- | src/libcollections/vec.rs | 76 |
2 files changed, 89 insertions, 15 deletions
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 0a460b64210..900cf9dfb44 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -28,7 +28,7 @@ use slice::CloneableVector; use str; use str::{CharRange, StrAllocating, MaybeOwned, Owned}; use str::Slice as MaybeOwnedSlice; // So many `Slice`s... -use vec::Vec; +use vec::{DerefVec, Vec, as_vec}; /// A growable string stored as a UTF-8 encoded buffer. #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)] @@ -973,6 +973,24 @@ impl ops::Slice<uint, str> for String { } } +/// Wrapper type providing a `&String` reference via `Deref`. +#[experimental] +pub struct DerefString<'a> { + x: DerefVec<'a, u8> +} + +impl<'a> Deref<String> for DerefString<'a> { + fn deref<'b>(&'b self) -> &'b String { + unsafe { mem::transmute(&*self.x) } + } +} + +/// Convert a string slice to a wrapper type providing a `&String` reference. +#[experimental] +pub fn as_string<'a>(x: &'a str) -> DerefString<'a> { + DerefString { x: as_vec(x.as_bytes()) } +} + /// Unsafe operations #[unstable = "waiting on raw module conventions"] pub mod raw { @@ -1039,10 +1057,16 @@ mod tests { use {Mutable, MutableSeq}; use str; use str::{Str, StrSlice, Owned}; - use super::String; + use super::{as_string, String}; use vec::Vec; #[test] + fn test_as_string() { + let x = "foo"; + assert_eq!(x, as_string(x).as_slice()); + } + + #[test] fn test_from_str() { let owned: Option<::std::string::String> = from_str("string"); assert_eq!(owned.as_ref().map(|s| s.as_slice()), Some("string")); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index da88b5efa61..857ffbcf4be 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -18,7 +18,7 @@ use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::cmp::max; use core::default::Default; use core::fmt; -use core::kinds::marker::InvariantType; +use core::kinds::marker::{ContravariantLifetime, InvariantType}; use core::mem; use core::num; use core::ops; @@ -1875,6 +1875,39 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) { (ts, us) } +/// Wrapper type providing a `&Vec<T>` reference via `Deref`. +#[experimental] +pub struct DerefVec<'a, T> { + x: Vec<T>, + l: ContravariantLifetime<'a> +} + +impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> { + fn deref<'b>(&'b self) -> &'b Vec<T> { + &self.x + } +} + +// Prevent the inner `Vec<T>` from attempting to deallocate memory. +#[unsafe_destructor] +impl<'a, T> Drop for DerefVec<'a, T> { + fn drop(&mut self) { + self.x.len = 0; + self.x.cap = 0; + } +} + +/// Convert a slice to a wrapper type providing a `&Vec<T>` reference. +#[experimental] +pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> { + unsafe { + DerefVec { + x: Vec::from_raw_parts(x.len(), x.len(), x.as_ptr() as *mut T), + l: ContravariantLifetime::<'a> + } + } +} + /// Unsafe vector operations. #[unstable] pub mod raw { @@ -2169,10 +2202,38 @@ mod tests { use std::prelude::*; use std::mem::size_of; use test::Bencher; - use super::{unzip, raw, Vec}; + use super::{as_vec, unzip, raw, Vec}; use MutableSeq; + struct DropCounter<'a> { + count: &'a mut int + } + + #[unsafe_destructor] + impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + *self.count += 1; + } + } + + #[test] + fn test_as_vec() { + let xs = [1u8, 2u8, 3u8]; + assert_eq!(as_vec(xs).as_slice(), xs.as_slice()); + } + + #[test] + fn test_as_vec_dtor() { + let (mut count_x, mut count_y) = (0, 0); + { + let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; + assert_eq!(as_vec(xs).len(), 2); + } + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); + } + #[test] fn test_small_vec_struct() { assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3); @@ -2185,17 +2246,6 @@ mod tests { y: Vec<T> } - struct DropCounter<'a> { - count: &'a mut int - } - - #[unsafe_destructor] - impl<'a> Drop for DropCounter<'a> { - fn drop(&mut self) { - *self.count += 1; - } - } - let (mut count_x, mut count_y) = (0, 0); { let mut tv = TwoVec { |
