Skip to content

Commit bc649ba

Browse files
committed
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.
2 parents 57af34b + f744479 commit bc649ba

File tree

2 files changed

+89
-15
lines changed

2 files changed

+89
-15
lines changed

src/libcollections/string.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use slice::CloneableVector;
2828
use str;
2929
use str::{CharRange, StrAllocating, MaybeOwned, Owned};
3030
use str::Slice as MaybeOwnedSlice; // So many `Slice`s...
31-
use vec::Vec;
31+
use vec::{DerefVec, Vec, as_vec};
3232

3333
/// A growable string stored as a UTF-8 encoded buffer.
3434
#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)]
@@ -973,6 +973,24 @@ impl ops::Slice<uint, str> for String {
973973
}
974974
}
975975

976+
/// Wrapper type providing a `&String` reference via `Deref`.
977+
#[experimental]
978+
pub struct DerefString<'a> {
979+
x: DerefVec<'a, u8>
980+
}
981+
982+
impl<'a> Deref<String> for DerefString<'a> {
983+
fn deref<'b>(&'b self) -> &'b String {
984+
unsafe { mem::transmute(&*self.x) }
985+
}
986+
}
987+
988+
/// Convert a string slice to a wrapper type providing a `&String` reference.
989+
#[experimental]
990+
pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
991+
DerefString { x: as_vec(x.as_bytes()) }
992+
}
993+
976994
/// Unsafe operations
977995
#[unstable = "waiting on raw module conventions"]
978996
pub mod raw {
@@ -1039,9 +1057,15 @@ mod tests {
10391057
use {Mutable, MutableSeq};
10401058
use str;
10411059
use str::{Str, StrSlice, Owned};
1042-
use super::String;
1060+
use super::{as_string, String};
10431061
use vec::Vec;
10441062

1063+
#[test]
1064+
fn test_as_string() {
1065+
let x = "foo";
1066+
assert_eq!(x, as_string(x).as_slice());
1067+
}
1068+
10451069
#[test]
10461070
fn test_from_str() {
10471071
let owned: Option<::std::string::String> = from_str("string");

src/libcollections/vec.rs

+63-13
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
1818
use core::cmp::max;
1919
use core::default::Default;
2020
use core::fmt;
21-
use core::kinds::marker::InvariantType;
21+
use core::kinds::marker::{ContravariantLifetime, InvariantType};
2222
use core::mem;
2323
use core::num;
2424
use core::ops;
@@ -1875,6 +1875,39 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
18751875
(ts, us)
18761876
}
18771877

1878+
/// Wrapper type providing a `&Vec<T>` reference via `Deref`.
1879+
#[experimental]
1880+
pub struct DerefVec<'a, T> {
1881+
x: Vec<T>,
1882+
l: ContravariantLifetime<'a>
1883+
}
1884+
1885+
impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> {
1886+
fn deref<'b>(&'b self) -> &'b Vec<T> {
1887+
&self.x
1888+
}
1889+
}
1890+
1891+
// Prevent the inner `Vec<T>` from attempting to deallocate memory.
1892+
#[unsafe_destructor]
1893+
impl<'a, T> Drop for DerefVec<'a, T> {
1894+
fn drop(&mut self) {
1895+
self.x.len = 0;
1896+
self.x.cap = 0;
1897+
}
1898+
}
1899+
1900+
/// Convert a slice to a wrapper type providing a `&Vec<T>` reference.
1901+
#[experimental]
1902+
pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
1903+
unsafe {
1904+
DerefVec {
1905+
x: Vec::from_raw_parts(x.len(), x.len(), x.as_ptr() as *mut T),
1906+
l: ContravariantLifetime::<'a>
1907+
}
1908+
}
1909+
}
1910+
18781911
/// Unsafe vector operations.
18791912
#[unstable]
18801913
pub mod raw {
@@ -2169,10 +2202,38 @@ mod tests {
21692202
use std::prelude::*;
21702203
use std::mem::size_of;
21712204
use test::Bencher;
2172-
use super::{unzip, raw, Vec};
2205+
use super::{as_vec, unzip, raw, Vec};
21732206

21742207
use MutableSeq;
21752208

2209+
struct DropCounter<'a> {
2210+
count: &'a mut int
2211+
}
2212+
2213+
#[unsafe_destructor]
2214+
impl<'a> Drop for DropCounter<'a> {
2215+
fn drop(&mut self) {
2216+
*self.count += 1;
2217+
}
2218+
}
2219+
2220+
#[test]
2221+
fn test_as_vec() {
2222+
let xs = [1u8, 2u8, 3u8];
2223+
assert_eq!(as_vec(xs).as_slice(), xs.as_slice());
2224+
}
2225+
2226+
#[test]
2227+
fn test_as_vec_dtor() {
2228+
let (mut count_x, mut count_y) = (0, 0);
2229+
{
2230+
let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }];
2231+
assert_eq!(as_vec(xs).len(), 2);
2232+
}
2233+
assert_eq!(count_x, 1);
2234+
assert_eq!(count_y, 1);
2235+
}
2236+
21762237
#[test]
21772238
fn test_small_vec_struct() {
21782239
assert!(size_of::<Vec<u8>>() == size_of::<uint>() * 3);
@@ -2185,17 +2246,6 @@ mod tests {
21852246
y: Vec<T>
21862247
}
21872248

2188-
struct DropCounter<'a> {
2189-
count: &'a mut int
2190-
}
2191-
2192-
#[unsafe_destructor]
2193-
impl<'a> Drop for DropCounter<'a> {
2194-
fn drop(&mut self) {
2195-
*self.count += 1;
2196-
}
2197-
}
2198-
21992249
let (mut count_x, mut count_y) = (0, 0);
22002250
{
22012251
let mut tv = TwoVec {

0 commit comments

Comments
 (0)