Skip to content

Commit f92b75a

Browse files
committed
auto merge of #7707 : thestinger/rust/double, r=cmr
00da76d r=cmr 6e75f2d r=cmr This implements the trait for vector iterators, replacing the reverse iterator types. The methods will stay, for implementing the future reverse Iterable traits and convenience. This can also be trivially implemented for circular buffers and other variants of arrays like strings. The `DoubleEndedIterator` trait will allow for implementing algorithms like in-place reverse on generic mutable iterators. The naming (`Range` vs. `Iterator`, `Bidirectional` vs. `DoubleEnded`) can be bikeshedded in the future.
2 parents 9fce8c9 + 6e75f2d commit f92b75a

File tree

5 files changed

+119
-63
lines changed

5 files changed

+119
-63
lines changed

src/etc/vim/ftplugin/rust.vim

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
" Vim syntax file
22
" Language: Rust
33
" Maintainer: Chris Morgan <[email protected]>
4-
" Last Change: 2013 Jul 6
4+
" Last Change: 2013 Jul 10
55

66
if exists("b:did_ftplugin")
77
finish
88
endif
99
let b:did_ftplugin = 1
1010

11-
setlocal comments=s1:/*,mb:*,ex:*/,:///,://!,://
11+
" The rust source code at present seems to typically omit a leader on /*!
12+
" comments, so we'll use that as our default, but make it easy to switch.
13+
" This does not affect indentation at all (I tested it with and without
14+
" leader), merely whether a leader is inserted by default or not.
15+
if exists("g:rust_bang_comment_leader") && g:rust_bang_comment_leader == 1
16+
" Why is the `,s0:/*,mb:\ ,ex:*/` there, you ask? I don't understand why,
17+
" but without it, */ gets indented one space even if there were no
18+
" leaders. I'm fairly sure that's a Vim bug.
19+
setlocal comments=s1:/*,mb:*,ex:*/,s0:/*,mb:\ ,ex:*/,:///,://!,://
20+
else
21+
setlocal comments=s0:/*!,m:\ ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,://
22+
endif
1223
setlocal commentstring=//%s
1324
setlocal formatoptions-=t formatoptions+=croqnlj
1425

src/etc/vim/indent/rust.vim

+15-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ endif
1010
let b:did_indent = 1
1111

1212
setlocal cindent
13-
setlocal cinoptions=L0,(0,Ws,JN
13+
setlocal cinoptions=L0,(0,Ws,JN,j1
1414
setlocal cinkeys=0{,0},!^F,o,O,0[,0]
1515
" Don't think cinwords will actually do anything at all... never mind
1616
setlocal cinwords=do,for,if,else,while,loop,impl,mod,unsafe,trait,struct,enum,fn,extern
@@ -66,12 +66,23 @@ function GetRustIndent(lnum)
6666
" Starting assumption: cindent (called at the end) will do it right
6767
" normally. We just want to fix up a few cases.
6868

69+
let line = getline(a:lnum)
70+
6971
if has('syntax_items')
70-
if synIDattr(synID(a:lnum, 1, 1), "name") == "rustString"
72+
let synname = synIDattr(synID(a:lnum, 1, 1), "name")
73+
if synname == "rustString"
7174
" If the start of the line is in a string, don't change the indent
7275
return -1
73-
elseif synIDattr(synID(a:lnum, 1, 1), "name") =~ "\\(Comment\\|Todo\\)"
74-
\ && getline(a:lnum) !~ "^\\s*/\\*"
76+
elseif synname =~ "\\(Comment\\|Todo\\)"
77+
\ && line !~ "^\\s*/\\*" " not /* opening line
78+
if synname =~ "CommentML" " multi-line
79+
if line !~ "^\\s*\\*" && getline(a:lnum - 1) =~ "^\\s*/\\*"
80+
" This is (hopefully) the line after a /*, and it has no
81+
" leader, so the correct indentation is that of the
82+
" previous line.
83+
return GetRustIndent(a:lnum - 1)
84+
endif
85+
endif
7586
" If it's in a comment, let cindent take care of it now. This is
7687
" for cases like "/*" where the next line should start " * ", not
7788
" "* " as the code below would otherwise cause for module scope
@@ -114,7 +125,6 @@ function GetRustIndent(lnum)
114125
" start with these two main cases (square brackets and not returning to
115126
" column zero)
116127

117-
let line = getline(a:lnum)
118128
call cursor(a:lnum, 1)
119129
if searchpair('{\|(', '', '}\|)', 'nbW') == 0
120130
if searchpair('\[', '', '\]', 'nbW') == 0

src/etc/vim/syntax/rust.vim

+4-2
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9
117117
syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
118118
syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'"
119119

120-
syn region rustComment start="/\*" end="\*/" contains=rustTodo
120+
syn region rustCommentML start="/\*" end="\*/" contains=rustTodo
121121
syn region rustComment start="//" skip="\\$" end="$" contains=rustTodo keepend
122-
syn region rustCommentDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
122+
syn region rustCommentMLDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
123123
syn region rustCommentDoc start="//[/!]" skip="\\$" end="$" contains=rustTodo keepend
124124

