DoubleEndedIterator for Args
The number of arguments given to a process is always known, which makes implementing DoubleEndedIterator possible. That way, the Iterator::rev() method becomes usable, among others. Signed-off-by: Sebastian Thiel <byronimo@gmail.com> Tidy for DoubleEndedIterator I chose to not create a new feature for it, even though technically, this makes me lie about the original availability of the implementation. Verify with @alexchrichton Setup feature flag for new std::env::Args iterators Add test for Args reverse iterator It's somewhat depending on the input of the test program, but made in such a way that should be somewhat flexible to changes to the way it is called. Deduplicate windows ArgsOS code for DEI DEI = DoubleEndedIterator Move env::args().rev() test to run-pass It must be controlling it's arguments for full isolation. Remove superfluous feature name Assert all arguments returned by env::args().rev() Let's be very sure it works as we expect, why take chances. Fix rval of os_string_from_ptr A trait cannot be returned, but only the corresponding object. Deref pointers to actually operate on the argument Put unsafe to correct location
This commit is contained in:
parent
728eea7dc1
commit
1aa8dad854
4 changed files with 76 additions and 10 deletions
|
|
@ -587,6 +587,13 @@ impl ExactSizeIterator for Args {
|
|||
fn len(&self) -> usize { self.inner.len() }
|
||||
}
|
||||
|
||||
#[stable(feature = "env_iterators", since = "1.11.0")]
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<String> {
|
||||
self.inner.next_back().map(|s| s.into_string().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
impl Iterator for ArgsOs {
|
||||
type Item = OsString;
|
||||
|
|
@ -599,6 +606,10 @@ impl ExactSizeIterator for ArgsOs {
|
|||
fn len(&self) -> usize { self.inner.len() }
|
||||
}
|
||||
|
||||
#[stable(feature = "env_iterators", since = "1.11.0")]
|
||||
impl DoubleEndedIterator for ArgsOs {
|
||||
fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
|
||||
}
|
||||
/// Constants associated with the current target
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub mod consts {
|
||||
|
|
|
|||
|
|
@ -308,6 +308,10 @@ impl ExactSizeIterator for Args {
|
|||
fn len(&self) -> usize { self.iter.len() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
/// Returns the command line arguments
|
||||
///
|
||||
/// Returns a list of the command line arguments.
|
||||
|
|
|
|||
|
|
@ -278,23 +278,30 @@ pub struct Args {
|
|||
cur: *mut *mut u16,
|
||||
}
|
||||
|
||||
unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
|
||||
let mut len = 0;
|
||||
while *ptr.offset(len) != 0 { len += 1; }
|
||||
|
||||
// Push it onto the list.
|
||||
let ptr = ptr as *const u16;
|
||||
let buf = slice::from_raw_parts(ptr, len as usize);
|
||||
OsStringExt::from_wide(buf)
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> {
|
||||
self.range.next().map(|i| unsafe {
|
||||
let ptr = *self.cur.offset(i);
|
||||
let mut len = 0;
|
||||
while *ptr.offset(len) != 0 { len += 1; }
|
||||
|
||||
// Push it onto the list.
|
||||
let ptr = ptr as *const u16;
|
||||
let buf = slice::from_raw_parts(ptr, len as usize);
|
||||
OsStringExt::from_wide(buf)
|
||||
})
|
||||
self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> {
|
||||
self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize { self.range.len() }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue