Skip to content

Commit 9b60ecc

Browse files
committed
auto merge of #6908 : bjz/rust/concat-connect, r=Aatch
This adds the following traits to `prelude`: In `std::str`, impled on `&[~[T]]` and `&[&[T]]`: ~~~rust pub trait StrVector { pub fn concat(&self) -> ~str; pub fn connect(&self, sep: &str) -> ~str; } ~~~ In `std::vec`, impled on `&[~str]` and `&[&str]`: ~~~rust pub trait VectorVector<T> { pub fn concat(&self) -> ~[T]; pub fn connect(&self, sep: &T) -> ~[T]; } ~~~
2 parents c40baf6 + dee7c5a commit 9b60ecc

File tree

3 files changed

+204
-90
lines changed

3 files changed

+204
-90
lines changed

src/libstd/prelude.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub use path::PosixPath;
4545
pub use path::WindowsPath;
4646
pub use ptr::Ptr;
4747
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
48-
pub use str::{StrSlice, OwnedStr, StrUtil};
48+
pub use str::{StrVector, StrSlice, OwnedStr, StrUtil};
4949
pub use from_str::{FromStr};
5050
pub use to_bytes::IterBytes;
5151
pub use to_str::{ToStr, ToStrConsume};
@@ -56,7 +56,7 @@ pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12};
5656
pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5};
5757
pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9};
5858
pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12};
59-
pub use vec::{CopyableVector, ImmutableVector};
59+
pub use vec::{VectorVector, CopyableVector, ImmutableVector};
6060
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
6161
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
6262
pub use io::{Reader, ReaderUtil, Writer, WriterUtil};

src/libstd/str.rs

+141-71
Original file line numberDiff line numberDiff line change
@@ -241,110 +241,165 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str {
241241
}
242242

243243
/// Concatenate a vector of strings
244-
pub fn concat(v: &[~str]) -> ~str {
245-
if v.is_empty() { return ~""; }
244+
pub fn concat(v: &[~str]) -> ~str { v.concat() }
246245

247-
let mut len = 0;
248-
for v.each |ss| {
249-
len += ss.len();
250-
}
251-
let mut s = ~"";
252-
253-
reserve(&mut s, len);
246+
/// Concatenate a vector of strings
247+
pub fn concat_slices(v: &[&str]) -> ~str { v.concat() }
254248

255-
unsafe {
256-
do as_buf(s) |buf, _len| {
257-
let mut buf = ::cast::transmute_mut_unsafe(buf);
258-
for v.each |ss| {
259-
do as_buf(*ss) |ssbuf, sslen| {
260-
let sslen = sslen - 1;
261-
ptr::copy_memory(buf, ssbuf, sslen);
262-
buf = buf.offset(sslen);
263-
}
264-
}
265-
}
266-
raw::set_len(&mut s, len);
267-
}
268-
s
269-
}
249+
/// Concatenate a vector of strings, placing a given separator between each
250+
pub fn connect(v: &[~str], sep: &str) -> ~str { v.connect(sep) }
270251