125125
syn keyword rustTodo contained TODO FIXME XXX NB NOTE
@@ -151,7 +151,9 @@ hi def link rustModPath Include
151151
hi def link rustModPathSep Delimiter
152152
hi def link rustFuncName Function
153153
hi def link rustFuncCall Function
154+
hi def link rustCommentMLDoc rustCommentDoc
154155
hi def link rustCommentDoc SpecialComment
156+
hi def link rustCommentML rustComment
155157
hi def link rustComment Comment
156158
hi def link rustAssert PreCondit
157159
hi def link rustFail PreCondit

src/libstd/iterator.rs

+52
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,49 @@ pub trait Iterator<A> {
4747
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
4848
}
4949

50+
/// A range iterator able to yield elements from both ends
51+
pub trait DoubleEndedIterator<A>: Iterator<A> {
52+
/// Yield an element from the end of the range, returning `None` if the range is empty.
53+
fn next_back(&mut self) -> Option<A>;
54+
}
55+
56+
/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
57+
///
58+
/// In the future these will be default methods instead of a utility trait.
59+
pub trait DoubleEndedIteratorUtil<A> {
60+
/// Flip the direction of the iterator
61+
fn invert(self) -> InvertIterator<A, Self>;
62+
}
63+
64+
/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
65+
///
66+
/// In the future these will be default methods instead of a utility trait.
67+
impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil<A> for T {
68+
/// Flip the direction of the iterator
69+
#[inline]
70+
fn invert(self) -> InvertIterator<A, T> {
71+
InvertIterator{iter: self}
72+
}
73+
}
74+
75+
/// An double-ended iterator with the direction inverted
76+
// FIXME #6967: Dummy A parameter to get around type inference bug
77+
pub struct InvertIterator<A, T> {
78+
priv iter: T
79+
}
80+
81+
impl<A, T: DoubleEndedIterator<A>> Iterator<A> for InvertIterator<A, T> {
82+
#[inline]
83+
fn next(&mut self) -> Option<A> { self.iter.next_back() }
84+
#[inline]
85+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
86+
}
87+
88+
impl<A, T: Iterator<A>> DoubleEndedIterator<A> for InvertIterator<A, T> {
89+
#[inline]
90+
fn next_back(&mut self) -> Option<A> { self.iter.next() }
91+
}
92+
5093
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
5194
/// implementations of the `Iterator` trait.
5295
///
@@ -1474,4 +1517,13 @@ mod tests {
14741517
let xs = [-3, 0, 1, 5, -10];
14751518
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
14761519
}
1520+
1521+
#[test]
1522+
fn test_invert() {
1523+
let xs = [2, 4, 6, 8, 10, 12, 14, 16];
1524+
let mut it = xs.iter();
1525+
it.next();
1526+
it.next();
1527+
assert_eq!(it.invert().transform(|&x| x).collect::<~[int]>(), ~[16, 14, 12, 10, 8, 6]);
1528+
}
14771529
}

