Skip to content

iterator: add DoubleEndedIterator concept + other small commits #7707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/etc/vim/ftplugin/rust.vim
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
" Vim syntax file
" Language: Rust
" Maintainer: Chris Morgan <[email protected]>
" Last Change: 2013 Jul 6
" Last Change: 2013 Jul 10

if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1

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

Expand Down
20 changes: 15 additions & 5 deletions src/etc/vim/indent/rust.vim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ endif
let b:did_indent = 1

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

let line = getline(a:lnum)

if has('syntax_items')
if synIDattr(synID(a:lnum, 1, 1), "name") == "rustString"
let synname = synIDattr(synID(a:lnum, 1, 1), "name")
if synname == "rustString"
" If the start of the line is in a string, don't change the indent
return -1
elseif synIDattr(synID(a:lnum, 1, 1), "name") =~ "\\(Comment\\|Todo\\)"
\ && getline(a:lnum) !~ "^\\s*/\\*"
elseif synname =~ "\\(Comment\\|Todo\\)"
\ && line !~ "^\\s*/\\*" " not /* opening line
if synname =~ "CommentML" " multi-line
if line !~ "^\\s*\\*" && getline(a:lnum - 1) =~ "^\\s*/\\*"
" This is (hopefully) the line after a /*, and it has no
" leader, so the correct indentation is that of the
" previous line.
return GetRustIndent(a:lnum - 1)
endif
endif
" If it's in a comment, let cindent take care of it now. This is
" for cases like "/*" where the next line should start " * ", not
" "* " as the code below would otherwise cause for module scope
Expand Down Expand Up @@ -114,7 +125,6 @@ function GetRustIndent(lnum)
" start with these two main cases (square brackets and not returning to
" column zero)

let line = getline(a:lnum)
call cursor(a:lnum, 1)
if searchpair('{\|(', '', '}\|)', 'nbW') == 0
if searchpair('\[', '', '\]', 'nbW') == 0
Expand Down
6 changes: 4 additions & 2 deletions src/etc/vim/syntax/rust.vim
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9
syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
syn match rustCharacter "'\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'"

syn region rustComment start="/\*" end="\*/" contains=rustTodo
syn region rustCommentML start="/\*" end="\*/" contains=rustTodo
syn region rustComment start="//" skip="\\$" end="$" contains=rustTodo keepend
syn region rustCommentDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
syn region rustCommentMLDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
syn region rustCommentDoc start="//[/!]" skip="\\$" end="$" contains=rustTodo keepend

syn keyword rustTodo contained TODO FIXME XXX NB NOTE
Expand Down Expand Up @@ -151,7 +151,9 @@ hi def link rustModPath Include
hi def link rustModPathSep Delimiter
hi def link rustFuncName Function
hi def link rustFuncCall Function
hi def link rustCommentMLDoc rustCommentDoc
hi def link rustCommentDoc SpecialComment
hi def link rustCommentML rustComment
hi def link rustComment Comment
hi def link rustAssert PreCondit
hi def link rustFail PreCondit
Expand Down
52 changes: 52 additions & 0 deletions src/libstd/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,49 @@ pub trait Iterator<A> {
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
}

/// A range iterator able to yield elements from both ends
pub trait DoubleEndedIterator<A>: Iterator<A> {
/// Yield an element from the end of the range, returning `None` if the range is empty.
fn next_back(&mut self) -> Option<A>;
}

/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
///
/// In the future these will be default methods instead of a utility trait.
pub trait DoubleEndedIteratorUtil<A> {
/// Flip the direction of the iterator
fn invert(self) -> InvertIterator<A, Self>;
}

/// Iterator adaptors provided for every `DoubleEndedIterator` implementation.
///
/// In the future these will be default methods instead of a utility trait.
impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil<A> for T {
/// Flip the direction of the iterator
#[inline]
fn invert(self) -> InvertIterator<A, T> {
InvertIterator{iter: self}
}
}

/// An double-ended iterator with the direction inverted
// FIXME #6967: Dummy A parameter to get around type inference bug
pub struct InvertIterator<A, T> {
priv iter: T
}

impl<A, T: DoubleEndedIterator<A>> Iterator<A> for InvertIterator<A, T> {
#[inline]
fn next(&mut self) -> Option<A> { self.iter.next_back() }
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

impl<A, T: Iterator<A>> DoubleEndedIterator<A> for InvertIterator<A, T> {
#[inline]
fn next_back(&mut self) -> Option<A> { self.iter.next() }
}

/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
/// implementations of the `Iterator` trait.
///
Expand Down Expand Up @@ -1474,4 +1517,13 @@ mod tests {
let xs = [-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
}

#[test]
fn test_invert() {
let xs = [2, 4, 6, 8, 10, 12, 14, 16];
let mut it = xs.iter();
it.next();
it.next();
assert_eq!(it.invert().transform(|&x| x).collect::<~[int]>(), ~[16, 14, 12, 10, 8, 6]);
}
}
89 changes: 35 additions & 54 deletions src/libstd/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use container::{Container, Mutable};
use cmp;
use cmp::{Eq, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use clone::Clone;
use iterator::{FromIterator, Iterator, IteratorUtil};
use iterator::*;
use kinds::Copy;
use libc::c_void;
use num::Zero;
Expand Down Expand Up @@ -760,12 +760,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
}
#[inline]
fn rev_iter(self) -> VecRevIterator<'self, T> {
unsafe {
let p = vec::raw::to_ptr(self);
VecRevIterator{ptr: p.offset(self.len() - 1),
end: p.offset(-1),
lifetime: cast::transmute(p)}
}
self.iter().invert()
}

