streaming-iterator-0.1.9/.cargo_vcs_info.json0000644000000001360000000000100146630ustar { "git": { "sha1": "69069dc9e46facef6caa79ee48e47420de92633d" }, "path_in_vcs": "" }streaming-iterator-0.1.9/.circleci/config.yml000064400000000000000000000016251046102023000173020ustar 00000000000000restore_registry: &RESTORE_REGISTRY restore_cache: key: registry save_registry: &SAVE_REGISTRY save_cache: key: registry-{{ .BuildNum }} paths: - /usr/local/cargo/registry/index deps_key: &DEPS_KEY key: deps-{{ checksum "~/rust-version" }}-{{ checksum "Cargo.lock" }} restore_deps: &RESTORE_DEPS restore_cache: <<: *DEPS_KEY save_deps: &SAVE_DEPS save_cache: <<: *DEPS_KEY paths: - target - /usr/local/cargo/registry/cache version: 2 jobs: build: docker: - image: rust:1.56.0 working_directory: ~/build environment: RUSTFLAGS: -D warnings steps: - checkout - *RESTORE_REGISTRY - run: cargo generate-lockfile - *SAVE_REGISTRY - run: rustc --version > ~/rust-version - *RESTORE_DEPS - run: cargo test - run: cargo test --features alloc - run: cargo test --features std - *SAVE_DEPS streaming-iterator-0.1.9/.gitignore000064400000000000000000000000361046102023000154420ustar 00000000000000target Cargo.lock .idea *.iml streaming-iterator-0.1.9/Cargo.toml0000644000000015370000000000100126670ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "streaming-iterator" version = "0.1.9" authors = ["Steven Fackler "] description = "Streaming iterators" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/sfackler/streaming-iterator" [package.metadata.docs.rs] features = ["std"] [dependencies] [features] alloc = [] std = ["alloc"] streaming-iterator-0.1.9/Cargo.toml.orig000064400000000000000000000006141046102023000163430ustar 00000000000000[package] name = "streaming-iterator" version = "0.1.9" authors = ["Steven Fackler "] license = "MIT OR Apache-2.0" description = "Streaming iterators" repository = "https://github.com/sfackler/streaming-iterator" readme = "README.md" edition = "2021" rust-version = "1.56" [package.metadata.docs.rs] features = ["std"] [features] alloc = [] std = ["alloc"] [dependencies] streaming-iterator-0.1.9/LICENSE-APACHE000064400000000000000000000261361046102023000154070ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. streaming-iterator-0.1.9/LICENSE-MIT000064400000000000000000000020421046102023000151050ustar 00000000000000Copyright (c) 2016 Steven Fackler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. streaming-iterator-0.1.9/README.md000064400000000000000000000013451046102023000147350ustar 00000000000000# streaming-iterator [![CircleCI](https://circleci.com/gh/sfackler/streaming-iterator.svg?style=badge)](https://circleci.com/gh/sfackler/streaming-iterator) [Documentation](https://docs.rs/streaming-iterator) Streaming iterators for Rust. ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. streaming-iterator-0.1.9/src/lib.rs000064400000000000000000002152721046102023000153670ustar 00000000000000//! Streaming iterators. //! //! The iterator APIs in the Rust standard library do not allow elements to be yielded which borrow //! from the iterator itself. That means, for example, that the `std::io::Lines` iterator must //! allocate a new `String` for each line rather than reusing an internal buffer. The //! `StreamingIterator` trait instead provides access to elements being iterated over only by //! reference rather than by value. //! //! `StreamingIterator`s cannot be used in Rust `for` loops, but `while let` loops offer a similar //! level of ergonomics: //! //! ```ignore //! while let Some(item) = iter.next() { //! // work with item //! } //! ``` //! //! However, **make sure to only use the above form with a mutable reference to an existing iterator**, //! not with an expression that creates an iterator. //! For example, the following code will loop forever over the first element of the array: //! //! ```no_run //! use streaming_iterator::{convert, StreamingIterator}; //! let array = [0, 1, 2, 3]; //! //! while let Some(item) = convert(array.iter()).next() { //! // This is an infinite loop! //! } //! ``` //! //! While the standard `Iterator` trait's functionality is based off of the `next` method, //! `StreamingIterator`'s functionality is based off of a pair of methods: `advance` and `get`. This //! essentially splits the logic of `next` in half (in fact, `StreamingIterator`'s `next` method //! does nothing but call `advance` followed by `get`). //! //! This is required because of Rust's lexical handling of borrows (more specifically a lack of //! single entry, multiple exit borrows). If `StreamingIterator` was defined like `Iterator` with //! just a required `next` method, operations like `filter` would be impossible to define. #![doc(html_root_url = "https://docs.rs/streaming-iterator/0.1")] #![warn(missing_docs)] #![no_std] #[cfg(feature = "alloc")] extern crate alloc; use core::cmp; #[cfg(feature = "alloc")] use alloc::{borrow::ToOwned, boxed::Box}; mod slice; pub use crate::slice::{windows_mut, WindowsMut}; mod sources; pub use crate::sources::{convert, Convert}; pub use crate::sources::{convert_mut, ConvertMut}; pub use crate::sources::{convert_ref, ConvertRef}; pub use crate::sources::{empty, Empty}; pub use crate::sources::{from_fn, FromFn}; pub use crate::sources::{once, Once}; pub use crate::sources::{once_with, OnceWith}; pub use crate::sources::{repeat, Repeat}; pub use crate::sources::{repeat_with, RepeatWith}; pub use crate::sources::{successors, Successors}; /// An interface for dealing with streaming iterators. pub trait StreamingIterator { /// The type of the elements being iterated over. type Item: ?Sized; /// Advances the iterator to the next element. /// /// Iterators start just before the first element, so this should be called before `get`. /// /// The behavior of calling this method after the end of the iterator has been reached is /// unspecified. fn advance(&mut self); /// Returns a reference to the current element of the iterator. /// /// The behavior of calling this method before `advance` has been called is unspecified. fn get(&self) -> Option<&Self::Item>; /// Advances the iterator and returns the next value. /// /// The behavior of calling this method after the end of the iterator has been reached is /// unspecified. /// /// The default implementation simply calls `advance` followed by `get`. #[inline] fn next(&mut self) -> Option<&Self::Item> { self.advance(); (*self).get() } /// Returns the bounds on the remaining length of the iterator. #[inline] fn size_hint(&self) -> (usize, Option) { (0, None) } /// Checks if `get()` will return `None`. fn is_done(&self) -> bool { self.get().is_none() } /// Determines if all elements of the iterator satisfy a predicate. #[inline] fn all(&mut self, mut f: F) -> bool where Self: Sized, F: FnMut(&Self::Item) -> bool, { while let Some(i) = self.next() { if !f(i) { return false; } } true } /// Determines if any elements of the iterator satisfy a predicate. #[inline] fn any(&mut self, mut f: F) -> bool where Self: Sized, F: FnMut(&Self::Item) -> bool, { !self.all(|i| !f(i)) } /// Borrows an iterator, rather than consuming it. /// /// This is useful to allow the application of iterator adaptors while still retaining ownership /// of the original adaptor. #[inline] fn by_ref(&mut self) -> &mut Self where Self: Sized, { self } /// Consumes two iterators and returns a new iterator that iterates over both in sequence. #[inline] fn chain(self, other: I) -> Chain where Self: Sized, I: StreamingIterator + Sized, { Chain { a: self, b: other, state: ChainState::BothForward, } } /// Produces a normal, non-streaming, iterator by cloning the elements of this iterator. #[inline] fn cloned(self) -> Cloned where Self: Sized, Self::Item: Clone, { Cloned(self) } /// Produces a normal, non-streaming, iterator by copying the elements of this iterator. #[inline] fn copied(self) -> Copied where Self: Sized, Self::Item: Copy, { Copied(self) } /// Consumes the iterator, counting the number of remaining elements and returning it. #[inline] fn count(self) -> usize where Self: Sized, { self.fold(0, |count, _| count + 1) } /// Creates an iterator which uses a closure to determine if an element should be yielded. #[inline] fn filter(self, f: F) -> Filter where Self: Sized, F: FnMut(&Self::Item) -> bool, { Filter { it: self, f } } /// Creates an iterator which both filters and maps by applying a closure to elements. #[inline] fn filter_map(self, f: F) -> FilterMap where Self: Sized, F: FnMut(&Self::Item) -> Option, { FilterMap { it: self, f, item: None, } } /// Creates an iterator which flattens iterators obtained by applying a closure to elements. /// Note that the returned iterators must be streaming iterators. #[inline] fn flat_map(self, f: F) -> FlatMap where Self: Sized, J: StreamingIterator, F: FnMut(&Self::Item) -> J, { FlatMap { it: self, f, sub_iter: None, } } /// Creates a regular, non-streaming iterator which both filters and maps by applying a closure to elements. #[inline] fn filter_map_deref(self, f: F) -> FilterMapDeref where Self: Sized, F: FnMut(&Self::Item) -> Option, { FilterMapDeref { it: self, f } } /// Returns the first element of the iterator that satisfies the predicate. #[inline] fn find(&mut self, mut f: F) -> Option<&Self::Item> where Self: Sized, F: FnMut(&Self::Item) -> bool, { loop { self.advance(); match self.get() { Some(i) => { if f(i) { break; } } None => break, } } (*self).get() } /// Creates an iterator which is "well behaved" at the beginning and end of iteration. /// /// The behavior of calling `get` before iteration has been started, and of continuing to call /// `advance` after `get` has returned `None` is normally unspecified, but this guarantees that /// `get` will return `None` in both cases. #[inline] fn fuse(self) -> Fuse where Self: Sized, { Fuse { it: self, state: FuseState::Start, } } /// Call a closure on each element, passing the element on. /// The closure is called upon calls to `advance` or `advance_back`, and exactly once per element /// regardless of how many times (if any) `get` is called. #[inline] fn inspect(self, f: F) -> Inspect where F: FnMut(&Self::Item), Self: Sized, { Inspect { it: self, f } } /// Creates an iterator which transforms elements of this iterator by passing them to a closure. #[inline] fn map(self, f: F) -> Map where Self: Sized, F: FnMut(&Self::Item) -> B, { Map { it: self, f, item: None, } } /// Creates a regular, non-streaming iterator which transforms elements of this iterator by passing them to a closure. #[inline] fn map_deref(self, f: F) -> MapDeref where Self: Sized, F: FnMut(&Self::Item) -> B, { MapDeref { it: self, f } } /// Creates an iterator which transforms elements of this iterator by passing them to a closure. /// /// Unlike `map`, this method takes a closure that returns a reference into the original value. /// /// The mapping function is only guaranteed to be called at some point before an element /// is actually consumed. This allows an expensive mapping function to be ignored /// during skipping (e.g. `nth`). #[inline] fn map_ref(self, f: F) -> MapRef where Self: Sized, F: Fn(&Self::Item) -> &B, { MapRef { it: self, f } } /// Consumes the first `n` elements of the iterator, returning the next one. #[inline] fn nth(&mut self, n: usize) -> Option<&Self::Item> { for _ in 0..n { self.advance(); if self.is_done() { return None; } } self.next() } /// Creates a normal, non-streaming, iterator with elements produced by calling `to_owned` on /// the elements of this iterator. /// /// Requires the `alloc` feature. #[cfg(feature = "alloc")] #[inline] fn owned(self) -> Owned where Self: Sized, Self::Item: ToOwned, { Owned(self) } /// Returns the index of the first element of the iterator matching a predicate. #[inline] fn position(&mut self, mut f: F) -> Option where Self: Sized, F: FnMut(&Self::Item) -> bool, { let mut n = 0; while let Some(i) = self.next() { if f(i) { return Some(n); } n += 1; } None } /// Creates an iterator which skips the first `n` elements. #[inline] fn skip(self, n: usize) -> Skip where Self: Sized, { Skip { it: self, n } } /// Creates an iterator that skips initial elements matching a predicate. #[inline] fn skip_while(self, f: F) -> SkipWhile where Self: Sized, F: FnMut(&Self::Item) -> bool, { SkipWhile { it: self, f, done: false, } } /// Creates an iterator which only returns the first `n` elements. #[inline] fn take(self, n: usize) -> Take where Self: Sized, { Take { it: self, n, done: false, } } /// Creates an iterator which only returns initial elements matching a predicate. #[inline] fn take_while(self, f: F) -> TakeWhile where Self: Sized, F: FnMut(&Self::Item) -> bool, { TakeWhile { it: self, f, done: false, } } /// Creates an iterator which returns elemens in the opposite order. #[inline] fn rev(self) -> Rev where Self: Sized + DoubleEndedStreamingIterator, { Rev(self) } /// Reduces the iterator's elements to a single, final value. #[inline] fn fold(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, &Self::Item) -> B, { let mut acc = init; while let Some(item) = self.next() { acc = f(acc, item); } acc } /// Calls a closure on each element of an iterator. #[inline] fn for_each(self, mut f: F) where Self: Sized, F: FnMut(&Self::Item), { self.fold((), move |(), item| f(item)); } } impl<'a, I: ?Sized> StreamingIterator for &'a mut I where I: StreamingIterator, { type Item = I::Item; #[inline] fn advance(&mut self) { (**self).advance() } #[inline] fn is_done(&self) -> bool { (**self).is_done() } #[inline] fn get(&self) -> Option<&Self::Item> { (**self).get() } #[inline] fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } #[inline] fn next(&mut self) -> Option<&Self::Item> { (**self).next() } } #[cfg(feature = "alloc")] impl StreamingIterator for Box where I: StreamingIterator, { type Item = I::Item; #[inline] fn advance(&mut self) { (**self).advance() } #[inline] fn is_done(&self) -> bool { (**self).is_done() } #[inline] fn get(&self) -> Option<&Self::Item> { (**self).get() } #[inline] fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } #[inline] fn next(&mut self) -> Option<&Self::Item> { (**self).next() } } /// A streaming iterator able to yield elements from both ends. pub trait DoubleEndedStreamingIterator: StreamingIterator { /// Advances the iterator to the next element from the back of the iterator. /// /// Double ended iterators just after the last element, so this should be called before `get` /// when iterating in reverse. /// /// The behavior of calling this method after the iterator has been exhausted is unspecified. fn advance_back(&mut self); /// Advances the iterator and returns the next value from the back. /// /// The behavior of calling this method after the iterator has been exhausted is unspecified. /// /// The default implementation simply calls `advance_back` followed by `get`. #[inline] fn next_back(&mut self) -> Option<&Self::Item> { self.advance_back(); (*self).get() } /// Reduces the iterator's elements to a single, final value, starting from the back. #[inline] fn rfold(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, &Self::Item) -> B, { let mut acc = init; while let Some(item) = self.next_back() { acc = f(acc, item); } acc } } /// An interface for dealing with mutable streaming iterators. pub trait StreamingIteratorMut: StreamingIterator { /// Returns a mutable reference to the current element of the iterator. /// /// The behavior of calling this method before `advance` has been called is unspecified. /// /// Modifications through this reference may also have an unspecified effect on further /// iterator advancement, but implementations are encouraged to document this. fn get_mut(&mut self) -> Option<&mut Self::Item>; /// Advances the iterator and returns the next mutable value. /// /// The behavior of calling this method after the end of the iterator has been reached is /// unspecified. /// /// The default implementation simply calls `advance` followed by `get_mut`. #[inline] fn next_mut(&mut self) -> Option<&mut Self::Item> { self.advance(); (*self).get_mut() } /// Reduces the iterator's mutable elements to a single, final value. #[inline] fn fold_mut(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { let mut acc = init; while let Some(item) = self.next_mut() { acc = f(acc, item); } acc } /// Calls a closure on each mutable element of an iterator. #[inline] fn for_each_mut(self, mut f: F) where Self: Sized, F: FnMut(&mut Self::Item), { self.fold_mut((), move |(), item| f(item)); } /// Creates a regular, non-streaming iterator which transforms mutable elements /// of this iterator by passing them to a closure. #[inline] fn map_deref_mut(self, f: F) -> MapDerefMut where Self: Sized, F: FnMut(&mut Self::Item) -> B, { MapDerefMut { it: self, f } } /// Creates an iterator which flattens nested streaming iterators. #[inline] fn flatten(self) -> Flatten where Self: Sized, Self::Item: StreamingIterator, { Flatten { iter: self, first: true, } } } impl<'a, I: ?Sized> StreamingIteratorMut for &'a mut I where I: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { (**self).get_mut() } #[inline] fn next_mut(&mut self) -> Option<&mut Self::Item> { (**self).next_mut() } } #[cfg(feature = "alloc")] impl StreamingIteratorMut for Box where I: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { (**self).get_mut() } #[inline] fn next_mut(&mut self) -> Option<&mut Self::Item> { (**self).next_mut() } } /// A mutable streaming iterator able to yield elements from both ends. pub trait DoubleEndedStreamingIteratorMut: DoubleEndedStreamingIterator + StreamingIteratorMut { /// Advances the iterator and returns the next mutable value from the back. /// /// The behavior of calling this method after the end of the iterator has been reached is /// unspecified. /// /// The default implementation simply calls `advance_back` followed by `get_mut`. #[inline] fn next_back_mut(&mut self) -> Option<&mut Self::Item> { self.advance_back(); (*self).get_mut() } /// Reduces the iterator's mutable elements to a single, final value, starting from the back. #[inline] fn rfold_mut(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { let mut acc = init; while let Some(item) = self.next_back_mut() { acc = f(acc, item); } acc } } // Note, in theory we could blanket-impl `DoubleEndedStreamingIteratorMut`, but that // wouldn't allow custom folding until we can do it with Rust specialization. /// A streaming iterator that concatenates two streaming iterators #[derive(Debug)] pub struct Chain { a: A, b: B, state: ChainState, } #[derive(Debug)] enum ChainState { // Both iterators have items remaining and we are iterating forward BothForward, // Both iterators have items remaining and we are iterating backward BothBackward, // Only the front iterator has items Front, // Only the back iterator has items Back, } impl StreamingIterator for Chain where A: StreamingIterator, B: StreamingIterator, { type Item = A::Item; #[inline] fn advance(&mut self) { use crate::ChainState::*; match self.state { BothForward | BothBackward => { self.a.advance(); self.state = if self.a.is_done() { self.b.advance(); Back } else { BothForward }; } Front => self.a.advance(), Back => self.b.advance(), } } #[inline] fn is_done(&self) -> bool { use crate::ChainState::*; match self.state { BothForward | Front => self.a.is_done(), BothBackward | Back => self.b.is_done(), } } #[inline] fn get(&self) -> Option<&Self::Item> { use crate::ChainState::*; match self.state { BothForward | Front => self.a.get(), BothBackward | Back => self.b.get(), } } #[inline] fn fold(self, init: Acc, mut f: F) -> Acc where Self: Sized, F: FnMut(Acc, &Self::Item) -> Acc, { let mut accum = init; match self.state { ChainState::Back => {} _ => accum = self.a.fold(accum, &mut f), } match self.state { ChainState::Front => {} _ => accum = self.b.fold(accum, &mut f), } accum } } impl DoubleEndedStreamingIterator for Chain where A: DoubleEndedStreamingIterator, B: DoubleEndedStreamingIterator, { #[inline] fn advance_back(&mut self) { use crate::ChainState::*; match self.state { BothForward | BothBackward => { self.b.advance_back(); self.state = if self.b.is_done() { self.a.advance_back(); Front } else { BothBackward }; } Front => self.a.advance_back(), Back => self.b.advance_back(), } } #[inline] fn rfold(self, init: Acc, mut f: F) -> Acc where Self: Sized, F: FnMut(Acc, &Self::Item) -> Acc, { let mut accum = init; match self.state { ChainState::Front => {} _ => accum = self.b.rfold(accum, &mut f), } match self.state { ChainState::Back => {} _ => accum = self.a.rfold(accum, &mut f), } accum } } impl StreamingIteratorMut for Chain where A: StreamingIteratorMut, B: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { use crate::ChainState::*; match self.state { BothForward | Front => self.a.get_mut(), BothBackward | Back => self.b.get_mut(), } } #[inline] fn fold_mut(self, init: Acc, mut f: F) -> Acc where Self: Sized, F: FnMut(Acc, &mut Self::Item) -> Acc, { let mut accum = init; match self.state { ChainState::Back => {} _ => accum = self.a.fold_mut(accum, &mut f), } match self.state { ChainState::Front => {} _ => accum = self.b.fold_mut(accum, &mut f), } accum } } impl DoubleEndedStreamingIteratorMut for Chain where A: DoubleEndedStreamingIteratorMut, B: DoubleEndedStreamingIteratorMut, { fn rfold_mut(self, init: Acc, mut f: F) -> Acc where Self: Sized, F: FnMut(Acc, &mut Self::Item) -> Acc, { let mut accum = init; match self.state { ChainState::Front => {} _ => accum = self.b.rfold_mut(accum, &mut f), } match self.state { ChainState::Back => {} _ => accum = self.a.rfold_mut(accum, &mut f), } accum } } /// A normal, non-streaming, iterator which converts the elements of a streaming iterator into owned /// values by cloning them. #[derive(Clone, Debug)] pub struct Cloned(I); impl Iterator for Cloned where I: StreamingIterator, I::Item: Clone, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { self.0.next().cloned() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { self.0.fold(init, move |acc, item| f(acc, item.clone())) } } impl DoubleEndedIterator for Cloned where I: DoubleEndedStreamingIterator, I::Item: Clone, { #[inline] fn next_back(&mut self) -> Option { self.0.next_back().cloned() } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { self.0.rfold(init, move |acc, item| f(acc, item.clone())) } } /// A normal, non-streaming, iterator which converts the elements of a streaming iterator into owned /// values by copying them. #[derive(Clone, Debug)] pub struct Copied(I); impl Iterator for Copied where I: StreamingIterator, I::Item: Copy, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { self.0.next().copied() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { self.0.fold(init, move |acc, &item| f(acc, item)) } } impl DoubleEndedIterator for Copied where I: DoubleEndedStreamingIterator, I::Item: Copy, { #[inline] fn next_back(&mut self) -> Option { self.0.next_back().copied() } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { self.0.rfold(init, move |acc, &item| f(acc, item)) } } /// A streaming iterator which filters the elements of a streaming iterator with a predicate. #[derive(Debug)] pub struct Filter { it: I, f: F, } impl StreamingIterator for Filter where I: StreamingIterator, F: FnMut(&I::Item) -> bool, { type Item = I::Item; #[inline] fn advance(&mut self) { while let Some(i) = self.it.next() { if (self.f)(i) { break; } } } #[inline] fn is_done(&self) -> bool { self.it.is_done() } #[inline] fn get(&self) -> Option<&I::Item> { self.it.get() } #[inline] fn size_hint(&self) -> (usize, Option) { (0, self.it.size_hint().1) } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.fold( init, move |acc, item| { if f(item) { fold(acc, item) } else { acc } }, ) } } impl DoubleEndedStreamingIterator for Filter where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> bool, { #[inline] fn advance_back(&mut self) { while let Some(i) = self.it.next_back() { if (self.f)(i) { break; } } } #[inline] fn rfold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.rfold( init, move |acc, item| { if f(item) { fold(acc, item) } else { acc } }, ) } } impl StreamingIteratorMut for Filter where I: StreamingIteratorMut, F: FnMut(&I::Item) -> bool, { #[inline] fn get_mut(&mut self) -> Option<&mut I::Item> { self.it.get_mut() } #[inline] fn fold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.fold_mut( init, move |acc, item| { if f(&*item) { fold(acc, item) } else { acc } }, ) } } impl DoubleEndedStreamingIteratorMut for Filter where I: DoubleEndedStreamingIteratorMut, F: FnMut(&I::Item) -> bool, { #[inline] fn rfold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.rfold_mut( init, move |acc, item| { if f(&*item) { fold(acc, item) } else { acc } }, ) } } /// An iterator which both filters and maps elements of a streaming iterator with a closure. #[derive(Debug)] pub struct FilterMap { it: I, f: F, item: Option, } impl StreamingIterator for FilterMap where I: StreamingIterator, F: FnMut(&I::Item) -> Option, { type Item = B; #[inline] fn advance(&mut self) { loop { match self.it.next() { Some(i) => { if let Some(i) = (self.f)(i) { self.item = Some(i); break; } } None => { self.item = None; break; } } } } #[inline] fn get(&self) -> Option<&B> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { (0, self.it.size_hint().1) } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.fold(init, move |acc, item| match f(item) { Some(item) => fold(acc, &item), None => acc, }) } } impl DoubleEndedStreamingIterator for FilterMap where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> Option, { #[inline] fn advance_back(&mut self) { loop { match self.it.next_back() { Some(i) => { if let Some(i) = (self.f)(i) { self.item = Some(i); break; } } None => { self.item = None; break; } } } } #[inline] fn rfold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.rfold(init, move |acc, item| match f(item) { Some(item) => fold(acc, &item), None => acc, }) } } impl StreamingIteratorMut for FilterMap where I: StreamingIterator, F: FnMut(&I::Item) -> Option, { #[inline] fn get_mut(&mut self) -> Option<&mut B> { self.item.as_mut() } #[inline] fn fold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.fold(init, move |acc, item| match f(item) { Some(mut item) => fold(acc, &mut item), None => acc, }) } } impl DoubleEndedStreamingIteratorMut for FilterMap where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> Option, { #[inline] fn rfold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.rfold(init, move |acc, item| match f(item) { Some(mut item) => fold(acc, &mut item), None => acc, }) } } /// A streaming iterator that maps elements to iterators with a closure and then yields the /// concatenation of the obtained iterators #[derive(Debug)] pub struct FlatMap { it: I, f: F, sub_iter: Option, } impl StreamingIterator for FlatMap where I: StreamingIterator, F: FnMut(&I::Item) -> J, J: StreamingIterator, { type Item = J::Item; #[inline] fn advance(&mut self) { loop { if let Some(ref mut iter) = self.sub_iter { iter.advance(); if !iter.is_done() { break; } } if let Some(item) = self.it.next() { self.sub_iter = Some((self.f)(item)); } else { break; } } } #[inline] fn is_done(&self) -> bool { match self.sub_iter { Some(ref iter) => iter.is_done(), None => true, } } #[inline] fn get(&self) -> Option<&Self::Item> { self.sub_iter.as_ref().and_then(J::get) } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut acc = init; if let Some(iter) = self.sub_iter { acc = iter.fold(acc, &mut fold); } let mut f = self.f; self.it.fold(acc, |acc, item| f(item).fold(acc, &mut fold)) } } impl StreamingIteratorMut for FlatMap where I: StreamingIterator, F: FnMut(&I::Item) -> J, J: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.sub_iter.as_mut().and_then(J::get_mut) } #[inline] fn fold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut acc = init; if let Some(iter) = self.sub_iter { acc = iter.fold_mut(acc, &mut fold); } let mut f = self.f; self.it .fold(acc, |acc, item| f(item).fold_mut(acc, &mut fold)) } } /// A streaming iterator that flattens nested streaming iterators. #[derive(Debug)] pub struct Flatten { iter: I, first: bool, } impl StreamingIterator for Flatten where I: StreamingIteratorMut, I::Item: StreamingIterator, { type Item = ::Item; #[inline] fn advance(&mut self) { if self.first { self.first = false; self.iter.advance(); } while let Some(iter) = self.iter.get_mut() { iter.advance(); if !iter.is_done() { break; } self.iter.advance(); // since we got Some, self.iter is not done and can be advanced } } #[inline] fn is_done(&self) -> bool { match self.iter.get() { Some(iter) => iter.is_done(), None => true, } } #[inline] fn get(&self) -> Option<&Self::Item> { self.iter.get().and_then(I::Item::get) } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.iter .fold_mut(init, |acc, item| item.fold(acc, &mut fold)) } } impl StreamingIteratorMut for Flatten where I: StreamingIteratorMut, I::Item: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.iter.get_mut().and_then(I::Item::get_mut) } #[inline] fn fold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { self.iter .fold_mut(init, |acc, item| item.fold_mut(acc, &mut fold)) } } /// A regular, non-streaming iterator which both filters and maps elements of a streaming iterator with a closure. #[derive(Debug)] pub struct FilterMapDeref { it: I, f: F, } impl Iterator for FilterMapDeref where I: StreamingIterator, F: FnMut(&I::Item) -> Option, { type Item = B; #[inline] fn next(&mut self) -> Option { while let Some(item) = self.it.next() { if let Some(mapped) = (self.f)(item) { return Some(mapped); } } None } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { let mut map = self.f; self.it.fold(init, move |acc, item| match map(item) { Some(mapped) => f(acc, mapped), None => acc, }) } } impl DoubleEndedIterator for FilterMapDeref where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> Option, { #[inline] fn next_back(&mut self) -> Option { while let Some(item) = self.it.next_back() { if let Some(mapped) = (self.f)(item) { return Some(mapped); } } None } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { let mut map = self.f; self.it.rfold(init, move |acc, item| match map(item) { Some(mapped) => f(acc, mapped), None => acc, }) } } #[derive(Copy, Clone, Debug)] enum FuseState { Start, Middle, End, } /// A streaming iterator which is well-defined before and after iteration. #[derive(Clone, Debug)] pub struct Fuse { it: I, state: FuseState, } impl StreamingIterator for Fuse where I: StreamingIterator, { type Item = I::Item; #[inline] fn advance(&mut self) { match self.state { FuseState::Start => { self.it.advance(); self.state = if self.it.is_done() { FuseState::End } else { FuseState::Middle }; } FuseState::Middle => { self.it.advance(); if self.it.is_done() { self.state = FuseState::End; } } FuseState::End => {} } } #[inline] fn is_done(&self) -> bool { match self.state { FuseState::Start | FuseState::End => true, FuseState::Middle => false, } } #[inline] fn get(&self) -> Option<&I::Item> { match self.state { FuseState::Start | FuseState::End => None, FuseState::Middle => self.it.get(), } } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn next(&mut self) -> Option<&I::Item> { match self.state { FuseState::Start => match self.it.next() { Some(i) => { self.state = FuseState::Middle; Some(i) } None => { self.state = FuseState::End; None } }, FuseState::Middle => match self.it.next() { Some(i) => Some(i), None => { self.state = FuseState::End; None } }, FuseState::End => None, } } #[inline] fn count(self) -> usize { match self.state { FuseState::Start | FuseState::Middle => self.it.count(), FuseState::End => 0, } } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { match self.state { FuseState::Start | FuseState::Middle => self.it.fold(init, fold), FuseState::End => init, } } } impl StreamingIteratorMut for Fuse where I: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut I::Item> { match self.state { FuseState::Start | FuseState::End => None, FuseState::Middle => self.it.get_mut(), } } #[inline] fn fold_mut(self, init: Acc, fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { match self.state { FuseState::Start | FuseState::Middle => self.it.fold_mut(init, fold), FuseState::End => init, } } } /// A streaming iterator that calls a function with element before yielding it. #[derive(Debug)] pub struct Inspect { it: I, f: F, } impl StreamingIterator for Inspect where I: StreamingIterator, F: FnMut(&I::Item), { type Item = I::Item; fn advance(&mut self) { if let Some(item) = self.it.next() { (self.f)(item); } } #[inline] fn is_done(&self) -> bool { self.it.is_done() } fn get(&self) -> Option<&Self::Item> { self.it.get() } fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.fold(init, |acc, item| { f(item); fold(acc, item) }) } } impl DoubleEndedStreamingIterator for Inspect where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item), { fn advance_back(&mut self) { if let Some(item) = self.it.next_back() { (self.f)(item); } } #[inline] fn rfold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.rfold(init, |acc, item| { f(item); fold(acc, item) }) } } impl StreamingIteratorMut for Inspect where I: StreamingIteratorMut, F: FnMut(&I::Item), { fn get_mut(&mut self) -> Option<&mut Self::Item> { self.it.get_mut() } #[inline] fn fold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.fold_mut(init, |acc, item| { f(&*item); fold(acc, item) }) } } impl DoubleEndedStreamingIteratorMut for Inspect where I: DoubleEndedStreamingIteratorMut, F: FnMut(&I::Item), { #[inline] fn rfold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.rfold_mut(init, |acc, item| { f(&*item); fold(acc, item) }) } } /// A streaming iterator which transforms the elements of a streaming iterator. #[derive(Debug)] pub struct Map { it: I, f: F, item: Option, } impl StreamingIterator for Map where I: StreamingIterator, F: FnMut(&I::Item) -> B, { type Item = B; #[inline] fn advance(&mut self) { self.item = self.it.next().map(&mut self.f); } #[inline] fn get(&self) -> Option<&B> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.fold(init, move |acc, item| fold(acc, &f(item))) } } impl DoubleEndedStreamingIterator for Map where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> B, { #[inline] fn advance_back(&mut self) { self.item = self.it.next_back().map(&mut self.f); } #[inline] fn rfold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let mut f = self.f; self.it.rfold(init, move |acc, item| fold(acc, &f(item))) } } impl StreamingIteratorMut for Map where I: StreamingIterator, F: FnMut(&I::Item) -> B, { #[inline] fn get_mut(&mut self) -> Option<&mut B> { self.item.as_mut() } #[inline] fn fold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it.fold(init, move |acc, item| fold(acc, &mut f(item))) } } impl DoubleEndedStreamingIteratorMut for Map where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> B, { #[inline] fn rfold_mut(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { let mut f = self.f; self.it .rfold(init, move |acc, item| fold(acc, &mut f(item))) } } /// A regular, non-streaming iterator which transforms the elements of a streaming iterator. #[derive(Debug)] pub struct MapDeref { it: I, f: F, } impl Iterator for MapDeref where I: StreamingIterator, F: FnMut(&I::Item) -> B, { type Item = B; #[inline] fn next(&mut self) -> Option { self.it.next().map(&mut self.f) } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { let mut map = self.f; self.it.fold(init, move |acc, item| f(acc, map(item))) } } impl DoubleEndedIterator for MapDeref where I: DoubleEndedStreamingIterator, F: FnMut(&I::Item) -> B, { #[inline] fn next_back(&mut self) -> Option { self.it.next_back().map(&mut self.f) } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { let mut map = self.f; self.it.rfold(init, move |acc, item| f(acc, map(item))) } } /// A regular, non-streaming iterator which transforms the elements of a mutable streaming iterator. #[derive(Debug)] pub struct MapDerefMut { it: I, f: F, } impl Iterator for MapDerefMut where I: StreamingIteratorMut, F: FnMut(&mut I::Item) -> B, { type Item = B; #[inline] fn next(&mut self) -> Option { self.it.next_mut().map(&mut self.f) } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { let mut map = self.f; self.it.fold_mut(init, move |acc, item| f(acc, map(item))) } } impl DoubleEndedIterator for MapDerefMut where I: DoubleEndedStreamingIteratorMut, F: FnMut(&mut I::Item) -> B, { #[inline] fn next_back(&mut self) -> Option { self.it.next_back_mut().map(&mut self.f) } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { let mut map = self.f; self.it.rfold_mut(init, move |acc, item| f(acc, map(item))) } } /// A streaming iterator which transforms the elements of a streaming iterator. #[derive(Debug)] pub struct MapRef { it: I, f: F, } impl StreamingIterator for MapRef where I: StreamingIterator, F: Fn(&I::Item) -> &B, { type Item = B; #[inline] fn advance(&mut self) { self.it.advance(); } #[inline] fn is_done(&self) -> bool { self.it.is_done() } #[inline] fn get(&self) -> Option<&B> { self.it.get().map(&self.f) } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn next(&mut self) -> Option<&B> { self.it.next().map(&self.f) } #[inline] fn fold(self, init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { let f = self.f; self.it.fold(init, move |acc, item| fold(acc, f(item))) } } /// A normal, non-streaming, iterator which converts the elements of a streaming iterator into owned /// versions. /// /// Requires the `alloc` feature. #[cfg(feature = "alloc")] #[derive(Clone, Debug)] pub struct Owned(I); #[cfg(feature = "alloc")] impl Iterator for Owned where I: StreamingIterator, I::Item: ToOwned, { type Item = ::Owned; #[inline] fn next(&mut self) -> Option<::Owned> { self.0.next().map(ToOwned::to_owned) } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { self.0.fold(init, move |acc, item| f(acc, item.to_owned())) } } #[cfg(feature = "alloc")] impl DoubleEndedIterator for Owned where I: DoubleEndedStreamingIterator, I::Item: Sized + ToOwned, { #[inline] fn next_back(&mut self) -> Option<::Owned> { self.0.next_back().map(ToOwned::to_owned) } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, Self::Item) -> Acc, { self.0.rfold(init, move |acc, item| f(acc, item.to_owned())) } } /// A streaming iterator which skips a number of elements in a streaming iterator. #[derive(Clone, Debug)] pub struct Skip { it: I, n: usize, } impl StreamingIterator for Skip where I: StreamingIterator, { type Item = I::Item; #[inline] fn advance(&mut self) { self.it.nth(self.n); self.n = 0; } #[inline] fn is_done(&self) -> bool { self.it.is_done() } #[inline] fn get(&self) -> Option<&I::Item> { self.it.get() } #[inline] fn size_hint(&self) -> (usize, Option) { let hint = self.it.size_hint(); ( hint.0.saturating_sub(self.n), hint.1.map(|n| n.saturating_sub(self.n)), ) } #[inline] fn fold(mut self, init: Acc, fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { if self.n > 0 { // nth(n) skips n+1 if self.it.nth(self.n - 1).is_none() { return init; } } self.it.fold(init, fold) } } impl StreamingIteratorMut for Skip where I: StreamingIteratorMut, { fn get_mut(&mut self) -> Option<&mut Self::Item> { self.it.get_mut() } #[inline] fn fold_mut(mut self, init: Acc, fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { if self.n > 0 { // nth(n) skips n+1 if self.it.nth(self.n - 1).is_none() { return init; } } self.it.fold_mut(init, fold) } } /// A streaming iterator which skips initial elements that match a predicate #[derive(Clone, Debug)] pub struct SkipWhile { it: I, f: F, done: bool, } impl StreamingIterator for SkipWhile where I: StreamingIterator, F: FnMut(&I::Item) -> bool, { type Item = I::Item; #[inline] fn advance(&mut self) { if !self.done { let f = &mut self.f; self.it.find(|i| !f(i)); self.done = true; } else { self.it.advance(); } } #[inline] fn is_done(&self) -> bool { self.it.is_done() } #[inline] fn get(&self) -> Option<&I::Item> { self.it.get() } #[inline] fn size_hint(&self) -> (usize, Option) { let hint = self.it.size_hint(); (0, hint.1) } #[inline] fn fold(mut self, mut init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { if !self.done { match self.next() { Some(item) => init = fold(init, item), None => return init, } } self.it.fold(init, fold) } } impl StreamingIteratorMut for SkipWhile where I: StreamingIteratorMut, F: FnMut(&I::Item) -> bool, { fn get_mut(&mut self) -> Option<&mut Self::Item> { self.it.get_mut() } #[inline] fn fold_mut(mut self, mut init: Acc, mut fold: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &mut Self::Item) -> Acc, { if !self.done { match self.next_mut() { Some(item) => init = fold(init, item), None => return init, } } self.it.fold_mut(init, fold) } } /// A streaming iterator which only yields a limited number of elements in a streaming iterator. #[derive(Clone, Debug)] pub struct Take { it: I, n: usize, done: bool, } impl StreamingIterator for Take where I: StreamingIterator, { type Item = I::Item; #[inline] fn advance(&mut self) { if self.n != 0 { self.it.advance(); self.n -= 1; } else { self.done = true; } } #[inline] fn is_done(&self) -> bool { self.done || self.it.is_done() } #[inline] fn get(&self) -> Option<&I::Item> { if self.done { None } else { self.it.get() } } #[inline] fn size_hint(&self) -> (usize, Option) { let hint = self.it.size_hint(); (cmp::min(hint.0, self.n), Some(self.n)) } } impl StreamingIteratorMut for Take where I: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut I::Item> { if self.done { None } else { self.it.get_mut() } } } /// A streaming iterator which only returns initial elements matching a predicate. #[derive(Debug)] pub struct TakeWhile { it: I, f: F, done: bool, } impl StreamingIterator for TakeWhile where I: StreamingIterator, F: FnMut(&I::Item) -> bool, { type Item = I::Item; #[inline] fn advance(&mut self) { if !self.done { self.it.advance(); if let Some(i) = self.it.get() { if !(self.f)(i) { self.done = true; } } } } #[inline] fn is_done(&self) -> bool { self.done || self.it.is_done() } #[inline] fn get(&self) -> Option<&I::Item> { if self.done { None } else { self.it.get() } } #[inline] fn next(&mut self) -> Option<&I::Item> { if self.done { None } else { match self.it.next() { Some(i) => { if (self.f)(i) { Some(i) } else { self.done = true; None } } None => None, } } } #[inline] fn size_hint(&self) -> (usize, Option) { let upper = if self.done { Some(0) } else { self.it.size_hint().1 }; (0, upper) } } impl StreamingIteratorMut for TakeWhile where I: StreamingIteratorMut, F: FnMut(&I::Item) -> bool, { #[inline] fn get_mut(&mut self) -> Option<&mut I::Item> { if self.done { None } else { self.it.get_mut() } } } /// A streaming iterator which returns elements in the opposite order. pub struct Rev(I); impl StreamingIterator for Rev where I: DoubleEndedStreamingIterator, { type Item = I::Item; #[inline] fn advance(&mut self) { self.0.advance_back(); } #[inline] fn is_done(&self) -> bool { self.0.is_done() } #[inline] fn get(&self) -> Option<&I::Item> { self.0.get() } #[inline] fn next(&mut self) -> Option<&I::Item> { self.0.next_back() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } #[inline] fn fold(self, init: Acc, f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.0.rfold(init, f) } } impl DoubleEndedStreamingIterator for Rev where I: DoubleEndedStreamingIterator, { #[inline] fn advance_back(&mut self) { self.0.advance(); } #[inline] fn next_back(&mut self) -> Option<&I::Item> { self.0.next() } #[inline] fn rfold(self, init: Acc, f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.0.fold(init, f) } } impl StreamingIteratorMut for Rev where I: DoubleEndedStreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut I::Item> { self.0.get_mut() } #[inline] fn fold_mut(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { self.0.rfold_mut(init, f) } } impl DoubleEndedStreamingIteratorMut for Rev where I: DoubleEndedStreamingIteratorMut, { #[inline] fn rfold_mut(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { self.0.fold_mut(init, f) } } /// Conversion from [`IntoIterator`] to [`StreamingIterator`]. pub trait IntoStreamingIterator: IntoIterator where Self: Sized, { /// Turns an [`IntoIterator`] into a [`StreamingIterator`]. /// /// Calling this method on an [`IntoIterator`] is equivalent to using [`convert`]. #[inline] fn into_streaming_iter(self) -> Convert { convert(self) } /// Turns an [`IntoIterator`] of references into a [`StreamingIterator`]. /// /// Calling this method on an [`IntoIterator`] is equivalent to using [`convert_ref`]. #[inline] fn into_streaming_iter_ref<'a, T: ?Sized>(self) -> ConvertRef<'a, Self::IntoIter, T> where Self: IntoIterator, { convert_ref(self) } /// Turns an [`IntoIterator`] of mutable references into a [`StreamingIteratorMut`]. /// /// Calling this method on an [`IntoIterator`] is equivalent to using [`convert_mut`]. #[inline] fn into_streaming_iter_mut<'a, T: ?Sized>(self) -> ConvertMut<'a, Self::IntoIter, T> where Self: IntoIterator, { convert_mut(self) } } impl IntoStreamingIterator for I where I: IntoIterator {} #[cfg(test)] mod test { use core::fmt::Debug; #[cfg(feature = "alloc")] use alloc::vec::Vec; use super::*; fn test(mut it: I, expected: &[I::Item]) where I: StreamingIterator, I::Item: Sized + PartialEq + Debug, { for item in expected { it.advance(); assert_eq!(it.get(), Some(item)); assert_eq!(it.get(), Some(item)); } it.advance(); assert_eq!(it.get(), None); assert_eq!(it.get(), None); } fn test_back(mut it: I, expected: &[I::Item]) where I: DoubleEndedStreamingIterator, I::Item: Sized + PartialEq + Debug, { for item in expected { it.advance_back(); assert_eq!(it.get(), Some(item)); assert_eq!(it.get(), Some(item)); } it.advance_back(); assert_eq!(it.get(), None); assert_eq!(it.get(), None); } fn test_deref(mut it: I, expected: &[I::Item]) where I: Iterator, I::Item: Sized + PartialEq + Debug, { for item in expected { assert_eq!(it.next().as_ref(), Some(item)); } assert_eq!(it.next(), None) } #[test] fn all() { let items = [0, 1, 2]; let mut it = convert(items); assert!(it.clone().all(|&i| i < 3)); assert!(!it.all(|&i| i % 2 == 0)); } #[test] fn any() { let items = [0, 1, 2]; let mut it = convert(items); assert!(it.clone().any(|&i| i > 1)); assert!(!it.any(|&i| i > 2)); } #[test] fn test_chain() { let items_a = [0, 1, 2, 3]; let items_b = [10, 20, 30]; let expected = [0, 1, 2, 3, 10, 20, 30]; let it = convert(items_a).chain(convert(items_b)); test(it, &expected); } #[test] fn test_chain_back() { let items_a = [0, 1, 2, 3]; let items_b = [10, 20, 30]; let expected = [30, 20, 10, 3, 2, 1, 0]; let it = convert(items_a).chain(convert(items_b)); test_back(it, &expected); } #[test] fn test_chain_mixed() { let items_a = [0, 1, 2, 3]; let items_b = [10, 20, 30]; let mut it = convert(items_a).chain(convert(items_b)); assert_eq!(it.get(), None); it.advance(); assert_eq!(it.get().copied(), Some(0)); it.advance_back(); assert_eq!(it.get().copied(), Some(30)); it.advance(); assert_eq!(it.get().copied(), Some(1)); it.advance_back(); assert_eq!(it.get().copied(), Some(20)); it.advance(); assert_eq!(it.get().copied(), Some(2)); it.advance_back(); assert_eq!(it.get().copied(), Some(10)); it.advance_back(); assert_eq!(it.get().copied(), Some(3)); } #[test] fn cloned() { let items = [0, 1]; let mut it = convert(items).cloned(); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), None); } #[test] fn copied() { let items = [0, 1]; let mut it = convert(items).copied(); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); assert_eq!(it.next(), None); } #[test] fn test_convert() { let items = [0, 1]; let it = convert(items); test(it, &items); } #[test] fn test_convert_ref() { let items = [&0, &1]; let it = convert_ref(items.iter()); test(it, &items); } #[test] fn count() { let items = [0, 1, 2, 3]; let it = convert(items); assert_eq!(it.count(), 4); } #[test] fn filter() { let items = [0, 1, 2, 3]; let it = convert(items).filter(|x| x % 2 == 0); test(it, &[0, 2]); } #[test] fn fuse() { struct Flicker(i32); impl StreamingIterator for Flicker { type Item = i32; fn advance(&mut self) { self.0 += 1; } fn get(&self) -> Option<&i32> { if self.0 % 4 == 3 { None } else { Some(&self.0) } } } let mut it = Flicker(0).fuse(); assert_eq!(it.get(), None); it.advance(); assert_eq!(it.get(), Some(&1)); assert_eq!(it.get(), Some(&1)); it.advance(); assert_eq!(it.get(), Some(&2)); assert_eq!(it.get(), Some(&2)); it.advance(); assert_eq!(it.get(), None); assert_eq!(it.get(), None); it.advance(); assert_eq!(it.get(), None); assert_eq!(it.get(), None); } #[test] fn inspect() { let items = [0, 1, 2, 3]; let mut idx = 0; let mut items_inspected = [-1, -1, -1, -1]; { let it = convert(items).inspect(|&i| { items_inspected[idx] = i; idx += 1; }); test(it, &items); } assert_eq!(&items_inspected, &items); } #[test] fn map() { let items = [0, 1]; let it = convert(items.iter().map(|&i| i as usize)).map(|&i| i as i32); test(it, &items); } #[test] fn map_deref() { let items = [0, 1]; let it = convert(items.iter().map(|&i| i as usize)).map_deref(|&i| i as i32); test_deref(it, &items); } #[test] fn map_deref_mut() { let mut items = [1, 2, 3]; { let it = convert_mut(&mut items).map_deref_mut(|i| -core::mem::replace(i, 0)); test_deref(it, &[-1, -2, -3]); } assert_eq!(items, [0, 0, 0]); } #[test] fn map_ref() { #[derive(Clone)] struct Foo(i32); let items = [Foo(0), Foo(1)]; let it = convert(items).map_ref(|f| &f.0); test(it, &[0, 1]); } #[test] fn flat_map() { let items = [[0, 1, 2], [3, 4, 5]]; let it = convert(items).flat_map(|&i| convert(i)); test(it, &[0, 1, 2, 3, 4, 5]); } #[test] fn flatten() { let mut items = [ convert_ref([].as_ref()), convert_ref([1].as_ref()), convert_ref([].as_ref()), convert_ref([2, 3].as_ref()), convert_ref([].as_ref()), ]; let it = convert_mut(&mut items).flatten(); test(it, &[1, 2, 3]); } #[test] fn flatten_unsized() { type DynI32 = dyn StreamingIterator; let mut items = [ &mut once(1) as &mut DynI32, &mut empty(), &mut convert(2..=3), ]; let iters = items.iter_mut().map(|iter| &mut **iter); let it = convert_mut(iters).flatten(); test(it, &[1, 2, 3]); } #[test] fn nth() { let items = [0, 1]; let mut it = convert(items); assert_eq!(it.clone().nth(0), Some(&0)); assert_eq!(it.clone().nth(1), Some(&1)); assert_eq!(it.nth(2), None); } #[test] fn filter_map() { let items = [0u8, 1, 1, 2, 4]; let it = convert(items).filter_map(|&i| if i % 2 == 0 { Some(i) } else { None }); test(it, &[0, 2, 4]) } #[test] fn filter_map_deref() { let items = [0u8, 1, 1, 2, 4]; let it = convert(items).filter_map_deref(|&i| if i % 2 == 0 { Some(i) } else { None }); test_deref(it, &[0, 2, 4]) } #[test] fn find() { let items = [0, 1]; let mut it = convert(items); assert_eq!(it.clone().find(|&x| x % 2 == 1), Some(&1)); assert_eq!(it.find(|&x| x % 3 == 2), None); } #[test] #[cfg(feature = "alloc")] fn owned() { let items = [0, 1]; let it = convert(items).owned(); assert_eq!(it.collect::>(), items); } #[test] #[cfg(feature = "alloc")] fn owned_str() { let s = "The quick brown fox jumps over the lazy dog"; let words = s.split_whitespace().map(str::to_owned).collect::>(); let it = convert_ref(s.split_whitespace()).owned(); assert_eq!(it.collect::>(), words); } #[test] fn position() { let items = [0, 1]; let mut it = convert(items); assert_eq!(it.clone().position(|&x| x % 2 == 1), Some(1)); assert_eq!(it.position(|&x| x % 3 == 2), None); } #[test] fn skip() { let items = [0, 1, 2, 3]; let it = convert(items); test(it.clone().skip(0), &[0, 1, 2, 3]); test(it.clone().skip(2), &[2, 3]); test(it.skip(5), &[]); } #[test] fn skip_while() { let items = [0, 1, 2, 3]; let it = convert(items); test(it.clone().skip_while(|&i| i < 0), &[0, 1, 2, 3]); test(it.clone().skip_while(|&i| i < 2), &[2, 3]); test(it.skip_while(|&i| i < 5), &[]); } #[test] fn take() { let items = [0, 1, 2, 3]; let it = convert(items); test(it.clone().take(0), &[]); test(it.clone().take(2), &[0, 1]); test(it.take(5), &[0, 1, 2, 3]); } #[test] fn take_while() { let items = [0, 1, 2, 3]; let it = convert(items); test(it.clone().take_while(|&i| i < 0), &[]); test(it.clone().take_while(|&i| i < 2), &[0, 1]); test(it.take_while(|&i| i < 5), &[0, 1, 2, 3]); } fn _is_object_safe(_: &dyn StreamingIterator) {} fn _is_object_safe_mut(_: &dyn StreamingIteratorMut) {} #[test] fn empty_iterator() { let mut it: Empty = empty(); assert_eq!(it.next(), None); } #[test] fn is_done_empty() { let mut empty = empty::(); empty.advance(); assert!(empty.is_done()); } #[test] fn is_done_map() { let items = [1]; let mut it = convert(items).map_ref::(|_| panic!("only called during get()")); it.advance(); assert!(!it.is_done()); it.advance(); assert!(it.is_done()); } #[test] fn rev() { let items = [0, 1, 2, 3]; let it = convert(items); test(it.rev(), &[3, 2, 1, 0]); } #[test] fn fold() { let items = [0, 1, 2, 3]; let it = convert(items); assert_eq!(it.fold(0, |acc, i| acc * 10 + i), 123); } #[test] fn for_each() { let items = [0, 1, 2, 3]; let it = convert(items); let mut acc = 0; it.for_each(|i| acc = acc * 10 + i); assert_eq!(acc, 123); } #[test] fn rfold() { let items = [0, 1, 2, 3]; let it = convert(items); assert_eq!(it.rfold(0, |acc, i| acc * 10 + i), 3210); } #[test] fn for_each_rev() { let items = [0, 1, 2, 3]; let it = convert(items); let mut acc = 0; it.rev().for_each(|i| acc = acc * 10 + i); assert_eq!(acc, 3210); } #[test] fn for_each_mut() { let mut items = [0, 1, 2, 3]; convert_mut(&mut items).for_each_mut(|i: &mut i32| *i += 10); assert_eq!(items, [10, 11, 12, 13]); // Note that filter sees a direct `&T` reference, // rather than `&&mut T` like `Iterator` would. convert_mut(&mut items) .filter(|&i: &i32| i & 1 == 0) .for_each_mut(|i: &mut i32| *i /= 2); assert_eq!(items, [5, 11, 6, 13]); } #[test] fn into_streaming_iter() { let items = [0, 1, 2, 3]; let iter = items.into_streaming_iter(); test(iter, &items); let iter = (&items).into_streaming_iter_ref(); test(iter, &items); let mut mut_items = items; let iter = (&mut mut_items).into_streaming_iter_mut(); test(iter, &items); } } streaming-iterator-0.1.9/src/slice.rs000064400000000000000000000120351046102023000157100ustar 00000000000000use crate::{ DoubleEndedStreamingIterator, DoubleEndedStreamingIteratorMut, StreamingIterator, StreamingIteratorMut, }; use core::mem; use core::num::NonZeroUsize; /// Creates an iterator over all contiguous windows of length `size` in a mutable `slice`. /// /// The windows overlap and may be mutated via `StreamingIteratorMut`. /// If the `slice` is shorter than `size`, the iterator returns no values. /// /// # Panics /// /// Panics if `size` is 0. pub fn windows_mut(slice: &mut [T], size: usize) -> WindowsMut<'_, T> { WindowsMut { slice, size: NonZeroUsize::new(size).expect("size is zero"), position: Position::Init, } } /// A streaming iterator which returns overlapping mutable subslices of length `size`. /// /// This struct is created by the [`windows_mut`] function. pub struct WindowsMut<'a, T> { slice: &'a mut [T], size: NonZeroUsize, position: Position, } enum Position { Init, Front, Back, } impl WindowsMut<'_, T> { fn consume(&mut self) { match self.position { Position::Init => {} Position::Front => { let slice = mem::take(&mut self.slice); if let Some((_, tail)) = slice.split_first_mut() { self.slice = tail; } } Position::Back => { let slice = mem::take(&mut self.slice); if let Some((_, head)) = slice.split_last_mut() { self.slice = head; } } } } fn get_front(&self) -> Option<&[T]> { self.slice.get(..self.size.get()) } fn get_front_mut(&mut self) -> Option<&mut [T]> { self.slice.get_mut(..self.size.get()) } fn get_back(&self) -> Option<&[T]> { let start = self.slice.len().checked_sub(self.size.get())?; self.slice.get(start..) } fn get_back_mut(&mut self) -> Option<&mut [T]> { let start = self.slice.len().checked_sub(self.size.get())?; self.slice.get_mut(start..) } fn len(&self) -> usize { let len = match self.position { Position::Init => self.slice.len(), _ => self.slice.len().saturating_sub(1), }; len.saturating_sub(self.size.get() - 1) } } impl StreamingIterator for WindowsMut<'_, T> { type Item = [T]; fn advance(&mut self) { self.consume(); self.position = Position::Front; } fn get(&self) -> Option<&Self::Item> { match self.position { Position::Init => None, Position::Front => self.get_front(), Position::Back => self.get_back(), } } fn next(&mut self) -> Option<&Self::Item> { self.advance(); self.get_front() } fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } fn is_done(&self) -> bool { self.slice.len() < self.size.get() } fn count(self) -> usize { self.len() } } impl StreamingIteratorMut for WindowsMut<'_, T> { fn get_mut(&mut self) -> Option<&mut Self::Item> { match self.position { Position::Init => None, Position::Front => self.get_front_mut(), Position::Back => self.get_back_mut(), } } fn next_mut(&mut self) -> Option<&mut Self::Item> { self.advance(); self.get_front_mut() } } impl DoubleEndedStreamingIterator for WindowsMut<'_, T> { fn advance_back(&mut self) { self.consume(); self.position = Position::Back; } fn next_back(&mut self) -> Option<&Self::Item> { self.advance_back(); self.get_back() } } impl DoubleEndedStreamingIteratorMut for WindowsMut<'_, T> { fn next_back_mut(&mut self) -> Option<&mut Self::Item> { self.advance_back(); self.get_back_mut() } } #[test] fn test_windows_mut() { let slice: &mut [_] = &mut [0; 6]; windows_mut(slice, 3).fold_mut(0, |i, win| { win.copy_from_slice(&[i; 3]); i + 1 }); assert_eq!(slice, &[0, 1, 2, 3, 3, 3]); windows_mut(slice, 2).rfold_mut(0, |i, win| { win.copy_from_slice(&[i; 2]); i + 1 }); assert_eq!(slice, &[4, 4, 3, 2, 1, 0]); let mut i = 0; let mut iter = windows_mut(slice, 1); while let Some(win) = iter.next_mut() { win.copy_from_slice(&[i]); i += 1; if let Some(win) = iter.next_back_mut() { win.copy_from_slice(&[i]); i += 1; } } assert_eq!(slice, &[0, 2, 4, 5, 3, 1]); } #[test] fn test_windows_mut_count() { let slice: &mut [_] = &mut [0; 6]; assert_eq!(windows_mut(slice, 3).count(), 4); assert_eq!(windows_mut(slice, 6).count(), 1); assert_eq!(windows_mut(slice, 9).count(), 0); let mut iter = windows_mut(slice, 3); assert_eq!(iter.size_hint(), (4, Some(4))); iter.advance(); assert_eq!(iter.count(), 3); } #[test] #[should_panic] fn test_windows_mut_0() { let _: WindowsMut<'_, i32> = windows_mut(&mut [], 0); } streaming-iterator-0.1.9/src/sources.rs000064400000000000000000000416331046102023000163020ustar 00000000000000use super::{DoubleEndedStreamingIterator, StreamingIterator}; use super::{DoubleEndedStreamingIteratorMut, StreamingIteratorMut}; use core::marker::PhantomData; use core::usize; /// Turns a normal, non-streaming iterator into a streaming iterator. /// /// ``` /// # use streaming_iterator::{StreamingIterator, convert}; /// let scores = vec![100, 50, 80]; /// let mut streaming_iter = convert(scores); /// while let Some(score) = streaming_iter.next() { /// println!("The score is: {}", score); /// } /// ``` #[inline] pub fn convert(it: I) -> Convert where I: IntoIterator, { Convert { it: it.into_iter(), item: None, } } /// Turns an iterator of references into a streaming iterator. /// /// ``` /// # use streaming_iterator::{StreamingIterator, convert_ref}; /// let scores = vec![100, 50, 80]; /// let mut streaming_iter = convert_ref(&scores); /// while let Some(score) = streaming_iter.next() { /// println!("The score is: {}", score); /// } /// ``` #[inline] pub fn convert_ref<'a, I, T: ?Sized>(iterator: I) -> ConvertRef<'a, I::IntoIter, T> where I: IntoIterator, { ConvertRef { it: iterator.into_iter(), item: None, } } /// Turns an iterator of mutable references into a streaming iterator. /// /// ``` /// # use streaming_iterator::{StreamingIteratorMut, convert_mut}; /// let mut scores = vec![Some(100), None, Some(80)]; /// { /// let mut streaming_iter = convert_mut(&mut scores); /// while let Some(opt_score) = streaming_iter.next_mut() { /// if let Some(score) = opt_score.take() { /// println!("The score is: {}", score); /// } /// // else already reported /// } /// } /// assert_eq!(scores, [None, None, None]); /// ``` #[inline] pub fn convert_mut<'a, I, T: ?Sized>(iterator: I) -> ConvertMut<'a, I::IntoIter, T> where I: IntoIterator, { ConvertMut { it: iterator.into_iter(), item: None, } } /// Creates an empty iterator. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// let mut streaming_iter = streaming_iterator::empty::(); /// assert_eq!(streaming_iter.next(), None); /// ``` #[inline] pub fn empty() -> Empty { Empty { phantom: PhantomData, } } /// Creates an iterator that returns items from a function call. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// let mut count = 0; /// let mut streaming_iter = streaming_iterator::from_fn(|| { /// count += 1; /// if count < 4 { Some(count) } else { None } /// }); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&2)); /// assert_eq!(streaming_iter.next(), Some(&3)); /// assert_eq!(streaming_iter.next(), None); /// ``` #[inline] pub fn from_fn Option>(gen: F) -> FromFn { FromFn { gen, item: None } } /// Creates an iterator that returns exactly one item. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// let mut streaming_iter = streaming_iterator::once(1); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), None); /// ``` #[inline] pub fn once(item: T) -> Once { Once { first: true, item: Some(item), } } /// Creates an iterator that returns exactly one item from a function call. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// #[derive(Debug, PartialEq)] /// struct Expensive(i32); /// let mut streaming_iter = streaming_iterator::once_with(|| Expensive(1)); /// assert_eq!(streaming_iter.next(), Some(&Expensive(1))); /// assert_eq!(streaming_iter.next(), None); /// ``` #[inline] pub fn once_with T>(gen: F) -> OnceWith { OnceWith { gen: Some(gen), item: None, } } /// Creates an iterator that returns an item endlessly. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// let mut streaming_iter = streaming_iterator::repeat(1); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&1)); /// // ... /// ``` #[inline] pub fn repeat(item: T) -> Repeat { Repeat { item } } /// Creates an iterator that endlessly returns items from a function call. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// let mut count = 0; /// let mut streaming_iter = streaming_iterator::repeat_with(|| { /// count += 1; /// count /// }); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&2)); /// assert_eq!(streaming_iter.next(), Some(&3)); /// assert_eq!(streaming_iter.next(), Some(&4)); /// assert_eq!(streaming_iter.next(), Some(&5)); /// // ... /// ``` #[inline] pub fn repeat_with T>(gen: F) -> RepeatWith { RepeatWith { gen, item: None } } /// Creates an iterator where each successive item is computed from the preceding one. /// /// ``` /// # use streaming_iterator::StreamingIterator; /// let mut streaming_iter = streaming_iterator::successors( /// Some(1), /// |count| if count < 3 { Some(count + 1) } else { None }, /// ); /// assert_eq!(streaming_iter.next(), Some(&1)); /// assert_eq!(streaming_iter.next(), Some(&2)); /// assert_eq!(streaming_iter.next(), Some(&3)); /// assert_eq!(streaming_iter.next(), None); /// ``` #[inline] pub fn successors Option>(first: Option, succ: F) -> Successors { Successors { first: true, item: first, succ, } } /// A streaming iterator which yields elements from a normal, non-streaming, iterator. #[derive(Clone, Debug)] pub struct Convert where I: Iterator, { it: I, item: Option, } impl StreamingIterator for Convert where I: Iterator, { type Item = I::Item; #[inline] fn advance(&mut self) { self.item = self.it.next(); } #[inline] fn get(&self) -> Option<&I::Item> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn count(self) -> usize { self.it.count() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.it.fold(init, move |acc, item| f(acc, &item)) } } impl DoubleEndedStreamingIterator for Convert where I: DoubleEndedIterator, { #[inline] fn advance_back(&mut self) { self.item = self.it.next_back(); } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.it.rfold(init, move |acc, item| f(acc, &item)) } } impl StreamingIteratorMut for Convert where I: Iterator, { #[inline] fn get_mut(&mut self) -> Option<&mut I::Item> { self.item.as_mut() } #[inline] fn fold_mut(self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { self.it.fold(init, move |acc, mut item| f(acc, &mut item)) } } impl DoubleEndedStreamingIteratorMut for Convert where I: DoubleEndedIterator, { #[inline] fn rfold_mut(self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { self.it.rfold(init, move |acc, mut item| f(acc, &mut item)) } } /// A streaming iterator which yields elements from an iterator of references. #[derive(Clone, Debug)] pub struct ConvertRef<'a, I, T: ?Sized> where I: Iterator, { it: I, item: Option<&'a T>, } impl<'a, I, T: ?Sized> StreamingIterator for ConvertRef<'a, I, T> where I: Iterator, { type Item = T; #[inline] fn advance(&mut self) { self.item = self.it.next(); } #[inline] fn get(&self) -> Option<&T> { self.item } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn count(self) -> usize { self.it.count() } #[inline] fn fold(self, init: Acc, f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.it.fold(init, f) } } impl<'a, I, T: ?Sized> DoubleEndedStreamingIterator for ConvertRef<'a, I, T> where I: DoubleEndedIterator, { #[inline] fn advance_back(&mut self) { self.item = self.it.next_back(); } #[inline] fn rfold(self, init: Acc, f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.it.rfold(init, f) } } /// A streaming iterator which yields elements from an iterator of mutable references. #[derive(Debug)] pub struct ConvertMut<'a, I, T: ?Sized> where I: Iterator, { it: I, item: Option<&'a mut T>, } impl<'a, I, T: ?Sized> StreamingIterator for ConvertMut<'a, I, T> where I: Iterator, { type Item = T; #[inline] fn advance(&mut self) { self.item = self.it.next(); } #[inline] fn get(&self) -> Option<&T> { match self.item { Some(&mut ref item) => Some(item), None => None, } } #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } #[inline] fn count(self) -> usize { self.it.count() } #[inline] fn fold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.it.fold(init, move |acc, item| f(acc, item)) } } impl<'a, I, T: ?Sized> DoubleEndedStreamingIterator for ConvertMut<'a, I, T> where I: DoubleEndedIterator, { #[inline] fn advance_back(&mut self) { self.item = self.it.next_back(); } #[inline] fn rfold(self, init: Acc, mut f: Fold) -> Acc where Self: Sized, Fold: FnMut(Acc, &Self::Item) -> Acc, { self.it.rfold(init, move |acc, item| f(acc, item)) } } impl<'a, I, T: ?Sized> StreamingIteratorMut for ConvertMut<'a, I, T> where I: Iterator, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { match self.item { Some(&mut ref mut item) => Some(item), None => None, } } #[inline] fn fold_mut(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { self.it.fold(init, f) } } impl<'a, I, T: ?Sized> DoubleEndedStreamingIteratorMut for ConvertMut<'a, I, T> where I: DoubleEndedIterator, { #[inline] fn rfold_mut(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, &mut Self::Item) -> B, { self.it.rfold(init, f) } } /// A simple iterator that returns nothing. #[derive(Clone, Debug)] pub struct Empty { phantom: PhantomData, } impl StreamingIterator for Empty { type Item = T; #[inline] fn advance(&mut self) {} #[inline] fn get(&self) -> Option<&Self::Item> { None } #[inline] fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } impl DoubleEndedStreamingIterator for Empty { #[inline] fn advance_back(&mut self) {} } impl StreamingIteratorMut for Empty { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { None } } impl DoubleEndedStreamingIteratorMut for Empty {} /// A simple iterator that returns items from a function call. #[derive(Clone, Debug)] pub struct FromFn { gen: F, item: Option, } impl Option> StreamingIterator for FromFn { type Item = T; #[inline] fn advance(&mut self) { self.item = (self.gen)(); } #[inline] fn get(&self) -> Option<&Self::Item> { self.item.as_ref() } } impl Option> StreamingIteratorMut for FromFn { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.item.as_mut() } } /// A simple iterator that returns exactly one item. #[derive(Clone, Debug)] pub struct Once { first: bool, item: Option, } impl StreamingIterator for Once { type Item = T; #[inline] fn advance(&mut self) { if self.first { self.first = false; } else { self.item = None; } } #[inline] fn get(&self) -> Option<&Self::Item> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.first as usize; (len, Some(len)) } } impl DoubleEndedStreamingIterator for Once { #[inline] fn advance_back(&mut self) { self.advance(); } } impl StreamingIteratorMut for Once { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.item.as_mut() } } impl DoubleEndedStreamingIteratorMut for Once {} /// A simple iterator that returns exactly one item from a function call. #[derive(Clone, Debug)] pub struct OnceWith { gen: Option, item: Option, } impl T> StreamingIterator for OnceWith { type Item = T; #[inline] fn advance(&mut self) { self.item = self.gen.take().map(|gen| gen()); } #[inline] fn get(&self) -> Option<&Self::Item> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.gen.is_some() as usize; (len, Some(len)) } } impl T> DoubleEndedStreamingIterator for OnceWith { #[inline] fn advance_back(&mut self) { self.advance(); } } impl T> StreamingIteratorMut for OnceWith { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.item.as_mut() } } impl T> DoubleEndedStreamingIteratorMut for OnceWith {} /// A simple iterator that repeats an item endlessly. /// /// Note: if the item is modified through `StreamingIteratorMut`, /// this will continue be reflected in further iterations! #[derive(Clone, Debug)] pub struct Repeat { item: T, } impl StreamingIterator for Repeat { type Item = T; #[inline] fn advance(&mut self) {} #[inline] fn get(&self) -> Option<&Self::Item> { Some(&self.item) } #[inline] fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } } impl DoubleEndedStreamingIterator for Repeat { #[inline] fn advance_back(&mut self) {} } impl StreamingIteratorMut for Repeat { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { Some(&mut self.item) } } impl DoubleEndedStreamingIteratorMut for Repeat {} /// A simple iterator that endlessly returns items from a function call. #[derive(Clone, Debug)] pub struct RepeatWith { gen: F, item: Option, } impl T> StreamingIterator for RepeatWith { type Item = T; #[inline] fn advance(&mut self) { self.item = Some((self.gen)()); } #[inline] fn get(&self) -> Option<&Self::Item> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } } impl T> StreamingIteratorMut for RepeatWith { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.item.as_mut() } } /// An iterator where each successive item is computed from the preceding one. /// /// Note: if an item is modified through `StreamingIteratorMut`, those changes /// will be visible to the successor function when the iterator is advanced. #[derive(Clone, Debug)] pub struct Successors { first: bool, item: Option, succ: F, } impl Option> StreamingIterator for Successors { type Item = T; #[inline] fn advance(&mut self) { if self.first { self.first = false; } else if let Some(item) = self.item.take() { self.item = (self.succ)(item); } } #[inline] fn get(&self) -> Option<&Self::Item> { self.item.as_ref() } #[inline] fn size_hint(&self) -> (usize, Option) { match (self.first, &self.item) { // We have a first item and unknown successors (true, &Some(_)) => (1, None), // We only have unknown successors (false, &Some(_)) => (0, None), // We have nothing. (_, &None) => (0, Some(0)), } } } impl Option> StreamingIteratorMut for Successors { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { self.item.as_mut() } }