Skip to content

Commit 41029c9

Browse files
committed
Implement a StringRef
This is the string equivalent of VecRef. I had some trouble with lifetimes trying to implement StrSlice, so I've left it for now, iterating on strings isn't as common and the .as_slice() method merely means you need to add an extra method call.
1 parent 38e25ea commit 41029c9

File tree

2 files changed

+122
-21
lines changed

2 files changed

+122
-21
lines changed

src/libstd/str.rs

+88-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use ptr::RawPtr;
3434
use to_str::ToStr;
3535
use uint;
3636
use vec;
37-
use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector};
37+
use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, Vector};
3838

3939
/*
4040
Section: Conditions
@@ -2238,6 +2238,82 @@ impl OwnedStr for ~str {
22382238
}
22392239
}
22402240
2241+
/**
2242+
* A StringRef is a string that can hold either a ~str or a &'static str.
2243+
* This can be useful as an optimization when an allocation is sometimes
2244+
* needed but the common case is statically known.
2245+
*/
2246+
#[deriving(Eq,Ord,Clone)]
2247+
pub struct StringRef {
2248+
priv r: ::vec::VecRef<u8>
2249+
}
2250+
2251+
impl StringRef {
2252+
2253+
/**
2254+
* Constructs a StringRef from an owned string
2255+
*/
2256+
#[inline]
2257+
pub fn from_owned(s: ~str) -> StringRef {
2258+
StringRef {
2259+
r: ::vec::VecRef::from_owned(s.as_bytes_with_null_consume())
2260+
}
2261+
}
2262+
2263+
/**
2264+
* Constructs a StringRef from a static string
2265+
*/
2266+
#[inline]
2267+
pub fn from_static(s: &'static str) -> StringRef {
2268+
unsafe {
2269+
StringRef {
2270+
r: ::vec::VecRef::from_static(::cast::transmute(s))
2271+
}
2272+
}
2273+
}
2274+
2275+
/**
2276+
* Converts this type into a standard owned string, consuming it in the process.
2277+
*
2278+
* If the StringRef holds a static string, it is copied to an owned one, otherwise the held
2279+
* owned vector is returned
2280+
*/
2281+
#[inline]
2282+
pub fn to_owned_consume(self) -> ~str {
2283+
unsafe {
2284+
::cast::transmute(self.r.to_owned_consume())
2285+
}
2286+
}
2287+
2288+
/**
2289+
* Returns the backing VecRef for this StringRef
2290+
*/
2291+
#[inline]
2292+
pub fn as_vec_ref<'r>(&'r self) -> &'r vec::VecRef<u8> {
2293+
&self.r
2294+
}
2295+
}
2296+
2297+
impl Str for StringRef {
2298+
#[inline(always)]
2299+
pub fn as_slice<'r>(&'r self) -> &'r str {
2300+
unsafe {
2301+
::cast::transmute(self.r.as_slice())
2302+
}
2303+
}
2304+
}
2305+
2306+
impl Container for StringRef {
2307+
#[inline]
2308+
fn len(&self) -> uint {
2309+
self.as_slice().len()
2310+
}
2311+
#[inline]
2312+
fn is_empty(&self) -> bool {
2313+
self.len() == 0
2314+
}
2315+
}
2316+
22412317
impl Clone for ~str {
22422318
#[inline]
22432319
fn clone(&self) -> ~str {
@@ -3448,4 +3524,15 @@ mod tests {
34483524
t::<@str>();
34493525
t::<~str>();
34503526
}
3527+
3528+
#[test]
3529+
fn test_str_ref() {
3530+
let r = StringRef::from_static("abcde");
3531+
assert_eq!(r.len(), 5);
3532+
assert_eq!(r.as_slice(), "abcde")
3533+
3534+
let r = StringRef::from_owned(~"abcde");
3535+
assert_eq!(r.len(), 5);
3536+
assert_eq!(r.as_slice(), "abcde")
3537+
}
34513538
}

src/libstd/vec.rs

+34-20
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use cast;
1717
use container::{Container, Mutable};
1818
use cmp;
1919
use cmp::{Eq, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
20+
use ops::Index;
2021
use clone::Clone;
2122
use iterator::{FromIterator, Iterator, IteratorUtil};
2223
use kinds::Copy;
@@ -1758,47 +1759,47 @@ impl<T> VecRef<T> {
17581759
// on self-by-value, which means VecRef would move into
17591760
// it. So I'm just gonna re-impl here
17601761

1761-
#[inline]
1762+
#[inline] #[allow(missing_doc)]
17621763
pub fn iter<'r>(&'r self) -> VecIterator<'r, T> {
17631764
self.as_slice().iter()
17641765
}
17651766

1766-
#[inline]
1767+
#[inline] #[allow(missing_doc)]
17671768
pub fn rev_iter<'r>(&'r self) -> VecRevIterator<'r, T> {
17681769
self.as_slice().rev_iter()
17691770
}
17701771

1771-
#[inline]
1772+
#[inline] #[allow(missing_doc)]
17721773
pub fn split_iter<'r>(&'r self, pred: &'r fn(&T) -> bool) -> VecSplitIterator<'r, T> {
17731774
self.as_slice().split_iter(pred)
17741775
}
17751776

