mirror of
https://github.com/openharmony/third_party_rust_rust-std-candidates.git
synced 2026-06-30 20:47:55 -04:00
Add matches! and zip_longest
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
target
|
||||
Cargo.lock
|
||||
@@ -0,0 +1,2 @@
|
||||
language: rust
|
||||
script: ./cargo-all.sh test
|
||||
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2014 Simon Sapin
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,57 @@
|
||||
These are candidates for addition to
|
||||
the [Rust](http://rust-lang.org/) standard library.
|
||||
Each crate is published separately on [crate.io](https://crates.io/)
|
||||
|
||||
# The `matches!` macro
|
||||
|
||||
[RFC #163](https://github.com/rust-lang/rfcs/pull/163)
|
||||
|
||||
A macro to evaluate, as a boolean, whether an expression matches a pattern.
|
||||
|
||||
|
||||
```rust
|
||||
#![feature(phase)]
|
||||
#[phase(plugin)] extern crate matches;
|
||||
|
||||
fn is_slash(input: &str, pos: uint) -> bool {
|
||||
matches!(input.char_at(pos), '/' | '\\')
|
||||
}
|
||||
```
|
||||
|
||||
```rust
|
||||
#![feature(phase)]
|
||||
#[phase(plugin)] extern crate matches;
|
||||
extern crate serialize;
|
||||
use serialize::json::Json;
|
||||
|
||||
fn object_has_key(json: &Json, key: &str) -> bool {
|
||||
matches!(json, &Json::Object(ref obj) if obj.contains_key(key))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
# The `zip_longest` iterator adaptor
|
||||
|
||||
[PR #19283](https://github.com/rust-lang/rust/pull/19283)
|
||||
|
||||
The standard library has an [`iterator.zip(other_iterator)`](
|
||||
http://doc.rust-lang.org/std/iter/trait.IteratorExt.html#tymethod.zip) method
|
||||
that returns a new iterator that yields pairs,
|
||||
and stops when one of the input iterators does.
|
||||
|
||||
`zip_longest` is similar,
|
||||
but instead continues until both iterators are exhausted.
|
||||
Instead of a pair of values `(A, B)`,
|
||||
it yield pairs of optional values `(Option<A>, Option<B>)`,
|
||||
where `None` indicates that one of the input iterator was exhausted before the other.
|
||||
(`(None, None)` never occurs.)
|
||||
|
||||
```rust
|
||||
extern crate "zip-longest" as zip_longest;
|
||||
use zip_longest::ZipLongestIteratorExt;
|
||||
|
||||
fn iter_eq<I, J, T>(i: I, j: J) -> bool
|
||||
where I: Iterator<T>, J: Iterator<T>, T: Eq {
|
||||
i.zip_longest(j).all(|(a, b)| a == b)
|
||||
}
|
||||
```
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
cd $(dirname $0)
|
||||
for lib in */
|
||||
do
|
||||
cd $lib
|
||||
cargo "$@"
|
||||
cd ..
|
||||
done
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
|
||||
name = "matches"
|
||||
version = "0.0.1"
|
||||
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/SimonSapin/rust-std-candidates"
|
||||
description ="A macro to evaluate, as a boolean, whether an expression matches a pattern."
|
||||
|
||||
|
||||
[lib]
|
||||
name = "matches"
|
||||
path = "lib.rs"
|
||||
doctest = false
|
||||
@@ -0,0 +1,23 @@
|
||||
#![feature(macro_rules)]
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! matches(
|
||||
($expression: expr, $($pattern:pat)|+) => (
|
||||
matches!($expression, $($pattern)|+ if true)
|
||||
);
|
||||
($expression: expr, $($pattern:pat)|+ if $guard: expr) => (
|
||||
match $expression {
|
||||
$($pattern)|+ => $guard,
|
||||
_ => false
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let foo = Some("-12");
|
||||
assert!(matches!(foo, Some(bar) if
|
||||
matches!(bar.char_at(0), '+' | '-') &&
|
||||
matches!(bar.char_at(1), '0'...'9')
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
|
||||
name = "zip-longest"
|
||||
version = "0.0.1"
|
||||
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/SimonSapin/rust-std-candidates"
|
||||
description ="Take two iterators and yield pairs until both are exhausted."
|
||||
|
||||
[lib]
|
||||
name = "zip-longest"
|
||||
path = "lib.rs"
|
||||
doctest = false
|
||||
@@ -0,0 +1,153 @@
|
||||
use std::cmp;
|
||||
|
||||
pub trait ZipLongestIteratorExt<A>: Iterator<A> {
|
||||
/// Creates an iterator which iterates over both this and the specified
|
||||
/// iterators simultaneously, yielding pairs of two optional elements.
|
||||
/// When both iterators return None, all further invocations of next() will
|
||||
/// return None.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let a = [0i];
|
||||
/// let b = [1i, 2i];
|
||||
/// let mut it = a.iter().zip(b.iter());
|
||||
/// let (x0, x1, x2) = (0i, 1i, 2i);
|
||||
/// assert_eq!(it.next().unwrap(), (Some(&x0), Some(&x1)));
|
||||
/// assert_eq!(it.next().unwrap(), (None, Some(&x2)));
|
||||
/// assert!(it.next().is_none());
|
||||
/// ```
|
||||
#[inline]
|
||||
fn zip_longest<B, U: Iterator<B>>(self, other: U) -> ZipLongest<Self, U> {
|
||||
ZipLongest{a: self, b: other}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// An iterator which iterates two other iterators simultaneously
|
||||
#[deriving(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub struct ZipLongest<T, U> {
|
||||
a: T,
|
||||
b: U
|
||||
}
|
||||
|
||||
impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(Option<A>, Option<B>)> for ZipLongest<T, U> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(Option<A>, Option<B>)> {
|
||||
match (self.a.next(), self.b.next()) {
|
||||
(None, None) => None,
|
||||
pair_of_options => Some(pair_of_options),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (a_lower, a_upper) = self.a.size_hint();
|
||||
let (b_lower, b_upper) = self.b.size_hint();
|
||||
|
||||
let lower = cmp::max(a_lower, b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => Some(cmp::max(x,y)),
|
||||
_ => None
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, T: ExactSizeIterator<A>, U: ExactSizeIterator<B>> DoubleEndedIterator<(Option<A>, Option<B>)>
|
||||
for ZipLongest<T, U> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(Option<A>, Option<B>)> {
|
||||
use std::cmp::{Equal, Greater, Less};
|
||||
match self.a.len().cmp(&self.b.len()) {
|
||||
Equal => match (self.a.next_back(), self.b.next_back()) {
|
||||
(None, None) => None,
|
||||
pair_of_options => Some(pair_of_options),
|
||||
},
|
||||
Greater => self.a.next_back().map(|x| (Some(x), None)),
|
||||
Less => self.b.next_back().map(|y| (None, Some(y))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, T: RandomAccessIterator<A>, U: RandomAccessIterator<B>>
|
||||
RandomAccessIterator<(Option<A>, Option<B>)> for ZipLongest<T, U> {
|
||||
#[inline]
|
||||
fn indexable(&self) -> uint {
|
||||
cmp::max(self.a.indexable(), self.b.indexable())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn idx(&mut self, index: uint) -> Option<(Option<A>, Option<B>)> {
|
||||
match (self.a.idx(index), self.b.idx(index)) {
|
||||
(None, None) => None,
|
||||
pair_of_options => Some(pair_of_options),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, T: ExactSizeIterator<A>, U: ExactSizeIterator<B>>
|
||||
ExactSizeIterator<(Option<A>, Option<B>)> for ZipLongest<T, U> {}
|
||||
|
||||
|
||||
impl<A, I> ZipLongestIteratorExt<A> for I where I: Iterator<A> {}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_iterator_size_hint() {
|
||||
use std::uint;
|
||||
use std::iter::count;
|
||||
|
||||
let c = count(0i, 1);
|
||||
let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let v2 = &[10i, 11, 12];
|
||||
let vi = v.iter();
|
||||
assert_eq!(c.zip_longest(vi).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(vi.zip_longest(v2.iter()).size_hint(), (10, Some(10)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_ended() {
|
||||
let xs = [1i, 2, 3, 4, 5, 6];
|
||||
let ys = [1i, 2, 3, 7];
|
||||
let a = xs.iter().map(|&x| x);
|
||||
let b = ys.iter().map(|&x| x);
|
||||
let mut it = a.zip_longest(b);
|
||||
assert_eq!(it.next(), Some((Some(1), Some(1))));
|
||||
assert_eq!(it.next(), Some((Some(2), Some(2))));
|
||||
assert_eq!(it.next_back(), Some((Some(6), None)));
|
||||
assert_eq!(it.next_back(), Some((Some(5), None)));
|
||||
assert_eq!(it.next_back(), Some((Some(4), Some(7))));
|
||||
assert_eq!(it.next(), Some((Some(3), Some(3))));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_access() {
|
||||
let xs = [1i, 2, 3, 4, 5];
|
||||
let ys = [7i, 9, 11];
|
||||
check_randacc_iter(xs.iter().zip_longest(ys.iter()),
|
||||
cmp::max(xs.len(), ys.len()));
|
||||
|
||||
fn check_randacc_iter<A, T>(a: T, len: uint)
|
||||
where A: PartialEq, T: Clone + RandomAccessIterator<A>
|
||||
{
|
||||
let mut b = a.clone();
|
||||
assert_eq!(len, b.indexable());
|
||||
let mut n = 0u;
|
||||
for (i, elt) in a.enumerate() {
|
||||
assert!(Some(elt) == b.idx(i));
|
||||
n += 1;
|
||||
}
|
||||
assert_eq!(n, len);
|
||||
assert!(None == b.idx(n));
|
||||
// call recursively to check after picking off an element
|
||||
if len > 0 {
|
||||
b.next();
|
||||
check_randacc_iter(b, len-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user