src/libstd/vec.rs

+35-54
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use container::{Container, Mutable};
1818
use cmp;
1919
use cmp::{Eq, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
2020
use clone::Clone;
21-
use iterator::{FromIterator, Iterator, IteratorUtil};
21+
use iterator::*;
2222
use kinds::Copy;
2323
use libc::c_void;
2424
use num::Zero;
@@ -762,12 +762,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
762762
}
763763
#[inline]
764764
fn rev_iter(self) -> VecRevIterator<'self, T> {
765-
unsafe {
766-
let p = vec::raw::to_ptr(self);
767-
VecRevIterator{ptr: p.offset(self.len() - 1),
768-
end: p.offset(-1),
769-
lifetime: cast::transmute(p)}
770-
}
765+
self.iter().invert()
771766
}
772767

773768
/// Returns an iterator over the subslices of the vector which are
@@ -1143,7 +1138,6 @@ impl<T> OwnedVector<T> for ~[T] {
11431138
*
11441139
* * n - The number of elements to reserve space for
11451140
*/
1146-
#[inline]
11471141
#[cfg(stage0)]
11481142
fn reserve(&mut self, n: uint) {
11491143
// Only make the (slow) call into the runtime if we have to
@@ -1177,7 +1171,6 @@ impl<T> OwnedVector<T> for ~[T] {
11771171
*
11781172
* * n - The number of elements to reserve space for
11791173
*/
1180-
#[inline]
11811174
#[cfg(not(stage0))]
11821175
fn reserve(&mut self, n: uint) {
11831176
// Only make the (slow) call into the runtime if we have to
@@ -1235,21 +1228,12 @@ impl<T> OwnedVector<T> for ~[T] {
12351228
let repr: **raw::VecRepr = transmute(&mut *self);
12361229
let fill = (**repr).unboxed.fill;
12371230
if (**repr).unboxed.alloc <= fill {
1238-
// need more space
1239-
reserve_no_inline(self);
1231+
let new_len = self.len() + 1;
1232+
self.reserve_at_least(new_len);
12401233
}
12411234

12421235
self.push_fast(t);
12431236
}
1244-
1245-
// this peculiar function is because reserve_at_least is very
1246-
// large (because of reserve), and will be inlined, which
1247-
// makes push too large.
1248-
#[inline(never)]
1249-
fn reserve_no_inline<T>(v: &mut ~[T]) {
1250-
let new_len = v.len() + 1;
1251-
v.reserve_at_least(new_len);
1252-
}
12531237
}
12541238

12551239
// This doesn't bother to make sure we have space.
@@ -1737,13 +1721,9 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
17371721
}
17381722
}
17391723

1724+
#[inline]
17401725
fn mut_rev_iter(self) -> VecMutRevIterator<'self, T> {
1741-
unsafe {
1742-
let p = vec::raw::to_mut_ptr(self);
1743-
VecMutRevIterator{ptr: p.offset(self.len() - 1),
1744-
end: p.offset(-1),
1745-
lifetime: cast::transmute(p)}
1746-
}
1726+
self.mut_iter().invert()
17471727
}
17481728