1776-
#[inline]
1777+
#[inline] #[allow(missing_doc)]
17771778
pub fn splitn_iter<'r>(&'r self, n: uint, pred: &'r fn(&T) -> bool) -> VecSplitIterator<'r, T> {
1778-
self.as_slice().split_iter(n, pred)
1779+
self.as_slice().splitn_iter(n, pred)
17791780
}
17801781

1781-
#[inline]
1782+
#[inline] #[allow(missing_doc)]
17821783
pub fn rsplit_iter<'r>(&'r self, pred: &'r fn(&T) -> bool) -> VecRSplitIterator<'r, T> {
17831784
self.as_slice().rsplit_iter(pred)
17841785
}
17851786

1786-
#[inline]
1787-
pub fn rsplitn_iter<'r>(&'r self, pred: &'r fn(&T) -> bool) -> VecRSplitIterator<'r, T> {
1788-
self.as_slice().rsplit_iter(pred)
1787+
#[inline] #[allow(missing_doc)]
1788+
pub fn rsplitn_iter<'r>(&'r self, n: uint, pred: &'r fn(&T) -> bool) -> VecRSplitIterator<'r, T> {
1789+
self.as_slice().rsplitn_iter(n, pred)
17891790
}
17901791

1791-
#[inline]
1792+
#[inline] #[allow(missing_doc)]
17921793
pub fn window_iter<'r>(&'r self, size: uint) -> VecWindowIter<'r, T> {
17931794
self.as_slice().window_iter(size)
17941795
}
17951796

1796-
#[inline]
1797+
#[inline] #[allow(missing_doc)]
17971798
pub fn chunk_iter<'r>(&'r self, size: uint) -> VecChunkIter<'r, T> {
1798-
self.as_slice().window_iter(size)
1799+
self.as_slice().chunk_iter(size)
17991800
}
18001801

1801-
#[inline]
1802+
#[inline] #[allow(missing_doc)]
18021803
pub fn as_imm_buf<U>(&self, f: &fn(*T, uint) -> U) -> U {
18031804
self.as_slice().as_imm_buf(f)
18041805
}
@@ -1809,7 +1810,7 @@ impl<T:Copy> VecRef<T> {
18091810
/**
18101811
* Converts this type into a standard owned vector, consuming it in the process.
18111812
*
1812-
* If the VecRef holds a static vector, it is converted to an owned one, otherwise the held
1813+
* If the VecRef holds a static vector, it is copied to an owned one, otherwise the held
18131814
* owned vector is returned.
18141815
*/
18151816
pub fn to_owned_consume(self) -> ~[T] {
@@ -1858,7 +1859,7 @@ impl<T:Eq> ImmutableEqVector<T> for VecRef<T> {
18581859

18591860
#[inline]
18601861
fn rposition_elem(&self, t: &T) -> Option<uint> {
1861-
self.as_slice().rposition(t)
1862+
self.as_slice().rposition_elem(t)
18621863
}
18631864

18641865
#[inline]
@@ -1887,8 +1888,8 @@ impl<T:Copy> ImmutableCopyableVector<T> for VecRef<T> {
18871888
}
18881889

18891890
impl<T:Copy> Index<uint, T> for VecRef<T> {
1890-
fn index(&self, index: uint) -> T {
1891-
copy self.as_slice()[index]
1891+
fn index(&self, index: &uint) -> T {
1892+
copy self.as_slice()[*index]
18921893
}
18931894
}
18941895

@@ -3443,10 +3444,10 @@ mod tests {
34433444
let v = VecRef::from_owned(~[1, 2, 3]);
34443445
assert_eq!(v.len(), 3);
34453446

3446-
let v : VecRef<int> = VecRef::from_static([]);
3447+
let v : VecRef<int> = VecRef::from_static(&[]);
34473448
assert!(v.is_empty());
34483449

3449-
let v : VecRef<int> = VecRef::from_static([1, 2, 3, 4]);
3450+
let v : VecRef<int> = VecRef::from_static(&[1, 2, 3, 4]);
34503451
assert_eq!(v.len(), 4);
34513452
}
34523453

@@ -3456,8 +3457,21 @@ mod tests {
34563457
let vec = v.to_owned_consume();
34573458
assert_eq!(vec, ~[1, 2, 3, 4]);
34583459

3459-
let v = VecRef::from_static([1, 2, 3, 4]);
3460+
let v = VecRef::from_static(&[1, 2, 3, 4]);
34603461
let vec = v.to_owned_consume();
34613462
assert_eq!(vec, ~[1, 2, 3, 4]);
34623463
}
3464+
3465+
#[test]
3466+
fn test_vec_iter() {
3467+
let v = VecRef::from_static(&[1, 2, 3, 4]);
3468+
3469+
let mut iter = v.iter().transform(|&x| x);
3470+
3471+
assert_eq!(iter.next(), Some(1));
3472+
assert_eq!(iter.next(), Some(2));
3473+
assert_eq!(iter.next(), Some(3));
3474+
assert_eq!(iter.next(), Some(4));
3475+
assert_eq!(iter.next(), None);
3476+
}
34633477
}

0 commit comments

Comments
 (0)