mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-06 20:13:42 +00:00
auto merge of #19060 : Gankro/rust/super-cloned, r=aturon
Edit: whoops, didn't mean to hit post.
Anyway, this is something I tried to do when I first implemented cloned, but couldn't figure out. Somewhere between then and the PR actually landing, we got Deref of references, so now this works! 🎉
Also turns out the test for the functionality was never marked as a #[test]. Oops!
Also added a Cloned iterator adaptor. If this isn't desirable, it can be taken out of the PR (seperate commits).
This commit is contained in:
commit
09e2ad13d0
@ -65,9 +65,10 @@ use cmp;
|
||||
use cmp::Ord;
|
||||
use mem;
|
||||
use num::{ToPrimitive, Int};
|
||||
use ops::Add;
|
||||
use ops::{Add, Deref};
|
||||
use option::{Option, Some, None};
|
||||
use uint;
|
||||
|
||||
#[deprecated = "renamed to Extend"] pub use self::Extend as Extendable;
|
||||
|
||||
/// Conversion from an `Iterator`
|
||||
@ -1021,6 +1022,44 @@ impl<T: Clone> MinMaxResult<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for iterators that contain cloneable elements
|
||||
pub trait CloneIteratorExt<A> {
|
||||
/// Creates an iterator that clones the elements it yields. Useful for converting an
|
||||
/// Iterator<&T> to an Iterator<T>.
|
||||
fn cloned(self) -> Cloned<Self>;
|
||||
}
|
||||
|
||||
|
||||
impl<A: Clone, D: Deref<A>, I: Iterator<D>> CloneIteratorExt<A> for I {
|
||||
fn cloned(self) -> Cloned<I> {
|
||||
Cloned { it: self }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that clones the elements of an underlying iterator
|
||||
pub struct Cloned<I> {
|
||||
it: I,
|
||||
}
|
||||
|
||||
impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> {
|
||||
fn next(&mut self) -> Option<A> {
|
||||
self.it.next().cloned()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.it.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>>
|
||||
DoubleEndedIterator<A> for Cloned<I> {
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
self.it.next_back().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Clone, D: Deref<A>, I: ExactSize<D>> ExactSize<A> for Cloned<I> {}
|
||||
|
||||
/// A trait for iterators that are cloneable.
|
||||
pub trait CloneableIterator {
|
||||
/// Repeats an iterator endlessly
|
||||
|
@ -153,6 +153,7 @@ use result::{Result, Ok, Err};
|
||||
use slice;
|
||||
use slice::AsSlice;
|
||||
use clone::Clone;
|
||||
use ops::Deref;
|
||||
|
||||
// Note that this is not a lang item per se, but it has a hidden dependency on
|
||||
// `Iterator`, which is one. The compiler assumes that the `next` method of
|
||||
@ -694,11 +695,12 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone> Option<&'a T> {
|
||||
/// Maps an Option<&T> to an Option<T> by cloning the contents of the Option<&T>.
|
||||
impl<'a, T: Clone, D: Deref<T>> Option<D> {
|
||||
/// Maps an Option<D> to an Option<T> by dereffing and cloning the contents of the Option.
|
||||
/// Useful for converting an Option<&T> to an Option<T>.
|
||||
#[unstable = "recently added as part of collections reform"]
|
||||
pub fn cloned(self) -> Option<T> {
|
||||
self.map(|t| t.clone())
|
||||
self.map(|t| t.deref().clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,6 +440,23 @@ fn test_rev() {
|
||||
vec![16, 14, 12, 10, 8, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cloned() {
|
||||
let xs = [2u8, 4, 6, 8];
|
||||
|
||||
let mut it = xs.iter().cloned();
|
||||
assert_eq!(it.len(), 4);
|
||||
assert_eq!(it.next(), Some(2));
|
||||
assert_eq!(it.len(), 3);
|
||||
assert_eq!(it.next(), Some(4));
|
||||
assert_eq!(it.len(), 2);
|
||||
assert_eq!(it.next_back(), Some(8));
|
||||
assert_eq!(it.len(), 1);
|
||||
assert_eq!(it.next_back(), Some(6));
|
||||
assert_eq!(it.len(), 0);
|
||||
assert_eq!(it.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_ended_map() {
|
||||
let xs = [1i, 2, 3, 4, 5, 6];
|
||||
|
@ -241,14 +241,29 @@ fn test_collect() {
|
||||
assert!(v == None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cloned() {
|
||||
let s = 1u32;
|
||||
let n: Option<&'static u32> = None;
|
||||
let o = Some(&s);
|
||||
let val1 = 1u32;
|
||||
let mut val2 = 2u32;
|
||||
let val1_ref = &val1;
|
||||
let opt_none: Option<&'static u32> = None;
|
||||
let opt_ref = Some(&val1);
|
||||
let opt_ref_ref = Some(&val1_ref);
|
||||
let opt_mut_ref = Some(&mut val2);
|
||||
|
||||
assert_eq!(o.clone(), Some(&s));
|
||||
assert_eq!(o.cloned(), Some(1u32));
|
||||
// None works
|
||||
assert_eq!(opt_none.clone(), None);
|
||||
assert_eq!(opt_none.cloned(), None);
|
||||
|
||||
assert_eq!(n.clone(), None);
|
||||
assert_eq!(n.cloned(), None);
|
||||
// Mutable refs work
|
||||
assert_eq!(opt_mut_ref.cloned(), Some(2u32));
|
||||
|
||||
// Immutable ref works
|
||||
assert_eq!(opt_ref.clone(), Some(&val1));
|
||||
assert_eq!(opt_ref.cloned(), Some(1u32));
|
||||
|
||||
// Double Immutable ref works
|
||||
assert_eq!(opt_ref_ref.clone(), Some(&val1_ref));
|
||||
assert_eq!(opt_ref_ref.clone().cloned(), Some(&val1));
|
||||
assert_eq!(opt_ref_ref.cloned().cloned(), Some(1u32));
|
||||
}
|
Loading…
Reference in New Issue
Block a user