mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #79319 - m-ou-se:rollup-d9n5viq, r=m-ou-se
Rollup of 10 pull requests Successful merges: - #76941 (Add f{32,64}::is_subnormal) - #77697 (Split each iterator adapter and source into individual modules) - #78305 (Stabilize alloc::Layout const functions) - #78608 (Stabilize refcell_take) - #78793 (Clean up `StructuralEq` docs) - #79267 (BTreeMap: address namespace conflicts) - #79293 (Add test for eval order for a+=b) - #79295 (BTreeMap: fix minor testing mistakes in #78903) - #79297 (BTreeMap: swap the names of NodeRef::new and Root::new_leaf) - #79299 (Stabilise `then`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
32da90b431
@ -1,5 +1,4 @@
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(extend_one)]
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(drain_filter)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
//! The main parser interface.
|
||||
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(iter_order_by)]
|
||||
|
@ -67,7 +67,7 @@ impl<K, V> Root<K, V> {
|
||||
|
||||
// Push key-value pair and new right subtree.
|
||||
let tree_height = open_node.height() - 1;
|
||||
let mut right_tree = Root::new_leaf();
|
||||
let mut right_tree = Root::new();
|
||||
for _ in 0..tree_height {
|
||||
right_tree.push_internal_level();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use core::ops::{Index, RangeBounds};
|
||||
use core::ptr;
|
||||
|
||||
use super::borrow::DormantMutRef;
|
||||
use super::node::{self, marker, ForceResult::*, Handle, NodeRef};
|
||||
use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root};
|
||||
use super::search::{self, SearchResult::*};
|
||||
use super::unwrap_unchecked;
|
||||
|
||||
@ -128,7 +128,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BTreeMap<K, V> {
|
||||
root: Option<node::Root<K, V>>,
|
||||
root: Option<Root<K, V>>,
|
||||
length: usize,
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap<K, V> {
|
||||
impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||
fn clone(&self) -> BTreeMap<K, V> {
|
||||
fn clone_subtree<'a, K: Clone, V: Clone>(
|
||||
node: node::NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>,
|
||||
node: NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>,
|
||||
) -> BTreeMap<K, V>
|
||||
where
|
||||
K: 'a,
|
||||
@ -153,7 +153,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||
{
|
||||
match node.force() {
|
||||
Leaf(leaf) => {
|
||||
let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
|
||||
let mut out_tree = BTreeMap { root: Some(Root::new()), length: 0 };
|
||||
|
||||
{
|
||||
let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped
|
||||
@ -198,7 +198,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||
(root, length)
|
||||
};
|
||||
|
||||
out_node.push(k, v, subroot.unwrap_or_else(node::Root::new_leaf));
|
||||
out_node.push(k, v, subroot.unwrap_or_else(Root::new));
|
||||
out_tree.length += 1 + sublength;
|
||||
}
|
||||
}
|
||||
@ -1558,7 +1558,7 @@ pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
|
||||
length: &'a mut usize,
|
||||
/// Burried reference to the root field in the borrowed map.
|
||||
/// Wrapped in `Option` to allow drop handler to `take` it.
|
||||
dormant_root: Option<DormantMutRef<'a, node::Root<K, V>>>,
|
||||
dormant_root: Option<DormantMutRef<'a, Root<K, V>>>,
|
||||
/// Contains a leaf edge preceding the next element to be returned, or the last leaf edge.
|
||||
/// Empty if the map has no root, if iteration went beyond the last leaf edge,
|
||||
/// or if a panic occurred in the predicate.
|
||||
@ -2160,8 +2160,8 @@ impl<K, V> BTreeMap<K, V> {
|
||||
|
||||
/// If the root node is the empty (non-allocated) root node, allocate our
|
||||
/// own node. Is an associated function to avoid borrowing the entire BTreeMap.
|
||||
fn ensure_is_owned(root: &mut Option<node::Root<K, V>>) -> &mut node::Root<K, V> {
|
||||
root.get_or_insert_with(node::Root::new_leaf)
|
||||
fn ensure_is_owned(root: &mut Option<Root<K, V>>) -> &mut Root<K, V> {
|
||||
root.get_or_insert_with(Root::new)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,14 @@ use crate::fmt::Debug;
|
||||
use crate::rc::Rc;
|
||||
use crate::string::{String, ToString};
|
||||
use crate::vec::Vec;
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryFrom;
|
||||
use std::iter::{self, FromIterator};
|
||||
use std::mem;
|
||||
use std::ops::Bound::{self, Excluded, Included, Unbounded};
|
||||
use std::ops::RangeBounds;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
||||
|
||||
mod ord_chaos;
|
||||
use ord_chaos::{Cyclic3, Governed, Governor};
|
||||
@ -56,24 +57,23 @@ impl<K, V> BTreeMap<K, V> {
|
||||
assert!(root_node.ascend().is_err());
|
||||
root_node.assert_back_pointers();
|
||||
|
||||
// Check consistenty of `length` and some of the navigation.
|
||||
// Check consistency of `length` with what navigation code encounters.
|
||||
assert_eq!(self.length, root_node.calc_length());
|
||||
assert_eq!(self.length, self.keys().count());
|
||||
|
||||
// Lastly, check the invariant causing the least harm.
|
||||
root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 });
|
||||
} else {
|
||||
// Check consistenty of `length` and some of the navigation.
|
||||
assert_eq!(self.length, 0);
|
||||
assert_eq!(self.length, self.keys().count());
|
||||
}
|
||||
|
||||
// Check that `assert_strictly_ascending` will encounter all keys.
|
||||
assert_eq!(self.length, self.keys().count());
|
||||
}
|
||||
|
||||
// Panics if the map is corrupted or if the keys are not in strictly
|
||||
// ascending order, in the current opinion of the `Ord` implementation.
|
||||
// If the `Ord` implementation does not honor transitivity, this method
|
||||
// does not guarantee that all the keys are unique, just that adjacent
|
||||
// keys are unique.
|
||||
// If the `Ord` implementation violates transitivity, this method does not
|
||||
// guarantee that all keys are unique, just that adjacent keys are unique.
|
||||
fn check(&self)
|
||||
where
|
||||
K: Debug + Ord,
|
||||
@ -879,6 +879,7 @@ mod test_drain_filter {
|
||||
map.check();
|
||||
}
|
||||
|
||||
// Explicitly consumes the iterator, where most test cases drop it instantly.
|
||||
#[test]
|
||||
fn consumed_keeping_all() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
@ -887,6 +888,7 @@ mod test_drain_filter {
|
||||
map.check();
|
||||
}
|
||||
|
||||
// Explicitly consumes the iterator, where most test cases drop it instantly.
|
||||
#[test]
|
||||
fn consumed_removing_all() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
@ -896,15 +898,7 @@ mod test_drain_filter {
|
||||
map.check();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dropped_removing_all() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
let mut map: BTreeMap<_, _> = pairs.collect();
|
||||
map.drain_filter(|_, _| true);
|
||||
assert!(map.is_empty());
|
||||
map.check();
|
||||
}
|
||||
|
||||
// Explicitly consumes the iterator and modifies values through it.
|
||||
#[test]
|
||||
fn mutating_and_keeping() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
@ -921,6 +915,7 @@ mod test_drain_filter {
|
||||
map.check();
|
||||
}
|
||||
|
||||
// Explicitly consumes the iterator and modifies values through it.
|
||||
#[test]
|
||||
fn mutating_and_removing() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
@ -1094,7 +1089,7 @@ mod test_drain_filter {
|
||||
struct D;
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
|
||||
if DROPS.fetch_add(1, SeqCst) == 1 {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
@ -1105,14 +1100,14 @@ mod test_drain_filter {
|
||||
|
||||
catch_unwind(move || {
|
||||
drop(map.drain_filter(|i, _| {
|
||||
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
|
||||
PREDS.fetch_add(1usize << i, SeqCst);
|
||||
true
|
||||
}))
|
||||
})
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
|
||||
assert_eq!(PREDS.load(SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(SeqCst), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1123,7 +1118,7 @@ mod test_drain_filter {
|
||||
struct D;
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
DROPS.fetch_add(1, Ordering::SeqCst);
|
||||
DROPS.fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1132,7 +1127,7 @@ mod test_drain_filter {
|
||||
|
||||
catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(map.drain_filter(|i, _| {
|
||||
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
|
||||
PREDS.fetch_add(1usize << i, SeqCst);
|
||||
match i {
|
||||
0 => true,
|
||||
_ => panic!(),
|
||||
@ -1141,8 +1136,8 @@ mod test_drain_filter {
|
||||
}))
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
|
||||
assert_eq!(PREDS.load(SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(SeqCst), 1);
|
||||
assert_eq!(map.len(), 2);
|
||||
assert_eq!(map.first_entry().unwrap().key(), &4);
|
||||
assert_eq!(map.last_entry().unwrap().key(), &8);
|
||||
@ -1158,7 +1153,7 @@ mod test_drain_filter {
|
||||
struct D;
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
DROPS.fetch_add(1, Ordering::SeqCst);
|
||||
DROPS.fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1167,7 +1162,7 @@ mod test_drain_filter {
|
||||
|
||||
{
|
||||
let mut it = map.drain_filter(|i, _| {
|
||||
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
|
||||
PREDS.fetch_add(1usize << i, SeqCst);
|
||||
match i {
|
||||
0 => true,
|
||||
_ => panic!(),
|
||||
@ -1180,8 +1175,8 @@ mod test_drain_filter {
|
||||
assert!(matches!(result, Ok(None)));
|
||||
}
|
||||
|
||||
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
|
||||
assert_eq!(PREDS.load(SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(SeqCst), 1);
|
||||
assert_eq!(map.len(), 2);
|
||||
assert_eq!(map.first_entry().unwrap().key(), &4);
|
||||
assert_eq!(map.last_entry().unwrap().key(), &8);
|
||||
@ -1315,8 +1310,6 @@ fn test_zst() {
|
||||
// undefined.
|
||||
#[test]
|
||||
fn test_bad_zst() {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Bad;
|
||||
|
||||
@ -1763,7 +1756,7 @@ fn test_append_drop_leak() {
|
||||
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
if DROPS.fetch_add(1, Ordering::SeqCst) == 0 {
|
||||
if DROPS.fetch_add(1, SeqCst) == 0 {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
@ -1779,7 +1772,7 @@ fn test_append_drop_leak() {
|
||||
|
||||
catch_unwind(move || left.append(&mut right)).unwrap_err();
|
||||
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 4); // Rust issue #47949 ate one little piggy
|
||||
assert_eq!(DROPS.load(SeqCst), 4); // Rust issue #47949 ate one little piggy
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1894,7 +1887,7 @@ fn test_into_iter_drop_leak_height_0() {
|
||||
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
if DROPS.fetch_add(1, Ordering::SeqCst) == 3 {
|
||||
if DROPS.fetch_add(1, SeqCst) == 3 {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
@ -1909,7 +1902,7 @@ fn test_into_iter_drop_leak_height_0() {
|
||||
|
||||
catch_unwind(move || drop(map.into_iter())).unwrap_err();
|
||||
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 5);
|
||||
assert_eq!(DROPS.load(SeqCst), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1921,18 +1914,18 @@ fn test_into_iter_drop_leak_height_1() {
|
||||
struct D;
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
|
||||
if DROPS.fetch_add(1, SeqCst) == PANIC_POINT.load(SeqCst) {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for panic_point in vec![0, 1, size - 2, size - 1] {
|
||||
DROPS.store(0, Ordering::SeqCst);
|
||||
PANIC_POINT.store(panic_point, Ordering::SeqCst);
|
||||
DROPS.store(0, SeqCst);
|
||||
PANIC_POINT.store(panic_point, SeqCst);
|
||||
let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
|
||||
catch_unwind(move || drop(map.into_iter())).unwrap_err();
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), size);
|
||||
assert_eq!(DROPS.load(SeqCst), size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ use std::cell::Cell;
|
||||
use std::cmp::Ordering::{self, *};
|
||||
use std::ptr;
|
||||
|
||||
// Minimal type with an `Ord` implementation violating transitivity.
|
||||
#[derive(Debug)]
|
||||
pub enum Cyclic3 {
|
||||
A,
|
||||
@ -34,6 +35,7 @@ impl PartialEq for Cyclic3 {
|
||||
|
||||
impl Eq for Cyclic3 {}
|
||||
|
||||
// Controls the ordering of values wrapped by `Governed`.
|
||||
#[derive(Debug)]
|
||||
pub struct Governor {
|
||||
flipped: Cell<bool>,
|
||||
@ -49,6 +51,9 @@ impl Governor {
|
||||
}
|
||||
}
|
||||
|
||||
// Type with an `Ord` implementation that forms a total order at any moment
|
||||
// (assuming that `T` respects total order), but can suddenly be made to invert
|
||||
// that total order.
|
||||
#[derive(Debug)]
|
||||
pub struct Governed<'a, T>(pub T, pub &'a Governor);
|
||||
|
||||
|
@ -134,13 +134,13 @@ pub type Root<K, V> = NodeRef<marker::Owned, K, V, marker::LeafOrInternal>;
|
||||
|
||||
impl<K, V> Root<K, V> {
|
||||
/// Returns a new owned tree, with its own root node that is initially empty.
|
||||
pub fn new_leaf() -> Self {
|
||||
NodeRef::new().forget_type()
|
||||
pub fn new() -> Self {
|
||||
NodeRef::new_leaf().forget_type()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
|
||||
fn new() -> Self {
|
||||
fn new_leaf() -> Self {
|
||||
Self::from_new_leaf(Box::new(unsafe { LeafNode::new() }))
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ fn test_splitpoint() {
|
||||
|
||||
#[test]
|
||||
fn test_partial_cmp_eq() {
|
||||
let mut root1 = NodeRef::new();
|
||||
let mut root1 = NodeRef::new_leaf();
|
||||
let mut leaf1 = root1.borrow_mut();
|
||||
leaf1.push(1, ());
|
||||
let mut root1 = root1.forget_type();
|
||||
root1.push_internal_level();
|
||||
let root2 = Root::new_leaf();
|
||||
let root2 = Root::new();
|
||||
root1.reborrow().assert_back_pointers();
|
||||
root2.reborrow().assert_back_pointers();
|
||||
|
||||
|
@ -50,7 +50,7 @@ where
|
||||
{
|
||||
match search_linear(&node, key) {
|
||||
(idx, true) => Found(unsafe { Handle::new_kv(node, idx) }),
|
||||
(idx, false) => SearchResult::GoDown(unsafe { Handle::new_edge(node, idx) }),
|
||||
(idx, false) => GoDown(unsafe { Handle::new_edge(node, idx) }),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
use super::super::DeterministicRng;
|
||||
use super::*;
|
||||
use crate::vec::Vec;
|
||||
use std::cmp::Ordering;
|
||||
use std::iter::FromIterator;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::atomic::{AtomicU32, Ordering::SeqCst};
|
||||
|
||||
#[test]
|
||||
fn test_clone_eq() {
|
||||
@ -355,7 +356,7 @@ fn test_drain_filter_drop_panic_leak() {
|
||||
struct D(i32);
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
|
||||
if DROPS.fetch_add(1, SeqCst) == 1 {
|
||||
panic!("panic in `drop`");
|
||||
}
|
||||
}
|
||||
@ -368,14 +369,14 @@ fn test_drain_filter_drop_panic_leak() {
|
||||
|
||||
catch_unwind(move || {
|
||||
drop(set.drain_filter(|d| {
|
||||
PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
|
||||
PREDS.fetch_add(1u32 << d.0, SeqCst);
|
||||
true
|
||||
}))
|
||||
})
|
||||
.ok();
|
||||
|
||||
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
|
||||
assert_eq!(PREDS.load(SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(SeqCst), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -387,7 +388,7 @@ fn test_drain_filter_pred_panic_leak() {
|
||||
struct D(i32);
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
DROPS.fetch_add(1, Ordering::SeqCst);
|
||||
DROPS.fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,7 +399,7 @@ fn test_drain_filter_pred_panic_leak() {
|
||||
|
||||
catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(set.drain_filter(|d| {
|
||||
PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
|
||||
PREDS.fetch_add(1u32 << d.0, SeqCst);
|
||||
match d.0 {
|
||||
0 => true,
|
||||
_ => panic!(),
|
||||
@ -407,8 +408,8 @@ fn test_drain_filter_pred_panic_leak() {
|
||||
}))
|
||||
.ok();
|
||||
|
||||
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
|
||||
assert_eq!(PREDS.load(SeqCst), 0x011);
|
||||
assert_eq!(DROPS.load(SeqCst), 1);
|
||||
assert_eq!(set.len(), 2);
|
||||
assert_eq!(set.first().unwrap().0, 4);
|
||||
assert_eq!(set.last().unwrap().0, 8);
|
||||
@ -498,8 +499,6 @@ fn test_extend_ref() {
|
||||
|
||||
#[test]
|
||||
fn test_recovery() {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo(&'static str, i32);
|
||||
|
||||
|
@ -50,7 +50,7 @@ impl Layout {
|
||||
/// must not overflow (i.e., the rounded value must be less than
|
||||
/// or equal to `usize::MAX`).
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
|
||||
#[inline]
|
||||
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
||||
if !align.is_power_of_two() {
|
||||
@ -96,7 +96,7 @@ impl Layout {
|
||||
|
||||
/// The minimum size in bytes for a memory block of this layout.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
|
||||
#[inline]
|
||||
pub const fn size(&self) -> usize {
|
||||
self.size_
|
||||
@ -104,7 +104,7 @@ impl Layout {
|
||||
|
||||
/// The minimum byte alignment for a memory block of this layout.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
|
||||
#[inline]
|
||||
pub const fn align(&self) -> usize {
|
||||
self.align_.get()
|
||||
|
@ -23,12 +23,10 @@ impl bool {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_option)]
|
||||
///
|
||||
/// assert_eq!(false.then(|| 0), None);
|
||||
/// assert_eq!(true.then(|| 0), Some(0));
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_option", issue = "64260")]
|
||||
#[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
|
||||
#[inline]
|
||||
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
|
||||
if self { Some(f()) } else { None }
|
||||
|
@ -1027,7 +1027,6 @@ impl<T: Default> RefCell<T> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(refcell_take)]
|
||||
/// use std::cell::RefCell;
|
||||
///
|
||||
/// let c = RefCell::new(5);
|
||||
@ -1036,7 +1035,7 @@ impl<T: Default> RefCell<T> {
|
||||
/// assert_eq!(five, 5);
|
||||
/// assert_eq!(c.into_inner(), 0);
|
||||
/// ```
|
||||
#[unstable(feature = "refcell_take", issue = "71395")]
|
||||
#[stable(feature = "refcell_take", since = "1.50.0")]
|
||||
pub fn take(&self) -> T {
|
||||
self.replace(Default::default())
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
use crate::usize;
|
||||
use crate::{ops::Try, usize};
|
||||
|
||||
/// An iterator that links two iterators together, in a chain.
|
||||
///
|
||||
|
139
library/core/src/iter/adapters/cloned.rs
Normal file
139
library/core/src/iter/adapters/cloned.rs
Normal file
@ -0,0 +1,139 @@
|
||||
use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that clones the elements of an underlying iterator.
|
||||
///
|
||||
/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`cloned`]: Iterator::cloned
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Cloned<I> {
|
||||
it: I,
|
||||
}
|
||||
|
||||
impl<I> Cloned<I> {
|
||||
pub(in crate::iter) fn new(it: I) -> Cloned<I> {
|
||||
Cloned { it }
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
|
||||
move |acc, elt| f(acc, elt.clone())
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
impl<'a, I, T: 'a> Iterator for Cloned<I>
|
||||
where
|
||||
I: Iterator<Item = &'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.it.next().cloned()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.it.size_hint()
|
||||
}
|
||||
|
||||
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.it.try_fold(init, clone_try_fold(f))
|
||||
}
|
||||
|
||||
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.it.map(T::clone).fold(init, f)
|
||||
}
|
||||
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
unsafe { try_get_unchecked(&mut self.it, idx).clone() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
|
||||
where
|
||||
I: DoubleEndedIterator<Item = &'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.it.next_back().cloned()
|
||||
}
|
||||
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.it.try_rfold(init, clone_try_fold(f))
|
||||
}
|
||||
|
||||
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.it.map(T::clone).rfold(init, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
|
||||
where
|
||||
I: ExactSizeIterator<Item = &'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.it.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.it.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, I, T: 'a> FusedIterator for Cloned<I>
|
||||
where
|
||||
I: FusedIterator<Item = &'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Cloned<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn may_have_side_effect() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
|
||||
where
|
||||
I: TrustedLen<Item = &'a T>,
|
||||
T: Clone,
|
||||
{
|
||||
}
|
155
library/core/src/iter/adapters/copied.rs
Normal file
155
library/core/src/iter/adapters/copied.rs
Normal file
@ -0,0 +1,155 @@
|
||||
use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that copies the elements of an underlying iterator.
|
||||
///
|
||||
/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`copied`]: Iterator::copied
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Copied<I> {
|
||||
it: I,
|
||||
}
|
||||
|
||||
impl<I> Copied<I> {
|
||||
pub(in crate::iter) fn new(it: I) -> Copied<I> {
|
||||
Copied { it }
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
|
||||
move |acc, &elt| f(acc, elt)
|
||||
}
|
||||
|
||||
fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
|
||||
move |acc, &elt| f(acc, elt)
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
impl<'a, I, T: 'a> Iterator for Copied<I>
|
||||
where
|
||||
I: Iterator<Item = &'a T>,
|
||||
T: Copy,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.it.next().copied()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.it.size_hint()
|
||||
}
|
||||
|
||||
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.it.try_fold(init, copy_try_fold(f))
|
||||
}
|
||||
|
||||
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.it.fold(init, copy_fold(f))
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<T> {
|
||||
self.it.nth(n).copied()
|
||||
}
|
||||
|
||||
fn last(self) -> Option<T> {
|
||||
self.it.last().copied()
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.it.count()
|
||||
}
|
||||
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
*unsafe { try_get_unchecked(&mut self.it, idx) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
|
||||
where
|
||||
I: DoubleEndedIterator<Item = &'a T>,
|
||||
T: Copy,
|
||||
{
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.it.next_back().copied()
|
||||
}
|
||||
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.it.try_rfold(init, copy_try_fold(f))
|
||||
}
|
||||
|
||||
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.it.rfold(init, copy_fold(f))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
|
||||
where
|
||||
I: ExactSizeIterator<Item = &'a T>,
|
||||
T: Copy,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.it.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.it.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
impl<'a, I, T: 'a> FusedIterator for Copied<I>
|
||||
where
|
||||
I: FusedIterator<Item = &'a T>,
|
||||
T: Copy,
|
||||
{
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Copied<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
|
||||
where
|
||||
I: TrustedLen<Item = &'a T>,
|
||||
T: Copy,
|
||||
{
|
||||
}
|
87
library/core/src/iter/adapters/cycle.rs
Normal file
87
library/core/src/iter/adapters/cycle.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use crate::{iter::FusedIterator, ops::Try};
|
||||
|
||||
/// An iterator that repeats endlessly.
|
||||
///
|
||||
/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`cycle`]: Iterator::cycle
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Cycle<I> {
|
||||
orig: I,
|
||||
iter: I,
|
||||
}
|
||||
|
||||
impl<I: Clone> Cycle<I> {
|
||||
pub(in crate::iter) fn new(iter: I) -> Cycle<I> {
|
||||
Cycle { orig: iter.clone(), iter }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Cycle<I>
|
||||
where
|
||||
I: Clone + Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
match self.iter.next() {
|
||||
None => {
|
||||
self.iter = self.orig.clone();
|
||||
self.iter.next()
|
||||
}
|
||||
y => y,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
// the cycle iterator is either empty or infinite
|
||||
match self.orig.size_hint() {
|
||||
sz @ (0, Some(0)) => sz,
|
||||
(0, _) => (0, None),
|
||||
_ => (usize::MAX, None),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
// fully iterate the current iterator. this is necessary because
|
||||
// `self.iter` may be empty even when `self.orig` isn't
|
||||
acc = self.iter.try_fold(acc, &mut f)?;
|
||||
self.iter = self.orig.clone();
|
||||
|
||||
// complete a full cycle, keeping track of whether the cycled
|
||||
// iterator is empty or not. we need to return early in case
|
||||
// of an empty iterator to prevent an infinite loop
|
||||
let mut is_empty = true;
|
||||
acc = self.iter.try_fold(acc, |acc, x| {
|
||||
is_empty = false;
|
||||
f(acc, x)
|
||||
})?;
|
||||
|
||||
if is_empty {
|
||||
return try { acc };
|
||||
}
|
||||
|
||||
loop {
|
||||
self.iter = self.orig.clone();
|
||||
acc = self.iter.try_fold(acc, &mut f)?;
|
||||
}
|
||||
}
|
||||
|
||||
// No `fold` override, because `fold` doesn't make much sense for `Cycle`,
|
||||
// and we can't do anything better than the default.
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
|
238
library/core/src/iter/adapters/enumerate.rs
Normal file
238
library/core/src/iter/adapters/enumerate.rs
Normal file
@ -0,0 +1,238 @@
|
||||
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
|
||||
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::ops::{Add, AddAssign, Try};
|
||||
|
||||
/// An iterator that yields the current count and the element during iteration.
|
||||
///
|
||||
/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`enumerate`]: Iterator::enumerate
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Enumerate<I> {
|
||||
iter: I,
|
||||
count: usize,
|
||||
}
|
||||
impl<I> Enumerate<I> {
|
||||
pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
|
||||
Enumerate { iter, count: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Enumerate<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = (usize, <I as Iterator>::Item);
|
||||
|
||||
/// # Overflow Behavior
|
||||
///
|
||||
/// The method does no guarding against overflows, so enumerating more than
|
||||
/// `usize::MAX` elements either produces the wrong result or panics. If
|
||||
/// debug assertions are enabled, a panic is guaranteed.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Might panic if the index of the element overflows a `usize`.
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
|
||||
let a = self.iter.next()?;
|
||||
let i = self.count;
|
||||
// Possible undefined overflow.
|
||||
AddAssign::add_assign(&mut self.count, 1);
|
||||
Some((i, a))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> {
|
||||
let a = self.iter.nth(n)?;
|
||||
// Possible undefined overflow.
|
||||
let i = Add::add(self.count, n);
|
||||
self.count = Add::add(i, 1);
|
||||
Some((i, a))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.iter.count()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn enumerate<'a, T, Acc, R>(
|
||||
count: &'a mut usize,
|
||||
mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, item| {
|
||||
let acc = fold(acc, (*count, item));
|
||||
// Possible undefined overflow.
|
||||
AddAssign::add_assign(count, 1);
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
self.iter.try_fold(init, enumerate(&mut self.count, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn enumerate<T, Acc>(
|
||||
mut count: usize,
|
||||
mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, item| {
|
||||
let acc = fold(acc, (count, item));
|
||||
// Possible undefined overflow.
|
||||
AddAssign::add_assign(&mut count, 1);
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
self.iter.fold(init, enumerate(self.count, fold))
|
||||
}
|
||||
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
|
||||
(Add::add(self.count, idx), value)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> DoubleEndedIterator for Enumerate<I>
|
||||
where
|
||||
I: ExactSizeIterator + DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
|
||||
let a = self.iter.next_back()?;
|
||||
let len = self.iter.len();
|
||||
// Can safely add, `ExactSizeIterator` promises that the number of
|
||||
// elements fits into a `usize`.
|
||||
Some((self.count + len, a))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> {
|
||||
let a = self.iter.nth_back(n)?;
|
||||
let len = self.iter.len();
|
||||
// Can safely add, `ExactSizeIterator` promises that the number of
|
||||
// elements fits into a `usize`.
|
||||
Some((self.count + len, a))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
// Can safely add and subtract the count, as `ExactSizeIterator` promises
|
||||
// that the number of elements fits into a `usize`.
|
||||
fn enumerate<T, Acc, R>(
|
||||
mut count: usize,
|
||||
mut fold: impl FnMut(Acc, (usize, T)) -> R,
|
||||
) -> impl FnMut(Acc, T) -> R {
|
||||
move |acc, item| {
|
||||
count -= 1;
|
||||
fold(acc, (count, item))
|
||||
}
|
||||
}
|
||||
|
||||
let count = self.count + self.iter.len();
|
||||
self.iter.try_rfold(init, enumerate(count, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
// Can safely add and subtract the count, as `ExactSizeIterator` promises
|
||||
// that the number of elements fits into a `usize`.
|
||||
fn enumerate<T, Acc>(
|
||||
mut count: usize,
|
||||
mut fold: impl FnMut(Acc, (usize, T)) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, item| {
|
||||
count -= 1;
|
||||
fold(acc, (count, item))
|
||||
}
|
||||
}
|
||||
|
||||
let count = self.count + self.iter.len();
|
||||
self.iter.rfold(init, enumerate(count, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Enumerate<I>
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Enumerate<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I> TrustedLen for Enumerate<I> where I: TrustedLen {}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, I: Iterator> SourceIter for Enumerate<I>
|
||||
where
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable> InPlaceIterable for Enumerate<I> {}
|
152
library/core/src/iter/adapters/filter.rs
Normal file
152
library/core/src/iter/adapters/filter.rs
Normal file
@ -0,0 +1,152 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that filters the elements of `iter` with `predicate`.
|
||||
///
|
||||
/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`filter`]: Iterator::filter
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct Filter<I, P> {
|
||||
iter: I,
|
||||
predicate: P,
|
||||
}
|
||||
impl<I, P> Filter<I, P> {
|
||||
pub(in crate::iter) fn new(iter: I, predicate: P) -> Filter<I, P> {
|
||||
Filter { iter, predicate }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Filter").field("iter", &self.iter).finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_fold<T, Acc>(
|
||||
mut predicate: impl FnMut(&T) -> bool,
|
||||
mut fold: impl FnMut(Acc, T) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
|
||||
}
|
||||
|
||||
fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
|
||||
predicate: &'a mut impl FnMut(&T) -> bool,
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, item| if predicate(&item) { fold(acc, item) } else { try { acc } }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator, P> Iterator for Filter<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
self.iter.find(&mut self.predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
|
||||
// this special case allows the compiler to make `.filter(_).count()`
|
||||
// branchless. Barring perfect branch prediction (which is unattainable in
|
||||
// the general case), this will be much faster in >90% of cases (containing
|
||||
// virtually all real workloads) and only a tiny bit slower in the rest.
|
||||
//
|
||||
// Having this specialization thus allows us to write `.filter(p).count()`
|
||||
// where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is
|
||||
// less readable and also less backwards-compatible to Rust before 1.10.
|
||||
//
|
||||
// Using the branchless version will also simplify the LLVM byte code, thus
|
||||
// leaving more budget for LLVM optimizations.
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
#[inline]
|
||||
fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize {
|
||||
move |x| predicate(&x) as usize
|
||||
}
|
||||
|
||||
self.iter.map(to_usize(self.predicate)).sum()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.fold(init, filter_fold(self.predicate, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<I::Item> {
|
||||
self.iter.rfind(&mut self.predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.rfold(init, filter_fold(self.predicate, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable, P> InPlaceIterable for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
|
150
library/core/src/iter/adapters/filter_map.rs
Normal file
150
library/core/src/iter/adapters/filter_map.rs
Normal file
@ -0,0 +1,150 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that uses `f` to both filter and map elements from `iter`.
|
||||
///
|
||||
/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`filter_map`]: Iterator::filter_map
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct FilterMap<I, F> {
|
||||
iter: I,
|
||||
f: F,
|
||||
}
|
||||
impl<I, F> FilterMap<I, F> {
|
||||
pub(in crate::iter) fn new(iter: I, f: F) -> FilterMap<I, F> {
|
||||
FilterMap { iter, f }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, F> fmt::Debug for FilterMap<I, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FilterMap").field("iter", &self.iter).finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_map_fold<T, B, Acc>(
|
||||
mut f: impl FnMut(T) -> Option<B>,
|
||||
mut fold: impl FnMut(Acc, B) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, item| match f(item) {
|
||||
Some(x) => fold(acc, x),
|
||||
None => acc,
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
|
||||
f: &'a mut impl FnMut(T) -> Option<B>,
|
||||
mut fold: impl FnMut(Acc, B) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, item| match f(item) {
|
||||
Some(x) => fold(acc, x),
|
||||
None => try { acc },
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> Option<B>,
|
||||
{
|
||||
type Item = B;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
self.iter.find_map(&mut self.f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.fold(init, filter_map_fold(self.f, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> Option<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<B> {
|
||||
#[inline]
|
||||
fn find<T, B>(
|
||||
f: &mut impl FnMut(T) -> Option<B>,
|
||||
) -> impl FnMut((), T) -> ControlFlow<B> + '_ {
|
||||
move |(), x| match f(x) {
|
||||
Some(x) => ControlFlow::Break(x),
|
||||
None => ControlFlow::CONTINUE,
|
||||
}
|
||||
}
|
||||
|
||||
self.iter.try_rfold((), find(&mut self.f)).break_value()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.rfold(init, filter_map_fold(self.f, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> Option<B>,
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for FilterMap<I, F> where
|
||||
F: FnMut(I::Item) -> Option<B>
|
||||
{
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map};
|
||||
use crate::ops::Try;
|
||||
|
||||
use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
|
||||
use super::Map;
|
||||
|
||||
/// An iterator that maps each element to an iterator, and yields the elements
|
||||
/// of the produced iterators.
|
||||
///
|
||||
@ -14,8 +12,9 @@ use super::Map;
|
||||
pub struct FlatMap<I, U: IntoIterator, F> {
|
||||
inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
|
||||
}
|
||||
|
||||
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
|
||||
pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
|
||||
pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
|
||||
FlatMap { inner: FlattenCompat::new(iter.map(f)) }
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
use super::InPlaceIterable;
|
||||
use crate::intrinsics;
|
||||
use crate::iter::adapters::zip::try_get_unchecked;
|
||||
use crate::iter::adapters::SourceIter;
|
||||
use crate::iter::TrustedRandomAccess;
|
||||
use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
|
||||
use crate::iter::adapters::{zip::try_get_unchecked, InPlaceIterable, SourceIter};
|
||||
use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedRandomAccess};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that yields `None` forever after the underlying iterator
|
||||
|
167
library/core/src/iter/adapters/inspect.rs
Normal file
167
library/core/src/iter/adapters/inspect.rs
Normal file
@ -0,0 +1,167 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that calls a function with a reference to each element before
|
||||
/// yielding it.
|
||||
///
|
||||
/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`inspect`]: Iterator::inspect
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct Inspect<I, F> {
|
||||
iter: I,
|
||||
f: F,
|
||||
}
|
||||
impl<I, F> Inspect<I, F> {
|
||||
pub(in crate::iter) fn new(iter: I, f: F) -> Inspect<I, F> {
|
||||
Inspect { iter, f }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, F> fmt::Debug for Inspect<I, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Inspect").field("iter", &self.iter).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator, F> Inspect<I, F>
|
||||
where
|
||||
F: FnMut(&I::Item),
|
||||
{
|
||||
#[inline]
|
||||
fn do_inspect(&mut self, elt: Option<I::Item>) -> Option<I::Item> {
|
||||
if let Some(ref a) = elt {
|
||||
(self.f)(a);
|
||||
}
|
||||
|
||||
elt
|
||||
}
|
||||
}
|
||||
|
||||
fn inspect_fold<T, Acc>(
|
||||
mut f: impl FnMut(&T),
|
||||
mut fold: impl FnMut(Acc, T) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, item| {
|
||||
f(&item);
|
||||
fold(acc, item)
|
||||
}
|
||||
}
|
||||
|
||||
fn inspect_try_fold<'a, T, Acc, R>(
|
||||
f: &'a mut impl FnMut(&T),
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, item| {
|
||||
f(&item);
|
||||
fold(acc, item)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator, F> Iterator for Inspect<I, F>
|
||||
where
|
||||
F: FnMut(&I::Item),
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
let next = self.iter.next();
|
||||
self.do_inspect(next)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.fold(init, inspect_fold(self.f, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
|
||||
where
|
||||
F: FnMut(&I::Item),
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<I::Item> {
|
||||
let next = self.iter.next_back();
|
||||
self.do_inspect(next)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.rfold(init, inspect_fold(self.f, fold))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
|
||||
where
|
||||
F: FnMut(&I::Item),
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F>
|
||||
where
|
||||
F: FnMut(&I::Item),
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Inspect<I, F> where F: FnMut(&I::Item) {}
|
213
library/core/src/iter/adapters/map.rs
Normal file
213
library/core/src/iter/adapters/map.rs
Normal file
@ -0,0 +1,213 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
|
||||
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that maps the values of `iter` with `f`.
|
||||
///
|
||||
/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`map`]: Iterator::map
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
///
|
||||
/// # Notes about side effects
|
||||
///
|
||||
/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that
|
||||
/// you can also [`map`] backwards:
|
||||
///
|
||||
/// ```rust
|
||||
/// let v: Vec<i32> = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect();
|
||||
///
|
||||
/// assert_eq!(v, [4, 3, 2]);
|
||||
/// ```
|
||||
///
|
||||
/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
|
||||
///
|
||||
/// But if your closure has state, iterating backwards may act in a way you do
|
||||
/// not expect. Let's go through an example. First, in the forward direction:
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut c = 0;
|
||||
///
|
||||
/// for pair in vec!['a', 'b', 'c'].into_iter()
|
||||
/// .map(|letter| { c += 1; (letter, c) }) {
|
||||
/// println!("{:?}", pair);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This will print "('a', 1), ('b', 2), ('c', 3)".
|
||||
///
|
||||
/// Now consider this twist where we add a call to `rev`. This version will
|
||||
/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
|
||||
/// but the values of the counter still go in order. This is because `map()` is
|
||||
/// still being called lazily on each item, but we are popping items off the
|
||||
/// back of the vector now, instead of shifting them from the front.
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut c = 0;
|
||||
///
|
||||
/// for pair in vec!['a', 'b', 'c'].into_iter()
|
||||
/// .map(|letter| { c += 1; (letter, c) })
|
||||
/// .rev() {
|
||||
/// println!("{:?}", pair);
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct Map<I, F> {
|
||||
iter: I,
|
||||
f: F,
|
||||
}
|
||||
impl<I, F> Map<I, F> {
|
||||
pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
|
||||
Map { iter, f }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Map").field("iter", &self.iter).finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn map_fold<T, B, Acc>(
|
||||
mut f: impl FnMut(T) -> B,
|
||||
mut g: impl FnMut(Acc, B) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, elt| g(acc, f(elt))
|
||||
}
|
||||
|
||||
fn map_try_fold<'a, T, B, Acc, R>(
|
||||
f: &'a mut impl FnMut(T) -> B,
|
||||
mut g: impl FnMut(Acc, B) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, elt| g(acc, f(elt))
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I: Iterator, F> Iterator for Map<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> B,
|
||||
{
|
||||
type Item = B;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
self.iter.next().map(&mut self.f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
G: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
|
||||
}
|
||||
|
||||
fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
|
||||
where
|
||||
G: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.fold(init, map_fold(self.f, g))
|
||||
}
|
||||
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> B,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<B> {
|
||||
self.iter.next_back().map(&mut self.f)
|
||||
}
|
||||
|
||||
fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
G: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
|
||||
}
|
||||
|
||||
fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
|
||||
where
|
||||
G: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.rfold(init, map_fold(self.f, g))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> B,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<B, I: FusedIterator, F> FusedIterator for Map<I, F> where F: FnMut(I::Item) -> B {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<B, I, F> TrustedLen for Map<I, F>
|
||||
where
|
||||
I: TrustedLen,
|
||||
F: FnMut(I::Item) -> B,
|
||||
{
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn may_have_side_effect() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for Map<I, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> B,
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for Map<I, F> where F: FnMut(I::Item) -> B {}
|
101
library/core/src/iter/adapters/map_while.rs
Normal file
101
library/core/src/iter/adapters/map_while.rs
Normal file
@ -0,0 +1,101 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, InPlaceIterable};
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that only accepts elements while `predicate` returns `Some(_)`.
|
||||
///
|
||||
/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`map_while`]: Iterator::map_while
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
#[derive(Clone)]
|
||||
pub struct MapWhile<I, P> {
|
||||
iter: I,
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
impl<I, P> MapWhile<I, P> {
|
||||
pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
|
||||
MapWhile { iter, predicate }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
|
||||
where
|
||||
P: FnMut(I::Item) -> Option<B>,
|
||||
{
|
||||
type Item = B;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
let x = self.iter.next()?;
|
||||
(self.predicate)(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
let Self { iter, predicate } = self;
|
||||
iter.try_fold(init, |acc, x| match predicate(x) {
|
||||
Some(item) => ControlFlow::from_try(fold(acc, item)),
|
||||
None => ControlFlow::Break(try { acc }),
|
||||
})
|
||||
.into_try()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_fold(init, ok(fold)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, B, I: Iterator, P> SourceIter for MapWhile<I, P>
|
||||
where
|
||||
P: FnMut(I::Item) -> Option<B>,
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<B, I: InPlaceIterable, P> InPlaceIterable for MapWhile<I, P> where
|
||||
P: FnMut(I::Item) -> Option<B>
|
||||
{
|
||||
}
|
File diff suppressed because it is too large
Load Diff
301
library/core/src/iter/adapters/peekable.rs
Normal file
301
library/core/src/iter/adapters/peekable.rs
Normal file
@ -0,0 +1,301 @@
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator with a `peek()` that returns an optional reference to the next
|
||||
/// element.
|
||||
///
|
||||
/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`peekable`]: Iterator::peekable
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Peekable<I: Iterator> {
|
||||
iter: I,
|
||||
/// Remember a peeked value, even if it was None.
|
||||
peeked: Option<Option<I::Item>>,
|
||||
}
|
||||
|
||||
impl<I: Iterator> Peekable<I> {
|
||||
pub(in crate::iter) fn new(iter: I) -> Peekable<I> {
|
||||
Peekable { iter, peeked: None }
|
||||
}
|
||||
}
|
||||
|
||||
// Peekable must remember if a None has been seen in the `.peek()` method.
|
||||
// It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
|
||||
// underlying iterator at most once. This does not by itself make the iterator
|
||||
// fused.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator> Iterator for Peekable<I> {
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
match self.peeked.take() {
|
||||
Some(v) => v,
|
||||
None => self.iter.next(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn count(mut self) -> usize {
|
||||
match self.peeked.take() {
|
||||
Some(None) => 0,
|
||||
Some(Some(_)) => 1 + self.iter.count(),
|
||||
None => self.iter.count(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
match self.peeked.take() {
|
||||
Some(None) => None,
|
||||
Some(v @ Some(_)) if n == 0 => v,
|
||||
Some(Some(_)) => self.iter.nth(n - 1),
|
||||
None => self.iter.nth(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<I::Item> {
|
||||
let peek_opt = match self.peeked.take() {
|
||||
Some(None) => return None,
|
||||
Some(v) => v,
|
||||
None => None,
|
||||
};
|
||||
self.iter.last().or(peek_opt)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let peek_len = match self.peeked {
|
||||
Some(None) => return (0, Some(0)),
|
||||
Some(Some(_)) => 1,
|
||||
None => 0,
|
||||
};
|
||||
let (lo, hi) = self.iter.size_hint();
|
||||
let lo = lo.saturating_add(peek_len);
|
||||
let hi = match hi {
|
||||
Some(x) => x.checked_add(peek_len),
|
||||
None => None,
|
||||
};
|
||||
(lo, hi)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
let acc = match self.peeked.take() {
|
||||
Some(None) => return try { init },
|
||||
Some(Some(v)) => f(init, v)?,
|
||||
None => init,
|
||||
};
|
||||
self.iter.try_fold(acc, f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let acc = match self.peeked {
|
||||
Some(None) => return init,
|
||||
Some(Some(v)) => fold(init, v),
|
||||
None => init,
|
||||
};
|
||||
self.iter.fold(acc, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "double_ended_peek_iterator", since = "1.38.0")]
|
||||
impl<I> DoubleEndedIterator for Peekable<I>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
match self.peeked.as_mut() {
|
||||
Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()),
|
||||
Some(None) => None,
|
||||
None => self.iter.next_back(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
match self.peeked.take() {
|
||||
Some(None) => try { init },
|
||||
Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
|
||||
Ok(acc) => f(acc, v),
|
||||
Err(e) => {
|
||||
self.peeked = Some(Some(v));
|
||||
Try::from_error(e)
|
||||
}
|
||||
},
|
||||
None => self.iter.try_rfold(init, f),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
match self.peeked {
|
||||
Some(None) => init,
|
||||
Some(Some(v)) => {
|
||||
let acc = self.iter.rfold(init, &mut fold);
|
||||
fold(acc, v)
|
||||
}
|
||||
None => self.iter.rfold(init, fold),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: ExactSizeIterator> ExactSizeIterator for Peekable<I> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I: FusedIterator> FusedIterator for Peekable<I> {}
|
||||
|
||||
impl<I: Iterator> Peekable<I> {
|
||||
/// Returns a reference to the next() value without advancing the iterator.
|
||||
///
|
||||
/// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
|
||||
/// But if the iteration is over, `None` is returned.
|
||||
///
|
||||
/// [`next`]: Iterator::next
|
||||
///
|
||||
/// Because `peek()` returns a reference, and many iterators iterate over
|
||||
/// references, there can be a possibly confusing situation where the
|
||||
/// return value is a double reference. You can see this effect in the
|
||||
/// examples below.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let xs = [1, 2, 3];
|
||||
///
|
||||
/// let mut iter = xs.iter().peekable();
|
||||
///
|
||||
/// // peek() lets us see into the future
|
||||
/// assert_eq!(iter.peek(), Some(&&1));
|
||||
/// assert_eq!(iter.next(), Some(&1));
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(&2));
|
||||
///
|
||||
/// // The iterator does not advance even if we `peek` multiple times
|
||||
/// assert_eq!(iter.peek(), Some(&&3));
|
||||
/// assert_eq!(iter.peek(), Some(&&3));
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(&3));
|
||||
///
|
||||
/// // After the iterator is finished, so is `peek()`
|
||||
/// assert_eq!(iter.peek(), None);
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn peek(&mut self) -> Option<&I::Item> {
|
||||
let iter = &mut self.iter;
|
||||
self.peeked.get_or_insert_with(|| iter.next()).as_ref()
|
||||
}
|
||||
|
||||
/// Consume and return the next value of this iterator if a condition is true.
|
||||
///
|
||||
/// If `func` returns `true` for the next value of this iterator, consume and return it.
|
||||
/// Otherwise, return `None`.
|
||||
///
|
||||
/// # Examples
|
||||
/// Consume a number if it's equal to 0.
|
||||
/// ```
|
||||
/// #![feature(peekable_next_if)]
|
||||
/// let mut iter = (0..5).peekable();
|
||||
/// // The first item of the iterator is 0; consume it.
|
||||
/// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
|
||||
/// // The next item returned is now 1, so `consume` will return `false`.
|
||||
/// assert_eq!(iter.next_if(|&x| x == 0), None);
|
||||
/// // `next_if` saves the value of the next item if it was not equal to `expected`.
|
||||
/// assert_eq!(iter.next(), Some(1));
|
||||
/// ```
|
||||
///
|
||||
/// Consume any number less than 10.
|
||||
/// ```
|
||||
/// #![feature(peekable_next_if)]
|
||||
/// let mut iter = (1..20).peekable();
|
||||
/// // Consume all numbers less than 10
|
||||
/// while iter.next_if(|&x| x < 10).is_some() {}
|
||||
/// // The next value returned will be 10
|
||||
/// assert_eq!(iter.next(), Some(10));
|
||||
/// ```
|
||||
#[unstable(feature = "peekable_next_if", issue = "72480")]
|
||||
pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
|
||||
match self.next() {
|
||||
Some(matched) if func(&matched) => Some(matched),
|
||||
other => {
|
||||
// Since we called `self.next()`, we consumed `self.peeked`.
|
||||
assert!(self.peeked.is_none());
|
||||
self.peeked = Some(other);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume and return the next item if it is equal to `expected`.
|
||||
///
|
||||
/// # Example
|
||||
/// Consume a number if it's equal to 0.
|
||||
/// ```
|
||||
/// #![feature(peekable_next_if)]
|
||||
/// let mut iter = (0..5).peekable();
|
||||
/// // The first item of the iterator is 0; consume it.
|
||||
/// assert_eq!(iter.next_if_eq(&0), Some(0));
|
||||
/// // The next item returned is now 1, so `consume` will return `false`.
|
||||
/// assert_eq!(iter.next_if_eq(&0), None);
|
||||
/// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
|
||||
/// assert_eq!(iter.next(), Some(1));
|
||||
/// ```
|
||||
#[unstable(feature = "peekable_next_if", issue = "72480")]
|
||||
pub fn next_if_eq<T>(&mut self, expected: &T) -> Option<I::Item>
|
||||
where
|
||||
T: ?Sized,
|
||||
I::Item: PartialEq<T>,
|
||||
{
|
||||
self.next_if(|next| next == expected)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I> TrustedLen for Peekable<I> where I: TrustedLen {}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, I: Iterator> SourceIter for Peekable<I>
|
||||
where
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable> InPlaceIterable for Peekable<I> {}
|
137
library/core/src/iter/adapters/rev.rs
Normal file
137
library/core/src/iter/adapters/rev.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// A double-ended iterator with the direction inverted.
|
||||
///
|
||||
/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`rev`]: Iterator::rev
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Rev<T> {
|
||||
iter: T,
|
||||
}
|
||||
|
||||
impl<T> Rev<T> {
|
||||
pub(in crate::iter) fn new(iter: T) -> Rev<T> {
|
||||
Rev { iter }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Rev<I>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
self.iter.next_back()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
self.iter.advance_back_by(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
|
||||
self.iter.nth_back(n)
|
||||
}
|
||||
|
||||
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.iter.try_rfold(init, f)
|
||||
}
|
||||
|
||||
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.rfold(init, f)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
self.iter.rfind(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> DoubleEndedIterator for Rev<I>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
self.iter.advance_by(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
|
||||
self.iter.nth(n)
|
||||
}
|
||||
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
self.iter.try_fold(init, f)
|
||||
}
|
||||
|
||||
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.iter.fold(init, f)
|
||||
}
|
||||
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
self.iter.find(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Rev<I>
|
||||
where
|
||||
I: ExactSizeIterator + DoubleEndedIterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> FusedIterator for Rev<I> where I: FusedIterator + DoubleEndedIterator {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I> TrustedLen for Rev<I> where I: TrustedLen + DoubleEndedIterator {}
|
111
library/core/src/iter/adapters/scan.rs
Normal file
111
library/core/src/iter/adapters/scan.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, InPlaceIterable};
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator to maintain state while iterating another iterator.
|
||||
///
|
||||
/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`scan`]: Iterator::scan
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct Scan<I, St, F> {
|
||||
iter: I,
|
||||
f: F,
|
||||
state: St,
|
||||
}
|
||||
|
||||
impl<I, St, F> Scan<I, St, F> {
|
||||
pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
|
||||
Scan { iter, state, f }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, St: fmt::Debug, F> fmt::Debug for Scan<I, St, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Scan").field("iter", &self.iter).field("state", &self.state).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I, St, F> Iterator for Scan<I, St, F>
|
||||
where
|
||||
I: Iterator,
|
||||
F: FnMut(&mut St, I::Item) -> Option<B>,
|
||||
{
|
||||
type Item = B;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
let a = self.iter.next()?;
|
||||
(self.f)(&mut self.state, a)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the scan function
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
|
||||
state: &'a mut St,
|
||||
f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
|
||||
mut fold: impl FnMut(Acc, B) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
|
||||
move |acc, x| match f(state, x) {
|
||||
None => ControlFlow::Break(try { acc }),
|
||||
Some(x) => ControlFlow::from_try(fold(acc, x)),
|
||||
}
|
||||
}
|
||||
|
||||
let state = &mut self.state;
|
||||
let f = &mut self.f;
|
||||
self.iter.try_fold(init, scan(state, f, fold)).into_try()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_fold(init, ok(fold)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F>
|
||||
where
|
||||
I: SourceIter<Source = S>,
|
||||
F: FnMut(&mut St, I::Item) -> Option<B>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<St, F, B, I: InPlaceIterable> InPlaceIterable for Scan<I, St, F> where
|
||||
F: FnMut(&mut St, I::Item) -> Option<B>
|
||||
{
|
||||
}
|
199
library/core/src/iter/adapters/skip.rs
Normal file
199
library/core/src/iter/adapters/skip.rs
Normal file
@ -0,0 +1,199 @@
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that skips over `n` elements of `iter`.
|
||||
///
|
||||
/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`skip`]: Iterator::skip
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Skip<I> {
|
||||
iter: I,
|
||||
n: usize,
|
||||
}
|
||||
|
||||
impl<I> Skip<I> {
|
||||
pub(in crate::iter) fn new(iter: I, n: usize) -> Skip<I> {
|
||||
Skip { iter, n }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Skip<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
if self.n == 0 {
|
||||
self.iter.next()
|
||||
} else {
|
||||
let old_n = self.n;
|
||||
self.n = 0;
|
||||
self.iter.nth(old_n)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
// Can't just add n + self.n due to overflow.
|
||||
if self.n > 0 {
|
||||
let to_skip = self.n;
|
||||
self.n = 0;
|
||||
// nth(n) skips n+1
|
||||
self.iter.nth(to_skip - 1)?;
|
||||
}
|
||||
self.iter.nth(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(mut self) -> usize {
|
||||
if self.n > 0 {
|
||||
// nth(n) skips n+1
|
||||
if self.iter.nth(self.n - 1).is_none() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
self.iter.count()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<I::Item> {
|
||||
if self.n > 0 {
|
||||
// nth(n) skips n+1
|
||||
self.iter.nth(self.n - 1)?;
|
||||
}
|
||||
self.iter.last()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (lower, upper) = self.iter.size_hint();
|
||||
|
||||
let lower = lower.saturating_sub(self.n);
|
||||
let upper = match upper {
|
||||
Some(x) => Some(x.saturating_sub(self.n)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
let n = self.n;
|
||||
self.n = 0;
|
||||
if n > 0 {
|
||||
// nth(n) skips n+1
|
||||
if self.iter.nth(n - 1).is_none() {
|
||||
return try { init };
|
||||
}
|
||||
}
|
||||
self.iter.try_fold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
if self.n > 0 {
|
||||
// nth(n) skips n+1
|
||||
if self.iter.nth(self.n - 1).is_none() {
|
||||
return init;
|
||||
}
|
||||
}
|
||||
self.iter.fold(init, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
|
||||
|
||||
#[stable(feature = "double_ended_skip_iterator", since = "1.9.0")]
|
||||
impl<I> DoubleEndedIterator for Skip<I>
|
||||
where
|
||||
I: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.len() > 0 { self.iter.next_back() } else { None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
|
||||
let len = self.len();
|
||||
if n < len {
|
||||
self.iter.nth_back(n)
|
||||
} else {
|
||||
if len > 0 {
|
||||
// consume the original iterator
|
||||
self.iter.nth_back(len - 1);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
fn check<T, Acc, R: Try<Ok = Acc>>(
|
||||
mut n: usize,
|
||||
mut fold: impl FnMut(Acc, T) -> R,
|
||||
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> {
|
||||
move |acc, x| {
|
||||
n -= 1;
|
||||
let r = fold(acc, x);
|
||||
if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
|
||||
}
|
||||
}
|
||||
|
||||
let n = self.len();
|
||||
if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() }
|
||||
}
|
||||
|
||||
fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_rfold(init, ok(fold)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, I: Iterator> SourceIter for Skip<I>
|
||||
where
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable> InPlaceIterable for Skip<I> {}
|
126
library/core/src/iter/adapters/skip_while.rs
Normal file
126
library/core/src/iter/adapters/skip_while.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that rejects elements while `predicate` returns `true`.
|
||||
///
|
||||
/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`skip_while`]: Iterator::skip_while
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct SkipWhile<I, P> {
|
||||
iter: I,
|
||||
flag: bool,
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
impl<I, P> SkipWhile<I, P> {
|
||||
pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
|
||||
SkipWhile { iter, flag: false, predicate }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, P> fmt::Debug for SkipWhile<I, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SkipWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator, P> Iterator for SkipWhile<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
fn check<'a, T>(
|
||||
flag: &'a mut bool,
|
||||
pred: &'a mut impl FnMut(&T) -> bool,
|
||||
) -> impl FnMut(&T) -> bool + 'a {
|
||||
move |x| {
|
||||
if *flag || !pred(x) {
|
||||
*flag = true;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let flag = &mut self.flag;
|
||||
let pred = &mut self.predicate;
|
||||
self.iter.find(check(flag, pred))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
if !self.flag {
|
||||
match self.next() {
|
||||
Some(v) => init = fold(init, v)?,
|
||||
None => return try { init },
|
||||
}
|
||||
}
|
||||
self.iter.try_fold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
if !self.flag {
|
||||
match self.next() {
|
||||
Some(v) => init = fold(init, v),
|
||||
None => return init,
|
||||
}
|
||||
}
|
||||
self.iter.fold(init, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I, P> FusedIterator for SkipWhile<I, P>
|
||||
where
|
||||
I: FusedIterator,
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable, F> InPlaceIterable for SkipWhile<I, F> where
|
||||
F: FnMut(&I::Item) -> bool
|
||||
{
|
||||
}
|
235
library/core/src/iter/adapters/step_by.rs
Normal file
235
library/core/src/iter/adapters/step_by.rs
Normal file
@ -0,0 +1,235 @@
|
||||
use crate::{intrinsics, iter::from_fn, ops::Try};
|
||||
|
||||
/// An iterator for stepping iterators by a custom amount.
|
||||
///
|
||||
/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`step_by`]: Iterator::step_by
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StepBy<I> {
|
||||
iter: I,
|
||||
step: usize,
|
||||
first_take: bool,
|
||||
}
|
||||
|
||||
impl<I> StepBy<I> {
|
||||
pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy<I> {
|
||||
assert!(step != 0);
|
||||
StepBy { iter, step: step - 1, first_take: true }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
impl<I> Iterator for StepBy<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.first_take {
|
||||
self.first_take = false;
|
||||
self.iter.next()
|
||||
} else {
|
||||
self.iter.nth(self.step)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
#[inline]
|
||||
fn first_size(step: usize) -> impl Fn(usize) -> usize {
|
||||
move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn other_size(step: usize) -> impl Fn(usize) -> usize {
|
||||
move |n| n / (step + 1)
|
||||
}
|
||||
|
||||
let (low, high) = self.iter.size_hint();
|
||||
|
||||
if self.first_take {
|
||||
let f = first_size(self.step);
|
||||
(f(low), high.map(f))
|
||||
} else {
|
||||
let f = other_size(self.step);
|
||||
(f(low), high.map(f))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
|
||||
if self.first_take {
|
||||
self.first_take = false;
|
||||
let first = self.iter.next();
|
||||
if n == 0 {
|
||||
return first;
|
||||
}
|
||||
n -= 1;
|
||||
}
|
||||
// n and self.step are indices, we need to add 1 to get the amount of elements
|
||||
// When calling `.nth`, we need to subtract 1 again to convert back to an index
|
||||
// step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1`
|
||||
let mut step = self.step + 1;
|
||||
// n + 1 could overflow
|
||||
// thus, if n is usize::MAX, instead of adding one, we call .nth(step)
|
||||
if n == usize::MAX {
|
||||
self.iter.nth(step - 1);
|
||||
} else {
|
||||
n += 1;
|
||||
}
|
||||
|
||||
// overflow handling
|
||||
loop {
|
||||
let mul = n.checked_mul(step);
|
||||
{
|
||||
if intrinsics::likely(mul.is_some()) {
|
||||
return self.iter.nth(mul.unwrap() - 1);
|
||||
}
|
||||
}
|
||||
let div_n = usize::MAX / n;
|
||||
let div_step = usize::MAX / step;
|
||||
let nth_n = div_n * n;
|
||||
let nth_step = div_step * step;
|
||||
let nth = if nth_n > nth_step {
|
||||
step -= div_n;
|
||||
nth_n
|
||||
} else {
|
||||
n -= div_step;
|
||||
nth_step
|
||||
};
|
||||
self.iter.nth(nth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
|
||||
move || iter.nth(step)
|
||||
}
|
||||
|
||||
if self.first_take {
|
||||
self.first_take = false;
|
||||
match self.iter.next() {
|
||||
None => return try { acc },
|
||||
Some(x) => acc = f(acc, x)?,
|
||||
}
|
||||
}
|
||||
from_fn(nth(&mut self.iter, self.step)).try_fold(acc, f)
|
||||
}
|
||||
|
||||
fn fold<Acc, F>(mut self, mut acc: Acc, mut f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
|
||||
move || iter.nth(step)
|
||||
}
|
||||
|
||||
if self.first_take {
|
||||
self.first_take = false;
|
||||
match self.iter.next() {
|
||||
None => return acc,
|
||||
Some(x) => acc = f(acc, x),
|
||||
}
|
||||
}
|
||||
from_fn(nth(&mut self.iter, self.step)).fold(acc, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> StepBy<I>
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
// The zero-based index starting from the end of the iterator of the
|
||||
// last element. Used in the `DoubleEndedIterator` implementation.
|
||||
fn next_back_index(&self) -> usize {
|
||||
let rem = self.iter.len() % (self.step + 1);
|
||||
if self.first_take {
|
||||
if rem == 0 { self.step } else { rem - 1 }
|
||||
} else {
|
||||
rem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "double_ended_step_by_iterator", since = "1.38.0")]
|
||||
impl<I> DoubleEndedIterator for StepBy<I>
|
||||
where
|
||||
I: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter.nth_back(self.next_back_index())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
// `self.iter.nth_back(usize::MAX)` does the right thing here when `n`
|
||||
// is out of bounds because the length of `self.iter` does not exceed
|
||||
// `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is
|
||||
// zero-indexed
|
||||
let n = n.saturating_mul(self.step + 1).saturating_add(self.next_back_index());
|
||||
self.iter.nth_back(n)
|
||||
}
|
||||
|
||||
fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn nth_back<I: DoubleEndedIterator>(
|
||||
iter: &mut I,
|
||||
step: usize,
|
||||
) -> impl FnMut() -> Option<I::Item> + '_ {
|
||||
move || iter.nth_back(step)
|
||||
}
|
||||
|
||||
match self.next_back() {
|
||||
None => try { init },
|
||||
Some(x) => {
|
||||
let acc = f(init, x)?;
|
||||
from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn nth_back<I: DoubleEndedIterator>(
|
||||
iter: &mut I,
|
||||
step: usize,
|
||||
) -> impl FnMut() -> Option<I::Item> + '_ {
|
||||
move || iter.nth_back(step)
|
||||
}
|
||||
|
||||
match self.next_back() {
|
||||
None => init,
|
||||
Some(x) => {
|
||||
let acc = f(init, x);
|
||||
from_fn(nth_back(&mut self.iter, self.step)).fold(acc, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StepBy can only make the iterator shorter, so the len will still fit.
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
|
209
library/core/src/iter/adapters/take.rs
Normal file
209
library/core/src/iter/adapters/take.rs
Normal file
@ -0,0 +1,209 @@
|
||||
use crate::cmp;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that only iterates over the first `n` iterations of `iter`.
|
||||
///
|
||||
/// This `struct` is created by the [`take`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`take`]: Iterator::take
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Take<I> {
|
||||
iter: I,
|
||||
n: usize,
|
||||
}
|
||||
|
||||
impl<I> Take<I> {
|
||||
pub(in crate::iter) fn new(iter: I, n: usize) -> Take<I> {
|
||||
Take { iter, n }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Take<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
if self.n != 0 {
|
||||
self.n -= 1;
|
||||
self.iter.next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
if self.n > n {
|
||||
self.n -= n + 1;
|
||||
self.iter.nth(n)
|
||||
} else {
|
||||
if self.n > 0 {
|
||||
self.iter.nth(self.n - 1);
|
||||
self.n = 0;
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.n == 0 {
|
||||
return (0, Some(0));
|
||||
}
|
||||
|
||||
let (lower, upper) = self.iter.size_hint();
|
||||
|
||||
let lower = cmp::min(lower, self.n);
|
||||
|
||||
let upper = match upper {
|
||||
Some(x) if x < self.n => Some(x),
|
||||
_ => Some(self.n),
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
|
||||
n: &'a mut usize,
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
|
||||
move |acc, x| {
|
||||
*n -= 1;
|
||||
let r = fold(acc, x);
|
||||
if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
|
||||
}
|
||||
}
|
||||
|
||||
if self.n == 0 {
|
||||
try { init }
|
||||
} else {
|
||||
let n = &mut self.n;
|
||||
self.iter.try_fold(init, check(n, fold)).into_try()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_fold(init, ok(fold)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I>
|
||||
where
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable> InPlaceIterable for Take<I> {}
|
||||
|
||||
#[stable(feature = "double_ended_take_iterator", since = "1.38.0")]
|
||||
impl<I> DoubleEndedIterator for Take<I>
|
||||
where
|
||||
I: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.n == 0 {
|
||||
None
|
||||
} else {
|
||||
let n = self.n;
|
||||
self.n -= 1;
|
||||
self.iter.nth_back(self.iter.len().saturating_sub(n))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let len = self.iter.len();
|
||||
if self.n > n {
|
||||
let m = len.saturating_sub(self.n) + n;
|
||||
self.n -= n + 1;
|
||||
self.iter.nth_back(m)
|
||||
} else {
|
||||
if len > 0 {
|
||||
self.iter.nth_back(len - 1);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
if self.n == 0 {
|
||||
try { init }
|
||||
} else {
|
||||
let len = self.iter.len();
|
||||
if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
|
||||
try { init }
|
||||
} else {
|
||||
self.iter.try_rfold(init, fold)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
if self.n == 0 {
|
||||
init
|
||||
} else {
|
||||
let len = self.iter.len();
|
||||
if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
|
||||
init
|
||||
} else {
|
||||
self.iter.rfold(init, fold)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> FusedIterator for Take<I> where I: FusedIterator {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
|
139
library/core/src/iter/adapters/take_while.rs
Normal file
139
library/core/src/iter/adapters/take_while.rs
Normal file
@ -0,0 +1,139 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that only accepts elements while `predicate` returns `true`.
|
||||
///
|
||||
/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`take_while`]: Iterator::take_while
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct TakeWhile<I, P> {
|
||||
iter: I,
|
||||
flag: bool,
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
impl<I, P> TakeWhile<I, P> {
|
||||
pub(in crate::iter) fn new(iter: I, predicate: P) -> TakeWhile<I, P> {
|
||||
TakeWhile { iter, flag: false, predicate }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, P> fmt::Debug for TakeWhile<I, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("TakeWhile").field("iter", &self.iter).field("flag", &self.flag).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator, P> Iterator for TakeWhile<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
if self.flag {
|
||||
None
|
||||
} else {
|
||||
let x = self.iter.next()?;
|
||||
if (self.predicate)(&x) {
|
||||
Some(x)
|
||||
} else {
|
||||
self.flag = true;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.flag {
|
||||
(0, Some(0))
|
||||
} else {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
|
||||
flag: &'a mut bool,
|
||||
p: &'a mut impl FnMut(&T) -> bool,
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
|
||||
move |acc, x| {
|
||||
if p(&x) {
|
||||
ControlFlow::from_try(fold(acc, x))
|
||||
} else {
|
||||
*flag = true;
|
||||
ControlFlow::Break(try { acc })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.flag {
|
||||
try { init }
|
||||
} else {
|
||||
let flag = &mut self.flag;
|
||||
let p = &mut self.predicate;
|
||||
self.iter.try_fold(init, check(flag, p, fold)).into_try()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_fold(init, ok(fold)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I, P> FusedIterator for TakeWhile<I, P>
|
||||
where
|
||||
I: FusedIterator,
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, P, I: Iterator> SourceIter for TakeWhile<I, P>
|
||||
where
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable, F> InPlaceIterable for TakeWhile<I, F> where
|
||||
F: FnMut(&I::Item) -> bool
|
||||
{
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
use crate::cmp;
|
||||
use crate::fmt::{self, Debug};
|
||||
|
||||
use super::super::{
|
||||
DoubleEndedIterator, ExactSizeIterator, FusedIterator, InPlaceIterable, Iterator, SourceIter,
|
||||
TrustedLen,
|
||||
};
|
||||
use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
|
||||
use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
|
||||
|
||||
/// An iterator that iterates two other iterators simultaneously.
|
||||
///
|
||||
@ -21,7 +18,7 @@ pub struct Zip<A, B> {
|
||||
len: usize,
|
||||
}
|
||||
impl<A: Iterator, B: Iterator> Zip<A, B> {
|
||||
pub(in super::super) fn new(a: A, b: B) -> Zip<A, B> {
|
||||
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
|
||||
ZipImpl::new(a, b)
|
||||
}
|
||||
fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
|
||||
|
@ -335,15 +335,14 @@ pub use self::sources::{successors, Successors};
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
pub use self::traits::FusedIterator;
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
pub use self::traits::InPlaceIterable;
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
pub use self::traits::TrustedLen;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{DoubleEndedIterator, Extend, FromIterator, IntoIterator};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{ExactSizeIterator, Product, Sum};
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
pub use self::traits::InPlaceIterable;
|
||||
pub use self::traits::{
|
||||
DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
|
||||
};
|
||||
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
pub use self::adapters::Cloned;
|
||||
@ -351,21 +350,19 @@ pub use self::adapters::Cloned;
|
||||
pub use self::adapters::Copied;
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
pub use self::adapters::Flatten;
|
||||
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
pub use self::adapters::MapWhile;
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
#[unstable(feature = "inplace_iteration", issue = "none")]
|
||||
pub use self::adapters::SourceIter;
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
pub use self::adapters::StepBy;
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
pub use self::adapters::TrustedRandomAccess;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Chain, Cycle, Enumerate, Filter, FilterMap, Map, Rev, Zip};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{FlatMap, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Fuse, Inspect};
|
||||
pub use self::adapters::{
|
||||
Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
|
||||
Skip, SkipWhile, Take, TakeWhile, Zip,
|
||||
};
|
||||
|
||||
pub(crate) use self::adapters::process_results;
|
||||
|
||||
|
@ -1,625 +1,27 @@
|
||||
use crate::fmt;
|
||||
use crate::marker;
|
||||
mod empty;
|
||||
mod from_fn;
|
||||
mod once;
|
||||
mod once_with;
|
||||
mod repeat;
|
||||
mod repeat_with;
|
||||
mod successors;
|
||||
|
||||
use super::{FusedIterator, TrustedLen};
|
||||
pub use self::repeat::{repeat, Repeat};
|
||||
|
||||
/// An iterator that repeats an element endlessly.
|
||||
///
|
||||
/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Repeat<A> {
|
||||
element: A,
|
||||
}
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
pub use self::empty::{empty, Empty};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Clone> Iterator for Repeat<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
Some(self.element.clone())
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Clone> DoubleEndedIterator for Repeat<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
Some(self.element.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A: Clone> FusedIterator for Repeat<A> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
|
||||
|
||||
/// Creates a new iterator that endlessly repeats a single element.
|
||||
///
|
||||
/// The `repeat()` function repeats a single value over and over again.
|
||||
///
|
||||
/// Infinite iterators like `repeat()` are often used with adapters like
|
||||
/// [`Iterator::take()`], in order to make them finite.
|
||||
///
|
||||
/// If the element type of the iterator you need does not implement `Clone`,
|
||||
/// or if you do not want to keep the repeated element in memory, you can
|
||||
/// instead use the [`repeat_with()`] function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // the number four 4ever:
|
||||
/// let mut fours = iter::repeat(4);
|
||||
///
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
///
|
||||
/// // yup, still four
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// ```
|
||||
///
|
||||
/// Going finite with [`Iterator::take()`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // that last example was too many fours. Let's only have four fours.
|
||||
/// let mut four_fours = iter::repeat(4).take(4);
|
||||
///
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
///
|
||||
/// // ... and now we're done
|
||||
/// assert_eq!(None, four_fours.next());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
|
||||
Repeat { element: elt }
|
||||
}
|
||||
|
||||
/// An iterator that repeats elements of type `A` endlessly by
|
||||
/// applying the provided closure `F: FnMut() -> A`.
|
||||
///
|
||||
/// This `struct` is created by the [`repeat_with()`] function.
|
||||
/// See its documentation for more.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub struct RepeatWith<F> {
|
||||
repeater: F,
|
||||
}
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub use self::once::{once, Once};
|
||||
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
Some((self.repeater)())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
|
||||
|
||||
/// Creates a new iterator that repeats elements of type `A` endlessly by
|
||||
/// applying the provided closure, the repeater, `F: FnMut() -> A`.
|
||||
///
|
||||
/// The `repeat_with()` function calls the repeater over and over again.
|
||||
///
|
||||
/// Infinite iterators like `repeat_with()` are often used with adapters like
|
||||
/// [`Iterator::take()`], in order to make them finite.
|
||||
///
|
||||
/// If the element type of the iterator you need implements [`Clone`], and
|
||||
/// it is OK to keep the source element in memory, you should instead use
|
||||
/// the [`repeat()`] function.
|
||||
///
|
||||
/// An iterator produced by `repeat_with()` is not a [`DoubleEndedIterator`].
|
||||
/// If you need `repeat_with()` to return a [`DoubleEndedIterator`],
|
||||
/// please open a GitHub issue explaining your use case.
|
||||
///
|
||||
/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // let's assume we have some value of a type that is not `Clone`
|
||||
/// // or which don't want to have in memory just yet because it is expensive:
|
||||
/// #[derive(PartialEq, Debug)]
|
||||
/// struct Expensive;
|
||||
///
|
||||
/// // a particular value forever:
|
||||
/// let mut things = iter::repeat_with(|| Expensive);
|
||||
///
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// ```
|
||||
///
|
||||
/// Using mutation and going finite:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // From the zeroth to the third power of two:
|
||||
/// let mut curr = 1;
|
||||
/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
|
||||
/// .take(4);
|
||||
///
|
||||
/// assert_eq!(Some(1), pow2.next());
|
||||
/// assert_eq!(Some(2), pow2.next());
|
||||
/// assert_eq!(Some(4), pow2.next());
|
||||
/// assert_eq!(Some(8), pow2.next());
|
||||
///
|
||||
/// // ... and now we're done
|
||||
/// assert_eq!(None, pow2.next());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
|
||||
RepeatWith { repeater }
|
||||
}
|
||||
|
||||
/// An iterator that yields nothing.
|
||||
///
|
||||
/// This `struct` is created by the [`empty()`] function. See its documentation for more.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
pub struct Empty<T>(marker::PhantomData<T>);
|
||||
|
||||
#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
|
||||
unsafe impl<T> Send for Empty<T> {}
|
||||
#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
|
||||
unsafe impl<T> Sync for Empty<T> {}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<T> fmt::Debug for Empty<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Empty")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Iterator for Empty<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
None
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> DoubleEndedIterator for Empty<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> ExactSizeIterator for Empty<T> {
|
||||
fn len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T> TrustedLen for Empty<T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Empty<T> {}
|
||||
|
||||
// not #[derive] because that adds a Clone bound on T,
|
||||
// which isn't necessary.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Clone for Empty<T> {
|
||||
fn clone(&self) -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// not #[derive] because that adds a Default bound on T,
|
||||
// which isn't necessary.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Default for Empty<T> {
|
||||
fn default() -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an iterator that yields nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // this could have been an iterator over i32, but alas, it's just not.
|
||||
/// let mut nope = iter::empty::<i32>();
|
||||
///
|
||||
/// assert_eq!(None, nope.next());
|
||||
/// ```
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
#[rustc_const_stable(feature = "const_iter_empty", since = "1.32.0")]
|
||||
pub const fn empty<T>() -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
|
||||
/// An iterator that yields an element exactly once.
|
||||
///
|
||||
/// This `struct` is created by the [`once()`] function. See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub struct Once<T> {
|
||||
inner: crate::option::IntoIter<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> Iterator for Once<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.inner.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> DoubleEndedIterator for Once<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> ExactSizeIterator for Once<T> {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T> TrustedLen for Once<T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Once<T> {}
|
||||
|
||||
/// Creates an iterator that yields an element exactly once.
|
||||
///
|
||||
/// This is commonly used to adapt a single value into a [`chain()`] of other
|
||||
/// kinds of iteration. Maybe you have an iterator that covers almost
|
||||
/// everything, but you need an extra special case. Maybe you have a function
|
||||
/// which works on iterators, but you only need to process one value.
|
||||
///
|
||||
/// [`chain()`]: Iterator::chain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // one is the loneliest number
|
||||
/// let mut one = iter::once(1);
|
||||
///
|
||||
/// assert_eq!(Some(1), one.next());
|
||||
///
|
||||
/// // just one, that's all we get
|
||||
/// assert_eq!(None, one.next());
|
||||
/// ```
|
||||
///
|
||||
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||
/// over each file of the `.foo` directory, but also a configuration file,
|
||||
/// `.foorc`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::iter;
|
||||
/// use std::fs;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||
///
|
||||
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||
/// // PathBufs, so we use map
|
||||
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||
///
|
||||
/// // now, our iterator just for our config file
|
||||
/// let config = iter::once(PathBuf::from(".foorc"));
|
||||
///
|
||||
/// // chain the two iterators together into one big iterator
|
||||
/// let files = dirs.chain(config);
|
||||
///
|
||||
/// // this will give us all of the files in .foo as well as .foorc
|
||||
/// for f in files {
|
||||
/// println!("{:?}", f);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub fn once<T>(value: T) -> Once<T> {
|
||||
Once { inner: Some(value).into_iter() }
|
||||
}
|
||||
|
||||
/// An iterator that yields a single element of type `A` by
|
||||
/// applying the provided closure `F: FnOnce() -> A`.
|
||||
///
|
||||
/// This `struct` is created by the [`once_with()`] function.
|
||||
/// See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub struct OnceWith<F> {
|
||||
gen: Option<F>,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
let f = self.gen.take()?;
|
||||
Some(f())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.gen.iter().size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
|
||||
fn len(&self) -> usize {
|
||||
self.gen.iter().len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}
|
||||
|
||||
/// Creates an iterator that lazily generates a value exactly once by invoking
|
||||
/// the provided closure.
|
||||
///
|
||||
/// This is commonly used to adapt a single value generator into a [`chain()`] of
|
||||
/// other kinds of iteration. Maybe you have an iterator that covers almost
|
||||
/// everything, but you need an extra special case. Maybe you have a function
|
||||
/// which works on iterators, but you only need to process one value.
|
||||
///
|
||||
/// Unlike [`once()`], this function will lazily generate the value on request.
|
||||
///
|
||||
/// [`chain()`]: Iterator::chain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // one is the loneliest number
|
||||
/// let mut one = iter::once_with(|| 1);
|
||||
///
|
||||
/// assert_eq!(Some(1), one.next());
|
||||
///
|
||||
/// // just one, that's all we get
|
||||
/// assert_eq!(None, one.next());
|
||||
/// ```
|
||||
///
|
||||
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||
/// over each file of the `.foo` directory, but also a configuration file,
|
||||
/// `.foorc`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::iter;
|
||||
/// use std::fs;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||
///
|
||||
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||
/// // PathBufs, so we use map
|
||||
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||
///
|
||||
/// // now, our iterator just for our config file
|
||||
/// let config = iter::once_with(|| PathBuf::from(".foorc"));
|
||||
///
|
||||
/// // chain the two iterators together into one big iterator
|
||||
/// let files = dirs.chain(config);
|
||||
///
|
||||
/// // this will give us all of the files in .foo as well as .foorc
|
||||
/// for f in files {
|
||||
/// println!("{:?}", f);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
|
||||
OnceWith { gen: Some(gen) }
|
||||
}
|
||||
|
||||
/// Creates a new iterator where each iteration calls the provided closure
|
||||
/// `F: FnMut() -> Option<T>`.
|
||||
///
|
||||
/// This allows creating a custom iterator with any behavior
|
||||
/// without using the more verbose syntax of creating a dedicated type
|
||||
/// and implementing the [`Iterator`] trait for it.
|
||||
///
|
||||
/// Note that the `FromFn` iterator doesn’t make assumptions about the behavior of the closure,
|
||||
/// and therefore conservatively does not implement [`FusedIterator`],
|
||||
/// or override [`Iterator::size_hint()`] from its default `(0, None)`.
|
||||
///
|
||||
/// The closure can use captures and its environment to track state across iterations. Depending on
|
||||
/// how the iterator is used, this may require specifying the [`move`] keyword on the closure.
|
||||
///
|
||||
/// [`move`]: ../../std/keyword.move.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Let’s re-implement the counter iterator from the [module-level documentation]:
|
||||
///
|
||||
/// [module-level documentation]: super
|
||||
///
|
||||
/// ```
|
||||
/// let mut count = 0;
|
||||
/// let counter = std::iter::from_fn(move || {
|
||||
/// // Increment our count. This is why we started at zero.
|
||||
/// count += 1;
|
||||
///
|
||||
/// // Check to see if we've finished counting or not.
|
||||
/// if count < 6 {
|
||||
/// Some(count)
|
||||
/// } else {
|
||||
/// None
|
||||
/// }
|
||||
/// });
|
||||
/// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub fn from_fn<T, F>(f: F) -> FromFn<F>
|
||||
where
|
||||
F: FnMut() -> Option<T>,
|
||||
{
|
||||
FromFn(f)
|
||||
}
|
||||
|
||||
/// An iterator where each iteration calls the provided closure `F: FnMut() -> Option<T>`.
|
||||
///
|
||||
/// This `struct` is created by the [`iter::from_fn()`] function.
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter::from_fn()`]: from_fn
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub struct FromFn<F>(F);
|
||||
pub use self::repeat_with::{repeat_with, RepeatWith};
|
||||
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
impl<T, F> Iterator for FromFn<F>
|
||||
where
|
||||
F: FnMut() -> Option<T>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
(self.0)()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
impl<F> fmt::Debug for FromFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FromFn").finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new iterator where each successive item is computed based on the preceding one.
|
||||
///
|
||||
/// The iterator starts with the given first item (if any)
|
||||
/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::successors;
|
||||
///
|
||||
/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
|
||||
/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
|
||||
/// ```
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
|
||||
where
|
||||
F: FnMut(&T) -> Option<T>,
|
||||
{
|
||||
// If this function returned `impl Iterator<Item=T>`
|
||||
// it could be based on `unfold` and not need a dedicated type.
|
||||
// However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
|
||||
Successors { next: first, succ }
|
||||
}
|
||||
|
||||
/// An new iterator where each successive item is computed based on the preceding one.
|
||||
///
|
||||
/// This `struct` is created by the [`iter::successors()`] function.
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter::successors()`]: successors
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub struct Successors<T, F> {
|
||||
next: Option<T>,
|
||||
succ: F,
|
||||
}
|
||||
pub use self::from_fn::{from_fn, FromFn};
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T, F> Iterator for Successors<T, F>
|
||||
where
|
||||
F: FnMut(&T) -> Option<T>,
|
||||
{
|
||||
type Item = T;
|
||||
pub use self::successors::{successors, Successors};
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let item = self.next.take()?;
|
||||
self.next = (self.succ)(&item);
|
||||
Some(item)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.next.is_some() { (1, None) } else { (0, Some(0)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Successors").field("next", &self.next).finish()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub use self::once_with::{once_with, OnceWith};
|
||||
|
92
library/core/src/iter/sources/empty.rs
Normal file
92
library/core/src/iter/sources/empty.rs
Normal file
@ -0,0 +1,92 @@
|
||||
use crate::fmt;
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::marker;
|
||||
|
||||
/// Creates an iterator that yields nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // this could have been an iterator over i32, but alas, it's just not.
|
||||
/// let mut nope = iter::empty::<i32>();
|
||||
///
|
||||
/// assert_eq!(None, nope.next());
|
||||
/// ```
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
#[rustc_const_stable(feature = "const_iter_empty", since = "1.32.0")]
|
||||
pub const fn empty<T>() -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
|
||||
/// An iterator that yields nothing.
|
||||
///
|
||||
/// This `struct` is created by the [`empty()`] function. See its documentation for more.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
pub struct Empty<T>(marker::PhantomData<T>);
|
||||
|
||||
#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
|
||||
unsafe impl<T> Send for Empty<T> {}
|
||||
#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
|
||||
unsafe impl<T> Sync for Empty<T> {}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<T> fmt::Debug for Empty<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Empty")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Iterator for Empty<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
None
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> DoubleEndedIterator for Empty<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> ExactSizeIterator for Empty<T> {
|
||||
fn len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T> TrustedLen for Empty<T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Empty<T> {}
|
||||
|
||||
// not #[derive] because that adds a Clone bound on T,
|
||||
// which isn't necessary.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Clone for Empty<T> {
|
||||
fn clone(&self) -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// not #[derive] because that adds a Default bound on T,
|
||||
// which isn't necessary.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Default for Empty<T> {
|
||||
fn default() -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
}
|
78
library/core/src/iter/sources/from_fn.rs
Normal file
78
library/core/src/iter/sources/from_fn.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use crate::fmt;
|
||||
|
||||
/// Creates a new iterator where each iteration calls the provided closure
|
||||
/// `F: FnMut() -> Option<T>`.
|
||||
///
|
||||
/// This allows creating a custom iterator with any behavior
|
||||
/// without using the more verbose syntax of creating a dedicated type
|
||||
/// and implementing the [`Iterator`] trait for it.
|
||||
///
|
||||
/// Note that the `FromFn` iterator doesn’t make assumptions about the behavior of the closure,
|
||||
/// and therefore conservatively does not implement [`FusedIterator`],
|
||||
/// or override [`Iterator::size_hint()`] from its default `(0, None)`.
|
||||
///
|
||||
/// The closure can use captures and its environment to track state across iterations. Depending on
|
||||
/// how the iterator is used, this may require specifying the [`move`] keyword on the closure.
|
||||
///
|
||||
/// [`move`]: ../../std/keyword.move.html
|
||||
/// [`FusedIterator`]: crate::iter::FusedIterator
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Let’s re-implement the counter iterator from [module-level documentation]:
|
||||
///
|
||||
/// [module-level documentation]: crate::iter
|
||||
///
|
||||
/// ```
|
||||
/// let mut count = 0;
|
||||
/// let counter = std::iter::from_fn(move || {
|
||||
/// // Increment our count. This is why we started at zero.
|
||||
/// count += 1;
|
||||
///
|
||||
/// // Check to see if we've finished counting or not.
|
||||
/// if count < 6 {
|
||||
/// Some(count)
|
||||
/// } else {
|
||||
/// None
|
||||
/// }
|
||||
/// });
|
||||
/// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub fn from_fn<T, F>(f: F) -> FromFn<F>
|
||||
where
|
||||
F: FnMut() -> Option<T>,
|
||||
{
|
||||
FromFn(f)
|
||||
}
|
||||
|
||||
/// An iterator where each iteration calls the provided closure `F: FnMut() -> Option<T>`.
|
||||
///
|
||||
/// This `struct` is created by the [`iter::from_fn()`] function.
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter::from_fn()`]: from_fn
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub struct FromFn<F>(F);
|
||||
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
impl<T, F> Iterator for FromFn<F>
|
||||
where
|
||||
F: FnMut() -> Option<T>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
(self.0)()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
impl<F> fmt::Debug for FromFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FromFn").finish()
|
||||
}
|
||||
}
|
99
library/core/src/iter/sources/once.rs
Normal file
99
library/core/src/iter/sources/once.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
|
||||
/// Creates an iterator that yields an element exactly once.
|
||||
///
|
||||
/// This is commonly used to adapt a single value into a [`chain()`] of other
|
||||
/// kinds of iteration. Maybe you have an iterator that covers almost
|
||||
/// everything, but you need an extra special case. Maybe you have a function
|
||||
/// which works on iterators, but you only need to process one value.
|
||||
///
|
||||
/// [`chain()`]: Iterator::chain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // one is the loneliest number
|
||||
/// let mut one = iter::once(1);
|
||||
///
|
||||
/// assert_eq!(Some(1), one.next());
|
||||
///
|
||||
/// // just one, that's all we get
|
||||
/// assert_eq!(None, one.next());
|
||||
/// ```
|
||||
///
|
||||
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||
/// over each file of the `.foo` directory, but also a configuration file,
|
||||
/// `.foorc`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::iter;
|
||||
/// use std::fs;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||
///
|
||||
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||
/// // PathBufs, so we use map
|
||||
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||
///
|
||||
/// // now, our iterator just for our config file
|
||||
/// let config = iter::once(PathBuf::from(".foorc"));
|
||||
///
|
||||
/// // chain the two iterators together into one big iterator
|
||||
/// let files = dirs.chain(config);
|
||||
///
|
||||
/// // this will give us all of the files in .foo as well as .foorc
|
||||
/// for f in files {
|
||||
/// println!("{:?}", f);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub fn once<T>(value: T) -> Once<T> {
|
||||
Once { inner: Some(value).into_iter() }
|
||||
}
|
||||
|
||||
/// An iterator that yields an element exactly once.
|
||||
///
|
||||
/// This `struct` is created by the [`once()`] function. See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub struct Once<T> {
|
||||
inner: crate::option::IntoIter<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> Iterator for Once<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.inner.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> DoubleEndedIterator for Once<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> ExactSizeIterator for Once<T> {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T> TrustedLen for Once<T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Once<T> {}
|
109
library/core/src/iter/sources/once_with.rs
Normal file
109
library/core/src/iter/sources/once_with.rs
Normal file
@ -0,0 +1,109 @@
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
|
||||
/// Creates an iterator that lazily generates a value exactly once by invoking
|
||||
/// the provided closure.
|
||||
///
|
||||
/// This is commonly used to adapt a single value generator into a [`chain()`] of
|
||||
/// other kinds of iteration. Maybe you have an iterator that covers almost
|
||||
/// everything, but you need an extra special case. Maybe you have a function
|
||||
/// which works on iterators, but you only need to process one value.
|
||||
///
|
||||
/// Unlike [`once()`], this function will lazily generate the value on request.
|
||||
///
|
||||
/// [`chain()`]: Iterator::chain
|
||||
/// [`once()`]: crate::iter::once
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // one is the loneliest number
|
||||
/// let mut one = iter::once_with(|| 1);
|
||||
///
|
||||
/// assert_eq!(Some(1), one.next());
|
||||
///
|
||||
/// // just one, that's all we get
|
||||
/// assert_eq!(None, one.next());
|
||||
/// ```
|
||||
///
|
||||
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||
/// over each file of the `.foo` directory, but also a configuration file,
|
||||
/// `.foorc`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::iter;
|
||||
/// use std::fs;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||
///
|
||||
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||
/// // PathBufs, so we use map
|
||||
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||
///
|
||||
/// // now, our iterator just for our config file
|
||||
/// let config = iter::once_with(|| PathBuf::from(".foorc"));
|
||||
///
|
||||
/// // chain the two iterators together into one big iterator
|
||||
/// let files = dirs.chain(config);
|
||||
///
|
||||
/// // this will give us all of the files in .foo as well as .foorc
|
||||
/// for f in files {
|
||||
/// println!("{:?}", f);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
|
||||
OnceWith { gen: Some(gen) }
|
||||
}
|
||||
|
||||
/// An iterator that yields a single element of type `A` by
|
||||
/// applying the provided closure `F: FnOnce() -> A`.
|
||||
///
|
||||
/// This `struct` is created by the [`once_with()`] function.
|
||||
/// See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub struct OnceWith<F> {
|
||||
gen: Option<F>,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
let f = self.gen.take()?;
|
||||
Some(f())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.gen.iter().size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
|
||||
fn len(&self) -> usize {
|
||||
self.gen.iter().len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}
|
93
library/core/src/iter/sources/repeat.rs
Normal file
93
library/core/src/iter/sources/repeat.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
|
||||
/// Creates a new iterator that endlessly repeats a single element.
|
||||
///
|
||||
/// The `repeat()` function repeats a single value over and over again.
|
||||
///
|
||||
/// Infinite iterators like `repeat()` are often used with adapters like
|
||||
/// [`Iterator::take()`], in order to make them finite.
|
||||
///
|
||||
/// If the element type of the iterator you need does not implement `Clone`,
|
||||
/// or if you do not want to keep the repeated element in memory, you can
|
||||
/// instead use the [`repeat_with()`] function.
|
||||
///
|
||||
/// [`repeat_with()`]: crate::iter::repeat_with
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // the number four 4ever:
|
||||
/// let mut fours = iter::repeat(4);
|
||||
///
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
///
|
||||
/// // yup, still four
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// ```
|
||||
///
|
||||
/// Going finite with [`Iterator::take()`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // that last example was too many fours. Let's only have four fours.
|
||||
/// let mut four_fours = iter::repeat(4).take(4);
|
||||
///
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
///
|
||||
/// // ... and now we're done
|
||||
/// assert_eq!(None, four_fours.next());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
|
||||
Repeat { element: elt }
|
||||
}
|
||||
|
||||
/// An iterator that repeats an element endlessly.
|
||||
///
|
||||
/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Repeat<A> {
|
||||
element: A,
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Clone> Iterator for Repeat<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
Some(self.element.clone())
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Clone> DoubleEndedIterator for Repeat<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
Some(self.element.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A: Clone> FusedIterator for Repeat<A> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
|
98
library/core/src/iter/sources/repeat_with.rs
Normal file
98
library/core/src/iter/sources/repeat_with.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
|
||||
/// Creates a new iterator that repeats elements of type `A` endlessly by
|
||||
/// applying the provided closure, the repeater, `F: FnMut() -> A`.
|
||||
///
|
||||
/// The `repeat_with()` function calls the repeater over and over again.
|
||||
///
|
||||
/// Infinite iterators like `repeat_with()` are often used with adapters like
|
||||
/// [`Iterator::take()`], in order to make them finite.
|
||||
///
|
||||
/// If the element type of the iterator you need implements [`Clone`], and
|
||||
/// it is OK to keep the source element in memory, you should instead use
|
||||
/// the [`repeat()`] function.
|
||||
///
|
||||
/// An iterator produced by `repeat_with()` is not a [`DoubleEndedIterator`].
|
||||
/// If you need `repeat_with()` to return a [`DoubleEndedIterator`],
|
||||
/// please open a GitHub issue explaining your use case.
|
||||
///
|
||||
/// [`repeat()`]: crate::iter::repeat
|
||||
/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // let's assume we have some value of a type that is not `Clone`
|
||||
/// // or which don't want to have in memory just yet because it is expensive:
|
||||
/// #[derive(PartialEq, Debug)]
|
||||
/// struct Expensive;
|
||||
///
|
||||
/// // a particular value forever:
|
||||
/// let mut things = iter::repeat_with(|| Expensive);
|
||||
///
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// ```
|
||||
///
|
||||
/// Using mutation and going finite:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // From the zeroth to the third power of two:
|
||||
/// let mut curr = 1;
|
||||
/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
|
||||
/// .take(4);
|
||||
///
|
||||
/// assert_eq!(Some(1), pow2.next());
|
||||
/// assert_eq!(Some(2), pow2.next());
|
||||
/// assert_eq!(Some(4), pow2.next());
|
||||
/// assert_eq!(Some(8), pow2.next());
|
||||
///
|
||||
/// // ... and now we're done
|
||||
/// assert_eq!(None, pow2.next());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
|
||||
RepeatWith { repeater }
|
||||
}
|
||||
|
||||
/// An iterator that repeats elements of type `A` endlessly by
|
||||
/// applying the provided closure `F: FnMut() -> A`.
|
||||
///
|
||||
/// This `struct` is created by the [`repeat_with()`] function.
|
||||
/// See its documentation for more.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub struct RepeatWith<F> {
|
||||
repeater: F,
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
Some((self.repeater)())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
|
66
library/core/src/iter/sources/successors.rs
Normal file
66
library/core/src/iter/sources/successors.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use crate::{fmt, iter::FusedIterator};
|
||||
|
||||
/// Creates a new iterator where each successive item is computed based on the preceding one.
|
||||
///
|
||||
/// The iterator starts with the given first item (if any)
|
||||
/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::successors;
|
||||
///
|
||||
/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
|
||||
/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
|
||||
/// ```
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
|
||||
where
|
||||
F: FnMut(&T) -> Option<T>,
|
||||
{
|
||||
// If this function returned `impl Iterator<Item=T>`
|
||||
// it could be based on `unfold` and not need a dedicated type.
|
||||
// However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
|
||||
Successors { next: first, succ }
|
||||
}
|
||||
|
||||
/// An new iterator where each successive item is computed based on the preceding one.
|
||||
///
|
||||
/// This `struct` is created by the [`iter::successors()`] function.
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter::successors()`]: successors
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub struct Successors<T, F> {
|
||||
next: Option<T>,
|
||||
succ: F,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T, F> Iterator for Successors<T, F>
|
||||
where
|
||||
F: FnMut(&T) -> Option<T>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let item = self.next.take()?;
|
||||
self.next = (self.succ)(&item);
|
||||
Some(item)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.next.is_some() { (1, None) } else { (0, Some(0)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Successors").field("next", &self.next).finish()
|
||||
}
|
||||
}
|
@ -156,18 +156,18 @@ pub trait StructuralPartialEq {
|
||||
/// Required trait for constants used in pattern matches.
|
||||
///
|
||||
/// Any type that derives `Eq` automatically implements this trait, *regardless*
|
||||
/// of whether its type-parameters implement `Eq`.
|
||||
/// of whether its type parameters implement `Eq`.
|
||||
///
|
||||
/// This is a hack to workaround a limitation in our type-system.
|
||||
/// This is a hack to work around a limitation in our type system.
|
||||
///
|
||||
/// Background:
|
||||
/// # Background
|
||||
///
|
||||
/// We want to require that types of consts used in pattern matches
|
||||
/// have the attribute `#[derive(PartialEq, Eq)]`.
|
||||
///
|
||||
/// In a more ideal world, we could check that requirement by just checking that
|
||||
/// the given type implements both (1.) the `StructuralPartialEq` trait *and*
|
||||
/// (2.) the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`,
|
||||
/// the given type implements both the `StructuralPartialEq` trait *and*
|
||||
/// the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`,
|
||||
/// and be a case that we want the compiler to accept, and yet the constant's
|
||||
/// type fails to implement `Eq`.
|
||||
///
|
||||
@ -176,8 +176,11 @@ pub trait StructuralPartialEq {
|
||||
/// ```rust
|
||||
/// #[derive(PartialEq, Eq)]
|
||||
/// struct Wrap<X>(X);
|
||||
///
|
||||
/// fn higher_order(_: &()) { }
|
||||
///
|
||||
/// const CFN: Wrap<fn(&())> = Wrap(higher_order);
|
||||
///
|
||||
/// fn main() {
|
||||
/// match CFN {
|
||||
/// CFN => {}
|
||||
|
@ -441,6 +441,32 @@ impl f32 {
|
||||
self.abs_private() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is [subnormal].
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_subnormal)]
|
||||
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
|
||||
/// let max = f32::MAX;
|
||||
/// let lower_than_min = 1.0e-40_f32;
|
||||
/// let zero = 0.0_f32;
|
||||
///
|
||||
/// assert!(!min.is_subnormal());
|
||||
/// assert!(!max.is_subnormal());
|
||||
///
|
||||
/// assert!(!zero.is_subnormal());
|
||||
/// assert!(!f32::NAN.is_subnormal());
|
||||
/// assert!(!f32::INFINITY.is_subnormal());
|
||||
/// // Values between `0` and `min` are Subnormal.
|
||||
/// assert!(lower_than_min.is_subnormal());
|
||||
/// ```
|
||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||
#[unstable(feature = "is_subnormal", issue = "79288")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_subnormal(self) -> bool {
|
||||
matches!(self.classify(), FpCategory::Subnormal)
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is neither zero, infinite,
|
||||
/// [subnormal], or `NaN`.
|
||||
///
|
||||
|
@ -440,6 +440,32 @@ impl f64 {
|
||||
self.abs_private() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is [subnormal].
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_subnormal)]
|
||||
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
|
||||
/// let max = f64::MAX;
|
||||
/// let lower_than_min = 1.0e-308_f64;
|
||||
/// let zero = 0.0_f64;
|
||||
///
|
||||
/// assert!(!min.is_subnormal());
|
||||
/// assert!(!max.is_subnormal());
|
||||
///
|
||||
/// assert!(!zero.is_subnormal());
|
||||
/// assert!(!f64::NAN.is_subnormal());
|
||||
/// assert!(!f64::INFINITY.is_subnormal());
|
||||
/// // Values between `0` and `min` are Subnormal.
|
||||
/// assert!(lower_than_min.is_subnormal());
|
||||
/// ```
|
||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||
#[unstable(feature = "is_subnormal", issue = "79288")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_subnormal(self) -> bool {
|
||||
matches!(self.classify(), FpCategory::Subnormal)
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is neither zero, infinite,
|
||||
/// [subnormal], or `NaN`.
|
||||
///
|
||||
|
@ -227,7 +227,6 @@
|
||||
#![feature(asm)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(atomic_mut_ptr)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(c_variadic)]
|
||||
#![feature(cfg_accessible)]
|
||||
@ -297,7 +296,6 @@
|
||||
#![feature(raw)]
|
||||
#![feature(raw_ref_macros)]
|
||||
#![feature(ready_macro)]
|
||||
#![feature(refcell_take)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(shrink_to)]
|
||||
|
@ -23,7 +23,6 @@
|
||||
#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(nll)]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(available_concurrency)]
|
||||
#![feature(internal_output_capture)]
|
||||
#![feature(panic_unwind)]
|
||||
|
76
src/test/ui/expr/compound-assignment/eval-order.rs
Normal file
76
src/test/ui/expr/compound-assignment/eval-order.rs
Normal file
@ -0,0 +1,76 @@
|
||||
// Test evaluation order of operands of the compound assignment operators
|
||||
|
||||
// run-pass
|
||||
|
||||
use std::ops::AddAssign;
|
||||
|
||||
enum Side {
|
||||
Lhs,
|
||||
Rhs,
|
||||
}
|
||||
|
||||
// In the following tests, we place our value into a wrapper type so that we
|
||||
// can do an element access as the outer place expression. If we just had the
|
||||
// block expression, it'd be a value expression and not compile.
|
||||
struct Wrapper<T>(T);
|
||||
|
||||
// Evaluation order for `a op= b` where typeof(a) and typeof(b) are primitives
|
||||
// is first `b` then `a`.
|
||||
fn primitive_compound() {
|
||||
let mut side_order = vec![];
|
||||
let mut int = Wrapper(0);
|
||||
|
||||
{
|
||||
side_order.push(Side::Lhs);
|
||||
int
|
||||
}.0 += {
|
||||
side_order.push(Side::Rhs);
|
||||
0
|
||||
};
|
||||
|
||||
assert!(matches!(side_order[..], [Side::Rhs, Side::Lhs]));
|
||||
}
|
||||
|
||||
// Evaluation order for `a op=b` otherwise is first `a` then `b`.
|
||||
fn generic_compound<T: AddAssign<T> + Default>() {
|
||||
let mut side_order = vec![];
|
||||
let mut add_assignable: Wrapper<T> = Wrapper(Default::default());
|
||||
|
||||
{
|
||||
side_order.push(Side::Lhs);
|
||||
add_assignable
|
||||
}.0 += {
|
||||
side_order.push(Side::Rhs);
|
||||
Default::default()
|
||||
};
|
||||
|
||||
assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs]));
|
||||
}
|
||||
|
||||
fn custom_compound() {
|
||||
struct Custom;
|
||||
|
||||
impl AddAssign<()> for Custom {
|
||||
fn add_assign(&mut self, _: ()) {
|
||||
// this block purposely left blank
|
||||
}
|
||||
}
|
||||
|
||||
let mut side_order = vec![];
|
||||
let mut custom = Wrapper(Custom);
|
||||
|
||||
{
|
||||
side_order.push(Side::Lhs);
|
||||
custom
|
||||
}.0 += {
|
||||
side_order.push(Side::Rhs);
|
||||
};
|
||||
|
||||
assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs]));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
primitive_compound();
|
||||
generic_compound::<i32>();
|
||||
custom_compound();
|
||||
}
|
@ -13,11 +13,13 @@ error[E0599]: no method named `collect` found for struct `Cloned<TakeWhile<&mut
|
||||
LL | .collect();
|
||||
| ^^^^^^^ method not found in `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>`
|
||||
|
|
||||
::: $SRC_DIR/core/src/iter/adapters/mod.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
|
||||
|
|
||||
LL | pub struct Cloned<I> {
|
||||
| -------------------- doesn't satisfy `_: Iterator`
|
||||
...
|
||||
|
|
||||
::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
|
||||
|
|
||||
LL | pub struct TakeWhile<I, P> {
|
||||
| -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
|
||||
|
|
||||
|
@ -15,7 +15,7 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
|
||||
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
|
||||
| doesn't satisfy `_: FnMut<(&&str,)>`
|
||||
|
|
||||
::: $SRC_DIR/core/src/iter/adapters/mod.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
|
||||
|
|
||||
LL | pub struct Filter<I, P> {
|
||||
| ----------------------- doesn't satisfy `_: Iterator`
|
||||
|
Loading…
Reference in New Issue
Block a user