about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-08 08:27:10 +0000
committerbors <bors@rust-lang.org>2014-10-08 08:27:10 +0000
commitbc649ba8f803913a23c767d57be01c693cd03d8a (patch)
treeebe322af4897bcc8e99a243435af8aec48f367bd /src
parent57af34b9ad2a4a5a8932ccb06d022d5f8c5807bc (diff)
parentf744479562aa69a8c8cd95900b548fea250236a4 (diff)
downloadrust-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.rs28
-rw-r--r--src/libcollections/vec.rs76
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 {