17491729
/**
@@ -2103,53 +2083,61 @@ macro_rules! iterator {
21032083
priv lifetime: $elem // FIXME: #5922
21042084
}
21052085
};*/
2106-
(impl $name:ident -> $elem:ty, $step:expr) => {
2107-
// could be implemented with &[T] with .slice(), but this avoids bounds checks
2086+
(impl $name:ident -> $elem:ty) => {
21082087
impl<'self, T> Iterator<$elem> for $name<'self, T> {
21092088
#[inline]
21102089
fn next(&mut self) -> Option<$elem> {
2090+
// could be implemented with slices, but this avoids bounds checks
21112091
unsafe {
21122092
if self.ptr == self.end {
21132093
None
21142094
} else {
21152095
let old = self.ptr;
2116-
self.ptr = self.ptr.offset($step);
2096+
self.ptr = self.ptr.offset(1);
21172097
Some(cast::transmute(old))
21182098
}
21192099
}
21202100
}
21212101

21222102
#[inline]
21232103
fn size_hint(&self) -> (uint, Option<uint>) {
2124-
let diff = if $step > 0 {
2125-
(self.end as uint) - (self.ptr as uint)
2126-
} else {
2127-
(self.ptr as uint) - (self.end as uint)
2128-
};
2104+
let diff = (self.end as uint) - (self.ptr as uint);
21292105
let exact = diff / size_of::<$elem>();
21302106
(exact, Some(exact))
21312107
}
21322108
}
21332109
}
21342110
}
21352111

2112+
macro_rules! double_ended_iterator {
2113+
(impl $name:ident -> $elem:ty) => {
2114+
impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> {
2115+
#[inline]
2116+
fn next_back(&mut self) -> Option<$elem> {
2117+
// could be implemented with slices, but this avoids bounds checks
2118+
unsafe {
2119+
if self.end == self.ptr {
2120+
None
2121+
} else {
2122+
self.end = self.end.offset(-1);
2123+
Some(cast::transmute(self.end))
2124+
}
2125+
}
2126+
}
2127+
}
2128+
}
2129+
}
2130+
21362131
//iterator!{struct VecIterator -> *T, &'self T}
21372132
/// An iterator for iterating over a vector.
21382133
pub struct VecIterator<'self, T> {
21392134
priv ptr: *T,
21402135
priv end: *T,
21412136
priv lifetime: &'self T // FIXME: #5922
21422137
}
2143-
iterator!{impl VecIterator -> &'self T, 1}
2144-
2145-
//iterator!{struct VecRevIterator -> *T, &'self T}
2146-
/// An iterator for iterating over a vector in reverse.
2147-
pub struct VecRevIterator<'self, T> {
2148-
priv ptr: *T,
2149-
priv end: *T,
2150-
priv lifetime: &'self T // FIXME: #5922
2151-
}
2152-
iterator!{impl VecRevIterator -> &'self T, -1}
2138+
iterator!{impl VecIterator -> &'self T}
2139+
double_ended_iterator!{impl VecIterator -> &'self T}
2140+
pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>;
21532141

21542142
//iterator!{struct VecMutIterator -> *mut T, &'self mut T}
21552143
/// An iterator for mutating the elements of a vector.
@@ -2158,16 +2146,9 @@ pub struct VecMutIterator<'self, T> {
21582146
priv end: *mut T,
21592147
priv lifetime: &'self mut T // FIXME: #5922
21602148
}
2161-
iterator!{impl VecMutIterator -> &'self mut T, 1}
2162-
2163-
//iterator!{struct VecMutRevIterator -> *mut T, &'self mut T}
2164-
/// An iterator for mutating the elements of a vector in reverse.
2165-
pub struct VecMutRevIterator<'self, T> {
2166-
priv ptr: *mut T,
2167-
priv end: *mut T,
2168-
priv lifetime: &'self mut T // FIXME: #5922
2169-
}
2170-
iterator!{impl VecMutRevIterator -> &'self mut T, -1}
2149+
iterator!{impl VecMutIterator -> &'self mut T}
2150+
double_ended_iterator!{impl VecMutIterator -> &'self mut T}
2151+
pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>;
21712152

21722153
/// An iterator that moves out of a vector.
21732154
pub struct VecConsumeIterator<T> {

0 commit comments

Comments
 (0)