/// Returns an iterator over the subslices of the vector which are
Expand Down Expand Up @@ -1141,7 +1136,6 @@ impl<T> OwnedVector<T> for ~[T] {
*
* * n - The number of elements to reserve space for
*/
#[inline]
#[cfg(stage0)]
fn reserve(&mut self, n: uint) {
// Only make the (slow) call into the runtime if we have to
Expand Down Expand Up @@ -1175,7 +1169,6 @@ impl<T> OwnedVector<T> for ~[T] {
*
* * n - The number of elements to reserve space for
*/
#[inline]
#[cfg(not(stage0))]
fn reserve(&mut self, n: uint) {
// Only make the (slow) call into the runtime if we have to
Expand Down Expand Up @@ -1233,21 +1226,12 @@ impl<T> OwnedVector<T> for ~[T] {
let repr: **raw::VecRepr = transmute(&mut *self);
let fill = (**repr).unboxed.fill;
if (**repr).unboxed.alloc <= fill {
// need more space
reserve_no_inline(self);
let new_len = self.len() + 1;
self.reserve_at_least(new_len);
}

self.push_fast(t);
}

// this peculiar function is because reserve_at_least is very
// large (because of reserve), and will be inlined, which
// makes push too large.
#[inline(never)]
fn reserve_no_inline<T>(v: &mut ~[T]) {
let new_len = v.len() + 1;
v.reserve_at_least(new_len);
}
}

// This doesn't bother to make sure we have space.
Expand Down Expand Up @@ -1717,13 +1701,9 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
}
}

#[inline]
fn mut_rev_iter(self) -> VecMutRevIterator<'self, T> {
unsafe {
let p = vec::raw::to_mut_ptr(self);
VecMutRevIterator{ptr: p.offset(self.len() - 1),
end: p.offset(-1),
lifetime: cast::transmute(p)}
}
self.mut_iter().invert()
}

/**
Expand Down Expand Up @@ -2083,53 +2063,61 @@ macro_rules! iterator {
priv lifetime: $elem // FIXME: #5922
}
};*/
(impl $name:ident -> $elem:ty, $step:expr) => {
// could be implemented with &[T] with .slice(), but this avoids bounds checks
(impl $name:ident -> $elem:ty) => {
impl<'self, T> Iterator<$elem> for $name<'self, T> {
#[inline]
fn next(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks
unsafe {
if self.ptr == self.end {
None
} else {
let old = self.ptr;
self.ptr = self.ptr.offset($step);
self.ptr = self.ptr.offset(1);
Some(cast::transmute(old))
}
}
}

#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let diff = if $step > 0 {
(self.end as uint) - (self.ptr as uint)
} else {
(self.ptr as uint) - (self.end as uint)
};
let diff = (self.end as uint) - (self.ptr as uint);
let exact = diff / size_of::<$elem>();
(exact, Some(exact))
}
}
}
}

macro_rules! double_ended_iterator {
(impl $name:ident -> $elem:ty) => {
impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> {
#[inline]
fn next_back(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks
unsafe {
if self.end == self.ptr {
None
} else {
self.end = self.end.offset(-1);
Some(cast::transmute(self.end))
}
}
}
}
}
}

//iterator!{struct VecIterator -> *T, &'self T}
/// An iterator for iterating over a vector.
pub struct VecIterator<'self, T> {
priv ptr: *T,
priv end: *T,
priv lifetime: &'self T // FIXME: #5922
}
iterator!{impl VecIterator -> &'self T, 1}

//iterator!{struct VecRevIterator -> *T, &'self T}
/// An iterator for iterating over a vector in reverse.
pub struct VecRevIterator<'self, T> {
priv ptr: *T,
priv end: *T,
priv lifetime: &'self T // FIXME: #5922
}
iterator!{impl VecRevIterator -> &'self T, -1}
iterator!{impl VecIterator -> &'self T}
double_ended_iterator!{impl VecIterator -> &'self T}
pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>;

//iterator!{struct VecMutIterator -> *mut T, &'self mut T}
/// An iterator for mutating the elements of a vector.
Expand All @@ -2138,16 +2126,9 @@ pub struct VecMutIterator<'self, T> {
priv end: *mut T,
priv lifetime: &'self mut T // FIXME: #5922
}
iterator!{impl VecMutIterator -> &'self mut T, 1}

//iterator!{struct VecMutRevIterator -> *mut T, &'self mut T}
/// An iterator for mutating the elements of a vector in reverse.
pub struct VecMutRevIterator<'self, T> {
priv ptr: *mut T,
priv end: *mut T,
priv lifetime: &'self mut T // FIXME: #5922
}
iterator!{impl VecMutRevIterator -> &'self mut T, -1}
iterator!{impl VecMutIterator -> &'self mut T}
double_ended_iterator!{impl VecMutIterator -> &'self mut T}
pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>;

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