271252
/// Concatenate a vector of strings, placing a given separator between each
272-
pub fn connect(v: &[~str], sep: &str) -> ~str {
273-
if v.is_empty() { return ~""; }
253+
pub fn connect_slices(v: &[&str], sep: &str) -> ~str { v.connect(sep) }
274254

275-
// concat is faster
276-
if sep.is_empty() { return concat(v); }
255+
#[allow(missing_doc)]
256+
pub trait StrVector {
257+
pub fn concat(&self) -> ~str;
258+
pub fn connect(&self, sep: &str) -> ~str;
259+
}
277260

278-
// this is wrong without the guarantee that v is non-empty
279-
let mut len = sep.len() * (v.len() - 1);
280-
for v.each |ss| {
281-
len += ss.len();
282-
}
283-
let mut s = ~"", first = true;
261+
impl<'self> StrVector for &'self [~str] {
262+
/// Concatenate a vector of strings.
263+
pub fn concat(&self) -> ~str {
264+
if self.is_empty() { return ~""; }
265+
266+
let mut len = 0;
267+
for self.each |ss| {
268+
len += ss.len();
269+
}
270+
let mut s = ~"";
284271

285-
reserve(&mut s, len);
272+
reserve(&mut s, len);
286273

287-
unsafe {
288-
do as_buf(s) |buf, _len| {
289-
do as_buf(sep) |sepbuf, seplen| {
290-
let seplen = seplen - 1;
274+
unsafe {
275+
do as_buf(s) |buf, _| {
291276
let mut buf = ::cast::transmute_mut_unsafe(buf);
292-
for v.each |ss| {
277+
for self.each |ss| {
293278
do as_buf(*ss) |ssbuf, sslen| {
294279
let sslen = sslen - 1;
295-
if first {
296-
first = false;
297-
} else {
298-
ptr::copy_memory(buf, sepbuf, seplen);
299-
buf = buf.offset(seplen);
300-
}
301280
ptr::copy_memory(buf, ssbuf, sslen);
302281
buf = buf.offset(sslen);
303282
}
304283
}
305284
}
285+
raw::set_len(&mut s, len);
306286
}
307-
raw::set_len(&mut s, len);
287+
s
308288
}
309-
s
310-
}
311289

312-
/// Concatenate a vector of strings, placing a given separator between each
313-
pub fn connect_slices(v: &[&str], sep: &str) -> ~str {
314-
if v.is_empty() { return ~""; }
290+
/// Concatenate a vector of strings, placing a given separator between each.
291+
pub fn connect(&self, sep: &str) -> ~str {
292+
if self.is_empty() { return ~""; }
293+
294+
// concat is faster
295+
if sep.is_empty() { return self.concat(); }
315296

316-
// this is wrong without the guarantee that v is non-empty
317-
let mut len = sep.len() * (v.len() - 1);
318-
for v.each |ss| {
319-
len += ss.len();
297+
// this is wrong without the guarantee that `self` is non-empty
298+
let mut len = sep.len() * (self.len() - 1);
299+
for self.each |ss| {
300+
len += ss.len();
301+
}
302+
let mut s = ~"";
303+
let mut first = true;
304+
305+
reserve(&mut s, len);
306+
307+
unsafe {
308+
do as_buf(s) |buf, _| {
309+
do as_buf(sep) |sepbuf, seplen| {
310+
let seplen = seplen - 1;
311+
let mut buf = ::cast::transmute_mut_unsafe(buf);
312+
for self.each |ss| {
313+
do as_buf(*ss) |ssbuf, sslen| {
314+
let sslen = sslen - 1;
315+
if first {
316+
first = false;
317+
} else {
318+
ptr::copy_memory(buf, sepbuf, seplen);
319+
buf = buf.offset(seplen);
320+
}
321+
ptr::copy_memory(buf, ssbuf, sslen);
322+
buf = buf.offset(sslen);
323+
}
324+
}
325+
}
326+
}
327+
raw::set_len(&mut s, len);
328+
}
329+
s
320330
}
321-
let mut s = ~"", first = true;
331+
}
322332

323-
reserve(&mut s, len);
333+
impl<'self> StrVector for &'self [&'self str] {
334+
/// Concatenate a vector of strings.
335+
pub fn concat(&self) -> ~str {
336+
if self.is_empty() { return ~""; }
324337

325-
unsafe {
326-
do as_buf(s) |buf, _len| {
327-
do as_buf(sep) |sepbuf, seplen| {
328-
let seplen = seplen - 1;
338+
let mut len = 0;
339+
for self.each |ss| {
340+
len += ss.len();
341+
}
342+
let mut s = ~"";
343+
344+
reserve(&mut s, len);
345+
346+
unsafe {
347+
do as_buf(s) |buf, _| {
329348
let mut buf = ::cast::transmute_mut_unsafe(buf);
330-
for v.each |ss| {
349+
for self.each |ss| {
331350
do as_buf(*ss) |ssbuf, sslen| {
332351
let sslen = sslen - 1;
333-
if first {
334-
first = false;
335-
} else if seplen > 0 {
336-
ptr::copy_memory(buf, sepbuf, seplen);
337-
buf = buf.offset(seplen);
338-
}
339352
ptr::copy_memory(buf, ssbuf, sslen);
340353
buf = buf.offset(sslen);
341354
}
342355
}
343356
}
357+
raw::set_len(&mut s, len);
344358
}
345-
raw::set_len(&mut s, len);
359+
s
360+
}
361+
362+
/// Concatenate a vector of strings, placing a given separator between each.
363+
pub fn connect(&self, sep: &str) -> ~str {
364+
if self.is_empty() { return ~""; }
365+
366+
// concat is faster
367+
if sep.is_empty() { return self.concat(); }
368+
369+
// this is wrong without the guarantee that `self` is non-empty
370+
let mut len = sep.len() * (self.len() - 1);
371+
for self.each |ss| {
372+
len += ss.len();
373+
}
374+
let mut s = ~"";
375+
let mut first = true;
376+
377+
reserve(&mut s, len);
378+
379+
unsafe {
380+
do as_buf(s) |buf, _| {
381+
do as_buf(sep) |sepbuf, seplen| {
382+
let seplen = seplen - 1;
383+
let mut buf = ::cast::transmute_mut_unsafe(buf);
384+
for self.each |ss| {
385+
do as_buf(*ss) |ssbuf, sslen| {
386+
let sslen = sslen - 1;
387+
if first {
388+
first = false;
389+
} else {
390+
ptr::copy_memory(buf, sepbuf, seplen);
391+
buf = buf.offset(seplen);
392+
}
393+
ptr::copy_memory(buf, ssbuf, sslen);
394+
buf = buf.offset(sslen);
395+
}
396+
}
397+
}
398+
}
399+
raw::set_len(&mut s, len);
400+
}
401+
s
346402
}
347-
s
348403
}
349404

350405
/// Given a string, make a new string with repeated copies of it
@@ -3184,6 +3239,7 @@ mod tests {
31843239
fn test_concat() {
31853240
fn t(v: &[~str], s: &str) {
31863241
assert_eq!(concat(v), s.to_str());
3242+
assert_eq!(v.concat(), s.to_str());
31873243
}
31883244
t([~"you", ~"know", ~"I'm", ~"no", ~"good"], "youknowI'mnogood");
31893245
let v: &[~str] = [];
@@ -3195,6 +3251,7 @@ mod tests {
31953251
fn test_connect() {
31963252
fn t(v: &[~str], sep: &str, s: &str) {
31973253
assert_eq!(connect(v, sep), s.to_str());
3254+
assert_eq!(v.connect(sep), s.to_str());
31983255
}
31993256
t([~"you", ~"know", ~"I'm", ~"no", ~"good"],
32003257
" ", "you know I'm no good");
@@ -3203,10 +3260,23 @@ mod tests {
32033260
t([~"hi"], " ", "hi");
32043261
}
32053262
3263+
#[test]
3264+
fn test_concat_slices() {
3265+
fn t(v: &[&str], s: &str) {
3266+
assert_eq!(concat_slices(v), s.to_str());
3267+
assert_eq!(v.concat(), s.to_str());
3268+
}
3269+
t(["you", "know", "I'm", "no", "good"], "youknowI'mnogood");
3270+
let v: &[&str] = [];
3271+
t(v, "");
3272+
t(["hi"], "hi");
3273+
}
3274+
32063275
#[test]
32073276
fn test_connect_slices() {
32083277
fn t(v: &[&str], sep: &str, s: &str) {
32093278
assert_eq!(connect_slices(v, sep), s.to_str());
3279+
assert_eq!(v.connect(sep), s.to_str());
32103280
}
32113281
t(["you", "know", "I'm", "no", "good"],
32123282
" ", "you know I'm no good");

src/libstd/vec.rs

+61-17
Original file line numberDiff line numberDiff line change
@@ -1011,26 +1011,58 @@ pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) {
10111011
}
10121012
}
10131013

1014-
/**
1015-
* Concatenate a vector of vectors.
1016-
*
1017-
* Flattens a vector of vectors of T into a single vector of T.
1018-
*/
1019-
pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] {
1020-
let mut r = ~[];
1021-
for each(v) |inner| { r.push_all(*inner); }
1022-
r
1023-
}
1014+
/// Flattens a vector of vectors of T into a single vector of T.
1015+
pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] { v.concat() }
1016+
1017+
/// Concatenate a vector of vectors, placing a given separator between each
1018+
pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] { v.connect(sep) }
1019+
1020+
/// Flattens a vector of vectors of T into a single vector of T.
1021+
pub fn concat_slices<T:Copy>(v: &[&[T]]) -> ~[T] { v.concat() }
10241022

10251023
/// Concatenate a vector of vectors, placing a given separator between each
1026-
pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] {
1027-
let mut r: ~[T] = ~[];
1028-
let mut first = true;
1029-
for each(v) |inner| {
1030-
if first { first = false; } else { r.push(*sep); }
1031-
r.push_all(*inner);
1024+
pub fn connect_slices<T:Copy>(v: &[&[T]], sep: &T) -> ~[T] { v.connect(sep) }
1025+
1026+
#[allow(missing_doc)]
1027+
pub trait VectorVector<T> {
1028+
pub fn concat(&self) -> ~[T];
1029+
pub fn connect(&self, sep: &T) -> ~[T];
1030+
}
1031+
1032+
impl<'self, T:Copy> VectorVector<T> for &'self [~[T]] {
1033+
/// Flattens a vector of slices of T into a single vector of T.
1034+
pub fn concat(&self) -> ~[T] {
1035+
self.flat_map(|&inner| inner)
1036+
}
1037+
1038+
/// Concatenate a vector of vectors, placing a given separator between each.
1039+
pub fn connect(&self, sep: &T) -> ~[T] {
1040+
let mut r = ~[];
1041+
let mut first = true;
1042+
for self.each |&inner| {
1043+
if first { first = false; } else { r.push(*sep); }
1044+
r.push_all(inner);
1045+
}
1046+
r
1047+
}
1048+
}
1049+
1050+
impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] {
1051+
/// Flattens a vector of slices of T into a single vector of T.
1052+
pub fn concat(&self) -> ~[T] {
1053+
self.flat_map(|&inner| inner.to_owned())
1054+
}
1055+
1056+
/// Concatenate a vector of slices, placing a given separator between each.
1057+
pub fn connect(&self, sep: &T) -> ~[T] {
1058+
let mut r = ~[];
1059+
let mut first = true;
1060+
for self.each |&inner| {
1061+
if first { first = false; } else { r.push(*sep); }
1062+
r.push_all(inner);
1063+
}
1064+
r
10321065
}
1033-
r
10341066
}
10351067

10361068
/**
@@ -3941,13 +3973,25 @@ mod tests {
39413973
#[test]
39423974
fn test_concat() {
39433975
assert_eq!(concat([~[1], ~[2,3]]), ~[1, 2, 3]);
3976+
assert_eq!([~[1], ~[2,3]].concat(), ~[1, 2, 3]);
3977+
3978+
assert_eq!(concat_slices([&[1], &[2,3]]), ~[1, 2, 3]);
3979+
assert_eq!([&[1], &[2,3]].concat(), ~[1, 2, 3]);
39443980
}
39453981

39463982
#[test]
39473983
fn test_connect() {
39483984
assert_eq!(connect([], &0), ~[]);
39493985
assert_eq!(connect([~[1], ~[2, 3]], &0), ~[1, 0, 2, 3]);
39503986
assert_eq!(connect([~[1], ~[2], ~[3]], &0), ~[1, 0, 2, 0, 3]);
3987+
assert_eq!([~[1], ~[2, 3]].connect(&0), ~[1, 0, 2, 3]);
3988+
assert_eq!([~[1], ~[2], ~[3]].connect(&0), ~[1, 0, 2, 0, 3]);
3989+
3990+
assert_eq!(connect_slices([], &0), ~[]);
3991+
assert_eq!(connect_slices([&[1], &[2, 3]], &0), ~[1, 0, 2, 3]);
3992+
assert_eq!(connect_slices([&[1], &[2], &[3]], &0), ~[1, 0, 2, 0, 3]);
3993+
assert_eq!([&[1], &[2, 3]].connect(&0), ~[1, 0, 2, 3]);
3994+
assert_eq!([&[1], &[2], &[3]].connect(&0), ~[1, 0, 2, 0, 3]);
39513995
}
39523996

39533997
#[test]

0 commit comments

Comments
 (0)