diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/itertools-0.8.0 | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/itertools-0.8.0')
53 files changed, 12008 insertions, 0 deletions
diff --git a/third_party/rust/itertools-0.8.0/.cargo-checksum.json b/third_party/rust/itertools-0.8.0/.cargo-checksum.json new file mode 100644 index 0000000000..d7eca710e8 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"a4dc734c8e5ac0e5b57ded98adeb9340621d5c586d196d423781d7ceab06538b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.rst":"9db27658be49c4d5501c6bb6fbed1dcc1e796c7d934757cf3e94eab14d241d1d","benches/bench1.rs":"9794e5377019e4cf8caee3e7bb30034cf8ac291a485e64407df321f3f33affa0","benches/extra/mod.rs":"4c5b03e74fc5b02383500c9da9fd6550262706ee569d70d085700f6d0b5749ba","benches/extra/zipslices.rs":"108dd488de366b2d83fb6bcc603ecbf9a017e165ac19d03440074fa244af3fb2","benches/tree_fold1.rs":"84cddbabb1a681f3196430a8e27b060103366143a3ee4c42c3b0628fc00a7543","benches/tuple_combinations.rs":"6a4b89eb2e45fa0c99e5e5942b3196b76998213c66c44b3765b869be42016a82","benches/tuples.rs":"412a952f08bb03695952d5cfd57949dcf28be8b99e3c6653994bdb8af9654653","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"3996ca0a62762aec2b102f0f4244fe90d4b4354286d68d80cdc40e35f4352ba3","src/adaptors/mod.rs":"11ef622421a5980a722a8cd2a732e9379470c1817d8b9c4bcde654c3e417b794","src/adaptors/multi_product.rs":"bb239555be38cde1f419bacfd09728f6ccaf51b6b4811c266b5677705175e685","src/combinations.rs":"a9a3fc78eb5c9f3933ff60275a635d0c81f4864a73515dc052aeb2add4ad4909","src/concat_impl.rs":"276339b00588f54c25f8ffbe0ae3c0031f7e52fb53c6578554a0bde1681b58a5","src/cons_tuples_impl.rs":"87c620d2ffdd3475218f5f493dbef601491be9f6cdfe57c44929449b32e6709f","src/diff.rs":"921e2b867d7b32ffedc72a5eb780811322d14d1e0883a608b9028a2afcad0df2","src/either_or_both.rs":"8ea6db74fa21535de45cb48ee7134495e8822a0fa181fdb646e081251ac9459f","src/format.rs":"412fbe02f12311c6fbcec1044f57ad6991783f5a3f323b9c391accfe4915106f","src/free.rs":"473d19906720eb2a1309c0505497658b1426f3ea0c845b40f41f3154194fff18","src/group_map.rs":"872d6e243e649ad30c94973c034596cc3377b10018e361bca07e11c612006de6","src/groupbylazy.rs":"a067a12671be9ae05a9152518103f39f7286fde09f758de8af75a1064a3b5567","src/impl_macros.rs":"eb0bb3f70ec1bcaffa6110ae4134c777951ed1e5f48d8c811dbf0a597dc48faa","src/intersperse.rs":"9c18f239654ebfcce1d68a0256d2df6d79a2b8c4fb5df87d67e2ebe04a07e1a9","src/kmerge_impl.rs":"51e71d3e76670a8efb16597a9224d2c9b40cee6bc6270d06b66aadafea6dc26b","src/lib.rs":"edac21e8bff7bc7695480022a33ded58916eb1c5ed43f5aa68a7c965b452af0b","src/merge_join.rs":"98e6fcc761a558ad21789efe041c3f90e62f6c75e05840670df45ad4f9b07e1f","src/minmax.rs":"4668a7f824fbc133599f43ffb6f7283e5bd603e07df2d8176abc6f25d6af9db0","src/multipeek_impl.rs":"ebe9544d94d0bf7200f7625241a3b5a291b7b564091a08cad40ff08b51f1b1bf","src/pad_tail.rs":"078615a2892f8c6db665074cf6f1be1bef4cf5ee418bc174edcfd4dc703e163f","src/peeking_take_while.rs":"6aea3bb40fb480e9f3695ce2a7a3a2e2346d437ca846d20e6bb3c09beb0934f4","src/process_results_impl.rs":"5f454cf62ceb82cab7c08c0c190de3ae083e219a8acc7a1a22f17eec9cfcd65c","src/put_back_n_impl.rs":"d35858184c525372b22d14d42cdf63726cf0fd50f5bd42ec7a82d55a8e180e9f","src/rciter_impl.rs":"8f51abc7e1ae3320cc5d56fadd66f880a7a06773be656bd8c4712357f01ae1d9","src/repeatn.rs":"4bd1782364b16105fbef3f3de7bf62780710e5c996db44a00e4b5f16c2625d86","src/size_hint.rs":"c1d35b422a696cf3d63e7c90d8f9fdf01a304cf8156e914287c4ef48fea62dd3","src/sources.rs":"cb6ebe06b05f7da0ac1073ba486c45afaeebf8b558c0f5499f0eacd2cd1785da","src/tee.rs":"59cf9ef0b41882307ea1e3503a2ff351f401f4c43d95acf423a990b0bf0e29ae","src/tuple_impl.rs":"0c7f907e85d2ef0661583b36c7b8a7341b8feadafe28d10539a211dff5c028ea","src/unique_impl.rs":"63db2d720ff5e3d9c0d6c2b245ffff25d4040e4fcbcb2a6524b0f912826f86af","src/with_position.rs":"d922f045f6fa090a431be928f3221c6dc37ac6f9bb54461b3b84f99a7e91244a","src/zip_eq_impl.rs":"f857c69120255db16ad6ddec628c79cb573b1d5179fcebab1906bf5b762c02e3","src/zip_longest.rs":"375325ef069970e6fb83c6097c2824877bb0f06e4f1e664e4fe681804abe003c","src/ziptuple.rs":"d7ae7d3c33185ad74ab2bba750ac337b5c236750cc8341dd9883faf6465712a1","tests/merge_join.rs":"546eaffae40010f15a7bcf95bc53f5e9b67424c5b93df6ffb0aaa1e48e8b90c0","tests/peeking_take_while.rs":"a2ae6474e09620a47bb8a6e3c62929261e72c52881370adb2d22e89aa9e9aec8","tests/quick.rs":"290d52047c66b5c493ff425cc527a476c55a150bc859709a8a8559f3f0a74274","tests/test_core.rs":"1a1c4c2dbb657e9ce5cd2bb0d6475cf965878e2a259b730ada9238c71c2a8d4f","tests/test_std.rs":"90d2794cbee64b3a5a1cb53193387e2d83d2b9bdf588edb506a7bf3c5191d2ec","tests/tuples.rs":"5323d15a7abf6545b2655167d3206b6cf6a947e9409a244ea6a8cf4ad8ceac64","tests/zip.rs":"fe213d70c4fa114cb4d1930a6b971f4af617a239041ddb87e6b5a9bbe62261b8"},"package":"5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"}
\ No newline at end of file diff --git a/third_party/rust/itertools-0.8.0/Cargo.toml b/third_party/rust/itertools-0.8.0/Cargo.toml new file mode 100644 index 0000000000..9141434fe4 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/Cargo.toml @@ -0,0 +1,47 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "itertools" +version = "0.8.0" +authors = ["bluss"] +exclude = ["/bors.toml"] +description = "Extra iterator adaptors, iterator methods, free functions, and macros." +documentation = "https://docs.rs/itertools/" +keywords = ["iterator", "data-structure", "zip", "product", "group-by"] +categories = ["algorithms", "rust-patterns"] +license = "MIT/Apache-2.0" +repository = "https://github.com/bluss/rust-itertools" +[package.metadata.release] +no-dev-version = true +[profile.bench] +debug = true + +[lib] +test = false +bench = false +[dependencies.either] +version = "1.0" +default-features = false +[dev-dependencies.permutohedron] +version = "0.2" + +[dev-dependencies.quickcheck] +version = "0.7" +default-features = false + +[dev-dependencies.rand] +version = "0.6" + +[features] +default = ["use_std"] +use_std = [] diff --git a/third_party/rust/itertools-0.8.0/LICENSE-APACHE b/third_party/rust/itertools-0.8.0/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/third_party/rust/itertools-0.8.0/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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. diff --git a/third_party/rust/itertools-0.8.0/LICENSE-MIT b/third_party/rust/itertools-0.8.0/LICENSE-MIT new file mode 100644 index 0000000000..9203baa055 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2015 + +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. diff --git a/third_party/rust/itertools-0.8.0/README.rst b/third_party/rust/itertools-0.8.0/README.rst new file mode 100644 index 0000000000..b0ddda3c81 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/README.rst @@ -0,0 +1,526 @@ + +Itertools +========= + +Extra iterator adaptors, functions and macros. + +Please read the `API documentation here`__ + +__ https://docs.rs/itertools/ + +|build_status|_ |crates|_ + +.. |build_status| image:: https://travis-ci.org/bluss/rust-itertools.svg?branch=master +.. _build_status: https://travis-ci.org/bluss/rust-itertools + +.. |crates| image:: http://meritbadge.herokuapp.com/itertools +.. _crates: https://crates.io/crates/itertools + +How to use with cargo: + +.. code:: toml + + [dependencies] + itertools = "0.8" + +How to use in your crate: + +.. code:: rust + + #[macro_use] extern crate itertools; + + use itertools::Itertools; + +How to contribute +----------------- + +- Fix a bug or implement a new thing +- Include tests for your new feature, preferably a quickcheck test +- Make a Pull Request + +For new features, please first consider filing a PR to `rust-lang/rust <https://github.com/rust-lang/rust/>`_, +adding your new feature to the `Iterator` trait of the standard library, if you believe it is reasonable. +If it isn't accepted there, proposing it for inclusion in ``itertools`` is a good idea. +The reason for doing is this is so that we avoid future breakage as with ``.flatten()``. +However, if your feature involves heap allocation, such as storing elements in a ``Vec<T>``, +then it can't be accepted into ``libcore``, and you should propose it for ``itertools`` directly instead. + +Recent Changes +-------------- + +- 0.8.0 + + - Added new adaptor ``.map_into()`` for conversions using ``Into`` by @vorner + - Improved ``Itertools`` docs by @JohnHeitmann + - The return type of ``.sorted/_by/_by_key()`` is now an iterator, not a Vec. + - The return type of the ``izip!(x, y)`` macro with exactly two arguments + is now the usual ``Iterator::zip``. + - Remove ``.flatten()`` in favour of std's ``.flatten()`` + - Deprecate ``.foreach()`` in favour of std's ``.for_each()`` + - Deprecate ``.step()`` in favour of std's ``.step_by()`` + - Deprecate ``repeat_call`` in favour of std's ``repeat_with`` + - Deprecate ``.fold_while()`` in favour of std's ``.try_fold()`` + - Require Rust 1.24 as minimal version. + +- 0.7.11 + + - Add convenience methods to ``EitherOrBoth``, making it more similar to ``Option`` + and ``Either`` by @jethrogb + +- 0.7.10 + + - No changes. + +- 0.7.9 + + - New inclusion policy: See the readme about suggesting features for std before + accepting them in itertools. + - The ``FoldWhile`` type now implements ``Eq`` and ``PartialEq`` by @jturner314 + +- 0.7.8 + + - Add new iterator method ``.tree_fold1()`` which is like ``.fold1()`` + except items are combined in a tree structure (see its docs). + By @scottmcm + - Add more ``Debug`` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy, + ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee, + ZipLongest, ZipEq, Zip. + +- 0.7.7 + + - Add new iterator method ``.into_group_map() -> HashMap<K, Vec<V>>`` + which turns an iterator of ``(K, V)`` elements into such a hash table, + where values are grouped by key. By @tobz1000 + - Add new free function ``flatten`` for the ``.flatten()`` adaptor. + **NOTE:** recent Rust nightlies have ``Iterator::flatten`` and thus a clash + with our flatten adaptor. One workaround is to use the itertools ``flatten`` + free function. + +- 0.7.6 + + - Add new adaptor ``.multi_cartesian_product()`` which is an n-ary product + iterator by @tobz1000 + - Add new method ``.sorted_by_key()`` by @Xion + - Provide simpler and faster ``.count()`` for ``.unique()`` and ``.unique_by()`` + +- 0.7.5 + + - ``.multipeek()`` now implements ``PeekingNext``, by @nicopap. + +- 0.7.4 + + - Add new adaptor ``.update()`` by @lucasem; this adaptor is used + to modify an element before passing it on in an iterator chain. + +- 0.7.3 + + - Add new method ``.collect_tuple()`` by @matklad; it makes a tuple out of + the iterator's elements if the number of them matches **exactly**. + - Implement ``fold`` and ``collect`` for ``.map_results()`` which means + it reuses the code of the standard ``.map()`` for these methods. + +- 0.7.2 + + - Add new adaptor ``.merge_join_by`` by @srijs; a heterogeneous merge join + for two ordered sequences. + +- 0.7.1 + + - Iterator adaptors and iterators in itertools now use the same ``must_use`` + reminder that the standard library adaptors do, by @matematikaedit and @bluss + *“iterator adaptors are lazy and do nothing unless consumed”*. + +- 0.7.0 + + - Faster ``izip!()`` by @krdln + + - ``izip!()`` is now a wrapper for repeated regular ``.zip()`` and + a single ``.map()``. This means it optimizes as well as the standard + library ``.zip()`` it uses. + **Note:** ``multizip`` and ``izip!()`` are now different! The former + has a named type but the latter optimizes better. + + - Faster ``.unique()`` + + - ``no_std`` support, which is opt-in! + + - Many lovable features are still there without std, like ``izip!()`` + or ``.format()`` or ``.merge()``, but not those that use collections. + + - Trait bounds were required up front instead of just on the type: + ``group_by``'s ``PartialEq`` by @Phlosioneer and ``repeat_call``'s + ``FnMut``. + - Removed deprecated constructor ``Zip::new`` — use ``izip!()`` or ``multizip()`` + +- 0.6.5 + + - Fix bug in ``.cartesian_product()``'s fold (which only was visible for + unfused iterators). + +- 0.6.4 + + - Add specific ``fold`` implementations for ``.cartesian_product()`` and + ``cons_tuples()``, which improves their performance in fold, foreach, and + iterator consumers derived from them. + +- 0.6.3 + + - Add iterator adaptor ``.positions(predicate)`` by @tmccombs + +- 0.6.2 + + - Add function ``process_results`` which can “lift” a function of the regular + values of an iterator so that it can process the ``Ok`` values from an + iterator of ``Results`` instead, by @shepmaster + - Add iterator method ``.concat()`` which combines all iterator elements + into a single collection using the ``Extend`` trait, by @srijs + +- 0.6.1 + + - Better size hint testing and subsequent size hint bugfixes by @rkarp. + Fixes bugs in product, interleave_shortest size hints. + - New iterator method ``.all_equal()`` by @phimuemue + +- 0.6.0 + + - Deprecated names were removed in favour of their replacements + - ``.flatten()`` does not implement double ended iteration anymore + - ``.fold_while()`` uses ``&mut self`` and returns ``FoldWhile<T>``, for + composability (#168) + - ``.foreach()`` and ``.fold1()`` use ``self``, like ``.fold()`` does. + - ``.combinations(0)`` now produces a single empty vector. (#174) + +- 0.5.10 + + - Add itertools method ``.kmerge_by()`` (and corresponding free function) + - Relaxed trait requirement of ``.kmerge()`` and ``.minmax()`` to PartialOrd. + +- 0.5.9 + + - Add multipeek method ``.reset_peek()`` + - Add categories + +- 0.5.8 + + - Add iterator adaptor ``.peeking_take_while()`` and its trait ``PeekingNext``. + +- 0.5.7 + + - Add iterator adaptor ``.with_position()`` + - Fix multipeek's performance for long peeks by using ``VecDeque``. + +- 0.5.6 + + - Add ``.map_results()`` + +- 0.5.5 + + - Many more adaptors now implement ``Debug`` + - Add free function constructor ``repeat_n``. ``RepeatN::new`` is now + deprecated. + +- 0.5.4 + + - Add infinite generator function ``iterate``, that takes a seed and a + closure. + +- 0.5.3 + + - Special-cased ``.fold()`` for flatten and put back. ``.foreach()`` + now uses fold on the iterator, to pick up any iterator specific loop + implementation. + - ``.combinations(n)`` asserts up front that ``n != 0``, instead of + running into an error on the second iterator element. + +- 0.5.2 + + - Add ``.tuples::<T>()`` that iterates by two, three or four elements at + a time (where ``T`` is a tuple type). + - Add ``.tuple_windows::<T>()`` that iterates using a window of the + two, three or four most recent elements. + - Add ``.next_tuple::<T>()`` method, that picks the next two, three or four + elements in one go. + - ``.interleave()`` now has an accurate size hint. + +- 0.5.1 + + - Workaround module/function name clash that made racer crash on completing + itertools. Only internal changes needed. + +- 0.5.0 + + - `Release announcement <http://bluss.github.io/rust/2016/09/26/itertools-0.5.0/>`_ + - Renamed: + + - combinations is now tuple_combinations + - combinations_n to combinations + - group_by_lazy, chunks_lazy to group_by, chunks + - Unfold::new to unfold() + - RepeatCall::new to repeat_call() + - Zip::new to multizip + - PutBack::new, PutBackN::new to put_back, put_back_n + - PutBack::with_value is now a builder setter, not a constructor + - MultiPeek::new, .multipeek() to multipeek() + - format to format_with and format_default to format + - .into_rc() to rciter + - ``Partition`` enum is now ``Either`` + + - Module reorganization: + + - All iterator structs are under ``itertools::structs`` but also + reexported to the top level, for backwards compatibility + - All free functions are reexported at the root, ``itertools::free`` will + be removed in the next version + + - Removed: + + - ZipSlices, use .zip() instead + - .enumerate_from(), ZipTrusted, due to being unstable + - .mend_slices(), moved to crate odds + - Stride, StrideMut, moved to crate odds + - linspace(), moved to crate itertools-num + - .sort_by(), use .sorted_by() + - .is_empty_hint(), use .size_hint() + - .dropn(), use .dropping() + - .map_fn(), use .map() + - .slice(), use .take() / .skip() + - helper traits in misc + - ``new`` constructors on iterator structs, use Itertools trait or free + functions instead + - ``itertools::size_hint`` is now private + + - Behaviour changes: + + - format and format_with helpers now panic if you try to format them more + than once. + - ``repeat_call`` is not double ended anymore + + - New features: + + - tuple flattening iterator is constructible with ``cons_tuples`` + - itertools reexports ``Either`` from the ``either`` crate. ``Either<L, R>`` + is an iterator when ``L, R`` are. + - ``MinMaxResult`` now implements Copy and Clone + - tuple_combinations supports 1-4 tuples of combinations (previously just 2) + +- 0.4.19 + + - Add ``.minmax_by()`` + - Add ``itertools::free::cloned`` + - Add ``itertools::free::rciter`` + - Improve ``.step(n)`` slightly to take advantage of specialized Fuse better. + +- 0.4.18 + + - Only changes related to the "unstable" crate feature. This feature is more + or less deprecated. + + - Use deprecated warnings when unstable is enabled. .enumerate_from() will + be removed imminently since it's using a deprecated libstd trait. + +- 0.4.17 + + - Fix bug in .kmerge() that caused it to often produce the wrong order (#134) + +- 0.4.16 + + - Improve precision of the interleave_shortest adaptor's size hint (it is + now computed exactly when possible). + +- 0.4.15 + + - Fixup on top of the workaround in 0.4.14. A function in itertools::free was + removed by mistake and now it is added back again. + +- 0.4.14 + + - Workaround an upstream regression in a rust nightly build that broke + compilation of of itertools::free::{interleave, merge} + +- 0.4.13 + + - Add .minmax() and .minmax_by_key(), iterator methods for finding both minimum + and maximum in one scan. + - Add .format_default(), a simpler version of .format() (lazy formatting + for iterators). + +- 0.4.12 + + - Add .zip_eq(), an adaptor like .zip() except it ensures iterators + of inequal length don't pass silently (instead it panics). + - Add .fold_while(), an iterator method that is a fold that + can short-circuit. + - Add .partition_map(), an iterator method that can separate elements + into two collections. + +- 0.4.11 + + - Add .get() for Stride{,Mut} and .get_mut() for StrideMut + +- 0.4.10 + + - Improve performance of .kmerge() + +- 0.4.9 + + - Add k-ary merge adaptor .kmerge() + - Fix a bug in .islice() with ranges a..b where a > b. + +- 0.4.8 + + - Implement Clone, Debug for Linspace + +- 0.4.7 + + - Add function diff_with() that compares two iterators + - Add .combinations_n(), an n-ary combinations iterator + - Add methods PutBack::with_value and PutBack::into_parts. + +- 0.4.6 + + - Add method .sorted() + - Add module ``itertools::free`` with free function variants of common + iterator adaptors and methods. + For example ``enumerate(iterable)``, ``rev(iterable)``, and so on. + +- 0.4.5 + + - Add .flatten() + +- 0.4.4 + + - Allow composing ZipSlices with itself + +- 0.4.3 + + - Write iproduct!() as a single expression; this allows temporary values + in its arguments. + +- 0.4.2 + + - Add .fold_options() + - Require Rust 1.1 or later + +- 0.4.1 + + - Update .dropping() to take advantage of .nth() + +- 0.4.0 + + - .merge(), .unique() and .dedup() now perform better due to not using + function pointers + - Add free functions enumerate() and rev() + - Breaking changes: + + - Return types of .merge() and .merge_by() renamed and changed + - Method Merge::new removed + - .merge_by() now takes a closure that returns bool. + - Return type of .dedup() changed + - Return type of .mend_slices() changed + - Return type of .unique() changed + - Removed function times(), struct Times: use a range instead + - Removed deprecated macro icompr!() + - Removed deprecated FnMap and method .fn_map(): use .map_fn() + - .interleave_shortest() is no longer guaranteed to act like fused + +- 0.3.25 + + - Rename .sort_by() to .sorted_by(). Old name is deprecated. + - Fix well-formedness warnings from RFC 1214, no user visible impact + +- 0.3.24 + + - Improve performance of .merge()'s ordering function slightly + +- 0.3.23 + + - Added .chunks(), similar to (and based on) .group_by_lazy(). + - Tweak linspace to match numpy.linspace and make it double ended. + +- 0.3.22 + + - Added ZipSlices, a fast zip for slices + +- 0.3.21 + + - Remove `Debug` impl for `Format`, it will have different use later + +- 0.3.20 + + - Optimize .group_by_lazy() + +- 0.3.19 + + - Added .group_by_lazy(), a possibly nonallocating group by + - Added .format(), a nonallocating formatting helper for iterators + - Remove uses of RandomAccessIterator since it has been deprecated in rust. + +- 0.3.17 + + - Added (adopted) Unfold from rust + +- 0.3.16 + + - Added adaptors .unique(), .unique_by() + +- 0.3.15 + + - Added method .sort_by() + +- 0.3.14 + + - Added adaptor .while_some() + +- 0.3.13 + + - Added adaptor .interleave_shortest() + - Added adaptor .pad_using() + +- 0.3.11 + + - Added assert_equal function + +- 0.3.10 + + - Bugfix .combinations() size_hint. + +- 0.3.8 + + - Added source RepeatCall + +- 0.3.7 + + - Added adaptor PutBackN + - Added adaptor .combinations() + +- 0.3.6 + + - Added itertools::partition, partition a sequence in place based on a predicate. + - Deprecate icompr!() with no replacement. + +- 0.3.5 + + - .map_fn() replaces deprecated .fn_map(). + +- 0.3.4 + + - .take_while_ref() *by-ref adaptor* + - .coalesce() *adaptor* + - .mend_slices() *adaptor* + +- 0.3.3 + + - .dropping_back() *method* + - .fold1() *method* + - .is_empty_hint() *method* + +License +------- + +Dual-licensed to be compatible with the Rust project. + +Licensed under the Apache License, Version 2.0 +http://www.apache.org/licenses/LICENSE-2.0 or the MIT license +http://opensource.org/licenses/MIT, at your +option. This file may not be copied, modified, or distributed +except according to those terms. diff --git a/third_party/rust/itertools-0.8.0/benches/bench1.rs b/third_party/rust/itertools-0.8.0/benches/bench1.rs new file mode 100644 index 0000000000..b9d3b4ff4b --- /dev/null +++ b/third_party/rust/itertools-0.8.0/benches/bench1.rs @@ -0,0 +1,733 @@ +#![feature(test)] + +extern crate test; +#[macro_use] extern crate itertools; + +use test::{black_box}; +use itertools::Itertools; + +use itertools::free::cloned; + +use std::iter::repeat; +use std::cmp; +use std::ops::Add; + +mod extra; + +use extra::ZipSlices; + +#[bench] +fn slice_iter(b: &mut test::Bencher) +{ + let xs: Vec<_> = repeat(1i32).take(20).collect(); + b.iter(|| for elt in xs.iter() { + test::black_box(elt); + }) +} + +#[bench] +fn slice_iter_rev(b: &mut test::Bencher) +{ + let xs: Vec<_> = repeat(1i32).take(20).collect(); + b.iter(|| for elt in xs.iter().rev() { + test::black_box(elt); + }) +} + +#[bench] +fn zip_default_zip(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + for (&x, &y) in xs.iter().zip(&ys) { + test::black_box(x); + test::black_box(y); + } + }) +} + +#[bench] +fn zipdot_i32_default_zip(b: &mut test::Bencher) +{ + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let mut s = 0; + for (&x, &y) in xs.iter().zip(&ys) { + s += x * y; + } + s + }) +} + +#[bench] +fn zipdot_f32_default_zip(b: &mut test::Bencher) +{ + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let mut s = 0.; + for (&x, &y) in xs.iter().zip(&ys) { + s += x * y; + } + s + }) +} + +#[bench] +fn zip_default_zip3(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let zs = vec![0; 766]; + let xs = black_box(xs); + let ys = black_box(ys); + let zs = black_box(zs); + + b.iter(|| { + for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) { + test::black_box(x); + test::black_box(y); + test::black_box(z); + } + }) +} + +#[bench] +fn zip_slices_ziptuple(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + + b.iter(|| { + let xs = black_box(&xs); + let ys = black_box(&ys); + for (&x, &y) in itertools::multizip((xs, ys)) { + test::black_box(x); + test::black_box(y); + } + }) +} + +#[bench] +fn zipslices(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + for (&x, &y) in ZipSlices::new(&xs, &ys) { + test::black_box(x); + test::black_box(y); + } + }) +} + +#[bench] +fn zipslices_mut(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let mut ys = black_box(ys); + + b.iter(|| { + for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { + test::black_box(x); + test::black_box(y); + } + }) +} + +#[bench] +fn zipdot_i32_zipslices(b: &mut test::Bencher) +{ + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let mut s = 0i32; + for (&x, &y) in ZipSlices::new(&xs, &ys) { + s += x * y; + } + s + }) +} + +#[bench] +fn zipdot_f32_zipslices(b: &mut test::Bencher) +{ + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let mut s = 0.; + for (&x, &y) in ZipSlices::new(&xs, &ys) { + s += x * y; + } + s + }) +} + + +#[bench] +fn zip_checked_counted_loop(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let xs = &xs[..len]; + let ys = &ys[..len]; + + for i in 0..len { + let x = xs[i]; + let y = ys[i]; + test::black_box(x); + test::black_box(y); + } + }) +} + +#[bench] +fn zipdot_i32_checked_counted_loop(b: &mut test::Bencher) +{ + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let xs = &xs[..len]; + let ys = &ys[..len]; + + let mut s = 0i32; + + for i in 0..len { + s += xs[i] * ys[i]; + } + s + }) +} + +#[bench] +fn zipdot_f32_checked_counted_loop(b: &mut test::Bencher) +{ + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let xs = &xs[..len]; + let ys = &ys[..len]; + + let mut s = 0.; + + for i in 0..len { + s += xs[i] * ys[i]; + } + s + }) +} + +#[bench] +fn zipdot_f32_checked_counted_unrolled_loop(b: &mut test::Bencher) +{ + let xs = vec![2f32; 1024]; + let ys = vec![2f32; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + // Must slice to equal lengths, and then bounds checks are eliminated! + let len = cmp::min(xs.len(), ys.len()); + let mut xs = &xs[..len]; + let mut ys = &ys[..len]; + + let mut s = 0.; + let (mut p0, mut p1, mut p2, mut p3, mut p4, mut p5, mut p6, mut p7) = + (0., 0., 0., 0., 0., 0., 0., 0.); + + // how to unroll and have bounds checks eliminated (by cristicbz) + // split sum into eight parts to enable vectorization (by bluss) + while xs.len() >= 8 { + p0 += xs[0] * ys[0]; + p1 += xs[1] * ys[1]; + p2 += xs[2] * ys[2]; + p3 += xs[3] * ys[3]; + p4 += xs[4] * ys[4]; + p5 += xs[5] * ys[5]; + p6 += xs[6] * ys[6]; + p7 += xs[7] * ys[7]; + + xs = &xs[8..]; + ys = &ys[8..]; + } + s += p0 + p4; + s += p1 + p5; + s += p2 + p6; + s += p3 + p7; + + for i in 0..xs.len() { + s += xs[i] * ys[i]; + } + s + }) +} + +#[bench] +fn zip_unchecked_counted_loop(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let len = cmp::min(xs.len(), ys.len()); + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + test::black_box(x); + test::black_box(y); + } + } + }) +} + +#[bench] +fn zipdot_i32_unchecked_counted_loop(b: &mut test::Bencher) +{ + let xs = vec![2; 1024]; + let ys = vec![2; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let len = cmp::min(xs.len(), ys.len()); + let mut s = 0i32; + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + s += x * y; + } + } + s + }) +} + +#[bench] +fn zipdot_f32_unchecked_counted_loop(b: &mut test::Bencher) +{ + let xs = vec![2.; 1024]; + let ys = vec![2.; 768]; + let xs = black_box(xs); + let ys = black_box(ys); + + b.iter(|| { + let len = cmp::min(xs.len(), ys.len()); + let mut s = 0f32; + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + s += x * y; + } + } + s + }) +} + +#[bench] +fn zip_unchecked_counted_loop3(b: &mut test::Bencher) +{ + let xs = vec![0; 1024]; + let ys = vec![0; 768]; + let zs = vec![0; 766]; + let xs = black_box(xs); + let ys = black_box(ys); + let zs = black_box(zs); + + b.iter(|| { + let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len())); + for i in 0..len { + unsafe { + let x = *xs.get_unchecked(i); + let y = *ys.get_unchecked(i); + let z = *zs.get_unchecked(i); + test::black_box(x); + test::black_box(y); + test::black_box(z); + } + } + }) +} + +#[bench] +fn group_by_lazy_1(b: &mut test::Bencher) { + let mut data = vec![0; 1024]; + for (index, elt) in data.iter_mut().enumerate() { + *elt = index / 10; + } + + let data = test::black_box(data); + + b.iter(|| { + for (_key, group) in &data.iter().group_by(|elt| **elt) { + for elt in group { + test::black_box(elt); + } + } + }) +} + +#[bench] +fn group_by_lazy_2(b: &mut test::Bencher) { + let mut data = vec![0; 1024]; + for (index, elt) in data.iter_mut().enumerate() { + *elt = index / 2; + } + + let data = test::black_box(data); + + b.iter(|| { + for (_key, group) in &data.iter().group_by(|elt| **elt) { + for elt in group { + test::black_box(elt); + } + } + }) +} + +#[bench] +fn slice_chunks(b: &mut test::Bencher) { + let data = vec![0; 1024]; + + let data = test::black_box(data); + let sz = test::black_box(10); + + b.iter(|| { + for group in data.chunks(sz) { + for elt in group { + test::black_box(elt); + } + } + }) +} + +#[bench] +fn chunks_lazy_1(b: &mut test::Bencher) { + let data = vec![0; 1024]; + + let data = test::black_box(data); + let sz = test::black_box(10); + + b.iter(|| { + for group in &data.iter().chunks(sz) { + for elt in group { + test::black_box(elt); + } + } + }) +} + +#[bench] +fn equal(b: &mut test::Bencher) { + let data = vec![7; 1024]; + let l = data.len(); + let alpha = test::black_box(&data[1..]); + let beta = test::black_box(&data[..l - 1]); + b.iter(|| { + itertools::equal(alpha, beta) + }) +} + +#[bench] +fn merge_default(b: &mut test::Bencher) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = test::black_box(data1); + let data2 = test::black_box(data2); + b.iter(|| { + data1.iter().merge(&data2).count() + }) +} + +#[bench] +fn merge_by_cmp(b: &mut test::Bencher) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = test::black_box(data1); + let data2 = test::black_box(data2); + b.iter(|| { + data1.iter().merge_by(&data2, PartialOrd::le).count() + }) +} + +#[bench] +fn merge_by_lt(b: &mut test::Bencher) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = test::black_box(data1); + let data2 = test::black_box(data2); + b.iter(|| { + data1.iter().merge_by(&data2, |a, b| a <= b).count() + }) +} + +#[bench] +fn kmerge_default(b: &mut test::Bencher) { + let mut data1 = vec![0; 1024]; + let mut data2 = vec![0; 800]; + let mut x = 0; + for (_, elt) in data1.iter_mut().enumerate() { + *elt = x; + x += 1; + } + + let mut y = 0; + for (i, elt) in data2.iter_mut().enumerate() { + *elt += y; + if i % 3 == 0 { + y += 3; + } else { + y += 0; + } + } + let data1 = test::black_box(data1); + let data2 = test::black_box(data2); + let its = &[data1.iter(), data2.iter()]; + b.iter(|| { + its.iter().cloned().kmerge().count() + }) +} + +#[bench] +fn kmerge_tenway(b: &mut test::Bencher) { + let mut data = vec![0; 10240]; + + let mut state = 1729u16; + fn rng(state: &mut u16) -> u16 { + let new = state.wrapping_mul(31421) + 6927; + *state = new; + new + } + + for elt in &mut data { + *elt = rng(&mut state); + } + + let mut chunks = Vec::new(); + let mut rest = &mut data[..]; + while rest.len() > 0 { + let chunk_len = 1 + rng(&mut state) % 512; + let chunk_len = cmp::min(rest.len(), chunk_len as usize); + let (fst, tail) = {rest}.split_at_mut(chunk_len); + fst.sort(); + chunks.push(fst.iter().cloned()); + rest = tail; + } + + // println!("Chunk lengths: {}", chunks.iter().format_with(", ", |elt, f| f(&elt.len()))); + + b.iter(|| { + chunks.iter().cloned().kmerge().count() + }) +} + + +fn fast_integer_sum<I>(iter: I) -> I::Item + where I: IntoIterator, + I::Item: Default + Add<Output=I::Item> +{ + iter.into_iter().fold(<_>::default(), |x, y| x + y) +} + + +#[bench] +fn step_vec_2(b: &mut test::Bencher) { + let v = vec![0; 1024]; + b.iter(|| { + fast_integer_sum(cloned(v.iter().step(2))) + }); +} + +#[bench] +fn step_vec_10(b: &mut test::Bencher) { + let v = vec![0; 1024]; + b.iter(|| { + fast_integer_sum(cloned(v.iter().step(10))) + }); +} + +#[bench] +fn step_range_2(b: &mut test::Bencher) { + let v = black_box(0..1024); + b.iter(|| { + fast_integer_sum(v.clone().step(2)) + }); +} + +#[bench] +fn step_range_10(b: &mut test::Bencher) { + let v = black_box(0..1024); + b.iter(|| { + fast_integer_sum(v.clone().step(10)) + }); +} + +#[bench] +fn cartesian_product_iterator(b: &mut test::Bencher) +{ + let xs = vec![0; 16]; + + b.iter(|| { + let mut sum = 0; + for (&x, &y, &z) in iproduct!(&xs, &xs, &xs) { + sum += x; + sum += y; + sum += z; + } + sum + }) +} + +#[bench] +fn cartesian_product_fold(b: &mut test::Bencher) +{ + let xs = vec![0; 16]; + + b.iter(|| { + let mut sum = 0; + iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| { + sum += x; + sum += y; + sum += z; + }); + sum + }) +} + +#[bench] +fn multi_cartesian_product_iterator(b: &mut test::Bencher) +{ + let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; + + b.iter(|| { + let mut sum = 0; + for x in xs.into_iter().multi_cartesian_product() { + sum += x[0]; + sum += x[1]; + sum += x[2]; + } + sum + }) +} + +#[bench] +fn multi_cartesian_product_fold(b: &mut test::Bencher) +{ + let xs = [vec![0; 16], vec![0; 16], vec![0; 16]]; + + b.iter(|| { + let mut sum = 0; + xs.into_iter().multi_cartesian_product().fold((), |(), x| { + sum += x[0]; + sum += x[1]; + sum += x[2]; + }); + sum + }) +} + +#[bench] +fn cartesian_product_nested_for(b: &mut test::Bencher) +{ + let xs = vec![0; 16]; + + b.iter(|| { + let mut sum = 0; + for &x in &xs { + for &y in &xs { + for &z in &xs { + sum += x; + sum += y; + sum += z; + } + } + } + sum + }) +} diff --git a/third_party/rust/itertools-0.8.0/benches/extra/mod.rs b/third_party/rust/itertools-0.8.0/benches/extra/mod.rs new file mode 100644 index 0000000000..5ddb5772f4 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/benches/extra/mod.rs @@ -0,0 +1,4 @@ + + +pub use self::zipslices::ZipSlices; +mod zipslices; diff --git a/third_party/rust/itertools-0.8.0/benches/extra/zipslices.rs b/third_party/rust/itertools-0.8.0/benches/extra/zipslices.rs new file mode 100644 index 0000000000..493a539fd6 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/benches/extra/zipslices.rs @@ -0,0 +1,189 @@ +use std::cmp; + +// Note: There are different ways to implement ZipSlices. +// This version performed the best in benchmarks. +// +// I also implemented a version with three pointes (tptr, tend, uptr), +// that mimiced slice::Iter and only checked bounds by using tptr == tend, +// but that was inferior to this solution. + +/// An iterator which iterates two slices simultaneously. +/// +/// `ZipSlices` acts like a double-ended `.zip()` iterator. +/// +/// It was intended to be more efficient than `.zip()`, and it was, then +/// rustc changed how it optimizes so it can not promise improved performance +/// at this time. +/// +/// Note that elements past the end of the shortest of the two slices are ignored. +/// +/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example, +/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`. +#[derive(Clone)] +pub struct ZipSlices<T, U> { + t: T, + u: U, + len: usize, + index: usize, +} + +impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> { + /// Create a new `ZipSlices` from slices `a` and `b`. + /// + /// Act like a double-ended `.zip()` iterator, but more efficiently. + /// + /// Note that elements past the end of the shortest of the two slices are ignored. + #[inline(always)] + pub fn new(a: &'a [A], b: &'b [B]) -> Self { + let minl = cmp::min(a.len(), b.len()); + ZipSlices { + t: a, + u: b, + len: minl, + index: 0, + } + } +} + +impl<T, U> ZipSlices<T, U> + where T: Slice, + U: Slice +{ + /// Create a new `ZipSlices` from slices `a` and `b`. + /// + /// Act like a double-ended `.zip()` iterator, but more efficiently. + /// + /// Note that elements past the end of the shortest of the two slices are ignored. + #[inline(always)] + pub fn from_slices(a: T, b: U) -> Self { + let minl = cmp::min(a.len(), b.len()); + ZipSlices { + t: a, + u: b, + len: minl, + index: 0, + } + } +} + +impl<T, U> Iterator for ZipSlices<T, U> + where T: Slice, + U: Slice +{ + type Item = (T::Item, U::Item); + + #[inline(always)] + fn next(&mut self) -> Option<Self::Item> { + unsafe { + if self.index >= self.len { + None + } else { + let i = self.index; + self.index += 1; + Some(( + self.t.get_unchecked(i), + self.u.get_unchecked(i))) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len - self.index; + (len, Some(len)) + } +} + +impl<T, U> DoubleEndedIterator for ZipSlices<T, U> + where T: Slice, + U: Slice +{ + #[inline(always)] + fn next_back(&mut self) -> Option<Self::Item> { + unsafe { + if self.index >= self.len { + None + } else { + self.len -= 1; + let i = self.len; + Some(( + self.t.get_unchecked(i), + self.u.get_unchecked(i))) + } + } + } +} + +impl<T, U> ExactSizeIterator for ZipSlices<T, U> + where T: Slice, + U: Slice +{} + +unsafe impl<T, U> Slice for ZipSlices<T, U> + where T: Slice, + U: Slice +{ + type Item = (T::Item, U::Item); + + fn len(&self) -> usize { + self.len - self.index + } + + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + (self.t.get_unchecked(i), + self.u.get_unchecked(i)) + } +} + +/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`. +/// +/// Unsafe trait because: +/// +/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`. +pub unsafe trait Slice { + /// The type of a reference to the slice's elements + type Item; + #[doc(hidden)] + fn len(&self) -> usize; + #[doc(hidden)] + unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; +} + +unsafe impl<'a, T> Slice for &'a [T] { + type Item = &'a T; + #[inline(always)] + fn len(&self) -> usize { (**self).len() } + #[inline(always)] + unsafe fn get_unchecked(&mut self, i: usize) -> &'a T { + debug_assert!(i < self.len()); + (**self).get_unchecked(i) + } +} + +unsafe impl<'a, T> Slice for &'a mut [T] { + type Item = &'a mut T; + #[inline(always)] + fn len(&self) -> usize { (**self).len() } + #[inline(always)] + unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T { + debug_assert!(i < self.len()); + // override the lifetime constraints of &mut &'a mut [T] + (*(*self as *mut [T])).get_unchecked_mut(i) + } +} + +#[test] +fn zipslices() { + + let xs = [1, 2, 3, 4, 5, 6]; + let ys = [1, 2, 3, 7]; + ::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys)); + + let xs = [1, 2, 3, 4, 5, 6]; + let mut ys = [0; 6]; + for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) { + *y = *x; + } + ::itertools::assert_equal(&xs, &ys); +} + diff --git a/third_party/rust/itertools-0.8.0/benches/tree_fold1.rs b/third_party/rust/itertools-0.8.0/benches/tree_fold1.rs new file mode 100644 index 0000000000..b71589f3fe --- /dev/null +++ b/third_party/rust/itertools-0.8.0/benches/tree_fold1.rs @@ -0,0 +1,126 @@ +#![feature(test)] + +extern crate test; +extern crate itertools; + +use itertools::Itertools; +use itertools::cloned; +use test::Bencher; + +trait IterEx : Iterator { + // Another efficient implementation against which to compare, + // but needs `std` so is less desirable. + fn tree_fold1_vec<F>(self, mut f: F) -> Option<Self::Item> + where F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + let hint = self.size_hint().0; + let cap = std::mem::size_of::<usize>() * 8 - hint.leading_zeros() as usize; + let mut stack = Vec::with_capacity(cap); + self.enumerate().foreach(|(mut i, mut x)| { + while (i & 1) != 0 { + x = f(stack.pop().unwrap(), x); + i >>= 1; + } + stack.push(x); + }); + stack.into_iter().fold1(f) + } +} +impl<T:Iterator> IterEx for T {} + +macro_rules! def_benchs { + ($N:expr, + $FUN:ident, + $BENCH_NAME:ident, + ) => ( + mod $BENCH_NAME { + use super::*; + + #[bench] + fn sum(b: &mut Bencher) { + let v: Vec<u32> = (0.. $N).collect(); + b.iter(|| { + cloned(&v).$FUN(|x, y| x + y) + }); + } + + #[bench] + fn complex_iter(b: &mut Bencher) { + let u = (3..).take($N / 2); + let v = (5..).take($N / 2); + let it = u.chain(v); + + b.iter(|| { + it.clone().map(|x| x as f32).$FUN(f32::atan2) + }); + } + + #[bench] + fn string_format(b: &mut Bencher) { + // This goes quadratic with linear `fold1`, so use a smaller + // size to not waste too much time in travis. The allocations + // in here are so expensive anyway that it'll still take + // way longer per iteration than the other two benchmarks. + let v: Vec<u32> = (0.. ($N/4)).collect(); + b.iter(|| { + cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y)) + }); + } + } + ) +} + +def_benchs!{ + 10_000, + fold1, + fold1_10k, +} + +def_benchs!{ + 10_000, + tree_fold1, + tree_fold1_stack_10k, +} + +def_benchs!{ + 10_000, + tree_fold1_vec, + tree_fold1_vec_10k, +} + +def_benchs!{ + 100, + fold1, + fold1_100, +} + +def_benchs!{ + 100, + tree_fold1, + tree_fold1_stack_100, +} + +def_benchs!{ + 100, + tree_fold1_vec, + tree_fold1_vec_100, +} + +def_benchs!{ + 8, + fold1, + fold1_08, +} + +def_benchs!{ + 8, + tree_fold1, + tree_fold1_stack_08, +} + +def_benchs!{ + 8, + tree_fold1_vec, + tree_fold1_vec_08, +} diff --git a/third_party/rust/itertools-0.8.0/benches/tuple_combinations.rs b/third_party/rust/itertools-0.8.0/benches/tuple_combinations.rs new file mode 100644 index 0000000000..4a14b1d0bd --- /dev/null +++ b/third_party/rust/itertools-0.8.0/benches/tuple_combinations.rs @@ -0,0 +1,97 @@ +#![feature(test)] + +extern crate test; +extern crate itertools; + +use test::{black_box, Bencher}; +use itertools::Itertools; + +// approximate 100_000 iterations for each combination +const N1: usize = 100_000; +const N2: usize = 448; +const N3: usize = 86; +const N4: usize = 41; + +#[bench] +fn comb_for1(b: &mut Bencher) { + b.iter(|| { + for i in 0..N1 { + black_box(i); + } + }); +} + +#[bench] +fn comb_for2(b: &mut Bencher) { + b.iter(|| { + for i in 0..N2 { + for j in (i + 1)..N2 { + black_box(i + j); + } + } + }); +} + +#[bench] +fn comb_for3(b: &mut Bencher) { + b.iter(|| { + for i in 0..N3 { + for j in (i + 1)..N3 { + for k in (j + 1)..N3 { + black_box(i + j + k); + } + } + } + }); +} + +#[bench] +fn comb_for4(b: &mut Bencher) { + b.iter(|| { + for i in 0..N4 { + for j in (i + 1)..N4 { + for k in (j + 1)..N4 { + for l in (k + 1)..N4 { + black_box(i + j + k + l); + } + } + } + } + }); +} + +#[bench] +fn comb_c1(b: &mut Bencher) { + b.iter(|| { + for (i,) in (0..N1).tuple_combinations() { + black_box(i); + } + }); +} + +#[bench] +fn comb_c2(b: &mut Bencher) { + b.iter(|| { + for (i, j) in (0..N2).tuple_combinations() { + black_box(i + j); + } + }); +} + +#[bench] +fn comb_c3(b: &mut Bencher) { + b.iter(|| { + for (i, j, k) in (0..N3).tuple_combinations() { + black_box(i + j + k); + } + }); +} + +#[bench] +fn comb_c4(b: &mut Bencher) { + b.iter(|| { + for (i, j, k, l) in (0..N4).tuple_combinations() { + black_box(i + j + k + l); + } + }); +} diff --git a/third_party/rust/itertools-0.8.0/benches/tuples.rs b/third_party/rust/itertools-0.8.0/benches/tuples.rs new file mode 100644 index 0000000000..b0f2990fdf --- /dev/null +++ b/third_party/rust/itertools-0.8.0/benches/tuples.rs @@ -0,0 +1,190 @@ +#![feature(test)] + +extern crate test; +extern crate itertools; + +use test::Bencher; +use itertools::Itertools; + +fn s1(a: u32) -> u32 { + a +} + +fn s2(a: u32, b: u32) -> u32 { + a + b +} + +fn s3(a: u32, b: u32, c: u32) -> u32 { + a + b + c +} + +fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 { + a + b + c + d +} + +fn sum_s1(s: &[u32]) -> u32 { + s1(s[0]) +} + +fn sum_s2(s: &[u32]) -> u32 { + s2(s[0], s[1]) +} + +fn sum_s3(s: &[u32]) -> u32 { + s3(s[0], s[1], s[2]) +} + +fn sum_s4(s: &[u32]) -> u32 { + s4(s[0], s[1], s[2], s[3]) +} + +fn sum_t1(s: &(&u32, )) -> u32 { + s1(*s.0) +} + +fn sum_t2(s: &(&u32, &u32)) -> u32 { + s2(*s.0, *s.1) +} + +fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 { + s3(*s.0, *s.1, *s.2) +} + +fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 { + s4(*s.0, *s.1, *s.2, *s.3) +} + +macro_rules! def_benchs { + ($N:expr; + $TUPLE_FUN:ident, + $TUPLES:ident, + $TUPLE_WINDOWS:ident; + $SLICE_FUN:ident, + $CHUNKS:ident, + $WINDOWS:ident; + $FOR_CHUNKS:ident, + $FOR_WINDOWS:ident + ) => ( + #[bench] + fn $FOR_CHUNKS(b: &mut Bencher) { + let v: Vec<u32> = (0.. $N * 1_000).collect(); + let mut s = 0; + b.iter(|| { + let mut j = 0; + for _ in 0..1_000 { + s += $SLICE_FUN(&v[j..(j + $N)]); + j += $N; + } + s + }); + } + + #[bench] + fn $FOR_WINDOWS(b: &mut Bencher) { + let v: Vec<u32> = (0..1_000).collect(); + let mut s = 0; + b.iter(|| { + for i in 0..(1_000 - $N) { + s += $SLICE_FUN(&v[i..(i + $N)]); + } + s + }); + } + + #[bench] + fn $TUPLES(b: &mut Bencher) { + let v: Vec<u32> = (0.. $N * 1_000).collect(); + let mut s = 0; + b.iter(|| { + for x in v.iter().tuples() { + s += $TUPLE_FUN(&x); + } + s + }); + } + + #[bench] + fn $CHUNKS(b: &mut Bencher) { + let v: Vec<u32> = (0.. $N * 1_000).collect(); + let mut s = 0; + b.iter(|| { + for x in v.chunks($N) { + s += $SLICE_FUN(x); + } + s + }); + } + + #[bench] + fn $TUPLE_WINDOWS(b: &mut Bencher) { + let v: Vec<u32> = (0..1_000).collect(); + let mut s = 0; + b.iter(|| { + for x in v.iter().tuple_windows() { + s += $TUPLE_FUN(&x); + } + s + }); + } + + #[bench] + fn $WINDOWS(b: &mut Bencher) { + let v: Vec<u32> = (0..1_000).collect(); + let mut s = 0; + b.iter(|| { + for x in v.windows($N) { + s += $SLICE_FUN(x); + } + s + }); + } + ) +} + +def_benchs!{ + 1; + sum_t1, + tuple_chunks_1, + tuple_windows_1; + sum_s1, + slice_chunks_1, + slice_windows_1; + for_chunks_1, + for_windows_1 +} + +def_benchs!{ + 2; + sum_t2, + tuple_chunks_2, + tuple_windows_2; + sum_s2, + slice_chunks_2, + slice_windows_2; + for_chunks_2, + for_windows_2 +} + +def_benchs!{ + 3; + sum_t3, + tuple_chunks_3, + tuple_windows_3; + sum_s3, + slice_chunks_3, + slice_windows_3; + for_chunks_3, + for_windows_3 +} + +def_benchs!{ + 4; + sum_t4, + tuple_chunks_4, + tuple_windows_4; + sum_s4, + slice_chunks_4, + slice_windows_4; + for_chunks_4, + for_windows_4 +} diff --git a/third_party/rust/itertools-0.8.0/examples/iris.data b/third_party/rust/itertools-0.8.0/examples/iris.data new file mode 100644 index 0000000000..a3490e0e07 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/examples/iris.data @@ -0,0 +1,150 @@ +5.1,3.5,1.4,0.2,Iris-setosa +4.9,3.0,1.4,0.2,Iris-setosa +4.7,3.2,1.3,0.2,Iris-setosa +4.6,3.1,1.5,0.2,Iris-setosa +5.0,3.6,1.4,0.2,Iris-setosa +5.4,3.9,1.7,0.4,Iris-setosa +4.6,3.4,1.4,0.3,Iris-setosa +5.0,3.4,1.5,0.2,Iris-setosa +4.4,2.9,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.4,3.7,1.5,0.2,Iris-setosa +4.8,3.4,1.6,0.2,Iris-setosa +4.8,3.0,1.4,0.1,Iris-setosa +4.3,3.0,1.1,0.1,Iris-setosa +5.8,4.0,1.2,0.2,Iris-setosa +5.7,4.4,1.5,0.4,Iris-setosa +5.4,3.9,1.3,0.4,Iris-setosa +5.1,3.5,1.4,0.3,Iris-setosa +5.7,3.8,1.7,0.3,Iris-setosa +5.1,3.8,1.5,0.3,Iris-setosa +5.4,3.4,1.7,0.2,Iris-setosa +5.1,3.7,1.5,0.4,Iris-setosa +4.6,3.6,1.0,0.2,Iris-setosa +5.1,3.3,1.7,0.5,Iris-setosa +4.8,3.4,1.9,0.2,Iris-setosa +5.0,3.0,1.6,0.2,Iris-setosa +5.0,3.4,1.6,0.4,Iris-setosa +5.2,3.5,1.5,0.2,Iris-setosa +5.2,3.4,1.4,0.2,Iris-setosa +4.7,3.2,1.6,0.2,Iris-setosa +4.8,3.1,1.6,0.2,Iris-setosa +5.4,3.4,1.5,0.4,Iris-setosa +5.2,4.1,1.5,0.1,Iris-setosa +5.5,4.2,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.0,3.2,1.2,0.2,Iris-setosa +5.5,3.5,1.3,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +4.4,3.0,1.3,0.2,Iris-setosa +5.1,3.4,1.5,0.2,Iris-setosa +5.0,3.5,1.3,0.3,Iris-setosa +4.5,2.3,1.3,0.3,Iris-setosa +4.4,3.2,1.3,0.2,Iris-setosa +5.0,3.5,1.6,0.6,Iris-setosa +5.1,3.8,1.9,0.4,Iris-setosa +4.8,3.0,1.4,0.3,Iris-setosa +5.1,3.8,1.6,0.2,Iris-setosa +4.6,3.2,1.4,0.2,Iris-setosa +5.3,3.7,1.5,0.2,Iris-setosa +5.0,3.3,1.4,0.2,Iris-setosa +7.0,3.2,4.7,1.4,Iris-versicolor +6.4,3.2,4.5,1.5,Iris-versicolor +6.9,3.1,4.9,1.5,Iris-versicolor +5.5,2.3,4.0,1.3,Iris-versicolor +6.5,2.8,4.6,1.5,Iris-versicolor +5.7,2.8,4.5,1.3,Iris-versicolor +6.3,3.3,4.7,1.6,Iris-versicolor +4.9,2.4,3.3,1.0,Iris-versicolor +6.6,2.9,4.6,1.3,Iris-versicolor +5.2,2.7,3.9,1.4,Iris-versicolor +5.0,2.0,3.5,1.0,Iris-versicolor +5.9,3.0,4.2,1.5,Iris-versicolor +6.0,2.2,4.0,1.0,Iris-versicolor +6.1,2.9,4.7,1.4,Iris-versicolor +5.6,2.9,3.6,1.3,Iris-versicolor +6.7,3.1,4.4,1.4,Iris-versicolor +5.6,3.0,4.5,1.5,Iris-versicolor +5.8,2.7,4.1,1.0,Iris-versicolor +6.2,2.2,4.5,1.5,Iris-versicolor +5.6,2.5,3.9,1.1,Iris-versicolor +5.9,3.2,4.8,1.8,Iris-versicolor +6.1,2.8,4.0,1.3,Iris-versicolor +6.3,2.5,4.9,1.5,Iris-versicolor +6.1,2.8,4.7,1.2,Iris-versicolor +6.4,2.9,4.3,1.3,Iris-versicolor +6.6,3.0,4.4,1.4,Iris-versicolor +6.8,2.8,4.8,1.4,Iris-versicolor +6.7,3.0,5.0,1.7,Iris-versicolor +6.0,2.9,4.5,1.5,Iris-versicolor +5.7,2.6,3.5,1.0,Iris-versicolor +5.5,2.4,3.8,1.1,Iris-versicolor +5.5,2.4,3.7,1.0,Iris-versicolor +5.8,2.7,3.9,1.2,Iris-versicolor +6.0,2.7,5.1,1.6,Iris-versicolor +5.4,3.0,4.5,1.5,Iris-versicolor +6.0,3.4,4.5,1.6,Iris-versicolor +6.7,3.1,4.7,1.5,Iris-versicolor +6.3,2.3,4.4,1.3,Iris-versicolor +5.6,3.0,4.1,1.3,Iris-versicolor +5.5,2.5,4.0,1.3,Iris-versicolor +5.5,2.6,4.4,1.2,Iris-versicolor +6.1,3.0,4.6,1.4,Iris-versicolor +5.8,2.6,4.0,1.2,Iris-versicolor +5.0,2.3,3.3,1.0,Iris-versicolor +5.6,2.7,4.2,1.3,Iris-versicolor +5.7,3.0,4.2,1.2,Iris-versicolor +5.7,2.9,4.2,1.3,Iris-versicolor +6.2,2.9,4.3,1.3,Iris-versicolor +5.1,2.5,3.0,1.1,Iris-versicolor +5.7,2.8,4.1,1.3,Iris-versicolor +6.3,3.3,6.0,2.5,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +7.1,3.0,5.9,2.1,Iris-virginica +6.3,2.9,5.6,1.8,Iris-virginica +6.5,3.0,5.8,2.2,Iris-virginica +7.6,3.0,6.6,2.1,Iris-virginica +4.9,2.5,4.5,1.7,Iris-virginica +7.3,2.9,6.3,1.8,Iris-virginica +6.7,2.5,5.8,1.8,Iris-virginica +7.2,3.6,6.1,2.5,Iris-virginica +6.5,3.2,5.1,2.0,Iris-virginica +6.4,2.7,5.3,1.9,Iris-virginica +6.8,3.0,5.5,2.1,Iris-virginica +5.7,2.5,5.0,2.0,Iris-virginica +5.8,2.8,5.1,2.4,Iris-virginica +6.4,3.2,5.3,2.3,Iris-virginica +6.5,3.0,5.5,1.8,Iris-virginica +7.7,3.8,6.7,2.2,Iris-virginica +7.7,2.6,6.9,2.3,Iris-virginica +6.0,2.2,5.0,1.5,Iris-virginica +6.9,3.2,5.7,2.3,Iris-virginica +5.6,2.8,4.9,2.0,Iris-virginica +7.7,2.8,6.7,2.0,Iris-virginica +6.3,2.7,4.9,1.8,Iris-virginica +6.7,3.3,5.7,2.1,Iris-virginica +7.2,3.2,6.0,1.8,Iris-virginica +6.2,2.8,4.8,1.8,Iris-virginica +6.1,3.0,4.9,1.8,Iris-virginica +6.4,2.8,5.6,2.1,Iris-virginica +7.2,3.0,5.8,1.6,Iris-virginica +7.4,2.8,6.1,1.9,Iris-virginica +7.9,3.8,6.4,2.0,Iris-virginica +6.4,2.8,5.6,2.2,Iris-virginica +6.3,2.8,5.1,1.5,Iris-virginica +6.1,2.6,5.6,1.4,Iris-virginica +7.7,3.0,6.1,2.3,Iris-virginica +6.3,3.4,5.6,2.4,Iris-virginica +6.4,3.1,5.5,1.8,Iris-virginica +6.0,3.0,4.8,1.8,Iris-virginica +6.9,3.1,5.4,2.1,Iris-virginica +6.7,3.1,5.6,2.4,Iris-virginica +6.9,3.1,5.1,2.3,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +6.8,3.2,5.9,2.3,Iris-virginica +6.7,3.3,5.7,2.5,Iris-virginica +6.7,3.0,5.2,2.3,Iris-virginica +6.3,2.5,5.0,1.9,Iris-virginica +6.5,3.0,5.2,2.0,Iris-virginica +6.2,3.4,5.4,2.3,Iris-virginica +5.9,3.0,5.1,1.8,Iris-virginica diff --git a/third_party/rust/itertools-0.8.0/examples/iris.rs b/third_party/rust/itertools-0.8.0/examples/iris.rs new file mode 100644 index 0000000000..c09afbea0d --- /dev/null +++ b/third_party/rust/itertools-0.8.0/examples/iris.rs @@ -0,0 +1,141 @@ +/// +/// This example parses, sorts and groups the iris dataset +/// and does some simple manipulations. +/// +/// Iterators and itertools functionality are used throughout. +/// +/// + +extern crate itertools; + +use itertools::Itertools; +use std::collections::HashMap; +use std::iter::repeat; +use std::num::ParseFloatError; +use std::str::FromStr; + +static DATA: &'static str = include_str!("iris.data"); + +#[derive(Clone, Debug)] +struct Iris { + name: String, + data: [f32; 4], +} + +#[derive(Clone, Debug)] +enum ParseError { + Numeric(ParseFloatError), + Other(&'static str), +} + +impl From<ParseFloatError> for ParseError { + fn from(err: ParseFloatError) -> Self { + ParseError::Numeric(err) + } +} + +/// Parse an Iris from a comma-separated line +impl FromStr for Iris { + type Err = ParseError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + let mut iris = Iris { name: "".into(), data: [0.; 4] }; + let mut parts = s.split(",").map(str::trim); + + // using Iterator::by_ref() + for (index, part) in parts.by_ref().take(4).enumerate() { + iris.data[index] = try!(part.parse::<f32>()); + } + if let Some(name) = parts.next() { + iris.name = name.into(); + } else { + return Err(ParseError::Other("Missing name")) + } + Ok(iris) + } +} + +fn main() { + // using Itertools::fold_results to create the result of parsing + let irises = DATA.lines() + .map(str::parse) + .fold_results(Vec::new(), |mut v, iris: Iris| { + v.push(iris); + v + }); + let mut irises = match irises { + Err(e) => { + println!("Error parsing: {:?}", e); + std::process::exit(1); + } + Ok(data) => data, + }; + + // Sort them and group them + irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name)); + + // using Iterator::cycle() + let mut plot_symbols = "+ox".chars().cycle(); + let mut symbolmap = HashMap::new(); + + // using Itertools::group_by + for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) { + // assign a plot symbol + symbolmap.entry(species).or_insert_with(|| { + plot_symbols.next().unwrap() + }); + println!("{} (symbol={})", species, symbolmap[species]); + + for iris in species_group { + // using Itertools::format for lazy formatting + println!("{:>3.1}", iris.data.iter().format(", ")); + } + + } + + // Look at all combinations of the four columns + // + // See https://en.wikipedia.org/wiki/Iris_flower_data_set + // + let n = 30; // plot size + let mut plot = vec![' '; n * n]; + + // using Itertools::tuple_combinations + for (a, b) in (0..4).tuple_combinations() { + println!("Column {} vs {}:", a, b); + + // Clear plot + // + // using std::iter::repeat; + // using Itertools::set_from + plot.iter_mut().set_from(repeat(' ')); + + // using Itertools::minmax + let min_max = |data: &[Iris], col| { + data.iter() + .map(|iris| iris.data[col]) + .minmax() + .into_option() + .expect("Can't find min/max of empty iterator") + }; + let (min_x, max_x) = min_max(&irises, a); + let (min_y, max_y) = min_max(&irises, b); + + // Plot the data points + let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize; + let flip = |ix| n - 1 - ix; // reverse axis direction + + for iris in &irises { + let ix = round_to_grid(iris.data[a], min_x, max_x); + let iy = flip(round_to_grid(iris.data[b], min_y, max_y)); + plot[n * iy + ix] = symbolmap[&iris.name]; + } + + // render plot + // + // using Itertools::join + for line in plot.chunks(n) { + println!("{}", line.iter().join(" ")) + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/adaptors/mod.rs b/third_party/rust/itertools-0.8.0/src/adaptors/mod.rs new file mode 100644 index 0000000000..59aebfaf06 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/adaptors/mod.rs @@ -0,0 +1,1278 @@ +//! Licensed under the Apache License, Version 2.0 +//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license +//! http://opensource.org/licenses/MIT, at your +//! option. This file may not be copied, modified, or distributed +//! except according to those terms. + +mod multi_product; +#[cfg(feature = "use_std")] +pub use self::multi_product::*; + +use std::fmt; +use std::mem::replace; +use std::iter::{Fuse, Peekable, FromIterator}; +use std::marker::PhantomData; +use size_hint; + +macro_rules! clone_fields { + ($name:ident, $base:expr, $($field:ident),+) => ( + $name { + $( + $field : $base . $field .clone() + ),* + } + ); +} + +/// An iterator adaptor that alternates elements from two iterators until both +/// run out. +/// +/// This iterator is *fused*. +/// +/// See [`.interleave()`](../trait.Itertools.html#method.interleave) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Interleave<I, J> { + a: Fuse<I>, + b: Fuse<J>, + flag: bool, +} + +/// Create an iterator that interleaves elements in `i` and `j`. +/// +/// `IntoIterator` enabled version of `i.interleave(j)`. +/// +/// ``` +/// use itertools::interleave; +/// +/// for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { +/// /* loop body */ +/// } +/// ``` +pub fn interleave<I, J>(i: I, j: J) -> Interleave<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> + where I: IntoIterator, + J: IntoIterator<Item = I::Item> +{ + Interleave { + a: i.into_iter().fuse(), + b: j.into_iter().fuse(), + flag: false, + } +} + +impl<I, J> Iterator for Interleave<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<I::Item> { + self.flag = !self.flag; + if self.flag { + match self.a.next() { + None => self.b.next(), + r => r, + } + } else { + match self.b.next() { + None => self.a.next(), + r => r, + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::add(self.a.size_hint(), self.b.size_hint()) + } +} + +/// An iterator adaptor that alternates elements from the two iterators until +/// one of them runs out. +/// +/// This iterator is *fused*. +/// +/// See [`.interleave_shortest()`](../trait.Itertools.html#method.interleave_shortest) +/// for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct InterleaveShortest<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + it0: I, + it1: J, + phase: bool, // false ==> it0, true ==> it1 +} + +/// Create a new `InterleaveShortest` iterator. +pub fn interleave_shortest<I, J>(a: I, b: J) -> InterleaveShortest<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + InterleaveShortest { + it0: a, + it1: b, + phase: false, + } +} + +impl<I, J> Iterator for InterleaveShortest<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option<I::Item> { + match self.phase { + false => match self.it0.next() { + None => None, + e => { + self.phase = true; + e + } + }, + true => match self.it1.next() { + None => None, + e => { + self.phase = false; + e + } + }, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let (curr_hint, next_hint) = { + let it0_hint = self.it0.size_hint(); + let it1_hint = self.it1.size_hint(); + if self.phase { + (it1_hint, it0_hint) + } else { + (it0_hint, it1_hint) + } + }; + let (curr_lower, curr_upper) = curr_hint; + let (next_lower, next_upper) = next_hint; + let (combined_lower, combined_upper) = + size_hint::mul_scalar(size_hint::min(curr_hint, next_hint), 2); + let lower = + if curr_lower > next_lower { + combined_lower + 1 + } else { + combined_lower + }; + let upper = { + let extra_elem = match (curr_upper, next_upper) { + (_, None) => false, + (None, Some(_)) => true, + (Some(curr_max), Some(next_max)) => curr_max > next_max, + }; + if extra_elem { + combined_upper.and_then(|x| x.checked_add(1)) + } else { + combined_upper + } + }; + (lower, upper) + } +} + +#[derive(Clone, Debug)] +/// An iterator adaptor that allows putting back a single +/// item to the front of the iterator. +/// +/// Iterator element type is `I::Item`. +pub struct PutBack<I> + where I: Iterator +{ + top: Option<I::Item>, + iter: I, +} + +/// Create an iterator where you can put back a single item +pub fn put_back<I>(iterable: I) -> PutBack<I::IntoIter> + where I: IntoIterator +{ + PutBack { + top: None, + iter: iterable.into_iter(), + } +} + +impl<I> PutBack<I> + where I: Iterator +{ + /// put back value `value` (builder method) + pub fn with_value(mut self, value: I::Item) -> Self { + self.put_back(value); + self + } + + /// Split the `PutBack` into its parts. + #[inline] + pub fn into_parts(self) -> (Option<I::Item>, I) { + let PutBack{top, iter} = self; + (top, iter) + } + + /// Put back a single value to the front of the iterator. + /// + /// If a value is already in the put back slot, it is overwritten. + #[inline] + pub fn put_back(&mut self, x: I::Item) { + self.top = Some(x) + } +} + +impl<I> Iterator for PutBack<I> + where I: Iterator +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<I::Item> { + match self.top { + None => self.iter.next(), + ref mut some => some.take(), + } + } + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add_scalar(self.iter.size_hint(), self.top.is_some() as usize) + } + + fn all<G>(&mut self, mut f: G) -> bool + where G: FnMut(Self::Item) -> bool + { + if let Some(elt) = self.top.take() { + if !f(elt) { + return false; + } + } + self.iter.all(f) + } + + fn fold<Acc, G>(mut self, init: Acc, mut f: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + if let Some(elt) = self.top.take() { + accum = f(accum, elt); + } + self.iter.fold(accum, f) + } +} + +#[derive(Debug, Clone)] +/// An iterator adaptor that iterates over the cartesian product of +/// the element sets of two iterators `I` and `J`. +/// +/// Iterator element type is `(I::Item, J::Item)`. +/// +/// See [`.cartesian_product()`](../trait.Itertools.html#method.cartesian_product) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Product<I, J> + where I: Iterator +{ + a: I, + a_cur: Option<I::Item>, + b: J, + b_orig: J, +} + +/// Create a new cartesian product iterator +/// +/// Iterator element type is `(I::Item, J::Item)`. +pub fn cartesian_product<I, J>(mut i: I, j: J) -> Product<I, J> + where I: Iterator, + J: Clone + Iterator, + I::Item: Clone +{ + Product { + a_cur: i.next(), + a: i, + b: j.clone(), + b_orig: j, + } +} + + +impl<I, J> Iterator for Product<I, J> + where I: Iterator, + J: Clone + Iterator, + I::Item: Clone +{ + type Item = (I::Item, J::Item); + fn next(&mut self) -> Option<(I::Item, J::Item)> { + let elt_b = match self.b.next() { + None => { + self.b = self.b_orig.clone(); + match self.b.next() { + None => return None, + Some(x) => { + self.a_cur = self.a.next(); + x + } + } + } + Some(x) => x + }; + match self.a_cur { + None => None, + Some(ref a) => { + Some((a.clone(), elt_b)) + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let has_cur = self.a_cur.is_some() as usize; + // Not ExactSizeIterator because size may be larger than usize + let (b_min, b_max) = self.b.size_hint(); + + // Compute a * b_orig + b for both lower and upper bound + size_hint::add( + size_hint::mul(self.a.size_hint(), self.b_orig.size_hint()), + (b_min * has_cur, b_max.map(move |x| x * has_cur))) + } + + fn fold<Acc, G>(mut self, mut accum: Acc, mut f: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + // use a split loop to handle the loose a_cur as well as avoiding to + // clone b_orig at the end. + if let Some(mut a) = self.a_cur.take() { + let mut b = self.b; + loop { + accum = b.fold(accum, |acc, elt| f(acc, (a.clone(), elt))); + + // we can only continue iterating a if we had a first element; + if let Some(next_a) = self.a.next() { + b = self.b_orig.clone(); + a = next_a; + } else { + break; + } + } + } + accum + } +} + +/// A “meta iterator adaptor”. Its closure receives a reference to the iterator +/// and may pick off as many elements as it likes, to produce the next iterator element. +/// +/// Iterator element type is *X*, if the return type of `F` is *Option\<X\>*. +/// +/// See [`.batching()`](../trait.Itertools.html#method.batching) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Batching<I, F> { + f: F, + iter: I, +} + +impl<I, F> fmt::Debug for Batching<I, F> where I: fmt::Debug { + debug_fmt_fields!(Batching, iter); +} + +/// Create a new Batching iterator. +pub fn batching<I, F>(iter: I, f: F) -> Batching<I, F> { + Batching { f: f, iter: iter } +} + +impl<B, F, I> Iterator for Batching<I, F> + where I: Iterator, + F: FnMut(&mut I) -> Option<B> +{ + type Item = B; + #[inline] + fn next(&mut self) -> Option<B> { + (self.f)(&mut self.iter) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + // No information about closue behavior + (0, None) + } +} + +/// An iterator adaptor that steps a number elements in the base iterator +/// for each iteration. +/// +/// The iterator steps by yielding the next element from the base iterator, +/// then skipping forward *n-1* elements. +/// +/// See [`.step()`](../trait.Itertools.html#method.step) for more information. +#[deprecated(note="Use std .step_by() instead", since="0.8")] +#[allow(deprecated)] +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Step<I> { + iter: Fuse<I>, + skip: usize, +} + +/// Create a `Step` iterator. +/// +/// **Panics** if the step is 0. +#[allow(deprecated)] +pub fn step<I>(iter: I, step: usize) -> Step<I> + where I: Iterator +{ + assert!(step != 0); + Step { + iter: iter.fuse(), + skip: step - 1, + } +} + +#[allow(deprecated)] +impl<I> Iterator for Step<I> + where I: Iterator +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<I::Item> { + let elt = self.iter.next(); + if self.skip > 0 { + self.iter.nth(self.skip - 1); + } + elt + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, high) = self.iter.size_hint(); + let div = |x: usize| { + if x == 0 { + 0 + } else { + 1 + (x - 1) / (self.skip + 1) + } + }; + (div(low), high.map(div)) + } +} + +// known size +#[allow(deprecated)] +impl<I> ExactSizeIterator for Step<I> + where I: ExactSizeIterator +{} + + +struct MergeCore<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + a: Peekable<I>, + b: Peekable<J>, + fused: Option<bool>, +} + + +impl<I, J> Clone for MergeCore<I, J> + where I: Iterator, + J: Iterator<Item = I::Item>, + Peekable<I>: Clone, + Peekable<J>: Clone +{ + fn clone(&self) -> Self { + clone_fields!(MergeCore, self, a, b, fused) + } +} + +impl<I, J> MergeCore<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + fn next_with<F>(&mut self, mut less_than: F) -> Option<I::Item> + where F: FnMut(&I::Item, &I::Item) -> bool + { + let less_than = match self.fused { + Some(lt) => lt, + None => match (self.a.peek(), self.b.peek()) { + (Some(a), Some(b)) => less_than(a, b), + (Some(_), None) => { + self.fused = Some(true); + true + } + (None, Some(_)) => { + self.fused = Some(false); + false + } + (None, None) => return None, + } + }; + + if less_than { + self.a.next() + } else { + self.b.next() + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + // Not ExactSizeIterator because size may be larger than usize + size_hint::add(self.a.size_hint(), self.b.size_hint()) + } +} + +/// An iterator adaptor that merges the two base iterators in ascending order. +/// If both base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.merge()`](../trait.Itertools.html#method.merge_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Merge<I, J> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + merge: MergeCore<I, J>, +} + +impl<I, J> Clone for Merge<I, J> + where I: Iterator, + J: Iterator<Item = I::Item>, + Peekable<I>: Clone, + Peekable<J>: Clone +{ + fn clone(&self) -> Self { + clone_fields!(Merge, self, merge) + } +} + +impl<I, J> fmt::Debug for Merge<I, J> + where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Merge, merge.a, merge.b); +} + +/// Create an iterator that merges elements in `i` and `j`. +/// +/// `IntoIterator` enabled version of `i.merge(j)`. +/// +/// ``` +/// use itertools::merge; +/// +/// for elt in merge(&[1, 2, 3], &[2, 3, 4]) { +/// /* loop body */ +/// } +/// ``` +pub fn merge<I, J>(i: I, j: J) -> Merge<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> + where I: IntoIterator, + J: IntoIterator<Item = I::Item>, + I::Item: PartialOrd +{ + Merge { + merge: MergeCore { + a: i.into_iter().peekable(), + b: j.into_iter().peekable(), + fused: None, + }, + } +} + +impl<I, J> Iterator for Merge<I, J> + where I: Iterator, + J: Iterator<Item = I::Item>, + I::Item: PartialOrd +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + self.merge.next_with(|a, b| a <= b) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.merge.size_hint() + } +} + +/// An iterator adaptor that merges the two base iterators in ascending order. +/// If both base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.merge_by()`](../trait.Itertools.html#method.merge_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MergeBy<I, J, F> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + merge: MergeCore<I, J>, + cmp: F, +} + +impl<I, J, F> fmt::Debug for MergeBy<I, J, F> + where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(MergeBy, merge.a, merge.b); +} + +/// Create a `MergeBy` iterator. +pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I, J, F> + where I: Iterator, + J: Iterator<Item = I::Item> +{ + MergeBy { + merge: MergeCore { + a: a.peekable(), + b: b.peekable(), + fused: None, + }, + cmp: cmp, + } +} + +impl<I, J, F> Clone for MergeBy<I, J, F> + where I: Iterator, + J: Iterator<Item = I::Item>, + Peekable<I>: Clone, + Peekable<J>: Clone, + F: Clone +{ + fn clone(&self) -> Self { + clone_fields!(MergeBy, self, merge, cmp) + } +} + +impl<I, J, F> Iterator for MergeBy<I, J, F> + where I: Iterator, + J: Iterator<Item = I::Item>, + F: FnMut(&I::Item, &I::Item) -> bool +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + self.merge.next_with(&mut self.cmp) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.merge.size_hint() + } +} + +#[derive(Clone, Debug)] +pub struct CoalesceCore<I> + where I: Iterator +{ + iter: I, + last: Option<I::Item>, +} + +impl<I> CoalesceCore<I> + where I: Iterator +{ + fn next_with<F>(&mut self, mut f: F) -> Option<I::Item> + where F: FnMut(I::Item, I::Item) -> Result<I::Item, (I::Item, I::Item)> + { + // this fuses the iterator + let mut last = match self.last.take() { + None => return None, + Some(x) => x, + }; + for next in &mut self.iter { + match f(last, next) { + Ok(joined) => last = joined, + Err((last_, next_)) => { + self.last = Some(next_); + return Some(last_); + } + } + } + + Some(last) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), + self.last.is_some() as usize); + ((low > 0) as usize, hi) + } +} + +/// An iterator adaptor that may join together adjacent elements. +/// +/// See [`.coalesce()`](../trait.Itertools.html#method.coalesce) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Coalesce<I, F> + where I: Iterator +{ + iter: CoalesceCore<I>, + f: F, +} + +impl<I: Clone, F: Clone> Clone for Coalesce<I, F> + where I: Iterator, + I::Item: Clone +{ + fn clone(&self) -> Self { + clone_fields!(Coalesce, self, iter, f) + } +} + +impl<I, F> fmt::Debug for Coalesce<I, F> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Coalesce, iter); +} + +/// Create a new `Coalesce`. +pub fn coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F> + where I: Iterator +{ + Coalesce { + iter: CoalesceCore { + last: iter.next(), + iter: iter, + }, + f: f, + } +} + +impl<I, F> Iterator for Coalesce<I, F> + where I: Iterator, + F: FnMut(I::Item, I::Item) -> Result<I::Item, (I::Item, I::Item)> +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + self.iter.next_with(&mut self.f) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +/// An iterator adaptor that removes repeated duplicates. +/// +/// See [`.dedup()`](../trait.Itertools.html#method.dedup) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Dedup<I> + where I: Iterator +{ + iter: CoalesceCore<I>, +} + +impl<I: Clone> Clone for Dedup<I> + where I: Iterator, + I::Item: Clone +{ + fn clone(&self) -> Self { + clone_fields!(Dedup, self, iter) + } +} + +/// Create a new `Dedup`. +pub fn dedup<I>(mut iter: I) -> Dedup<I> + where I: Iterator +{ + Dedup { + iter: CoalesceCore { + last: iter.next(), + iter: iter, + }, + } +} + +impl<I> fmt::Debug for Dedup<I> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Dedup, iter); +} + +impl<I> Iterator for Dedup<I> + where I: Iterator, + I::Item: PartialEq +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + self.iter.next_with(|x, y| { + if x == y { Ok(x) } else { Err((x, y)) } + }) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + + fn fold<Acc, G>(self, mut accum: Acc, mut f: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(mut last) = self.iter.last { + accum = self.iter.iter.fold(accum, |acc, elt| { + if elt == last { + acc + } else { + f(acc, replace(&mut last, elt)) + } + }); + f(accum, last) + } else { + accum + } + } +} + +/// An iterator adaptor that borrows from a `Clone`-able iterator +/// to only pick off elements while the predicate returns `true`. +/// +/// See [`.take_while_ref()`](../trait.Itertools.html#method.take_while_ref) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct TakeWhileRef<'a, I: 'a, F> { + iter: &'a mut I, + f: F, +} + +impl<'a, I, F> fmt::Debug for TakeWhileRef<'a, I, F> + where I: Iterator + fmt::Debug, +{ + debug_fmt_fields!(TakeWhileRef, iter); +} + +/// Create a new `TakeWhileRef` from a reference to clonable iterator. +pub fn take_while_ref<I, F>(iter: &mut I, f: F) -> TakeWhileRef<I, F> + where I: Iterator + Clone +{ + TakeWhileRef { iter: iter, f: f } +} + +impl<'a, I, F> Iterator for TakeWhileRef<'a, I, F> + where I: Iterator + Clone, + F: FnMut(&I::Item) -> bool +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + let old = self.iter.clone(); + match self.iter.next() { + None => None, + Some(elt) => { + if (self.f)(&elt) { + Some(elt) + } else { + *self.iter = old; + None + } + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (_, hi) = self.iter.size_hint(); + (0, hi) + } +} + +/// An iterator adaptor that filters `Option<A>` iterator elements +/// and produces `A`. Stops on the first `None` encountered. +/// +/// See [`.while_some()`](../trait.Itertools.html#method.while_some) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct WhileSome<I> { + iter: I, +} + +/// Create a new `WhileSome<I>`. +pub fn while_some<I>(iter: I) -> WhileSome<I> { + WhileSome { iter: iter } +} + +impl<I, A> Iterator for WhileSome<I> + where I: Iterator<Item = Option<A>> +{ + type Item = A; + + fn next(&mut self) -> Option<A> { + match self.iter.next() { + None | Some(None) => None, + Some(elt) => elt, + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let sh = self.iter.size_hint(); + (0, sh.1) + } +} + +/// An iterator to iterate through all combinations in a `Clone`-able iterator that produces tuples +/// of a specific size. +/// +/// See [`.tuple_combinations()`](../trait.Itertools.html#method.tuple_combinations) for more +/// information. +#[derive(Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct TupleCombinations<I, T> + where I: Iterator, + T: HasCombination<I> +{ + iter: T::Combination, + _mi: PhantomData<I>, + _mt: PhantomData<T> +} + +pub trait HasCombination<I>: Sized { + type Combination: From<I> + Iterator<Item = Self>; +} + +/// Create a new `TupleCombinations` from a clonable iterator. +pub fn tuple_combinations<T, I>(iter: I) -> TupleCombinations<I, T> + where I: Iterator + Clone, + I::Item: Clone, + T: HasCombination<I>, +{ + TupleCombinations { + iter: T::Combination::from(iter), + _mi: PhantomData, + _mt: PhantomData, + } +} + +impl<I, T> Iterator for TupleCombinations<I, T> + where I: Iterator, + T: HasCombination<I>, +{ + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next() + } +} + +#[derive(Debug)] +pub struct Tuple1Combination<I> { + iter: I, +} + +impl<I> From<I> for Tuple1Combination<I> { + fn from(iter: I) -> Self { + Tuple1Combination { iter: iter } + } +} + +impl<I: Iterator> Iterator for Tuple1Combination<I> { + type Item = (I::Item,); + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|x| (x,)) + } +} + +impl<I: Iterator> HasCombination<I> for (I::Item,) { + type Combination = Tuple1Combination<I>; +} + +macro_rules! impl_tuple_combination { + ($C:ident $P:ident ; $A:ident, $($I:ident),* ; $($X:ident)*) => ( + #[derive(Debug)] + pub struct $C<I: Iterator> { + item: Option<I::Item>, + iter: I, + c: $P<I>, + } + + impl<I: Iterator + Clone> From<I> for $C<I> { + fn from(mut iter: I) -> Self { + $C { + item: iter.next(), + iter: iter.clone(), + c: $P::from(iter), + } + } + } + + impl<I: Iterator + Clone> From<I> for $C<Fuse<I>> { + fn from(iter: I) -> Self { + let mut iter = iter.fuse(); + $C { + item: iter.next(), + iter: iter.clone(), + c: $P::from(iter), + } + } + } + + impl<I, $A> Iterator for $C<I> + where I: Iterator<Item = $A> + Clone, + I::Item: Clone + { + type Item = ($($I),*); + + fn next(&mut self) -> Option<Self::Item> { + if let Some(($($X),*,)) = self.c.next() { + let z = self.item.clone().unwrap(); + Some((z, $($X),*)) + } else { + self.item = self.iter.next(); + self.item.clone().and_then(|z| { + self.c = $P::from(self.iter.clone()); + self.c.next().map(|($($X),*,)| (z, $($X),*)) + }) + } + } + } + + impl<I, $A> HasCombination<I> for ($($I),*) + where I: Iterator<Item = $A> + Clone, + I::Item: Clone + { + type Combination = $C<Fuse<I>>; + } + ) +} + +impl_tuple_combination!(Tuple2Combination Tuple1Combination ; A, A, A ; a); +impl_tuple_combination!(Tuple3Combination Tuple2Combination ; A, A, A, A ; a b); +impl_tuple_combination!(Tuple4Combination Tuple3Combination ; A, A, A, A, A; a b c); + +/// An iterator adapter to apply `Into` conversion to each element. +/// +/// See [`.map_into()`](../trait.Itertools.html#method.map_into) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MapInto<I, R> { + iter: I, + _res: PhantomData<fn() -> R>, +} + +/// Create a new [`MapInto`](struct.MapInto.html) iterator. +pub fn map_into<I, R>(iter: I) -> MapInto<I, R> { + MapInto { + iter: iter, + _res: PhantomData, + } +} + +impl<I, R> Iterator for MapInto<I, R> + where I: Iterator, + I::Item: Into<R>, +{ + type Item = R; + + fn next(&mut self) -> Option<R> { + self.iter + .next() + .map(|i| i.into()) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + + fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, move |acc, v| fold_f(acc, v.into())) + } +} + +impl<I, R> DoubleEndedIterator for MapInto<I, R> + where I: DoubleEndedIterator, + I::Item: Into<R>, +{ + fn next_back(&mut self) -> Option<Self::Item> { + self.iter + .next_back() + .map(|i| i.into()) + } +} + +impl<I, R> ExactSizeIterator for MapInto<I, R> +where + I: ExactSizeIterator, + I::Item: Into<R>, +{} + +/// An iterator adapter to apply a transformation within a nested `Result`. +/// +/// See [`.map_results()`](../trait.Itertools.html#method.map_results) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MapResults<I, F> { + iter: I, + f: F +} + +/// Create a new `MapResults` iterator. +pub fn map_results<I, F, T, U, E>(iter: I, f: F) -> MapResults<I, F> + where I: Iterator<Item = Result<T, E>>, + F: FnMut(T) -> U, +{ + MapResults { + iter: iter, + f: f, + } +} + +impl<I, F, T, U, E> Iterator for MapResults<I, F> + where I: Iterator<Item = Result<T, E>>, + F: FnMut(T) -> U, +{ + type Item = Result<U, E>; + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|v| v.map(&mut self.f)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + + fn fold<Acc, Fold>(self, init: Acc, mut fold_f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, v| fold_f(acc, v.map(&mut f))) + } + + fn collect<C>(self) -> C + where C: FromIterator<Self::Item> + { + let mut f = self.f; + self.iter.map(move |v| v.map(&mut f)).collect() + } +} + +/// An iterator adapter to get the positions of each element that matches a predicate. +/// +/// See [`.positions()`](../trait.Itertools.html#method.positions) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Positions<I, F> { + iter: I, + f: F, + count: usize, +} + +/// Create a new `Positions` iterator. +pub fn positions<I, F>(iter: I, f: F) -> Positions<I, F> + where I: Iterator, + F: FnMut(I::Item) -> bool, +{ + Positions { + iter: iter, + f: f, + count: 0 + } +} + +impl<I, F> Iterator for Positions<I, F> + where I: Iterator, + F: FnMut(I::Item) -> bool, +{ + type Item = usize; + + fn next(&mut self) -> Option<Self::Item> { + while let Some(v) = self.iter.next() { + let i = self.count; + self.count = i + 1; + if (self.f)(v) { + return Some(i); + } + } + None + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (0, self.iter.size_hint().1) + } +} + +impl<I, F> DoubleEndedIterator for Positions<I, F> + where I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(I::Item) -> bool, +{ + fn next_back(&mut self) -> Option<Self::Item> { + while let Some(v) = self.iter.next_back() { + if (self.f)(v) { + return Some(self.count + self.iter.len()) + } + } + None + } +} + +/// An iterator adapter to apply a mutating function to each element before yielding it. +/// +/// See [`.update()`](../trait.Itertools.html#method.update) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Update<I, F> { + iter: I, + f: F, +} + +/// Create a new `Update` iterator. +pub fn update<I, F>(iter: I, f: F) -> Update<I, F> +where + I: Iterator, + F: FnMut(&mut I::Item), +{ + Update { iter: iter, f: f } +} + +impl<I, F> Iterator for Update<I, F> +where + I: Iterator, + F: FnMut(&mut I::Item), +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + if let Some(mut v) = self.iter.next() { + (self.f)(&mut v); + Some(v) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + + fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc, + { + let mut f = self.f; + self.iter.fold(init, move |acc, mut v| { f(&mut v); g(acc, v) }) + } + + // if possible, re-use inner iterator specializations in collect + fn collect<C>(self) -> C + where C: FromIterator<Self::Item> + { + let mut f = self.f; + self.iter.map(move |mut v| { f(&mut v); v }).collect() + } +} + +impl<I, F> ExactSizeIterator for Update<I, F> +where + I: ExactSizeIterator, + F: FnMut(&mut I::Item), +{} + +impl<I, F> DoubleEndedIterator for Update<I, F> +where + I: DoubleEndedIterator, + F: FnMut(&mut I::Item), +{ + fn next_back(&mut self) -> Option<Self::Item> { + if let Some(mut v) = self.iter.next_back() { + (self.f)(&mut v); + Some(v) + } else { + None + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/adaptors/multi_product.rs b/third_party/rust/itertools-0.8.0/src/adaptors/multi_product.rs new file mode 100644 index 0000000000..a6796386ed --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/adaptors/multi_product.rs @@ -0,0 +1,220 @@ +#![cfg(feature = "use_std")] + +use size_hint; +use Itertools; + +#[derive(Clone)] +/// An iterator adaptor that iterates over the cartesian product of +/// multiple iterators of type `I`. +/// +/// An iterator element type is `Vec<I>`. +/// +/// See [`.multi_cartesian_product()`](../trait.Itertools.html#method.multi_cartesian_product) +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MultiProduct<I>(Vec<MultiProductIter<I>>) + where I: Iterator + Clone, + I::Item: Clone; + +/// Create a new cartesian product iterator over an arbitrary number +/// of iterators of the same type. +/// +/// Iterator element is of type `Vec<H::Item::Item>`. +pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter> + where H: Iterator, + H::Item: IntoIterator, + <H::Item as IntoIterator>::IntoIter: Clone, + <H::Item as IntoIterator>::Item: Clone +{ + MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect()) +} + +#[derive(Clone, Debug)] +/// Holds the state of a single iterator within a MultiProduct. +struct MultiProductIter<I> + where I: Iterator + Clone, + I::Item: Clone +{ + cur: Option<I::Item>, + iter: I, + iter_orig: I, +} + +/// Holds the current state during an iteration of a MultiProduct. +#[derive(Debug)] +enum MultiProductIterState { + StartOfIter, + MidIter { on_first_iter: bool }, +} + +impl<I> MultiProduct<I> + where I: Iterator + Clone, + I::Item: Clone +{ + /// Iterates the rightmost iterator, then recursively iterates iterators + /// to the left if necessary. + /// + /// Returns true if the iteration succeeded, else false. + fn iterate_last( + multi_iters: &mut [MultiProductIter<I>], + mut state: MultiProductIterState + ) -> bool { + use self::MultiProductIterState::*; + + if let Some((last, rest)) = multi_iters.split_last_mut() { + let on_first_iter = match state { + StartOfIter => { + let on_first_iter = !last.in_progress(); + state = MidIter { on_first_iter: on_first_iter }; + on_first_iter + }, + MidIter { on_first_iter } => on_first_iter + }; + + if !on_first_iter { + last.iterate(); + } + + if last.in_progress() { + true + } else if MultiProduct::iterate_last(rest, state) { + last.reset(); + last.iterate(); + // If iterator is None twice consecutively, then iterator is + // empty; whole product is empty. + last.in_progress() + } else { + false + } + } else { + // Reached end of iterator list. On initialisation, return true. + // At end of iteration (final iterator finishes), finish. + match state { + StartOfIter => false, + MidIter { on_first_iter } => on_first_iter + } + } + } + + /// Returns the unwrapped value of the next iteration. + fn curr_iterator(&self) -> Vec<I::Item> { + self.0.iter().map(|multi_iter| { + multi_iter.cur.clone().unwrap() + }).collect() + } + + /// Returns true if iteration has started and has not yet finished; false + /// otherwise. + fn in_progress(&self) -> bool { + if let Some(last) = self.0.last() { + last.in_progress() + } else { + false + } + } +} + +impl<I> MultiProductIter<I> + where I: Iterator + Clone, + I::Item: Clone +{ + fn new(iter: I) -> Self { + MultiProductIter { + cur: None, + iter: iter.clone(), + iter_orig: iter + } + } + + /// Iterate the managed iterator. + fn iterate(&mut self) { + self.cur = self.iter.next(); + } + + /// Reset the managed iterator. + fn reset(&mut self) { + self.iter = self.iter_orig.clone(); + } + + /// Returns true if the current iterator has been started and has not yet + /// finished; false otherwise. + fn in_progress(&self) -> bool { + self.cur.is_some() + } +} + +impl<I> Iterator for MultiProduct<I> + where I: Iterator + Clone, + I::Item: Clone +{ + type Item = Vec<I::Item>; + + fn next(&mut self) -> Option<Self::Item> { + if MultiProduct::iterate_last( + &mut self.0, + MultiProductIterState::StartOfIter + ) { + Some(self.curr_iterator()) + } else { + None + } + } + + fn count(self) -> usize { + if self.0.len() == 0 { + return 0; + } + + if !self.in_progress() { + return self.0.into_iter().fold(1, |acc, multi_iter| { + acc * multi_iter.iter.count() + }); + } + + self.0.into_iter().fold( + 0, + |acc, MultiProductIter { iter, iter_orig, cur: _ }| { + let total_count = iter_orig.count(); + let cur_count = iter.count(); + acc * total_count + cur_count + } + ) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + // Not ExactSizeIterator because size may be larger than usize + if self.0.len() == 0 { + return (0, Some(0)); + } + + if !self.in_progress() { + return self.0.iter().fold((1, Some(1)), |acc, multi_iter| { + size_hint::mul(acc, multi_iter.iter.size_hint()) + }); + } + + self.0.iter().fold( + (0, Some(0)), + |acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| { + let cur_size = iter.size_hint(); + let total_size = iter_orig.size_hint(); + size_hint::add(size_hint::mul(acc, total_size), cur_size) + } + ) + } + + fn last(self) -> Option<Self::Item> { + let iter_count = self.0.len(); + + let lasts: Self::Item = self.0.into_iter() + .map(|multi_iter| multi_iter.iter.last()) + .while_some() + .collect(); + + if lasts.len() == iter_count { + Some(lasts) + } else { + None + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/combinations.rs b/third_party/rust/itertools-0.8.0/src/combinations.rs new file mode 100644 index 0000000000..a7744151c9 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/combinations.rs @@ -0,0 +1,165 @@ + +use std::ops::Index; +use std::fmt; + +/// An iterator to iterate through all the `n`-length combinations in an iterator. +/// +/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Combinations<I: Iterator> { + n: usize, + indices: Vec<usize>, + pool: LazyBuffer<I>, + first: bool, +} + +impl<I> fmt::Debug for Combinations<I> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(Combinations, n, indices, pool, first); +} + +/// Create a new `Combinations` from a clonable iterator. +pub fn combinations<I>(iter: I, n: usize) -> Combinations<I> + where I: Iterator +{ + let mut indices: Vec<usize> = Vec::with_capacity(n); + for i in 0..n { + indices.push(i); + } + let mut pool: LazyBuffer<I> = LazyBuffer::new(iter); + + for _ in 0..n { + if !pool.get_next() { + break; + } + } + + Combinations { + n: n, + indices: indices, + pool: pool, + first: true, + } +} + +impl<I> Iterator for Combinations<I> + where I: Iterator, + I::Item: Clone +{ + type Item = Vec<I::Item>; + fn next(&mut self) -> Option<Self::Item> { + let mut pool_len = self.pool.len(); + if self.pool.is_done() { + if pool_len == 0 || self.n > pool_len { + return None; + } + } + + if self.first { + self.first = false; + } else if self.n == 0 { + return None; + } else { + // Scan from the end, looking for an index to increment + let mut i: usize = self.n - 1; + + // Check if we need to consume more from the iterator + if self.indices[i] == pool_len - 1 && !self.pool.is_done() { + if self.pool.get_next() { + pool_len += 1; + } + } + + while self.indices[i] == i + pool_len - self.n { + if i > 0 { + i -= 1; + } else { + // Reached the last combination + return None; + } + } + + // Increment index, and reset the ones to its right + self.indices[i] += 1; + let mut j = i + 1; + while j < self.n { + self.indices[j] = self.indices[j - 1] + 1; + j += 1; + } + } + + // Create result vector based on the indices + let mut result = Vec::with_capacity(self.n); + for i in self.indices.iter() { + result.push(self.pool[*i].clone()); + } + Some(result) + } +} + +#[derive(Debug)] +struct LazyBuffer<I: Iterator> { + it: I, + done: bool, + buffer: Vec<I::Item>, +} + +impl<I> LazyBuffer<I> + where I: Iterator +{ + pub fn new(it: I) -> LazyBuffer<I> { + let mut it = it; + let mut buffer = Vec::new(); + let done; + if let Some(first) = it.next() { + buffer.push(first); + done = false; + } else { + done = true; + } + LazyBuffer { + it: it, + done: done, + buffer: buffer, + } + } + + pub fn len(&self) -> usize { + self.buffer.len() + } + + pub fn is_done(&self) -> bool { + self.done + } + + pub fn get_next(&mut self) -> bool { + if self.done { + return false; + } + let next_item = self.it.next(); + match next_item { + Some(x) => { + self.buffer.push(x); + true + } + None => { + self.done = true; + false + } + } + } +} + +impl<I> Index<usize> for LazyBuffer<I> + where I: Iterator, + I::Item: Sized +{ + type Output = I::Item; + + fn index<'b>(&'b self, _index: usize) -> &'b I::Item { + self.buffer.index(_index) + } +} + diff --git a/third_party/rust/itertools-0.8.0/src/concat_impl.rs b/third_party/rust/itertools-0.8.0/src/concat_impl.rs new file mode 100644 index 0000000000..05b370e1c6 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/concat_impl.rs @@ -0,0 +1,22 @@ +use Itertools; + +/// Combine all an iterator's elements into one element by using `Extend`. +/// +/// `IntoIterator`-enabled version of `.concat()` +/// +/// This combinator will extend the first item with each of the rest of the +/// items of the iterator. If the iterator is empty, the default value of +/// `I::Item` is returned. +/// +/// ```rust +/// use itertools::concat; +/// +/// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; +/// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]); +/// ``` +pub fn concat<I>(iterable: I) -> I::Item + where I: IntoIterator, + I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default +{ + iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(|| <_>::default()) +} diff --git a/third_party/rust/itertools-0.8.0/src/cons_tuples_impl.rs b/third_party/rust/itertools-0.8.0/src/cons_tuples_impl.rs new file mode 100644 index 0000000000..9b27e7580f --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/cons_tuples_impl.rs @@ -0,0 +1,68 @@ + +macro_rules! impl_cons_iter( + ($_A:ident, $_B:ident, ) => (); // stop + + ($A:ident, $($B:ident,)*) => ( + impl_cons_iter!($($B,)*); + #[allow(non_snake_case)] + impl<X, Iter, $($B),*> Iterator for ConsTuples<Iter, (($($B,)*), X)> + where Iter: Iterator<Item = (($($B,)*), X)>, + { + type Item = ($($B,)* X, ); + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + fn fold<Acc, Fold>(self, accum: Acc, mut f: Fold) -> Acc + where Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, ))) + } + } + + #[allow(non_snake_case)] + impl<X, Iter, $($B),*> DoubleEndedIterator for ConsTuples<Iter, (($($B,)*), X)> + where Iter: DoubleEndedIterator<Item = (($($B,)*), X)>, + { + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) + } + } + + ); +); + +impl_cons_iter!(A, B, C, D, E, F, G, H,); + +/// An iterator that maps an iterator of tuples like +/// `((A, B), C)` to an iterator of `(A, B, C)`. +/// +/// Used by the `iproduct!()` macro. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct ConsTuples<I, J> + where I: Iterator<Item=J>, +{ + iter: I, +} + +impl<I, J> Clone for ConsTuples<I, J> + where I: Clone + Iterator<Item=J>, +{ + fn clone(&self) -> Self { + ConsTuples { + iter: self.iter.clone(), + } + } +} + +/// Create an iterator that maps for example iterators of +/// `((A, B), C)` to `(A, B, C)`. +pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I, J> + where I: Iterator<Item=J> +{ + ConsTuples { iter: iterable.into_iter() } +} diff --git a/third_party/rust/itertools-0.8.0/src/diff.rs b/third_party/rust/itertools-0.8.0/src/diff.rs new file mode 100644 index 0000000000..2951bc422e --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/diff.rs @@ -0,0 +1,61 @@ +//! "Diff"ing iterators for caching elements to sequential collections without requiring the new +//! elements' iterator to be `Clone`. +//! +//! - [**Diff**](./enum.Diff.html) (produced by the [**diff_with**](./fn.diff_with.html) function) +//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from +//! a lock-step comparison. + +use free::put_back; +use structs::PutBack; + +/// A type returned by the [`diff_with`](./fn.diff_with.html) function. +/// +/// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some +/// iterator `J`. +pub enum Diff<I, J> + where I: Iterator, + J: Iterator +{ + /// The index of the first non-matching element along with both iterator's remaining elements + /// starting with the first mis-match. + FirstMismatch(usize, PutBack<I>, PutBack<J>), + /// The total number of elements that were in `J` along with the remaining elements of `I`. + Shorter(usize, PutBack<I>), + /// The total number of elements that were in `I` along with the remaining elements of `J`. + Longer(usize, PutBack<J>), +} + +/// Compares every element yielded by both `i` and `j` with the given function in lock-step and +/// returns a `Diff` which describes how `j` differs from `i`. +/// +/// If the number of elements yielded by `j` is less than the number of elements yielded by `i`, +/// the number of `j` elements yielded will be returned along with `i`'s remaining elements as +/// `Diff::Shorter`. +/// +/// If the two elements of a step differ, the index of those elements along with the remaining +/// elements of both `i` and `j` are returned as `Diff::FirstMismatch`. +/// +/// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with +/// the remaining `j` elements will be returned as `Diff::Longer`. +pub fn diff_with<I, J, F>(i: I, j: J, is_equal: F) + -> Option<Diff<I::IntoIter, J::IntoIter>> + where I: IntoIterator, + J: IntoIterator, + F: Fn(&I::Item, &J::Item) -> bool +{ + let mut i = i.into_iter(); + let mut j = j.into_iter(); + let mut idx = 0; + while let Some(i_elem) = i.next() { + match j.next() { + None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))), + Some(j_elem) => if !is_equal(&i_elem, &j_elem) { + let remaining_i = put_back(i).with_value(i_elem); + let remaining_j = put_back(j).with_value(j_elem); + return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j)); + }, + } + idx += 1; + } + j.next().map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem))) +} diff --git a/third_party/rust/itertools-0.8.0/src/either_or_both.rs b/third_party/rust/itertools-0.8.0/src/either_or_both.rs new file mode 100644 index 0000000000..55ae06c6b4 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/either_or_both.rs @@ -0,0 +1,58 @@ +use EitherOrBoth::*; + +/// Value that either holds a single A or B, or both. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum EitherOrBoth<A, B> { + /// Both values are present. + Both(A, B), + /// Only the left value of type `A` is present. + Left(A), + /// Only the right value of type `B` is present. + Right(B), +} + +impl<A, B> EitherOrBoth<A, B> { + /// If `Left`, or `Both`, return true, otherwise, return false. + pub fn has_left(&self) -> bool { + self.as_ref().left().is_some() + } + + /// If `Right`, or `Both`, return true, otherwise, return false. + pub fn has_right(&self) -> bool { + self.as_ref().right().is_some() + } + + /// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`. + pub fn left(self) -> Option<A> { + match self { + Left(left) | Both(left, _) => Some(left), + _ => None + } + } + + /// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`. + pub fn right(self) -> Option<B> { + match self { + Right(right) | Both(_, right) => Some(right), + _ => None + } + } + + /// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&A, &B>`. + pub fn as_ref(&self) -> EitherOrBoth<&A, &B> { + match *self { + Left(ref left) => Left(left), + Right(ref right) => Right(right), + Both(ref left, ref right) => Both(left, right), + } + } + + /// Converts from `&mut EitherOrBoth<A, B>` to `EitherOrBoth<&mut A, &mut B>`. + pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> { + match *self { + Left(ref mut left) => Left(left), + Right(ref mut right) => Right(right), + Both(ref mut left, ref mut right) => Both(left, right), + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/format.rs b/third_party/rust/itertools-0.8.0/src/format.rs new file mode 100644 index 0000000000..c42806b01c --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/format.rs @@ -0,0 +1,113 @@ +use std::fmt; +use std::cell::RefCell; + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information. +pub struct FormatWith<'a, I, F> { + sep: &'a str, + /// FormatWith uses interior mutability because Display::fmt takes &self. + inner: RefCell<Option<(I, F)>>, +} + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format()`](../trait.Itertools.html#method.format) +/// for more information. +#[derive(Clone)] +pub struct Format<'a, I> { + sep: &'a str, + /// Format uses interior mutability because Display::fmt takes &self. + inner: RefCell<Option<I>>, +} + +pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F> + where I: Iterator, + F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result +{ + FormatWith { + sep: separator, + inner: RefCell::new(Some((iter, f))), + } +} + +pub fn new_format_default<'a, I>(iter: I, separator: &'a str) -> Format<'a, I> + where I: Iterator, +{ + Format { + sep: separator, + inner: RefCell::new(Some(iter)), + } +} + +impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> + where I: Iterator, + F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (mut iter, mut format) = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("FormatWith: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + try!(format(fst, &mut |disp: &fmt::Display| disp.fmt(f))); + for elt in iter { + if self.sep.len() > 0 { + + try!(f.write_str(self.sep)); + } + try!(format(elt, &mut |disp: &fmt::Display| disp.fmt(f))); + } + } + Ok(()) + } +} + +impl<'a, I> Format<'a, I> + where I: Iterator, +{ + fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result + where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, + { + let mut iter = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("Format: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + try!(cb(&fst, f)); + for elt in iter { + if self.sep.len() > 0 { + try!(f.write_str(self.sep)); + } + try!(cb(&elt, f)); + } + } + Ok(()) + } +} + +macro_rules! impl_format { + ($($fmt_trait:ident)*) => { + $( + impl<'a, I> fmt::$fmt_trait for Format<'a, I> + where I: Iterator, + I::Item: fmt::$fmt_trait, + { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f, fmt::$fmt_trait::fmt) + } + } + )* + } +} + +impl_format!{Display Debug + UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} diff --git a/third_party/rust/itertools-0.8.0/src/free.rs b/third_party/rust/itertools-0.8.0/src/free.rs new file mode 100644 index 0000000000..2bc72a9aa1 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/free.rs @@ -0,0 +1,236 @@ +//! Free functions that create iterator adaptors or call iterator methods. +//! +//! The benefit of free functions is that they accept any `IntoIterator` as +//! argument, so the resulting code may be easier to read. + +#[cfg(feature = "use_std")] +use std::fmt::Display; +use std::iter::{self, Zip}; +#[cfg(feature = "use_std")] +type VecIntoIter<T> = ::std::vec::IntoIter<T>; + +#[cfg(feature = "use_std")] +use Itertools; + +pub use adaptors::{ + interleave, + merge, + put_back, +}; +#[cfg(feature = "use_std")] +pub use put_back_n_impl::put_back_n; +#[cfg(feature = "use_std")] +pub use multipeek_impl::multipeek; +#[cfg(feature = "use_std")] +pub use kmerge_impl::kmerge; +pub use zip_eq_impl::zip_eq; +pub use merge_join::merge_join_by; +#[cfg(feature = "use_std")] +pub use rciter_impl::rciter; + +/// Iterate `iterable` with a running index. +/// +/// `IntoIterator` enabled version of `.enumerate()`. +/// +/// ``` +/// use itertools::enumerate; +/// +/// for (i, elt) in enumerate(&[1, 2, 3]) { +/// /* loop body */ +/// } +/// ``` +pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter> + where I: IntoIterator +{ + iterable.into_iter().enumerate() +} + +/// Iterate `iterable` in reverse. +/// +/// `IntoIterator` enabled version of `.rev()`. +/// +/// ``` +/// use itertools::rev; +/// +/// for elt in rev(&[1, 2, 3]) { +/// /* loop body */ +/// } +/// ``` +pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter> + where I: IntoIterator, + I::IntoIter: DoubleEndedIterator +{ + iterable.into_iter().rev() +} + +/// Iterate `i` and `j` in lock step. +/// +/// `IntoIterator` enabled version of `i.zip(j)`. +/// +/// ``` +/// use itertools::zip; +/// +/// let data = [1, 2, 3, 4, 5]; +/// for (a, b) in zip(&data, &data[1..]) { +/// /* loop body */ +/// } +/// ``` +pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter> + where I: IntoIterator, + J: IntoIterator +{ + i.into_iter().zip(j) +} + +/// Create an iterator that first iterates `i` and then `j`. +/// +/// `IntoIterator` enabled version of `i.chain(j)`. +/// +/// ``` +/// use itertools::chain; +/// +/// for elt in chain(&[1, 2, 3], &[4]) { +/// /* loop body */ +/// } +/// ``` +pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter> + where I: IntoIterator, + J: IntoIterator<Item = I::Item> +{ + i.into_iter().chain(j) +} + +/// Create an iterator that clones each element from &T to T +/// +/// `IntoIterator` enabled version of `i.cloned()`. +/// +/// ``` +/// use itertools::cloned; +/// +/// assert_eq!(cloned(b"abc").next(), Some(b'a')); +/// ``` +pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter> + where I: IntoIterator<Item=&'a T>, + T: Clone, +{ + iterable.into_iter().cloned() +} + +/// Perform a fold operation over the iterable. +/// +/// `IntoIterator` enabled version of `i.fold(init, f)` +/// +/// ``` +/// use itertools::fold; +/// +/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.); +/// ``` +pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B + where I: IntoIterator, + F: FnMut(B, I::Item) -> B +{ + iterable.into_iter().fold(init, f) +} + +/// Test whether the predicate holds for all elements in the iterable. +/// +/// `IntoIterator` enabled version of `i.all(f)` +/// +/// ``` +/// use itertools::all; +/// +/// assert!(all(&[1, 2, 3], |elt| *elt > 0)); +/// ``` +pub fn all<I, F>(iterable: I, f: F) -> bool + where I: IntoIterator, + F: FnMut(I::Item) -> bool +{ + iterable.into_iter().all(f) +} + +/// Test whether the predicate holds for any elements in the iterable. +/// +/// `IntoIterator` enabled version of `i.any(f)` +/// +/// ``` +/// use itertools::any; +/// +/// assert!(any(&[0, -1, 2], |elt| *elt > 0)); +/// ``` +pub fn any<I, F>(iterable: I, f: F) -> bool + where I: IntoIterator, + F: FnMut(I::Item) -> bool +{ + iterable.into_iter().any(f) +} + +/// Return the maximum value of the iterable. +/// +/// `IntoIterator` enabled version of `i.max()`. +/// +/// ``` +/// use itertools::max; +/// +/// assert_eq!(max(0..10), Some(9)); +/// ``` +pub fn max<I>(iterable: I) -> Option<I::Item> + where I: IntoIterator, + I::Item: Ord +{ + iterable.into_iter().max() +} + +/// Return the minimum value of the iterable. +/// +/// `IntoIterator` enabled version of `i.min()`. +/// +/// ``` +/// use itertools::min; +/// +/// assert_eq!(min(0..10), Some(0)); +/// ``` +pub fn min<I>(iterable: I) -> Option<I::Item> + where I: IntoIterator, + I::Item: Ord +{ + iterable.into_iter().min() +} + + +/// Combine all iterator elements into one String, seperated by `sep`. +/// +/// `IntoIterator` enabled version of `iterable.join(sep)`. +/// +/// ``` +/// use itertools::join; +/// +/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3"); +/// ``` +#[cfg(feature = "use_std")] +pub fn join<I>(iterable: I, sep: &str) -> String + where I: IntoIterator, + I::Item: Display +{ + iterable.into_iter().join(sep) +} + +/// Sort all iterator elements into a new iterator in ascending order. +/// +/// `IntoIterator` enabled version of [`iterable.sorted()`][1]. +/// +/// [1]: trait.Itertools.html#method.sorted +/// +/// ``` +/// use itertools::sorted; +/// use itertools::assert_equal; +/// +/// assert_equal(sorted("rust".chars()), "rstu".chars()); +/// ``` +#[cfg(feature = "use_std")] +pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item> + where I: IntoIterator, + I::Item: Ord +{ + iterable.into_iter().sorted() +} + diff --git a/third_party/rust/itertools-0.8.0/src/group_map.rs b/third_party/rust/itertools-0.8.0/src/group_map.rs new file mode 100644 index 0000000000..be9f8420d8 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/group_map.rs @@ -0,0 +1,22 @@ +#![cfg(feature = "use_std")] + +use std::collections::HashMap; +use std::hash::Hash; +use std::iter::Iterator; + +/// Return a `HashMap` of keys mapped to a list of their corresponding values. +/// +/// See [`.into_group_map()`](../trait.Itertools.html#method.into_group_map) +/// for more information. +pub fn into_group_map<I, K, V>(iter: I) -> HashMap<K, Vec<V>> + where I: Iterator<Item=(K, V)>, + K: Hash + Eq, +{ + let mut lookup = HashMap::new(); + + for (key, val) in iter { + lookup.entry(key).or_insert(Vec::new()).push(val); + } + + lookup +}
\ No newline at end of file diff --git a/third_party/rust/itertools-0.8.0/src/groupbylazy.rs b/third_party/rust/itertools-0.8.0/src/groupbylazy.rs new file mode 100644 index 0000000000..ff253e845d --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/groupbylazy.rs @@ -0,0 +1,571 @@ +use std::cell::{Cell, RefCell}; +use std::vec; + +/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks +trait KeyFunction<A> { + type Key; + fn call_mut(&mut self, arg: A) -> Self::Key; +} + +impl<'a, A, K, F: ?Sized> KeyFunction<A> for F + where F: FnMut(A) -> K +{ + type Key = K; + #[inline] + fn call_mut(&mut self, arg: A) -> Self::Key { + (*self)(arg) + } +} + + +/// ChunkIndex acts like the grouping key function for IntoChunks +#[derive(Debug)] +struct ChunkIndex { + size: usize, + index: usize, + key: usize, +} + +impl ChunkIndex { + #[inline(always)] + fn new(size: usize) -> Self { + ChunkIndex { + size: size, + index: 0, + key: 0, + } + } +} + +impl<'a, A> KeyFunction<A> for ChunkIndex { + type Key = usize; + #[inline(always)] + fn call_mut(&mut self, _arg: A) -> Self::Key { + if self.index == self.size { + self.key += 1; + self.index = 0; + } + self.index += 1; + self.key + } +} + + +struct GroupInner<K, I, F> + where I: Iterator +{ + key: F, + iter: I, + current_key: Option<K>, + current_elt: Option<I::Item>, + /// flag set if iterator is exhausted + done: bool, + /// Index of group we are currently buffering or visiting + top_group: usize, + /// Least index for which we still have elements buffered + oldest_buffered_group: usize, + /// Group index for `buffer[0]` -- the slots + /// bottom_group..oldest_buffered_group are unused and will be erased when + /// that range is large enough. + bottom_group: usize, + /// Buffered groups, from `bottom_group` (index 0) to `top_group`. + buffer: Vec<vec::IntoIter<I::Item>>, + /// index of last group iter that was dropped, usize::MAX == none + dropped_group: usize, +} + +impl<K, I, F> GroupInner<K, I, F> + where I: Iterator, + F: for<'a> KeyFunction<&'a I::Item, Key=K>, + K: PartialEq, +{ + /// `client`: Index of group that requests next element + #[inline(always)] + fn step(&mut self, client: usize) -> Option<I::Item> { + /* + println!("client={}, bottom_group={}, oldest_buffered_group={}, top_group={}, buffers=[{}]", + client, self.bottom_group, self.oldest_buffered_group, + self.top_group, + self.buffer.iter().map(|elt| elt.len()).format(", ")); + */ + if client < self.oldest_buffered_group { + None + } else if client < self.top_group || + (client == self.top_group && + self.buffer.len() > self.top_group - self.bottom_group) + { + self.lookup_buffer(client) + } else if self.done { + None + } else if self.top_group == client { + self.step_current() + } else { + self.step_buffering(client) + } + } + + #[inline(never)] + fn lookup_buffer(&mut self, client: usize) -> Option<I::Item> { + // if `bufidx` doesn't exist in self.buffer, it might be empty + let bufidx = client - self.bottom_group; + if client < self.oldest_buffered_group { + return None; + } + let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next()); + if elt.is_none() && client == self.oldest_buffered_group { + // FIXME: VecDeque is unfortunately not zero allocation when empty, + // so we do this job manually. + // `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it. + self.oldest_buffered_group += 1; + // skip forward further empty queues too + while self.buffer.get(self.oldest_buffered_group - self.bottom_group) + .map_or(false, |buf| buf.len() == 0) + { + self.oldest_buffered_group += 1; + } + + let nclear = self.oldest_buffered_group - self.bottom_group; + if nclear > 0 && nclear >= self.buffer.len() / 2 { + let mut i = 0; + self.buffer.retain(|buf| { + i += 1; + debug_assert!(buf.len() == 0 || i > nclear); + i > nclear + }); + self.bottom_group = self.oldest_buffered_group; + } + } + elt + } + + /// Take the next element from the iterator, and set the done + /// flag if exhausted. Must not be called after done. + #[inline(always)] + fn next_element(&mut self) -> Option<I::Item> { + debug_assert!(!self.done); + match self.iter.next() { + None => { self.done = true; None } + otherwise => otherwise, + } + } + + + #[inline(never)] + fn step_buffering(&mut self, client: usize) -> Option<I::Item> { + // requested a later group -- walk through the current group up to + // the requested group index, and buffer the elements (unless + // the group is marked as dropped). + // Because the `Groups` iterator is always the first to request + // each group index, client is the next index efter top_group. + debug_assert!(self.top_group + 1 == client); + let mut group = Vec::new(); + + if let Some(elt) = self.current_elt.take() { + if self.top_group != self.dropped_group { + group.push(elt); + } + } + let mut first_elt = None; // first element of the next group + + while let Some(elt) = self.next_element() { + let key = self.key.call_mut(&elt); + match self.current_key.take() { + None => {} + Some(old_key) => if old_key != key { + self.current_key = Some(key); + first_elt = Some(elt); + break; + }, + } + self.current_key = Some(key); + if self.top_group != self.dropped_group { + group.push(elt); + } + } + + if self.top_group != self.dropped_group { + self.push_next_group(group); + } + if first_elt.is_some() { + self.top_group += 1; + debug_assert!(self.top_group == client); + } + first_elt + } + + fn push_next_group(&mut self, group: Vec<I::Item>) { + // When we add a new buffered group, fill up slots between oldest_buffered_group and top_group + while self.top_group - self.bottom_group > self.buffer.len() { + if self.buffer.is_empty() { + self.bottom_group += 1; + self.oldest_buffered_group += 1; + } else { + self.buffer.push(Vec::new().into_iter()); + } + } + self.buffer.push(group.into_iter()); + debug_assert!(self.top_group + 1 - self.bottom_group == self.buffer.len()); + } + + /// This is the immediate case, where we use no buffering + #[inline] + fn step_current(&mut self) -> Option<I::Item> { + debug_assert!(!self.done); + if let elt @ Some(..) = self.current_elt.take() { + return elt; + } + match self.next_element() { + None => None, + Some(elt) => { + let key = self.key.call_mut(&elt); + match self.current_key.take() { + None => {} + Some(old_key) => if old_key != key { + self.current_key = Some(key); + self.current_elt = Some(elt); + self.top_group += 1; + return None; + }, + } + self.current_key = Some(key); + Some(elt) + } + } + } + + /// Request the just started groups' key. + /// + /// `client`: Index of group + /// + /// **Panics** if no group key is available. + fn group_key(&mut self, client: usize) -> K { + // This can only be called after we have just returned the first + // element of a group. + // Perform this by simply buffering one more element, grabbing the + // next key. + debug_assert!(!self.done); + debug_assert!(client == self.top_group); + debug_assert!(self.current_key.is_some()); + debug_assert!(self.current_elt.is_none()); + let old_key = self.current_key.take().unwrap(); + if let Some(elt) = self.next_element() { + let key = self.key.call_mut(&elt); + if old_key != key { + self.top_group += 1; + } + self.current_key = Some(key); + self.current_elt = Some(elt); + } + old_key + } +} + +impl<K, I, F> GroupInner<K, I, F> + where I: Iterator, +{ + /// Called when a group is dropped + fn drop_group(&mut self, client: usize) { + // It's only useful to track the maximal index + if self.dropped_group == !0 || client > self.dropped_group { + self.dropped_group = client; + } + } +} + +/// `GroupBy` is the storage for the lazy grouping operation. +/// +/// If the groups are consumed in their original order, or if each +/// group is dropped without keeping it around, then `GroupBy` uses +/// no allocations. It needs allocations only if several group iterators +/// are alive at the same time. +/// +/// This type implements `IntoIterator` (it is **not** an iterator +/// itself), because the group iterators need to borrow from this +/// value. It should be stored in a local variable or temporary and +/// iterated. +/// +/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct GroupBy<K, I, F> + where I: Iterator, +{ + inner: RefCell<GroupInner<K, I, F>>, + // the group iterator's current index. Keep this in the main value + // so that simultaneous iterators all use the same state. + index: Cell<usize>, +} + +/// Create a new +pub fn new<K, J, F>(iter: J, f: F) -> GroupBy<K, J::IntoIter, F> + where J: IntoIterator, + F: FnMut(&J::Item) -> K, +{ + GroupBy { + inner: RefCell::new(GroupInner { + key: f, + iter: iter.into_iter(), + current_key: None, + current_elt: None, + done: false, + top_group: 0, + oldest_buffered_group: 0, + bottom_group: 0, + buffer: Vec::new(), + dropped_group: !0, + }), + index: Cell::new(0), + } +} + +impl<K, I, F> GroupBy<K, I, F> + where I: Iterator, +{ + /// `client`: Index of group that requests next element + fn step(&self, client: usize) -> Option<I::Item> + where F: FnMut(&I::Item) -> K, + K: PartialEq, + { + self.inner.borrow_mut().step(client) + } + + /// `client`: Index of group + fn drop_group(&self, client: usize) { + self.inner.borrow_mut().drop_group(client) + } +} + +impl<'a, K, I, F> IntoIterator for &'a GroupBy<K, I, F> + where I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq +{ + type Item = (K, Group<'a, K, I, F>); + type IntoIter = Groups<'a, K, I, F>; + + fn into_iter(self) -> Self::IntoIter { + Groups { parent: self } + } +} + + +/// An iterator that yields the Group iterators. +/// +/// Iterator element type is `(K, Group)`: +/// the group's key `K` and the group's iterator. +/// +/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Groups<'a, K: 'a, I: 'a, F: 'a> + where I: Iterator, + I::Item: 'a +{ + parent: &'a GroupBy<K, I, F>, +} + +impl<'a, K, I, F> Iterator for Groups<'a, K, I, F> + where I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq +{ + type Item = (K, Group<'a, K, I, F>); + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + let index = self.parent.index.get(); + self.parent.index.set(index + 1); + let inner = &mut *self.parent.inner.borrow_mut(); + inner.step(index).map(|elt| { + let key = inner.group_key(index); + (key, Group { + parent: self.parent, + index: index, + first: Some(elt), + }) + }) + } +} + +/// An iterator for the elements in a single group. +/// +/// Iterator element type is `I::Item`. +pub struct Group<'a, K: 'a, I: 'a, F: 'a> + where I: Iterator, + I::Item: 'a, +{ + parent: &'a GroupBy<K, I, F>, + index: usize, + first: Option<I::Item>, +} + +impl<'a, K, I, F> Drop for Group<'a, K, I, F> + where I: Iterator, + I::Item: 'a, +{ + fn drop(&mut self) { + self.parent.drop_group(self.index); + } +} + +impl<'a, K, I, F> Iterator for Group<'a, K, I, F> + where I: Iterator, + I::Item: 'a, + F: FnMut(&I::Item) -> K, + K: PartialEq, +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + if let elt @ Some(..) = self.first.take() { + return elt; + } + self.parent.step(self.index) + } +} + +///// IntoChunks ///// + +/// Create a new +pub fn new_chunks<J>(iter: J, size: usize) -> IntoChunks<J::IntoIter> + where J: IntoIterator, +{ + IntoChunks { + inner: RefCell::new(GroupInner { + key: ChunkIndex::new(size), + iter: iter.into_iter(), + current_key: None, + current_elt: None, + done: false, + top_group: 0, + oldest_buffered_group: 0, + bottom_group: 0, + buffer: Vec::new(), + dropped_group: !0, + }), + index: Cell::new(0), + } +} + + +/// `ChunkLazy` is the storage for a lazy chunking operation. +/// +/// `IntoChunks` behaves just like `GroupBy`: it is iterable, and +/// it only buffers if several chunk iterators are alive at the same time. +/// +/// This type implements `IntoIterator` (it is **not** an iterator +/// itself), because the chunk iterators need to borrow from this +/// value. It should be stored in a local variable or temporary and +/// iterated. +/// +/// Iterator element type is `Chunk`, each chunk's iterator. +/// +/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct IntoChunks<I> + where I: Iterator, +{ + inner: RefCell<GroupInner<usize, I, ChunkIndex>>, + // the chunk iterator's current index. Keep this in the main value + // so that simultaneous iterators all use the same state. + index: Cell<usize>, +} + + +impl<I> IntoChunks<I> + where I: Iterator, +{ + /// `client`: Index of chunk that requests next element + fn step(&self, client: usize) -> Option<I::Item> { + self.inner.borrow_mut().step(client) + } + + /// `client`: Index of chunk + fn drop_group(&self, client: usize) { + self.inner.borrow_mut().drop_group(client) + } +} + +impl<'a, I> IntoIterator for &'a IntoChunks<I> + where I: Iterator, + I::Item: 'a, +{ + type Item = Chunk<'a, I>; + type IntoIter = Chunks<'a, I>; + + fn into_iter(self) -> Self::IntoIter { + Chunks { + parent: self, + } + } +} + + +/// An iterator that yields the Chunk iterators. +/// +/// Iterator element type is `Chunk`. +/// +/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Chunks<'a, I: 'a> + where I: Iterator, + I::Item: 'a, +{ + parent: &'a IntoChunks<I>, +} + +impl<'a, I> Iterator for Chunks<'a, I> + where I: Iterator, + I::Item: 'a, +{ + type Item = Chunk<'a, I>; + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + let index = self.parent.index.get(); + self.parent.index.set(index + 1); + let inner = &mut *self.parent.inner.borrow_mut(); + inner.step(index).map(|elt| { + Chunk { + parent: self.parent, + index: index, + first: Some(elt), + } + }) + } +} + +/// An iterator for the elements in a single chunk. +/// +/// Iterator element type is `I::Item`. +pub struct Chunk<'a, I: 'a> + where I: Iterator, + I::Item: 'a, +{ + parent: &'a IntoChunks<I>, + index: usize, + first: Option<I::Item>, +} + +impl<'a, I> Drop for Chunk<'a, I> + where I: Iterator, + I::Item: 'a, +{ + fn drop(&mut self) { + self.parent.drop_group(self.index); + } +} + +impl<'a, I> Iterator for Chunk<'a, I> + where I: Iterator, + I::Item: 'a, +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + if let elt @ Some(..) = self.first.take() { + return elt; + } + self.parent.step(self.index) + } +} diff --git a/third_party/rust/itertools-0.8.0/src/impl_macros.rs b/third_party/rust/itertools-0.8.0/src/impl_macros.rs new file mode 100644 index 0000000000..b41760aee8 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/impl_macros.rs @@ -0,0 +1,14 @@ +//! +//! Implementation's internal macros + +macro_rules! debug_fmt_fields { + ($tyname:ident, $($($field:ident).+),*) => { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(stringify!($tyname)) + $( + .field(stringify!($($field).+), &self.$($field).+) + )* + .finish() + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/intersperse.rs b/third_party/rust/itertools-0.8.0/src/intersperse.rs new file mode 100644 index 0000000000..b1dc732117 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/intersperse.rs @@ -0,0 +1,60 @@ +use std::iter::Fuse; +use super::size_hint; + +#[derive(Clone)] +/// An iterator adaptor to insert a particular value +/// between each element of the adapted iterator. +/// +/// Iterator element type is `I::Item` +/// +/// This iterator is *fused*. +/// +/// See [`.intersperse()`](../trait.Itertools.html#method.intersperse) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct Intersperse<I> + where I: Iterator +{ + element: I::Item, + iter: Fuse<I>, + peek: Option<I::Item>, +} + +/// Create a new Intersperse iterator +pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I> + where I: Iterator +{ + let mut iter = iter.fuse(); + Intersperse { + peek: iter.next(), + iter: iter, + element: elt, + } +} + +impl<I> Iterator for Intersperse<I> + where I: Iterator, + I::Item: Clone +{ + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<I::Item> { + if self.peek.is_some() { + self.peek.take() + } else { + self.peek = self.iter.next(); + if self.peek.is_some() { + Some(self.element.clone()) + } else { + None + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + // 2 * SH + { 1 or 0 } + let has_peek = self.peek.is_some() as usize; + let sh = self.iter.size_hint(); + size_hint::add_scalar(size_hint::add(sh, sh), has_peek) + } +} diff --git a/third_party/rust/itertools-0.8.0/src/kmerge_impl.rs b/third_party/rust/itertools-0.8.0/src/kmerge_impl.rs new file mode 100644 index 0000000000..0720899e37 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/kmerge_impl.rs @@ -0,0 +1,256 @@ + +use size_hint; +use Itertools; + +use std::mem::replace; +use std::fmt; + +macro_rules! clone_fields { + ($name:ident, $base:expr, $($field:ident),+) => ( + $name { + $( + $field : $base . $field .clone() + ),* + } + ); +} + +/// Head element and Tail iterator pair +/// +/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on +/// first items (which are guaranteed to exist). +/// +/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in +/// `KMerge` into a min-heap. +#[derive(Debug)] +struct HeadTail<I> + where I: Iterator +{ + head: I::Item, + tail: I, +} + +impl<I> HeadTail<I> + where I: Iterator +{ + /// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty. + fn new(mut it: I) -> Option<HeadTail<I>> { + let head = it.next(); + head.map(|h| { + HeadTail { + head: h, + tail: it, + } + }) + } + + /// Get the next element and update `head`, returning the old head in `Some`. + /// + /// Returns `None` when the tail is exhausted (only `head` then remains). + fn next(&mut self) -> Option<I::Item> { + if let Some(next) = self.tail.next() { + Some(replace(&mut self.head, next)) + } else { + None + } + } + + /// Hints at the size of the sequence, same as the `Iterator` method. + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::add_scalar(self.tail.size_hint(), 1) + } +} + +impl<I> Clone for HeadTail<I> + where I: Iterator + Clone, + I::Item: Clone +{ + fn clone(&self) -> Self { + clone_fields!(HeadTail, self, head, tail) + } +} + +/// Make `data` a heap (min-heap w.r.t the sorting). +fn heapify<T, S>(data: &mut [T], mut less_than: S) + where S: FnMut(&T, &T) -> bool +{ + for i in (0..data.len() / 2).rev() { + sift_down(data, i, &mut less_than); + } +} + +/// Sift down element at `index` (`heap` is a min-heap wrt the ordering) +fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S) + where S: FnMut(&T, &T) -> bool +{ + debug_assert!(index <= heap.len()); + let mut pos = index; + let mut child = 2 * pos + 1; + // the `pos` conditional is to avoid a bounds check + while pos < heap.len() && child < heap.len() { + let right = child + 1; + + // pick the smaller of the two children + if right < heap.len() && less_than(&heap[right], &heap[child]) { + child = right; + } + + // sift down is done if we are already in order + if !less_than(&heap[child], &heap[pos]) { + return; + } + heap.swap(pos, child); + pos = child; + child = 2 * pos + 1; + } +} + +/// An iterator adaptor that merges an abitrary number of base iterators in ascending order. +/// If all base iterators are sorted (ascending), the result is sorted. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct KMerge<I> + where I: Iterator +{ + heap: Vec<HeadTail<I>>, +} + +impl<I> fmt::Debug for KMerge<I> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(KMerge, heap); +} + +/// Create an iterator that merges elements of the contained iterators using +/// the ordering function. +/// +/// Equivalent to `iterable.into_iter().kmerge()`. +/// +/// ``` +/// use itertools::kmerge; +/// +/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) { +/// /* loop body */ +/// } +/// ``` +pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter> + where I: IntoIterator, + I::Item: IntoIterator, + <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd +{ + let iter = iterable.into_iter(); + let (lower, _) = iter.size_hint(); + let mut heap = Vec::with_capacity(lower); + heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter()))); + heapify(&mut heap, |a, b| a.head < b.head); + KMerge { heap: heap } +} + +impl<I> Clone for KMerge<I> + where I: Iterator + Clone, + I::Item: Clone +{ + fn clone(&self) -> KMerge<I> { + clone_fields!(KMerge, self, heap) + } +} + +impl<I> Iterator for KMerge<I> + where I: Iterator, + I::Item: PartialOrd +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + if self.heap.is_empty() { + return None; + } + let result = if let Some(next) = self.heap[0].next() { + next + } else { + self.heap.swap_remove(0).head + }; + sift_down(&mut self.heap, 0, |a, b| a.head < b.head); + Some(result) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.heap.iter() + .map(|i| i.size_hint()) + .fold1(size_hint::add) + .unwrap_or((0, Some(0))) + } +} + +/// An iterator adaptor that merges an abitrary number of base iterators +/// according to an ordering function. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more +/// information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct KMergeBy<I, F> + where I: Iterator, +{ + heap: Vec<HeadTail<I>>, + less_than: F, +} + +impl<I, F> fmt::Debug for KMergeBy<I, F> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, +{ + debug_fmt_fields!(KMergeBy, heap); +} + +/// Create an iterator that merges elements of the contained iterators. +/// +/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`. +pub fn kmerge_by<I, F>(iterable: I, mut less_than: F) + -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F> + where I: IntoIterator, + I::Item: IntoIterator, + F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item, + &<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool +{ + let iter = iterable.into_iter(); + let (lower, _) = iter.size_hint(); + let mut heap: Vec<_> = Vec::with_capacity(lower); + heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter()))); + heapify(&mut heap, |a, b| less_than(&a.head, &b.head)); + KMergeBy { heap: heap, less_than: less_than } +} + + +impl<I, F> Iterator for KMergeBy<I, F> + where I: Iterator, + F: FnMut(&I::Item, &I::Item) -> bool +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + if self.heap.is_empty() { + return None; + } + let result = if let Some(next) = self.heap[0].next() { + next + } else { + self.heap.swap_remove(0).head + }; + let less_than = &mut self.less_than; + sift_down(&mut self.heap, 0, |a, b| less_than(&a.head, &b.head)); + Some(result) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.heap.iter() + .map(|i| i.size_hint()) + .fold1(size_hint::add) + .unwrap_or((0, Some(0))) + } +} diff --git a/third_party/rust/itertools-0.8.0/src/lib.rs b/third_party/rust/itertools-0.8.0/src/lib.rs new file mode 100644 index 0000000000..ab98bcdf9b --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/lib.rs @@ -0,0 +1,2176 @@ +#![warn(missing_docs)] +#![crate_name="itertools"] +#![cfg_attr(not(feature = "use_std"), no_std)] + +//! Extra iterator adaptors, functions and macros. +//! +//! To extend [`Iterator`] with methods in this crate, import +//! the [`Itertools` trait](./trait.Itertools.html): +//! +//! ``` +//! use itertools::Itertools; +//! ``` +//! +//! Now, new methods like [`interleave`](./trait.Itertools.html#method.interleave) +//! are available on all iterators: +//! +//! ``` +//! use itertools::Itertools; +//! +//! let it = (1..3).interleave(vec![-1, -2]); +//! itertools::assert_equal(it, vec![1, -1, 2, -2]); +//! ``` +//! +//! Most iterator methods are also provided as functions (with the benefit +//! that they convert parameters using [`IntoIterator`]): +//! +//! ``` +//! use itertools::interleave; +//! +//! for elt in interleave(&[1, 2, 3], &[2, 3, 4]) { +//! /* loop body */ +//! } +//! ``` +//! +//! ## Crate Features +//! +//! - `use_std` +//! - Enabled by default. +//! - Disable to compile itertools using `#![no_std]`. This disables +//! any items that depend on collections (like `group_by`, `unique`, +//! `kmerge`, `join` and many more). +//! +//! ## Rust Version +//! +//! This version of itertools requires Rust 1.24 or later. +//! +//! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html +#![doc(html_root_url="https://docs.rs/itertools/0.8/")] + +extern crate either; + +#[cfg(not(feature = "use_std"))] +extern crate core as std; + +pub use either::Either; + +#[cfg(feature = "use_std")] +use std::collections::HashMap; +use std::iter::{IntoIterator}; +use std::cmp::Ordering; +use std::fmt; +#[cfg(feature = "use_std")] +use std::hash::Hash; +#[cfg(feature = "use_std")] +use std::fmt::Write; +#[cfg(feature = "use_std")] +type VecIntoIter<T> = ::std::vec::IntoIter<T>; +#[cfg(feature = "use_std")] +use std::iter::FromIterator; + +#[macro_use] +mod impl_macros; + +// for compatibility with no std and macros +#[doc(hidden)] +pub use std::iter as __std_iter; + +/// The concrete iterator types. +pub mod structs { + pub use adaptors::{ + Dedup, + Interleave, + InterleaveShortest, + Product, + PutBack, + Batching, + MapInto, + MapResults, + Merge, + MergeBy, + TakeWhileRef, + WhileSome, + Coalesce, + TupleCombinations, + Positions, + Update, + }; + #[allow(deprecated)] + pub use adaptors::Step; + #[cfg(feature = "use_std")] + pub use adaptors::MultiProduct; + #[cfg(feature = "use_std")] + pub use combinations::Combinations; + pub use cons_tuples_impl::ConsTuples; + pub use format::{Format, FormatWith}; + #[cfg(feature = "use_std")] + pub use groupbylazy::{IntoChunks, Chunk, Chunks, GroupBy, Group, Groups}; + pub use intersperse::Intersperse; + #[cfg(feature = "use_std")] + pub use kmerge_impl::{KMerge, KMergeBy}; + pub use merge_join::MergeJoinBy; + #[cfg(feature = "use_std")] + pub use multipeek_impl::MultiPeek; + pub use pad_tail::PadUsing; + pub use peeking_take_while::PeekingTakeWhile; + pub use process_results_impl::ProcessResults; + #[cfg(feature = "use_std")] + pub use put_back_n_impl::PutBackN; + #[cfg(feature = "use_std")] + pub use rciter_impl::RcIter; + pub use repeatn::RepeatN; + #[allow(deprecated)] + pub use sources::{RepeatCall, Unfold, Iterate}; + #[cfg(feature = "use_std")] + pub use tee::Tee; + pub use tuple_impl::{TupleBuffer, TupleWindows, Tuples}; + #[cfg(feature = "use_std")] + pub use unique_impl::{Unique, UniqueBy}; + pub use with_position::WithPosition; + pub use zip_eq_impl::ZipEq; + pub use zip_longest::ZipLongest; + pub use ziptuple::Zip; +} +#[allow(deprecated)] +pub use structs::*; +pub use concat_impl::concat; +pub use cons_tuples_impl::cons_tuples; +pub use diff::diff_with; +pub use diff::Diff; +#[cfg(feature = "use_std")] +pub use kmerge_impl::{kmerge_by}; +pub use minmax::MinMaxResult; +pub use peeking_take_while::PeekingNext; +pub use process_results_impl::process_results; +pub use repeatn::repeat_n; +#[allow(deprecated)] +pub use sources::{repeat_call, unfold, iterate}; +pub use with_position::Position; +pub use ziptuple::multizip; +mod adaptors; +mod either_or_both; +pub use either_or_both::EitherOrBoth; +#[doc(hidden)] +pub mod free; +#[doc(inline)] +pub use free::*; +mod concat_impl; +mod cons_tuples_impl; +#[cfg(feature = "use_std")] +mod combinations; +mod diff; +mod format; +#[cfg(feature = "use_std")] +mod group_map; +#[cfg(feature = "use_std")] +mod groupbylazy; +mod intersperse; +#[cfg(feature = "use_std")] +mod kmerge_impl; +mod merge_join; +mod minmax; +#[cfg(feature = "use_std")] +mod multipeek_impl; +mod pad_tail; +mod peeking_take_while; +mod process_results_impl; +#[cfg(feature = "use_std")] +mod put_back_n_impl; +#[cfg(feature = "use_std")] +mod rciter_impl; +mod repeatn; +mod size_hint; +mod sources; +#[cfg(feature = "use_std")] +mod tee; +mod tuple_impl; +#[cfg(feature = "use_std")] +mod unique_impl; +mod with_position; +mod zip_eq_impl; +mod zip_longest; +mod ziptuple; + +#[macro_export] +/// Create an iterator over the “cartesian product” of iterators. +/// +/// Iterator element type is like `(A, B, ..., E)` if formed +/// from iterators `(I, J, ..., M)` with element types `I::Item = A`, `J::Item = B`, etc. +/// +/// ``` +/// #[macro_use] extern crate itertools; +/// # fn main() { +/// // Iterate over the coordinates of a 4 x 4 x 4 grid +/// // from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3) +/// for (i, j, k) in iproduct!(0..4, 0..4, 0..4) { +/// // .. +/// } +/// # } +/// ``` +/// +/// **Note:** To enable the macros in this crate, use the `#[macro_use]` +/// attribute when importing the crate: +/// +/// ``` +/// #[macro_use] extern crate itertools; +/// # fn main() { } +/// ``` +macro_rules! iproduct { + (@flatten $I:expr,) => ( + $I + ); + (@flatten $I:expr, $J:expr, $($K:expr,)*) => ( + iproduct!(@flatten $crate::cons_tuples(iproduct!($I, $J)), $($K,)*) + ); + ($I:expr) => ( + $crate::__std_iter::IntoIterator::into_iter($I) + ); + ($I:expr, $J:expr) => ( + $crate::Itertools::cartesian_product(iproduct!($I), iproduct!($J)) + ); + ($I:expr, $J:expr, $($K:expr),+) => ( + iproduct!(@flatten iproduct!($I, $J), $($K,)+) + ); +} + +#[macro_export] +/// Create an iterator running multiple iterators in lockstep. +/// +/// The `izip!` iterator yields elements until any subiterator +/// returns `None`. +/// +/// This is a version of the standard ``.zip()`` that's supporting more than +/// two iterators. The iterator element type is a tuple with one element +/// from each of the input iterators. Just like ``.zip()``, the iteration stops +/// when the shortest of the inputs reaches its end. +/// +/// **Note:** The result of this macro is in the general case an iterator +/// composed of repeated `.zip()` and a `.map()`; it has an anonymous type. +/// The special cases of one and two arguments produce the equivalent of +/// `$a.into_iter()` and `$a.into_iter().zip($b)` respectively. +/// +/// Prefer this macro `izip!()` over [`multizip`] for the performance benefits +/// of using the standard library `.zip()`. +/// +/// [`multizip`]: fn.multizip.html +/// +/// ``` +/// #[macro_use] extern crate itertools; +/// # fn main() { +/// +/// // iterate over three sequences side-by-side +/// let mut results = [0, 0, 0, 0]; +/// let inputs = [3, 7, 9, 6]; +/// +/// for (r, index, input) in izip!(&mut results, 0..10, &inputs) { +/// *r = index * 10 + input; +/// } +/// +/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); +/// # } +/// ``` +/// +/// **Note:** To enable the macros in this crate, use the `#[macro_use]` +/// attribute when importing the crate: +/// +/// ``` +/// #[macro_use] extern crate itertools; +/// # fn main() { } +/// ``` +macro_rules! izip { + // @closure creates a tuple-flattening closure for .map() call. usage: + // @closure partial_pattern => partial_tuple , rest , of , iterators + // eg. izip!( @closure ((a, b), c) => (a, b, c) , dd , ee ) + ( @closure $p:pat => $tup:expr ) => { + |$p| $tup + }; + + // The "b" identifier is a different identifier on each recursion level thanks to hygiene. + ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => { + izip!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*) + }; + + // unary + ($first:expr $(,)*) => { + $crate::__std_iter::IntoIterator::into_iter($first) + }; + + // binary + ($first:expr, $second:expr $(,)*) => { + izip!($first) + .zip($second) + }; + + // n-ary where n > 2 + ( $first:expr $( , $rest:expr )* $(,)* ) => { + izip!($first) + $( + .zip($rest) + )* + .map( + izip!(@closure a => (a) $( , $rest )*) + ) + }; +} + +/// An [`Iterator`] blanket implementation that provides extra adaptors and +/// methods. +/// +/// This trait defines a number of methods. They are divided into two groups: +/// +/// * *Adaptors* take an iterator and parameter as input, and return +/// a new iterator value. These are listed first in the trait. An example +/// of an adaptor is [`.interleave()`](#method.interleave) +/// +/// * *Regular methods* are those that don't return iterators and instead +/// return a regular value of some other kind. +/// [`.next_tuple()`](#method.next_tuple) is an example and the first regular +/// method in the list. +/// +/// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html +pub trait Itertools : Iterator { + // adaptors + + /// Alternate elements from two iterators until both have run out. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..7).interleave(vec![-1, -2]); + /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3, 4, 5, 6]); + /// ``` + fn interleave<J>(self, other: J) -> Interleave<Self, J::IntoIter> + where J: IntoIterator<Item = Self::Item>, + Self: Sized + { + interleave(self, other) + } + + /// Alternate elements from two iterators until at least one of them has run + /// out. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..7).interleave_shortest(vec![-1, -2]); + /// itertools::assert_equal(it, vec![1, -1, 2, -2, 3]); + /// ``` + fn interleave_shortest<J>(self, other: J) -> InterleaveShortest<Self, J::IntoIter> + where J: IntoIterator<Item = Self::Item>, + Self: Sized + { + adaptors::interleave_shortest(self, other.into_iter()) + } + + /// An iterator adaptor to insert a particular value + /// between each element of the adapted iterator. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// itertools::assert_equal((0..3).intersperse(8), vec![0, 8, 1, 8, 2]); + /// ``` + fn intersperse(self, element: Self::Item) -> Intersperse<Self> + where Self: Sized, + Self::Item: Clone + { + intersperse::intersperse(self, element) + } + + /// Create an iterator which iterates over both this and the specified + /// iterator simultaneously, yielding pairs of two optional elements. + /// + /// This iterator is *fused*. + /// + /// As long as neither input iterator is exhausted yet, it yields two values + /// via `EitherOrBoth::Both`. + /// + /// When the parameter iterator is exhausted, it only yields a value from the + /// `self` iterator via `EitherOrBoth::Left`. + /// + /// When the `self` iterator is exhausted, it only yields a value from the + /// parameter iterator via `EitherOrBoth::Right`. + /// + /// When both iterators return `None`, all further invocations of `.next()` + /// will return `None`. + /// + /// Iterator element type is + /// [`EitherOrBoth<Self::Item, J::Item>`](enum.EitherOrBoth.html). + /// + /// ```rust + /// use itertools::EitherOrBoth::{Both, Right}; + /// use itertools::Itertools; + /// let it = (0..1).zip_longest(1..3); + /// itertools::assert_equal(it, vec![Both(0, 1), Right(2)]); + /// ``` + #[inline] + fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J::IntoIter> + where J: IntoIterator, + Self: Sized + { + zip_longest::zip_longest(self, other.into_iter()) + } + + /// Create an iterator which iterates over both this and the specified + /// iterator simultaneously, yielding pairs of elements. + /// + /// **Panics** if the iterators reach an end and they are not of equal + /// lengths. + #[inline] + fn zip_eq<J>(self, other: J) -> ZipEq<Self, J::IntoIter> + where J: IntoIterator, + Self: Sized + { + zip_eq(self, other) + } + + /// A “meta iterator adaptor”. Its closure receives a reference to the + /// iterator and may pick off as many elements as it likes, to produce the + /// next iterator element. + /// + /// Iterator element type is `B`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // An adaptor that gathers elements in pairs + /// let pit = (0..4).batching(|it| { + /// match it.next() { + /// None => None, + /// Some(x) => match it.next() { + /// None => None, + /// Some(y) => Some((x, y)), + /// } + /// } + /// }); + /// + /// itertools::assert_equal(pit, vec![(0, 1), (2, 3)]); + /// ``` + /// + fn batching<B, F>(self, f: F) -> Batching<Self, F> + where F: FnMut(&mut Self) -> Option<B>, + Self: Sized + { + adaptors::batching(self, f) + } + + /// Return an *iterable* that can group iterator elements. + /// Consecutive elements that map to the same key (“runs”), are assigned + /// to the same group. + /// + /// `GroupBy` is the storage for the lazy grouping operation. + /// + /// If the groups are consumed in order, or if each group's iterator is + /// dropped without keeping it around, then `GroupBy` uses no + /// allocations. It needs allocations only if several group iterators + /// are alive at the same time. + /// + /// This type implements `IntoIterator` (it is **not** an iterator + /// itself), because the group iterators need to borrow from this + /// value. It should be stored in a local variable or temporary and + /// iterated. + /// + /// Iterator element type is `(K, Group)`: the group's key and the + /// group iterator. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // group data into runs of larger than zero or not. + /// let data = vec![1, 3, -2, -2, 1, 0, 1, 2]; + /// // groups: |---->|------>|--------->| + /// + /// // Note: The `&` is significant here, `GroupBy` is iterable + /// // only by reference. You can also call `.into_iter()` explicitly. + /// for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) { + /// // Check that the sum of each group is +/- 4. + /// assert_eq!(4, group.sum::<i32>().abs()); + /// } + /// ``` + #[cfg(feature = "use_std")] + fn group_by<K, F>(self, key: F) -> GroupBy<K, Self, F> + where Self: Sized, + F: FnMut(&Self::Item) -> K, + K: PartialEq, + { + groupbylazy::new(self, key) + } + + /// Return an *iterable* that can chunk the iterator. + /// + /// Yield subiterators (chunks) that each yield a fixed number elements, + /// determined by `size`. The last chunk will be shorter if there aren't + /// enough elements. + /// + /// `IntoChunks` is based on `GroupBy`: it is iterable (implements + /// `IntoIterator`, **not** `Iterator`), and it only buffers if several + /// chunk iterators are alive at the same time. + /// + /// Iterator element type is `Chunk`, each chunk's iterator. + /// + /// **Panics** if `size` is 0. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 1, 2, -2, 6, 0, 3, 1]; + /// //chunk size=3 |------->|-------->|--->| + /// + /// // Note: The `&` is significant here, `IntoChunks` is iterable + /// // only by reference. You can also call `.into_iter()` explicitly. + /// for chunk in &data.into_iter().chunks(3) { + /// // Check that the sum of each chunk is 4. + /// assert_eq!(4, chunk.sum()); + /// } + /// ``` + #[cfg(feature = "use_std")] + fn chunks(self, size: usize) -> IntoChunks<Self> + where Self: Sized, + { + assert!(size != 0); + groupbylazy::new_chunks(self, size) + } + + /// Return an iterator over all contiguous windows producing tuples of + /// a specific size (up to 4). + /// + /// `tuple_windows` clones the iterator elements so that they can be + /// part of successive windows, this makes it most suited for iterators + /// of references and other values that are cheap to copy. + /// + /// ``` + /// use itertools::Itertools; + /// let mut v = Vec::new(); + /// for (a, b) in (1..5).tuple_windows() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (2, 3), (3, 4)]); + /// + /// let mut it = (1..5).tuple_windows(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((2, 3, 4)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..5).tuple_windows::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); + /// + /// // you can also specify the complete type + /// use itertools::TupleWindows; + /// use std::ops::Range; + /// + /// let it: TupleWindows<Range<u32>, (u32, u32, u32)> = (1..5).tuple_windows(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (2, 3, 4)]); + /// ``` + fn tuple_windows<T>(self) -> TupleWindows<Self, T> + where Self: Sized + Iterator<Item = T::Item>, + T: tuple_impl::TupleCollect, + T::Item: Clone + { + tuple_impl::tuple_windows(self) + } + + /// Return an iterator that groups the items in tuples of a specific size + /// (up to 4). + /// + /// See also the method [`.next_tuple()`](#method.next_tuple). + /// + /// ``` + /// use itertools::Itertools; + /// let mut v = Vec::new(); + /// for (a, b) in (1..5).tuples() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (3, 4)]); + /// + /// let mut it = (1..7).tuples(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((4, 5, 6)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..7).tuples::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); + /// + /// // you can also specify the complete type + /// use itertools::Tuples; + /// use std::ops::Range; + /// + /// let it: Tuples<Range<u32>, (u32, u32, u32)> = (1..7).tuples(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (4, 5, 6)]); + /// ``` + /// + /// See also [`Tuples::into_buffer`](structs/struct.Tuples.html#method.into_buffer). + fn tuples<T>(self) -> Tuples<Self, T> + where Self: Sized + Iterator<Item = T::Item>, + T: tuple_impl::TupleCollect + { + tuple_impl::tuples(self) + } + + /// Split into an iterator pair that both yield all elements from + /// the original iterator. + /// + /// **Note:** If the iterator is clonable, prefer using that instead + /// of using this method. It is likely to be more efficient. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// let xs = vec![0, 1, 2, 3]; + /// + /// let (mut t1, t2) = xs.into_iter().tee(); + /// itertools::assert_equal(t1.next(), Some(0)); + /// itertools::assert_equal(t2, 0..4); + /// itertools::assert_equal(t1, 1..4); + /// ``` + #[cfg(feature = "use_std")] + fn tee(self) -> (Tee<Self>, Tee<Self>) + where Self: Sized, + Self::Item: Clone + { + tee::new(self) + } + + /// Return an iterator adaptor that steps `n` elements in the base iterator + /// for each iteration. + /// + /// The iterator steps by yielding the next element from the base iterator, + /// then skipping forward `n - 1` elements. + /// + /// Iterator element type is `Self::Item`. + /// + /// **Panics** if the step is 0. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (0..8).step(3); + /// itertools::assert_equal(it, vec![0, 3, 6]); + /// ``` + #[deprecated(note="Use std .step_by() instead", since="0.8")] + #[allow(deprecated)] + fn step(self, n: usize) -> Step<Self> + where Self: Sized + { + adaptors::step(self, n) + } + + /// Convert each item of the iterator using the `Into` trait. + /// + /// ```rust + /// use itertools::Itertools; + /// + /// (1i32..42i32).map_into::<f64>().collect_vec(); + /// ``` + fn map_into<R>(self) -> MapInto<Self, R> + where Self: Sized, + Self::Item: Into<R>, + { + adaptors::map_into(self) + } + + /// Return an iterator adaptor that applies the provided closure + /// to every `Result::Ok` value. `Result::Err` values are + /// unchanged. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![Ok(41), Err(false), Ok(11)]; + /// let it = input.into_iter().map_results(|i| i + 1); + /// itertools::assert_equal(it, vec![Ok(42), Err(false), Ok(12)]); + /// ``` + fn map_results<F, T, U, E>(self, f: F) -> MapResults<Self, F> + where Self: Iterator<Item = Result<T, E>> + Sized, + F: FnMut(T) -> U, + { + adaptors::map_results(self, f) + } + + /// Return an iterator adaptor that merges the two base iterators in + /// ascending order. If both base iterators are sorted (ascending), the + /// result is sorted. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = (0..11).step(3); + /// let b = (0..11).step(5); + /// let it = a.merge(b); + /// itertools::assert_equal(it, vec![0, 0, 3, 5, 6, 9, 10]); + /// ``` + fn merge<J>(self, other: J) -> Merge<Self, J::IntoIter> + where Self: Sized, + Self::Item: PartialOrd, + J: IntoIterator<Item = Self::Item> + { + merge(self, other) + } + + /// Return an iterator adaptor that merges the two base iterators in order. + /// This is much like `.merge()` but allows for a custom ordering. + /// + /// This can be especially useful for sequences of tuples. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = (0..).zip("bc".chars()); + /// let b = (0..).zip("ad".chars()); + /// let it = a.merge_by(b, |x, y| x.1 <= y.1); + /// itertools::assert_equal(it, vec![(0, 'a'), (0, 'b'), (1, 'c'), (1, 'd')]); + /// ``` + + fn merge_by<J, F>(self, other: J, is_first: F) -> MergeBy<Self, J::IntoIter, F> + where Self: Sized, + J: IntoIterator<Item = Self::Item>, + F: FnMut(&Self::Item, &Self::Item) -> bool + { + adaptors::merge_by_new(self, other.into_iter(), is_first) + } + + /// Create an iterator that merges items from both this and the specified + /// iterator in ascending order. + /// + /// It chooses whether to pair elements based on the `Ordering` returned by the + /// specified compare function. At any point, inspecting the tip of the + /// iterators `I` and `J` as items `i` of type `I::Item` and `j` of type + /// `J::Item` respectively, the resulting iterator will: + /// + /// - Emit `EitherOrBoth::Left(i)` when `i < j`, + /// and remove `i` from its source iterator + /// - Emit `EitherOrBoth::Right(j)` when `i > j`, + /// and remove `j` from its source iterator + /// - Emit `EitherOrBoth::Both(i, j)` when `i == j`, + /// and remove both `i` and `j` from their respective source iterators + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::EitherOrBoth::{Left, Right, Both}; + /// + /// let ki = (0..10).step(3); + /// let ku = (0..10).step(5); + /// let ki_ku = ki.merge_join_by(ku, |i, j| i.cmp(j)).map(|either| { + /// match either { + /// Left(_) => "Ki", + /// Right(_) => "Ku", + /// Both(_, _) => "KiKu" + /// } + /// }); + /// + /// itertools::assert_equal(ki_ku, vec!["KiKu", "Ki", "Ku", "Ki", "Ki"]); + /// ``` + #[inline] + fn merge_join_by<J, F>(self, other: J, cmp_fn: F) -> MergeJoinBy<Self, J::IntoIter, F> + where J: IntoIterator, + F: FnMut(&Self::Item, &J::Item) -> std::cmp::Ordering, + Self: Sized + { + merge_join_by(self, other, cmp_fn) + } + + + /// Return an iterator adaptor that flattens an iterator of iterators by + /// merging them in ascending order. + /// + /// If all base iterators are sorted (ascending), the result is sorted. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = (0..6).step(3); + /// let b = (1..6).step(3); + /// let c = (2..6).step(3); + /// let it = vec![a, b, c].into_iter().kmerge(); + /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5]); + /// ``` + #[cfg(feature = "use_std")] + fn kmerge(self) -> KMerge<<Self::Item as IntoIterator>::IntoIter> + where Self: Sized, + Self::Item: IntoIterator, + <Self::Item as IntoIterator>::Item: PartialOrd, + { + kmerge(self) + } + + /// Return an iterator adaptor that flattens an iterator of iterators by + /// merging them according to the given closure. + /// + /// The closure `first` is called with two elements *a*, *b* and should + /// return `true` if *a* is ordered before *b*. + /// + /// If all base iterators are sorted according to `first`, the result is + /// sorted. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let a = vec![-1f64, 2., 3., -5., 6., -7.]; + /// let b = vec![0., 2., -4.]; + /// let mut it = vec![a, b].into_iter().kmerge_by(|a, b| a.abs() < b.abs()); + /// assert_eq!(it.next(), Some(0.)); + /// assert_eq!(it.last(), Some(-7.)); + /// ``` + #[cfg(feature = "use_std")] + fn kmerge_by<F>(self, first: F) + -> KMergeBy<<Self::Item as IntoIterator>::IntoIter, F> + where Self: Sized, + Self::Item: IntoIterator, + F: FnMut(&<Self::Item as IntoIterator>::Item, + &<Self::Item as IntoIterator>::Item) -> bool + { + kmerge_by(self, first) + } + + /// Return an iterator adaptor that iterates over the cartesian product of + /// the element sets of two iterators `self` and `J`. + /// + /// Iterator element type is `(Self::Item, J::Item)`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (0..2).cartesian_product("αβ".chars()); + /// itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]); + /// ``` + fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoIter> + where Self: Sized, + Self::Item: Clone, + J: IntoIterator, + J::IntoIter: Clone + { + adaptors::cartesian_product(self, other.into_iter()) + } + + /// Return an iterator adaptor that iterates over the cartesian product of + /// all subiterators returned by meta-iterator `self`. + /// + /// All provided iterators must yield the same `Item` type. To generate + /// the product of iterators yielding multiple types, use the + /// [`iproduct`](macro.iproduct.html) macro instead. + /// + /// + /// The iterator element type is `Vec<T>`, where `T` is the iterator element + /// of the subiterators. + /// + /// ``` + /// use itertools::Itertools; + /// let mut multi_prod = (0..3).map(|i| (i * 2)..(i * 2 + 2)) + /// .multi_cartesian_product(); + /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![0, 2, 5])); + /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![0, 3, 5])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 2, 5])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 4])); + /// assert_eq!(multi_prod.next(), Some(vec![1, 3, 5])); + /// assert_eq!(multi_prod.next(), None); + /// ``` + #[cfg(feature = "use_std")] + fn multi_cartesian_product(self) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter> + where Self: Iterator + Sized, + Self::Item: IntoIterator, + <Self::Item as IntoIterator>::IntoIter: Clone, + <Self::Item as IntoIterator>::Item: Clone + { + adaptors::multi_cartesian_product(self) + } + + /// Return an iterator adaptor that uses the passed-in closure to + /// optionally merge together consecutive elements. + /// + /// The closure `f` is passed two elements, `previous` and `current` and may + /// return either (1) `Ok(combined)` to merge the two values or + /// (2) `Err((previous', current'))` to indicate they can't be merged. + /// In (2), the value `previous'` is emitted by the iterator. + /// Either (1) `combined` or (2) `current'` becomes the previous value + /// when coalesce continues with the next pair of elements to merge. The + /// value that remains at the end is also emitted by the iterator. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sum same-sign runs together + /// let data = vec![-1., -2., -3., 3., 1., 0., -1.]; + /// itertools::assert_equal(data.into_iter().coalesce(|x, y| + /// if (x >= 0.) == (y >= 0.) { + /// Ok(x + y) + /// } else { + /// Err((x, y)) + /// }), + /// vec![-6., 4., -1.]); + /// ``` + fn coalesce<F>(self, f: F) -> Coalesce<Self, F> + where Self: Sized, + F: FnMut(Self::Item, Self::Item) + -> Result<Self::Item, (Self::Item, Self::Item)> + { + adaptors::coalesce(self, f) + } + + /// Remove duplicates from sections of consecutive identical elements. + /// If the iterator is sorted, all elements will be unique. + /// + /// Iterator element type is `Self::Item`. + /// + /// This iterator is *fused*. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1., 1., 2., 3., 3., 2., 2.]; + /// itertools::assert_equal(data.into_iter().dedup(), + /// vec![1., 2., 3., 2.]); + /// ``` + fn dedup(self) -> Dedup<Self> + where Self: Sized, + Self::Item: PartialEq, + { + adaptors::dedup(self) + } + + /// Return an iterator adaptor that filters out elements that have + /// already been produced once during the iteration. Duplicates + /// are detected using hash and equality. + /// + /// Clones of visited elements are stored in a hash set in the + /// iterator. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![10, 20, 30, 20, 40, 10, 50]; + /// itertools::assert_equal(data.into_iter().unique(), + /// vec![10, 20, 30, 40, 50]); + /// ``` + #[cfg(feature = "use_std")] + fn unique(self) -> Unique<Self> + where Self: Sized, + Self::Item: Clone + Eq + Hash + { + unique_impl::unique(self) + } + + /// Return an iterator adaptor that filters out elements that have + /// already been produced once during the iteration. + /// + /// Duplicates are detected by comparing the key they map to + /// with the keying function `f` by hash and equality. + /// The keys are stored in a hash set in the iterator. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec!["a", "bb", "aa", "c", "ccc"]; + /// itertools::assert_equal(data.into_iter().unique_by(|s| s.len()), + /// vec!["a", "bb", "ccc"]); + /// ``` + #[cfg(feature = "use_std")] + fn unique_by<V, F>(self, f: F) -> UniqueBy<Self, V, F> + where Self: Sized, + V: Eq + Hash, + F: FnMut(&Self::Item) -> V + { + unique_impl::unique_by(self, f) + } + + /// Return an iterator adaptor that borrows from this iterator and + /// takes items while the closure `accept` returns `true`. + /// + /// This adaptor can only be used on iterators that implement `PeekingNext` + /// like `.peekable()`, `put_back` and a few other collection iterators. + /// + /// The last and rejected element (first `false`) is still available when + /// `peeking_take_while` is done. + /// + /// + /// See also [`.take_while_ref()`](#method.take_while_ref) + /// which is a similar adaptor. + fn peeking_take_while<F>(&mut self, accept: F) -> PeekingTakeWhile<Self, F> + where Self: Sized + PeekingNext, + F: FnMut(&Self::Item) -> bool, + { + peeking_take_while::peeking_take_while(self, accept) + } + + /// Return an iterator adaptor that borrows from a `Clone`-able iterator + /// to only pick off elements while the predicate `accept` returns `true`. + /// + /// It uses the `Clone` trait to restore the original iterator so that the + /// last and rejected element (first `false`) is still available when + /// `take_while_ref` is done. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut hexadecimals = "0123456789abcdef".chars(); + /// + /// let decimals = hexadecimals.take_while_ref(|c| c.is_numeric()) + /// .collect::<String>(); + /// assert_eq!(decimals, "0123456789"); + /// assert_eq!(hexadecimals.next(), Some('a')); + /// + /// ``` + fn take_while_ref<F>(&mut self, accept: F) -> TakeWhileRef<Self, F> + where Self: Clone, + F: FnMut(&Self::Item) -> bool + { + adaptors::take_while_ref(self, accept) + } + + /// Return an iterator adaptor that filters `Option<A>` iterator elements + /// and produces `A`. Stops on the first `None` encountered. + /// + /// Iterator element type is `A`, the unwrapped element. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // List all hexadecimal digits + /// itertools::assert_equal( + /// (0..).map(|i| std::char::from_digit(i, 16)).while_some(), + /// "0123456789abcdef".chars()); + /// + /// ``` + fn while_some<A>(self) -> WhileSome<Self> + where Self: Sized + Iterator<Item = Option<A>> + { + adaptors::while_some(self) + } + + /// Return an iterator adaptor that iterates over the combinations of the + /// elements from an iterator. + /// + /// Iterator element can be any homogeneous tuple of type `Self::Item` with + /// size up to 4. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut v = Vec::new(); + /// for (a, b) in (1..5).tuple_combinations() { + /// v.push((a, b)); + /// } + /// assert_eq!(v, vec![(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]); + /// + /// let mut it = (1..5).tuple_combinations(); + /// assert_eq!(Some((1, 2, 3)), it.next()); + /// assert_eq!(Some((1, 2, 4)), it.next()); + /// assert_eq!(Some((1, 3, 4)), it.next()); + /// assert_eq!(Some((2, 3, 4)), it.next()); + /// assert_eq!(None, it.next()); + /// + /// // this requires a type hint + /// let it = (1..5).tuple_combinations::<(_, _, _)>(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); + /// + /// // you can also specify the complete type + /// use itertools::TupleCombinations; + /// use std::ops::Range; + /// + /// let it: TupleCombinations<Range<u32>, (u32, u32, u32)> = (1..5).tuple_combinations(); + /// itertools::assert_equal(it, vec![(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]); + /// ``` + fn tuple_combinations<T>(self) -> TupleCombinations<Self, T> + where Self: Sized + Clone, + Self::Item: Clone, + T: adaptors::HasCombination<Self>, + { + adaptors::tuple_combinations(self) + } + + /// Return an iterator adaptor that iterates over the `n`-length combinations of + /// the elements from an iterator. + /// + /// Iterator element type is `Vec<Self::Item>`. The iterator produces a new Vec per iteration, + /// and clones the iterator elements. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (1..5).combinations(3); + /// itertools::assert_equal(it, vec![ + /// vec![1, 2, 3], + /// vec![1, 2, 4], + /// vec![1, 3, 4], + /// vec![2, 3, 4], + /// ]); + /// ``` + #[cfg(feature = "use_std")] + fn combinations(self, n: usize) -> Combinations<Self> + where Self: Sized, + Self::Item: Clone + { + combinations::combinations(self, n) + } + + /// Return an iterator adaptor that pads the sequence to a minimum length of + /// `min` by filling missing elements using a closure `f`. + /// + /// Iterator element type is `Self::Item`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let it = (0..5).pad_using(10, |i| 2*i); + /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 10, 12, 14, 16, 18]); + /// + /// let it = (0..10).pad_using(5, |i| 2*i); + /// itertools::assert_equal(it, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// + /// let it = (0..5).pad_using(10, |i| 2*i).rev(); + /// itertools::assert_equal(it, vec![18, 16, 14, 12, 10, 4, 3, 2, 1, 0]); + /// ``` + fn pad_using<F>(self, min: usize, f: F) -> PadUsing<Self, F> + where Self: Sized, + F: FnMut(usize) -> Self::Item + { + pad_tail::pad_using(self, min, f) + } + + /// Return an iterator adaptor that wraps each element in a `Position` to + /// ease special-case handling of the first or last elements. + /// + /// Iterator element type is + /// [`Position<Self::Item>`](enum.Position.html) + /// + /// ``` + /// use itertools::{Itertools, Position}; + /// + /// let it = (0..4).with_position(); + /// itertools::assert_equal(it, + /// vec![Position::First(0), + /// Position::Middle(1), + /// Position::Middle(2), + /// Position::Last(3)]); + /// + /// let it = (0..1).with_position(); + /// itertools::assert_equal(it, vec![Position::Only(0)]); + /// ``` + fn with_position(self) -> WithPosition<Self> + where Self: Sized, + { + with_position::with_position(self) + } + + /// Return an iterator adaptor that yields the indices of all elements + /// satisfying a predicate, counted from the start of the iterator. + /// + /// Equivalent to `iter.enumerate().filter(|(_, v)| predicate(v)).map(|(i, _)| i)`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 2, 3, 3, 4, 6, 7, 9]; + /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 0), vec![1, 4, 5]); + /// + /// itertools::assert_equal(data.iter().positions(|v| v % 2 == 1).rev(), vec![7, 6, 3, 2, 0]); + /// ``` + fn positions<P>(self, predicate: P) -> Positions<Self, P> + where Self: Sized, + P: FnMut(Self::Item) -> bool, + { + adaptors::positions(self, predicate) + } + + /// Return an iterator adaptor that applies a mutating function + /// to each element before yielding it. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let input = vec![vec![1], vec![3, 2, 1]]; + /// let it = input.into_iter().update(|mut v| v.push(0)); + /// itertools::assert_equal(it, vec![vec![1, 0], vec![3, 2, 1, 0]]); + /// ``` + fn update<F>(self, updater: F) -> Update<Self, F> + where Self: Sized, + F: FnMut(&mut Self::Item), + { + adaptors::update(self, updater) + } + + // non-adaptor methods + /// Advances the iterator and returns the next items grouped in a tuple of + /// a specific size (up to 4). + /// + /// If there are enough elements to be grouped in a tuple, then the tuple is + /// returned inside `Some`, otherwise `None` is returned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = 1..5; + /// + /// assert_eq!(Some((1, 2)), iter.next_tuple()); + /// ``` + fn next_tuple<T>(&mut self) -> Option<T> + where Self: Sized + Iterator<Item = T::Item>, + T: tuple_impl::TupleCollect + { + T::collect_from_iter_no_buf(self) + } + + /// Collects all items from the iterator into a tuple of a specific size + /// (up to 4). + /// + /// If the number of elements inside the iterator is **exactly** equal to + /// the tuple size, then the tuple is returned inside `Some`, otherwise + /// `None` is returned. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let iter = 1..3; + /// + /// if let Some((x, y)) = iter.collect_tuple() { + /// assert_eq!((x, y), (1, 2)) + /// } else { + /// panic!("Expected two elements") + /// } + /// ``` + fn collect_tuple<T>(mut self) -> Option<T> + where Self: Sized + Iterator<Item = T::Item>, + T: tuple_impl::TupleCollect + { + match self.next_tuple() { + elt @ Some(_) => match self.next() { + Some(_) => None, + None => elt, + }, + _ => None + } + } + + + /// Find the position and value of the first element satisfying a predicate. + /// + /// The iterator is not advanced past the first element found. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let text = "Hα"; + /// assert_eq!(text.chars().find_position(|ch| ch.is_lowercase()), Some((1, 'α'))); + /// ``` + fn find_position<P>(&mut self, mut pred: P) -> Option<(usize, Self::Item)> + where P: FnMut(&Self::Item) -> bool + { + let mut index = 0usize; + for elt in self { + if pred(&elt) { + return Some((index, elt)); + } + index += 1; + } + None + } + + /// Check whether all elements compare equal. + /// + /// Empty iterators are considered to have equal elements: + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; + /// assert!(!data.iter().all_equal()); + /// assert!(data[0..3].iter().all_equal()); + /// assert!(data[3..5].iter().all_equal()); + /// assert!(data[5..8].iter().all_equal()); + /// + /// let data : Option<usize> = None; + /// assert!(data.into_iter().all_equal()); + /// ``` + fn all_equal(&mut self) -> bool + where Self::Item: PartialEq, + { + self.dedup().nth(1).is_none() + } + + /// Consume the first `n` elements from the iterator eagerly, + /// and return the same iterator again. + /// + /// It works similarly to *.skip(* `n` *)* except it is eager and + /// preserves the iterator type. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = "αβγ".chars().dropping(2); + /// itertools::assert_equal(iter, "γ".chars()); + /// ``` + /// + /// *Fusing notes: if the iterator is exhausted by dropping, + /// the result of calling `.next()` again depends on the iterator implementation.* + fn dropping(mut self, n: usize) -> Self + where Self: Sized + { + if n > 0 { + self.nth(n - 1); + } + self + } + + /// Consume the last `n` elements from the iterator eagerly, + /// and return the same iterator again. + /// + /// This is only possible on double ended iterators. `n` may be + /// larger than the number of elements. + /// + /// Note: This method is eager, dropping the back elements immediately and + /// preserves the iterator type. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let init = vec![0, 3, 6, 9].into_iter().dropping_back(1); + /// itertools::assert_equal(init, vec![0, 3, 6]); + /// ``` + fn dropping_back(mut self, n: usize) -> Self + where Self: Sized, + Self: DoubleEndedIterator + { + if n > 0 { + (&mut self).rev().nth(n - 1); + } + self + } + + /// Run the closure `f` eagerly on each element of the iterator. + /// + /// Consumes the iterator until its end. + /// + /// ``` + /// use std::sync::mpsc::channel; + /// use itertools::Itertools; + /// + /// let (tx, rx) = channel(); + /// + /// // use .foreach() to apply a function to each value -- sending it + /// (0..5).map(|x| x * 2 + 1).foreach(|x| { tx.send(x).unwrap(); } ); + /// + /// drop(tx); + /// + /// itertools::assert_equal(rx.iter(), vec![1, 3, 5, 7, 9]); + /// ``` + #[deprecated(note="Use .for_each() instead", since="0.8")] + fn foreach<F>(self, f: F) + where F: FnMut(Self::Item), + Self: Sized, + { + self.for_each(f) + } + + /// Combine all an iterator's elements into one element by using `Extend`. + /// + /// This combinator will extend the first item with each of the rest of the + /// items of the iterator. If the iterator is empty, the default value of + /// `I::Item` is returned. + /// + /// ```rust + /// use itertools::Itertools; + /// + /// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]]; + /// assert_eq!(input.into_iter().concat(), + /// vec![1, 2, 3, 4, 5, 6]); + /// ``` + fn concat(self) -> Self::Item + where Self: Sized, + Self::Item: Extend<<<Self as Iterator>::Item as IntoIterator>::Item> + IntoIterator + Default + { + concat(self) + } + + /// `.collect_vec()` is simply a type specialization of `.collect()`, + /// for convenience. + #[cfg(feature = "use_std")] + fn collect_vec(self) -> Vec<Self::Item> + where Self: Sized + { + self.collect() + } + + /// Assign to each reference in `self` from the `from` iterator, + /// stopping at the shortest of the two iterators. + /// + /// The `from` iterator is queried for its next element before the `self` + /// iterator, and if either is exhausted the method is done. + /// + /// Return the number of elements written. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut xs = [0; 4]; + /// xs.iter_mut().set_from(1..); + /// assert_eq!(xs, [1, 2, 3, 4]); + /// ``` + #[inline] + fn set_from<'a, A: 'a, J>(&mut self, from: J) -> usize + where Self: Iterator<Item = &'a mut A>, + J: IntoIterator<Item = A> + { + let mut count = 0; + for elt in from { + match self.next() { + None => break, + Some(ptr) => *ptr = elt, + } + count += 1; + } + count + } + + /// Combine all iterator elements into one String, seperated by `sep`. + /// + /// Use the `Display` implementation of each element. + /// + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!(["a", "b", "c"].iter().join(", "), "a, b, c"); + /// assert_eq!([1, 2, 3].iter().join(", "), "1, 2, 3"); + /// ``` + #[cfg(feature = "use_std")] + fn join(&mut self, sep: &str) -> String + where Self::Item: std::fmt::Display + { + match self.next() { + None => String::new(), + Some(first_elt) => { + // estimate lower bound of capacity needed + let (lower, _) = self.size_hint(); + let mut result = String::with_capacity(sep.len() * lower); + write!(&mut result, "{}", first_elt).unwrap(); + for elt in self { + result.push_str(sep); + write!(&mut result, "{}", elt).unwrap(); + } + result + } + } + } + + /// Format all iterator elements, separated by `sep`. + /// + /// All elements are formatted (any formatting trait) + /// with `sep` inserted between each element. + /// + /// **Panics** if the formatter helper is formatted more than once. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = [1.1, 2.71828, -3.]; + /// assert_eq!( + /// format!("{:.2}", data.iter().format(", ")), + /// "1.10, 2.72, -3.00"); + /// ``` + fn format(self, sep: &str) -> Format<Self> + where Self: Sized, + { + format::new_format_default(self, sep) + } + + /// Format all iterator elements, separated by `sep`. + /// + /// This is a customizable version of `.format()`. + /// + /// The supplied closure `format` is called once per iterator element, + /// with two arguments: the element and a callback that takes a + /// `&Display` value, i.e. any reference to type that implements `Display`. + /// + /// Using `&format_args!(...)` is the most versatile way to apply custom + /// element formatting. The callback can be called multiple times if needed. + /// + /// **Panics** if the formatter helper is formatted more than once. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = [1.1, 2.71828, -3.]; + /// let data_formatter = data.iter().format_with(", ", |elt, f| f(&format_args!("{:.2}", elt))); + /// assert_eq!(format!("{}", data_formatter), + /// "1.10, 2.72, -3.00"); + /// + /// // .format_with() is recursively composable + /// let matrix = [[1., 2., 3.], + /// [4., 5., 6.]]; + /// let matrix_formatter = matrix.iter().format_with("\n", |row, f| { + /// f(&row.iter().format_with(", ", |elt, g| g(&elt))) + /// }); + /// assert_eq!(format!("{}", matrix_formatter), + /// "1, 2, 3\n4, 5, 6"); + /// + /// + /// ``` + fn format_with<F>(self, sep: &str, format: F) -> FormatWith<Self, F> + where Self: Sized, + F: FnMut(Self::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result, + { + format::new_format(self, sep, format) + } + + /// Fold `Result` values from an iterator. + /// + /// Only `Ok` values are folded. If no error is encountered, the folded + /// value is returned inside `Ok`. Otherwise, the operation terminates + /// and returns the first `Err` value it encounters. No iterator elements are + /// consumed after the first error. + /// + /// The first accumulator value is the `start` parameter. + /// Each iteration passes the accumulator value and the next value inside `Ok` + /// to the fold function `f` and its return value becomes the new accumulator value. + /// + /// For example the sequence *Ok(1), Ok(2), Ok(3)* will result in a + /// computation like this: + /// + /// ```ignore + /// let mut accum = start; + /// accum = f(accum, 1); + /// accum = f(accum, 2); + /// accum = f(accum, 3); + /// ``` + /// + /// With a `start` value of 0 and an addition as folding function, + /// this effetively results in *((0 + 1) + 2) + 3* + /// + /// ``` + /// use std::ops::Add; + /// use itertools::Itertools; + /// + /// let values = [1, 2, -2, -1, 2, 1]; + /// assert_eq!( + /// values.iter() + /// .map(Ok::<_, ()>) + /// .fold_results(0, Add::add), + /// Ok(3) + /// ); + /// assert!( + /// values.iter() + /// .map(|&x| if x >= 0 { Ok(x) } else { Err("Negative number") }) + /// .fold_results(0, Add::add) + /// .is_err() + /// ); + /// ``` + fn fold_results<A, E, B, F>(&mut self, mut start: B, mut f: F) -> Result<B, E> + where Self: Iterator<Item = Result<A, E>>, + F: FnMut(B, A) -> B + { + for elt in self { + match elt { + Ok(v) => start = f(start, v), + Err(u) => return Err(u), + } + } + Ok(start) + } + + /// Fold `Option` values from an iterator. + /// + /// Only `Some` values are folded. If no `None` is encountered, the folded + /// value is returned inside `Some`. Otherwise, the operation terminates + /// and returns `None`. No iterator elements are consumed after the `None`. + /// + /// This is the `Option` equivalent to `fold_results`. + /// + /// ``` + /// use std::ops::Add; + /// use itertools::Itertools; + /// + /// let mut values = vec![Some(1), Some(2), Some(-2)].into_iter(); + /// assert_eq!(values.fold_options(5, Add::add), Some(5 + 1 + 2 - 2)); + /// + /// let mut more_values = vec![Some(2), None, Some(0)].into_iter(); + /// assert!(more_values.fold_options(0, Add::add).is_none()); + /// assert_eq!(more_values.next().unwrap(), Some(0)); + /// ``` + fn fold_options<A, B, F>(&mut self, mut start: B, mut f: F) -> Option<B> + where Self: Iterator<Item = Option<A>>, + F: FnMut(B, A) -> B + { + for elt in self { + match elt { + Some(v) => start = f(start, v), + None => return None, + } + } + Some(start) + } + + /// Accumulator of the elements in the iterator. + /// + /// Like `.fold()`, without a base case. If the iterator is + /// empty, return `None`. With just one element, return it. + /// Otherwise elements are accumulated in sequence using the closure `f`. + /// + /// ``` + /// use itertools::Itertools; + /// + /// assert_eq!((0..10).fold1(|x, y| x + y).unwrap_or(0), 45); + /// assert_eq!((0..0).fold1(|x, y| x * y), None); + /// ``` + fn fold1<F>(mut self, f: F) -> Option<Self::Item> + where F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + self.next().map(move |x| self.fold(x, f)) + } + + /// Accumulate the elements in the iterator in a tree-like manner. + /// + /// You can think of it as, while there's more than one item, repeatedly + /// combining adjacent items. It does so in bottom-up-merge-sort order, + /// however, so that it needs only logarithmic stack space. + /// + /// This produces a call tree like the following (where the calls under + /// an item are done after reading that item): + /// + /// ```text + /// 1 2 3 4 5 6 7 + /// │ │ │ │ │ │ │ + /// └─f └─f └─f │ + /// │ │ │ │ + /// └───f └─f + /// │ │ + /// └─────f + /// ``` + /// + /// Which, for non-associative functions, will typically produce a different + /// result than the linear call tree used by `fold1`: + /// + /// ```text + /// 1 2 3 4 5 6 7 + /// │ │ │ │ │ │ │ + /// └─f─f─f─f─f─f + /// ``` + /// + /// If `f` is associative, prefer the normal `fold1` instead. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // The same tree as above + /// let num_strings = (1..8).map(|x| x.to_string()); + /// assert_eq!(num_strings.tree_fold1(|x, y| format!("f({}, {})", x, y)), + /// Some(String::from("f(f(f(1, 2), f(3, 4)), f(f(5, 6), 7))"))); + /// + /// // Like fold1, an empty iterator produces None + /// assert_eq!((0..0).tree_fold1(|x, y| x * y), None); + /// + /// // tree_fold1 matches fold1 for associative operations... + /// assert_eq!((0..10).tree_fold1(|x, y| x + y), + /// (0..10).fold1(|x, y| x + y)); + /// // ...but not for non-associative ones + /// assert!((0..10).tree_fold1(|x, y| x - y) + /// != (0..10).fold1(|x, y| x - y)); + /// ``` + // FIXME: If minver changes to >= 1.13, use `assert_ne!` in the doctest. + fn tree_fold1<F>(mut self, mut f: F) -> Option<Self::Item> + where F: FnMut(Self::Item, Self::Item) -> Self::Item, + Self: Sized, + { + type State<T> = Result<T, Option<T>>; + + fn inner0<T, II, FF>(it: &mut II, f: &mut FF) -> State<T> + where + II: Iterator<Item = T>, + FF: FnMut(T, T) -> T + { + // This function could be replaced with `it.next().ok_or(None)`, + // but half the useful tree_fold1 work is combining adjacent items, + // so put that in a form that LLVM is more likely to optimize well. + + let a = + if let Some(v) = it.next() { v } + else { return Err(None) }; + let b = + if let Some(v) = it.next() { v } + else { return Err(Some(a)) }; + Ok(f(a, b)) + } + + fn inner<T, II, FF>(stop: usize, it: &mut II, f: &mut FF) -> State<T> + where + II: Iterator<Item = T>, + FF: FnMut(T, T) -> T + { + let mut x = try!(inner0(it, f)); + for height in 0..stop { + // Try to get another tree the same size with which to combine it, + // creating a new tree that's twice as big for next time around. + let next = + if height == 0 { + inner0(it, f) + } else { + inner(height, it, f) + }; + match next { + Ok(y) => x = f(x, y), + + // If we ran out of items, combine whatever we did manage + // to get. It's better combined with the current value + // than something in a parent frame, because the tree in + // the parent is always as least as big as this one. + Err(None) => return Err(Some(x)), + Err(Some(y)) => return Err(Some(f(x, y))), + } + } + Ok(x) + } + + match inner(usize::max_value(), &mut self, &mut f) { + Err(x) => x, + _ => unreachable!(), + } + } + + /// An iterator method that applies a function, producing a single, final value. + /// + /// `fold_while()` is basically equivalent to `fold()` but with additional support for + /// early exit via short-circuiting. + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::FoldWhile::{Continue, Done}; + /// + /// let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + /// + /// let mut result = 0; + /// + /// // for loop: + /// for i in &numbers { + /// if *i > 5 { + /// break; + /// } + /// result = result + i; + /// } + /// + /// // fold: + /// let result2 = numbers.iter().fold(0, |acc, x| { + /// if *x > 5 { acc } else { acc + x } + /// }); + /// + /// // fold_while: + /// let result3 = numbers.iter().fold_while(0, |acc, x| { + /// if *x > 5 { Done(acc) } else { Continue(acc + x) } + /// }).into_inner(); + /// + /// // they're the same + /// assert_eq!(result, result2); + /// assert_eq!(result2, result3); + /// ``` + /// + /// The big difference between the computations of `result2` and `result3` is that while + /// `fold()` called the provided closure for every item of the callee iterator, + /// `fold_while()` actually stopped iterating as soon as it encountered `Fold::Done(_)`. + #[deprecated(note="Use .try_fold() instead", since="0.8")] + fn fold_while<B, F>(&mut self, init: B, mut f: F) -> FoldWhile<B> + where Self: Sized, + F: FnMut(B, Self::Item) -> FoldWhile<B> + { + let mut acc = init; + while let Some(item) = self.next() { + match f(acc, item) { + FoldWhile::Continue(res) => acc = res, + res @ FoldWhile::Done(_) => return res, + } + } + FoldWhile::Continue(acc) + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// `slice::sort()` method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort the letters of the text in ascending order + /// let text = "bdacfe"; + /// itertools::assert_equal(text.chars().sorted(), + /// "abcdef".chars()); + /// ``` + #[cfg(feature = "use_std")] + fn sorted(self) -> VecIntoIter<Self::Item> + where Self: Sized, + Self::Item: Ord + { + // Use .sort() directly since it is not quite identical with + // .sort_by(Ord::cmp) + let mut v = Vec::from_iter(self); + v.sort(); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// `slice::sort_by()` method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_by(|a, b| Ord::cmp(&b.1, &a.1)) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_std")] + fn sorted_by<F>(self, cmp: F) -> VecIntoIter<Self::Item> + where Self: Sized, + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + let mut v = Vec::from_iter(self); + v.sort_by(cmp); + v.into_iter() + } + + /// Sort all iterator elements into a new iterator in ascending order. + /// + /// **Note:** This consumes the entire iterator, uses the + /// `slice::sort_by_key()` method and returns the result as a new + /// iterator that owns its elements. + /// + /// The sorted iterator, if directly collected to a `Vec`, is converted + /// without any extra copying or allocation cost. + /// + /// ``` + /// use itertools::Itertools; + /// + /// // sort people in descending order by age + /// let people = vec![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 27)]; + /// + /// let oldest_people_first = people + /// .into_iter() + /// .sorted_by_key(|x| -x.1) + /// .map(|(person, _age)| person); + /// + /// itertools::assert_equal(oldest_people_first, + /// vec!["Jill", "Jack", "Jane", "John"]); + /// ``` + #[cfg(feature = "use_std")] + fn sorted_by_key<K, F>(self, f: F) -> VecIntoIter<Self::Item> + where Self: Sized, + K: Ord, + F: FnMut(&Self::Item) -> K, + { + let mut v = Vec::from_iter(self); + v.sort_by_key(f); + v.into_iter() + } + + /// Collect all iterator elements into one of two + /// partitions. Unlike `Iterator::partition`, each partition may + /// have a distinct type. + /// + /// ``` + /// use itertools::{Itertools, Either}; + /// + /// let successes_and_failures = vec![Ok(1), Err(false), Err(true), Ok(2)]; + /// + /// let (successes, failures): (Vec<_>, Vec<_>) = successes_and_failures + /// .into_iter() + /// .partition_map(|r| { + /// match r { + /// Ok(v) => Either::Left(v), + /// Err(v) => Either::Right(v), + /// } + /// }); + /// + /// assert_eq!(successes, [1, 2]); + /// assert_eq!(failures, [false, true]); + /// ``` + fn partition_map<A, B, F, L, R>(self, predicate: F) -> (A, B) + where Self: Sized, + F: Fn(Self::Item) -> Either<L, R>, + A: Default + Extend<L>, + B: Default + Extend<R>, + { + let mut left = A::default(); + let mut right = B::default(); + + for val in self { + match predicate(val) { + Either::Left(v) => left.extend(Some(v)), + Either::Right(v) => right.extend(Some(v)), + } + } + + (left, right) + } + + /// Return a `HashMap` of keys mapped to `Vec`s of values. Keys and values + /// are taken from `(Key, Value)` tuple pairs yielded by the input iterator. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let data = vec![(0, 10), (2, 12), (3, 13), (0, 20), (3, 33), (2, 42)]; + /// let lookup = data.into_iter().into_group_map(); + /// + /// assert_eq!(lookup[&0], vec![10, 20]); + /// assert_eq!(lookup.get(&1), None); + /// assert_eq!(lookup[&2], vec![12, 42]); + /// assert_eq!(lookup[&3], vec![13, 33]); + /// ``` + #[cfg(feature = "use_std")] + fn into_group_map<K, V>(self) -> HashMap<K, Vec<V>> + where Self: Iterator<Item=(K, V)> + Sized, + K: Hash + Eq, + { + group_map::into_group_map(self) + } + + /// Return the minimum and maximum elements in the iterator. + /// + /// The return type `MinMaxResult` is an enum of three variants: + /// + /// - `NoElements` if the iterator is empty. + /// - `OneElement(x)` if the iterator has exactly one element. + /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two + /// values are equal if and only if there is more than one + /// element in the iterator and all elements are equal. + /// + /// On an iterator of length `n`, `minmax` does `1.5 * n` comparisons, + /// and so is faster than calling `min` and `max` separately which does + /// `2 * n` comparisons. + /// + /// # Examples + /// + /// ``` + /// use itertools::Itertools; + /// use itertools::MinMaxResult::{NoElements, OneElement, MinMax}; + /// + /// let a: [i32; 0] = []; + /// assert_eq!(a.iter().minmax(), NoElements); + /// + /// let a = [1]; + /// assert_eq!(a.iter().minmax(), OneElement(&1)); + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert_eq!(a.iter().minmax(), MinMax(&1, &5)); + /// + /// let a = [1, 1, 1, 1]; + /// assert_eq!(a.iter().minmax(), MinMax(&1, &1)); + /// ``` + /// + /// The elements can be floats but no particular result is guaranteed + /// if an element is NaN. + fn minmax(self) -> MinMaxResult<Self::Item> + where Self: Sized, Self::Item: PartialOrd + { + minmax::minmax_impl(self, |_| (), |x, y, _, _| x < y) + } + + /// Return the minimum and maximum element of an iterator, as determined by + /// the specified function. + /// + /// The return value is a variant of `MinMaxResult` like for `minmax()`. + /// + /// For the minimum, the first minimal element is returned. For the maximum, + /// the last maximal element wins. This matches the behavior of the standard + /// `Iterator::min()` and `Iterator::max()` methods. + /// + /// The keys can be floats but no particular result is guaranteed + /// if a key is NaN. + fn minmax_by_key<K, F>(self, key: F) -> MinMaxResult<Self::Item> + where Self: Sized, K: PartialOrd, F: FnMut(&Self::Item) -> K + { + minmax::minmax_impl(self, key, |_, _, xk, yk| xk < yk) + } + + /// Return the minimum and maximum element of an iterator, as determined by + /// the specified comparison function. + /// + /// The return value is a variant of `MinMaxResult` like for `minmax()`. + /// + /// For the minimum, the first minimal element is returned. For the maximum, + /// the last maximal element wins. This matches the behavior of the standard + /// `Iterator::min()` and `Iterator::max()` methods. + fn minmax_by<F>(self, mut compare: F) -> MinMaxResult<Self::Item> + where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering + { + minmax::minmax_impl( + self, + |_| (), + |x, y, _, _| Ordering::Less == compare(x, y) + ) + } +} + +impl<T: ?Sized> Itertools for T where T: Iterator { } + +/// Return `true` if both iterables produce equal sequences +/// (elements pairwise equal and sequences of the same length), +/// `false` otherwise. +/// +/// This is an `IntoIterator` enabled function that is similar to the standard +/// library method `Iterator::eq`. +/// +/// ``` +/// assert!(itertools::equal(vec![1, 2, 3], 1..4)); +/// assert!(!itertools::equal(&[0, 0], &[0, 0, 0])); +/// ``` +pub fn equal<I, J>(a: I, b: J) -> bool + where I: IntoIterator, + J: IntoIterator, + I::Item: PartialEq<J::Item> +{ + let mut ia = a.into_iter(); + let mut ib = b.into_iter(); + loop { + match ia.next() { + Some(x) => match ib.next() { + Some(y) => if x != y { return false; }, + None => return false, + }, + None => return ib.next().is_none() + } + } +} + +/// Assert that two iterables produce equal sequences, with the same +/// semantics as *equal(a, b)*. +/// +/// **Panics** on assertion failure with a message that shows the +/// two iteration elements. +/// +/// ```ignore +/// assert_equal("exceed".split('c'), "excess".split('c')); +/// // ^PANIC: panicked at 'Failed assertion Some("eed") == Some("ess") for iteration 1', +/// ``` +pub fn assert_equal<I, J>(a: I, b: J) + where I: IntoIterator, + J: IntoIterator, + I::Item: fmt::Debug + PartialEq<J::Item>, + J::Item: fmt::Debug, +{ + let mut ia = a.into_iter(); + let mut ib = b.into_iter(); + let mut i = 0; + loop { + match (ia.next(), ib.next()) { + (None, None) => return, + (a, b) => { + let equal = match (&a, &b) { + (&Some(ref a), &Some(ref b)) => a == b, + _ => false, + }; + assert!(equal, "Failed assertion {a:?} == {b:?} for iteration {i}", + i=i, a=a, b=b); + i += 1; + } + } + } +} + +/// Partition a sequence using predicate `pred` so that elements +/// that map to `true` are placed before elements which map to `false`. +/// +/// The order within the partitions is arbitrary. +/// +/// Return the index of the split point. +/// +/// ``` +/// use itertools::partition; +/// +/// # // use repeated numbers to not promise any ordering +/// let mut data = [7, 1, 1, 7, 1, 1, 7]; +/// let split_index = partition(&mut data, |elt| *elt >= 3); +/// +/// assert_eq!(data, [7, 7, 7, 1, 1, 1, 1]); +/// assert_eq!(split_index, 3); +/// ``` +pub fn partition<'a, A: 'a, I, F>(iter: I, mut pred: F) -> usize + where I: IntoIterator<Item = &'a mut A>, + I::IntoIter: DoubleEndedIterator, + F: FnMut(&A) -> bool +{ + let mut split_index = 0; + let mut iter = iter.into_iter(); + 'main: while let Some(front) = iter.next() { + if !pred(front) { + loop { + match iter.next_back() { + Some(back) => if pred(back) { + std::mem::swap(front, back); + break; + }, + None => break 'main, + } + } + } + split_index += 1; + } + split_index +} + +/// An enum used for controlling the execution of `.fold_while()`. +/// +/// See [`.fold_while()`](trait.Itertools.html#method.fold_while) for more information. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum FoldWhile<T> { + /// Continue folding with this value + Continue(T), + /// Fold is complete and will return this value + Done(T), +} + +impl<T> FoldWhile<T> { + /// Return the value in the continue or done. + pub fn into_inner(self) -> T { + match self { + FoldWhile::Continue(x) | FoldWhile::Done(x) => x, + } + } + + /// Return true if `self` is `Done`, false if it is `Continue`. + pub fn is_done(&self) -> bool { + match *self { + FoldWhile::Continue(_) => false, + FoldWhile::Done(_) => true, + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/merge_join.rs b/third_party/rust/itertools-0.8.0/src/merge_join.rs new file mode 100644 index 0000000000..5f9a0f4013 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/merge_join.rs @@ -0,0 +1,87 @@ +use std::cmp::Ordering; +use std::iter::Fuse; +use std::fmt; + +use super::adaptors::{PutBack, put_back}; +use either_or_both::EitherOrBoth; + +/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order. +/// +/// See [`.merge_join_by()`](trait.Itertools.html#method.merge_join_by) for more information. +pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F) + -> MergeJoinBy<I::IntoIter, J::IntoIter, F> + where I: IntoIterator, + J: IntoIterator, + F: FnMut(&I::Item, &J::Item) -> Ordering +{ + MergeJoinBy { + left: put_back(left.into_iter().fuse()), + right: put_back(right.into_iter().fuse()), + cmp_fn: cmp_fn + } +} + +/// An iterator adaptor that merge-joins items from the two base iterators in ascending order. +/// +/// See [`.merge_join_by()`](../trait.Itertools.html#method.merge_join_by) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct MergeJoinBy<I: Iterator, J: Iterator, F> { + left: PutBack<Fuse<I>>, + right: PutBack<Fuse<J>>, + cmp_fn: F +} + +impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F> + where I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + J: Iterator + fmt::Debug, + J::Item: fmt::Debug, +{ + debug_fmt_fields!(MergeJoinBy, left, right); +} + +impl<I, J, F> Iterator for MergeJoinBy<I, J, F> + where I: Iterator, + J: Iterator, + F: FnMut(&I::Item, &J::Item) -> Ordering +{ + type Item = EitherOrBoth<I::Item, J::Item>; + + fn next(&mut self) -> Option<Self::Item> { + match (self.left.next(), self.right.next()) { + (None, None) => None, + (Some(left), None) => + Some(EitherOrBoth::Left(left)), + (None, Some(right)) => + Some(EitherOrBoth::Right(right)), + (Some(left), Some(right)) => { + match (self.cmp_fn)(&left, &right) { + Ordering::Equal => + Some(EitherOrBoth::Both(left, right)), + Ordering::Less => { + self.right.put_back(right); + Some(EitherOrBoth::Left(left)) + }, + Ordering::Greater => { + self.left.put_back(left); + Some(EitherOrBoth::Right(right)) + } + } + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (a_lower, a_upper) = self.left.size_hint(); + let (b_lower, b_upper) = self.right.size_hint(); + + let lower = ::std::cmp::max(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(x + y), + _ => None, + }; + + (lower, upper) + } +} diff --git a/third_party/rust/itertools-0.8.0/src/minmax.rs b/third_party/rust/itertools-0.8.0/src/minmax.rs new file mode 100644 index 0000000000..38180ef6d0 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/minmax.rs @@ -0,0 +1,114 @@ + +/// `MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for +/// more detail. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum MinMaxResult<T> { + /// Empty iterator + NoElements, + + /// Iterator with one element, so the minimum and maximum are the same + OneElement(T), + + /// More than one element in the iterator, the first element is not larger + /// than the second + MinMax(T, T) +} + +impl<T: Clone> MinMaxResult<T> { + /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` + /// has variant `None` if and only if the `MinMaxResult` has variant + /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. + /// If the `MinMaxResult` has variant `OneElement(x)`, performing this + /// operation will make one clone of `x`. + /// + /// # Examples + /// + /// ``` + /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; + /// + /// let r: MinMaxResult<i32> = NoElements; + /// assert_eq!(r.into_option(), None); + /// + /// let r = OneElement(1); + /// assert_eq!(r.into_option(), Some((1, 1))); + /// + /// let r = MinMax(1, 2); + /// assert_eq!(r.into_option(), Some((1, 2))); + /// ``` + pub fn into_option(self) -> Option<(T,T)> { + match self { + MinMaxResult::NoElements => None, + MinMaxResult::OneElement(x) => Some((x.clone(), x)), + MinMaxResult::MinMax(x, y) => Some((x, y)) + } + } +} + +/// Implementation guts for `minmax` and `minmax_by_key`. +pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, + mut lt: L) -> MinMaxResult<I::Item> + where I: Iterator, + F: FnMut(&I::Item) -> K, + L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, +{ + let (mut min, mut max, mut min_key, mut max_key) = match it.next() { + None => return MinMaxResult::NoElements, + Some(x) => { + match it.next() { + None => return MinMaxResult::OneElement(x), + Some(y) => { + let xk = key_for(&x); + let yk = key_for(&y); + if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)} + } + } + } + }; + + loop { + // `first` and `second` are the two next elements we want to look + // at. We first compare `first` and `second` (#1). The smaller one + // is then compared to current minimum (#2). The larger one is + // compared to current maximum (#3). This way we do 3 comparisons + // for 2 elements. + let first = match it.next() { + None => break, + Some(x) => x + }; + let second = match it.next() { + None => { + let first_key = key_for(&first); + if lt(&first, &min, &first_key, &min_key) { + min = first; + } else if !lt(&first, &max, &first_key, &max_key) { + max = first; + } + break; + } + Some(x) => x + }; + let first_key = key_for(&first); + let second_key = key_for(&second); + if !lt(&second, &first, &second_key, &first_key) { + if lt(&first, &min, &first_key, &min_key) { + min = first; + min_key = first_key; + } + if !lt(&second, &max, &second_key, &max_key) { + max = second; + max_key = second_key; + } + } else { + if lt(&second, &min, &second_key, &min_key) { + min = second; + min_key = second_key; + } + if !lt(&first, &max, &first_key, &max_key) { + max = first; + max_key = first_key; + } + } + } + + MinMaxResult::MinMax(min, max) +} diff --git a/third_party/rust/itertools-0.8.0/src/multipeek_impl.rs b/third_party/rust/itertools-0.8.0/src/multipeek_impl.rs new file mode 100644 index 0000000000..a6a2fb33eb --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/multipeek_impl.rs @@ -0,0 +1,104 @@ + + +use std::iter::Fuse; +use std::collections::VecDeque; +use size_hint; +use PeekingNext; + +/// See [`multipeek()`](../fn.multipeek.html) for more information. +#[derive(Clone, Debug)] +pub struct MultiPeek<I> + where I: Iterator +{ + iter: Fuse<I>, + buf: VecDeque<I::Item>, + index: usize, +} + +/// An iterator adaptor that allows the user to peek at multiple `.next()` +/// values without advancing the base iterator. +pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter> + where I: IntoIterator +{ + MultiPeek { + iter: iterable.into_iter().fuse(), + buf: VecDeque::new(), + index: 0, + } +} + +impl<I> MultiPeek<I> + where I: Iterator +{ + /// Reset the peeking “cursor” + pub fn reset_peek(&mut self) { + self.index = 0; + } +} + +impl<I: Iterator> MultiPeek<I> { + /// Works exactly like `.next()` with the only difference that it doesn't + /// advance itself. `.peek()` can be called multiple times, to peek + /// further ahead. + pub fn peek(&mut self) -> Option<&I::Item> { + let ret = if self.index < self.buf.len() { + Some(&self.buf[self.index]) + } else { + match self.iter.next() { + Some(x) => { + self.buf.push_back(x); + Some(&self.buf[self.index]) + } + None => return None, + } + }; + + self.index += 1; + ret + } +} + +impl<I> PeekingNext for MultiPeek<I> + where I: Iterator, +{ + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + if self.buf.is_empty() { + if let Some(r) = self.peek() { + if !accept(r) { return None } + } + } else { + if let Some(r) = self.buf.get(0) { + if !accept(r) { return None } + } + } + self.next() + } +} + +impl<I> Iterator for MultiPeek<I> + where I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + self.index = 0; + if self.buf.is_empty() { + self.iter.next() + } else { + self.buf.pop_front() + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::add_scalar(self.iter.size_hint(), self.buf.len()) + } +} + +// Same size +impl<I> ExactSizeIterator for MultiPeek<I> + where I: ExactSizeIterator +{} + + diff --git a/third_party/rust/itertools-0.8.0/src/pad_tail.rs b/third_party/rust/itertools-0.8.0/src/pad_tail.rs new file mode 100644 index 0000000000..c9cfe6af30 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/pad_tail.rs @@ -0,0 +1,83 @@ +use std::iter::Fuse; +use size_hint; + +/// An iterator adaptor that pads a sequence to a minimum length by filling +/// missing elements using a closure. +/// +/// Iterator element type is `I::Item`. +/// +/// See [`.pad_using()`](../trait.Itertools.html#method.pad_using) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct PadUsing<I, F> { + iter: Fuse<I>, + min: usize, + pos: usize, + filler: F, +} + +/// Create a new **PadUsing** iterator. +pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F> + where I: Iterator, + F: FnMut(usize) -> I::Item +{ + PadUsing { + iter: iter.fuse(), + min: min, + pos: 0, + filler: filler, + } +} + +impl<I, F> Iterator for PadUsing<I, F> + where I: Iterator, + F: FnMut(usize) -> I::Item +{ + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option<I::Item> { + match self.iter.next() { + None => { + if self.pos < self.min { + let e = Some((self.filler)(self.pos)); + self.pos += 1; + e + } else { + None + } + }, + e => { + self.pos += 1; + e + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let tail = self.min.saturating_sub(self.pos); + size_hint::max(self.iter.size_hint(), (tail, Some(tail))) + } +} + +impl<I, F> DoubleEndedIterator for PadUsing<I, F> + where I: DoubleEndedIterator + ExactSizeIterator, + F: FnMut(usize) -> I::Item +{ + fn next_back(&mut self) -> Option<I::Item> { + if self.min == 0 { + self.iter.next_back() + } else if self.iter.len() >= self.min { + self.min -= 1; + self.iter.next_back() + } else { + self.min -= 1; + Some((self.filler)(self.min)) + } + } +} + +impl<I, F> ExactSizeIterator for PadUsing<I, F> + where I: ExactSizeIterator, + F: FnMut(usize) -> I::Item +{} diff --git a/third_party/rust/itertools-0.8.0/src/peeking_take_while.rs b/third_party/rust/itertools-0.8.0/src/peeking_take_while.rs new file mode 100644 index 0000000000..0b2291dfdd --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/peeking_take_while.rs @@ -0,0 +1,149 @@ + +use std::iter::Peekable; +use PutBack; +#[cfg(feature = "use_std")] +use PutBackN; + +/// An iterator that allows peeking at an element before deciding to accept it. +/// +/// See [`.peeking_take_while()`](trait.Itertools.html#method.peeking_take_while) +/// for more information. +/// +/// This is implemented by peeking adaptors like peekable and put back, +/// but also by a few iterators that can be peeked natively, like the slice’s +/// by reference iterator (`std::slice::Iter`). +pub trait PeekingNext : Iterator { + /// Pass a reference to the next iterator element to the closure `accept`; + /// if `accept` returns true, return it as the next element, + /// else None. + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool; +} + +impl<I> PeekingNext for Peekable<I> + where I: Iterator, +{ + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + if let Some(r) = self.peek() { + if !accept(r) { + return None; + } + } + self.next() + } +} + +impl<I> PeekingNext for PutBack<I> + where I: Iterator, +{ + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + if let Some(r) = self.next() { + if !accept(&r) { + self.put_back(r); + return None; + } + Some(r) + } else { + None + } + } +} + +#[cfg(feature = "use_std")] +impl<I> PeekingNext for PutBackN<I> + where I: Iterator, +{ + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + if let Some(r) = self.next() { + if !accept(&r) { + self.put_back(r); + return None; + } + Some(r) + } else { + None + } + } +} + +/// An iterator adaptor that takes items while a closure returns `true`. +/// +/// See [`.peeking_take_while()`](../trait.Itertools.html#method.peeking_take_while) +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct PeekingTakeWhile<'a, I: 'a, F> + where I: Iterator, +{ + iter: &'a mut I, + f: F, +} + +/// Create a PeekingTakeWhile +pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F> + where I: Iterator, +{ + PeekingTakeWhile { + iter: iter, + f: f, + } +} + +impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F> + where I: PeekingNext, + F: FnMut(&I::Item) -> bool, + +{ + type Item = I::Item; + fn next(&mut self) -> Option<Self::Item> { + self.iter.peeking_next(&mut self.f) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (_, hi) = self.iter.size_hint(); + (0, hi) + } +} + +// Some iterators are so lightweight we can simply clone them to save their +// state and use that for peeking. +macro_rules! peeking_next_by_clone { + ([$($typarm:tt)*] $type_:ty) => { + impl<$($typarm)*> PeekingNext for $type_ { + fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item> + where F: FnOnce(&Self::Item) -> bool + { + let saved_state = self.clone(); + if let Some(r) = self.next() { + if !accept(&r) { + *self = saved_state; + } else { + return Some(r) + } + } + None + } + } + } +} + +peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> } +peeking_next_by_clone! { ['a] ::std::str::Chars<'a> } +peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> } +peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> } +peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> } +peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> } +peeking_next_by_clone! { [T] ::std::iter::Empty<T> } +#[cfg(feature = "use_std")] +peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> } +#[cfg(feature = "use_std")] +peeking_next_by_clone! { ['a, T] ::std::collections::vec_deque::Iter<'a, T> } + +// cloning a Rev has no extra overhead; peekable and put backs are never DEI. +peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator] + ::std::iter::Rev<I> } diff --git a/third_party/rust/itertools-0.8.0/src/process_results_impl.rs b/third_party/rust/itertools-0.8.0/src/process_results_impl.rs new file mode 100644 index 0000000000..f78515d77f --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/process_results_impl.rs @@ -0,0 +1,81 @@ + +/// An iterator that produces only the `T` values as long as the +/// inner iterator produces `Ok(T)`. +/// +/// Used by [`process_results`](../fn.process_results.html), see its docs +/// for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct ProcessResults<'a, I, E: 'a> { + error: &'a mut Result<(), E>, + iter: I, +} + +impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E> + where I: Iterator<Item = Result<T, E>> +{ + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + match self.iter.next() { + Some(Ok(x)) => Some(x), + Some(Err(e)) => { + *self.error = Err(e); + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let (_, hi) = self.iter.size_hint(); + (0, hi) + } +} + +/// “Lift” a function of the values of an iterator so that it can process +/// an iterator of `Result` values instead. +/// +/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where +/// `T` is the value type and `E` the error type. +/// +/// `processor` is a closure that receives an adapted version of the iterable +/// as the only argument — the adapted iterator produces elements of type `T`, +/// as long as the original iterator produces `Ok` values. +/// +/// If the original iterable produces an error at any point, the adapted +/// iterator ends and the `process_results` function will return the +/// error iself. +/// +/// Otherwise, the return value from the closure is returned wrapped +/// inside `Ok`. +/// +/// # Example +/// +/// ``` +/// use itertools::process_results; +/// +/// type R = Result<i32, &'static str>; +/// +/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)]; +/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")]; +/// +/// // “Lift” the iterator .max() method to work on the values in Results using process_results +/// +/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0)); +/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0)); +/// +/// assert_eq!(first_max, Ok(3)); +/// assert!(second_max.is_err()); +/// ``` +pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E> + where I: IntoIterator<Item = Result<T, E>>, + F: FnOnce(ProcessResults<I::IntoIter, E>) -> R +{ + let iter = iterable.into_iter(); + let mut error = Ok(()); + + let result = processor(ProcessResults { error: &mut error, iter: iter }); + + error.map(|_| result) +} diff --git a/third_party/rust/itertools-0.8.0/src/put_back_n_impl.rs b/third_party/rust/itertools-0.8.0/src/put_back_n_impl.rs new file mode 100644 index 0000000000..cc08320714 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/put_back_n_impl.rs @@ -0,0 +1,63 @@ +use size_hint; + +/// An iterator adaptor that allows putting multiple +/// items in front of the iterator. +/// +/// Iterator element type is `I::Item`. +#[derive(Debug, Clone)] +pub struct PutBackN<I: Iterator> { + top: Vec<I::Item>, + iter: I, +} + +/// Create an iterator where you can put back multiple values to the front +/// of the iteration. +/// +/// Iterator element type is `I::Item`. +pub fn put_back_n<I>(iterable: I) -> PutBackN<I::IntoIter> + where I: IntoIterator +{ + PutBackN { + top: Vec::new(), + iter: iterable.into_iter(), + } +} + +impl<I: Iterator> PutBackN<I> { + /// Puts x in front of the iterator. + /// The values are yielded in order of the most recently put back + /// values first. + /// + /// ```rust + /// use itertools::put_back_n; + /// + /// let mut it = put_back_n(1..5); + /// it.next(); + /// it.put_back(1); + /// it.put_back(0); + /// + /// assert!(itertools::equal(it, 0..5)); + /// ``` + #[inline] + pub fn put_back(&mut self, x: I::Item) { + self.top.push(x); + } +} + +impl<I: Iterator> Iterator for PutBackN<I> { + type Item = I::Item; + #[inline] + fn next(&mut self) -> Option<I::Item> { + if self.top.is_empty() { + self.iter.next() + } else { + self.top.pop() + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::add_scalar(self.iter.size_hint(), self.top.len()) + } +} + diff --git a/third_party/rust/itertools-0.8.0/src/rciter_impl.rs b/third_party/rust/itertools-0.8.0/src/rciter_impl.rs new file mode 100644 index 0000000000..1c3b03b5bc --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/rciter_impl.rs @@ -0,0 +1,98 @@ + +use std::iter::IntoIterator; +use std::rc::Rc; +use std::cell::RefCell; + +/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait. +#[derive(Debug)] +pub struct RcIter<I> { + /// The boxed iterator. + pub rciter: Rc<RefCell<I>>, +} + +/// Return an iterator inside a `Rc<RefCell<_>>` wrapper. +/// +/// The returned `RcIter` can be cloned, and each clone will refer back to the +/// same original iterator. +/// +/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with +/// itself, at the cost of runtime borrow checking which may have a performance +/// penalty. +/// +/// Iterator element type is `Self::Item`. +/// +/// ``` +/// use itertools::rciter; +/// use itertools::zip; +/// +/// // In this example a range iterator is created and we iterate it using +/// // three separate handles (two of them given to zip). +/// // We also use the IntoIterator implementation for `&RcIter`. +/// +/// let mut iter = rciter(0..9); +/// let mut z = zip(&iter, &iter); +/// +/// assert_eq!(z.next(), Some((0, 1))); +/// assert_eq!(z.next(), Some((2, 3))); +/// assert_eq!(z.next(), Some((4, 5))); +/// assert_eq!(iter.next(), Some(6)); +/// assert_eq!(z.next(), Some((7, 8))); +/// assert_eq!(z.next(), None); +/// ``` +/// +/// **Panics** in iterator methods if a borrow error is encountered in the +/// iterator methods. It can only happen if the `RcIter` is reentered in +/// `.next()`, i.e. if it somehow participates in an “iterator knot” +/// where it is an adaptor of itself. +pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter> + where I: IntoIterator +{ + RcIter { rciter: Rc::new(RefCell::new(iterable.into_iter())) } +} + +impl<I> Clone for RcIter<I> { + #[inline] + fn clone(&self) -> RcIter<I> { + RcIter { rciter: self.rciter.clone() } + } +} + +impl<A, I> Iterator for RcIter<I> + where I: Iterator<Item = A> +{ + type Item = A; + #[inline] + fn next(&mut self) -> Option<A> { + self.rciter.borrow_mut().next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + // To work sanely with other API that assume they own an iterator, + // so it can't change in other places, we can't guarantee as much + // in our size_hint. Other clones may drain values under our feet. + let (_, hi) = self.rciter.borrow().size_hint(); + (0, hi) + } +} + +impl<I> DoubleEndedIterator for RcIter<I> + where I: DoubleEndedIterator +{ + #[inline] + fn next_back(&mut self) -> Option<I::Item> { + self.rciter.borrow_mut().next_back() + } +} + +/// Return an iterator from `&RcIter<I>` (by simply cloning it). +impl<'a, I> IntoIterator for &'a RcIter<I> + where I: Iterator +{ + type Item = I::Item; + type IntoIter = RcIter<I>; + + fn into_iter(self) -> RcIter<I> { + self.clone() + } +} diff --git a/third_party/rust/itertools-0.8.0/src/repeatn.rs b/third_party/rust/itertools-0.8.0/src/repeatn.rs new file mode 100644 index 0000000000..1c7c310014 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/repeatn.rs @@ -0,0 +1,54 @@ + +/// An iterator that produces *n* repetitions of an element. +/// +/// See [`repeat_n()`](../fn.repeat_n.html) for more information. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct RepeatN<A> { + elt: Option<A>, + n: usize, +} + +/// Create an iterator that produces `n` repetitions of `element`. +pub fn repeat_n<A>(element: A, n: usize) -> RepeatN<A> + where A: Clone, +{ + if n == 0 { + RepeatN { elt: None, n: n, } + } else { + RepeatN { elt: Some(element), n: n, } + } +} + +impl<A> Iterator for RepeatN<A> + where A: Clone +{ + type Item = A; + + fn next(&mut self) -> Option<Self::Item> { + if self.n > 1 { + self.n -= 1; + self.elt.as_ref().cloned() + } else { + self.n = 0; + self.elt.take() + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.n, Some(self.n)) + } +} + +impl<A> DoubleEndedIterator for RepeatN<A> + where A: Clone +{ + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + self.next() + } +} + +impl<A> ExactSizeIterator for RepeatN<A> + where A: Clone +{} diff --git a/third_party/rust/itertools-0.8.0/src/size_hint.rs b/third_party/rust/itertools-0.8.0/src/size_hint.rs new file mode 100644 index 0000000000..be54443f29 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/size_hint.rs @@ -0,0 +1,104 @@ +//! Arithmetic on **Iterator** *.size_hint()* values. +//! + +use std::usize; +use std::cmp; + +/// **SizeHint** is the return type of **Iterator::size_hint()**. +pub type SizeHint = (usize, Option<usize>); + +/// Add **SizeHint** correctly. +#[inline] +pub fn add(a: SizeHint, b: SizeHint) -> SizeHint { + let min = a.0.checked_add(b.0).unwrap_or(usize::MAX); + let max = match (a.1, b.1) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None, + }; + + (min, max) +} + +/// Add **x** correctly to a **SizeHint**. +#[inline] +pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint { + let (mut low, mut hi) = sh; + low = low.saturating_add(x); + hi = hi.and_then(|elt| elt.checked_add(x)); + (low, hi) +} + +/// Sbb **x** correctly to a **SizeHint**. +#[inline] +#[allow(dead_code)] +pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint { + let (mut low, mut hi) = sh; + low = low.saturating_sub(x); + hi = hi.map(|elt| elt.saturating_sub(x)); + (low, hi) +} + + +/// Multiply **SizeHint** correctly +/// +/// ```ignore +/// use std::usize; +/// use itertools::size_hint; +/// +/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))), +/// (9, Some(16))); +/// +/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)), +/// (usize::MAX, None)); +/// +/// assert_eq!(size_hint::mul((3, None), (0, Some(0))), +/// (0, Some(0))); +/// ``` +#[inline] +pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint { + let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX); + let hi = match (a.1, b.1) { + (Some(x), Some(y)) => x.checked_mul(y), + (Some(0), None) | (None, Some(0)) => Some(0), + _ => None, + }; + (low, hi) +} + +/// Multiply **x** correctly with a **SizeHint**. +#[inline] +pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint { + let (mut low, mut hi) = sh; + low = low.saturating_mul(x); + hi = hi.and_then(|elt| elt.checked_mul(x)); + (low, hi) +} + +/// Return the maximum +#[inline] +pub fn max(a: SizeHint, b: SizeHint) -> SizeHint { + let (a_lower, a_upper) = a; + let (b_lower, b_upper) = b; + + let lower = cmp::max(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::max(x, y)), + _ => None, + }; + + (lower, upper) +} + +/// Return the minimum +#[inline] +pub fn min(a: SizeHint, b: SizeHint) -> SizeHint { + let (a_lower, a_upper) = a; + let (b_lower, b_upper) = b; + let lower = cmp::min(a_lower, b_lower); + let upper = match (a_upper, b_upper) { + (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)), + _ => a_upper.or(b_upper), + }; + (lower, upper) +} diff --git a/third_party/rust/itertools-0.8.0/src/sources.rs b/third_party/rust/itertools-0.8.0/src/sources.rs new file mode 100644 index 0000000000..a579f3d9c2 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/sources.rs @@ -0,0 +1,190 @@ +//! Iterators that are sources (produce elements from parameters, +//! not from another iterator). +#![allow(deprecated)] + +use std::fmt; +use std::mem; + +/// See [`repeat_call`](../fn.repeat_call.html) for more information. +#[deprecated(note="Use std repeat_with() instead", since="0.8")] +pub struct RepeatCall<F> { + f: F, +} + +impl<F> fmt::Debug for RepeatCall<F> +{ + debug_fmt_fields!(RepeatCall, ); +} + +/// An iterator source that produces elements indefinitely by calling +/// a given closure. +/// +/// Iterator element type is the return type of the closure. +/// +/// ``` +/// use itertools::repeat_call; +/// use itertools::Itertools; +/// use std::collections::BinaryHeap; +/// +/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]); +/// +/// // extract each element in sorted order +/// for element in repeat_call(|| heap.pop()).while_some() { +/// print!("{}", element); +/// } +/// +/// itertools::assert_equal( +/// repeat_call(|| 1).take(5), +/// vec![1, 1, 1, 1, 1] +/// ); +/// ``` +#[deprecated(note="Use std repeat_with() instead", since="0.8")] +pub fn repeat_call<F, A>(function: F) -> RepeatCall<F> + where F: FnMut() -> A +{ + RepeatCall { f: function } +} + +impl<A, F> Iterator for RepeatCall<F> + where F: FnMut() -> A +{ + type Item = A; + + #[inline] + fn next(&mut self) -> Option<A> { + Some((self.f)()) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (usize::max_value(), None) + } +} + +/// Creates a new unfold source with the specified closure as the "iterator +/// function" and an initial state to eventually pass to the closure +/// +/// `unfold` is a general iterator builder: it has a mutable state value, +/// and a closure with access to the state that produces the next value. +/// +/// This more or less equivalent to a regular struct with an `Iterator` +/// implementation, and is useful for one-off iterators. +/// +/// ``` +/// // an iterator that yields sequential Fibonacci numbers, +/// // and stops at the maximum representable value. +/// +/// use itertools::unfold; +/// +/// let (mut x1, mut x2) = (1u32, 1u32); +/// let mut fibonacci = unfold((), move |_| { +/// // Attempt to get the next Fibonacci number +/// let next = x1.saturating_add(x2); +/// +/// // Shift left: ret <- x1 <- x2 <- next +/// let ret = x1; +/// x1 = x2; +/// x2 = next; +/// +/// // If addition has saturated at the maximum, we are finished +/// if ret == x1 && ret > 1 { +/// return None; +/// } +/// +/// Some(ret) +/// }); +/// +/// itertools::assert_equal(fibonacci.by_ref().take(8), +/// vec![1, 1, 2, 3, 5, 8, 13, 21]); +/// assert_eq!(fibonacci.last(), Some(2_971_215_073)) +/// ``` +pub fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F> + where F: FnMut(&mut St) -> Option<A> +{ + Unfold { + f: f, + state: initial_state, + } +} + +impl<St, F> fmt::Debug for Unfold<St, F> + where St: fmt::Debug, +{ + debug_fmt_fields!(Unfold, state); +} + +/// See [`unfold`](../fn.unfold.html) for more information. +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Unfold<St, F> { + f: F, + /// Internal state that will be passed to the closure on the next iteration + pub state: St, +} + +impl<A, St, F> Iterator for Unfold<St, F> + where F: FnMut(&mut St) -> Option<A> +{ + type Item = A; + + #[inline] + fn next(&mut self) -> Option<A> { + (self.f)(&mut self.state) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + // no possible known bounds at this point + (0, None) + } +} + +/// An iterator that infinitely applies function to value and yields results. +/// +/// This `struct` is created by the [`iterate()`] function. See its documentation for more. +/// +/// [`iterate()`]: ../fn.iterate.html +#[derive(Clone)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct Iterate<St, F> { + state: St, + f: F, +} + +impl<St, F> fmt::Debug for Iterate<St, F> + where St: fmt::Debug, +{ + debug_fmt_fields!(Iterate, state); +} + +impl<St, F> Iterator for Iterate<St, F> + where F: FnMut(&St) -> St +{ + type Item = St; + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + let next_state = (self.f)(&self.state); + Some(mem::replace(&mut self.state, next_state)) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + (usize::max_value(), None) + } +} + +/// Creates a new iterator that infinitely applies function to value and yields results. +/// +/// ``` +/// use itertools::iterate; +/// +/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]); +/// ``` +pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F> + where F: FnMut(&St) -> St +{ + Iterate { + state: initial_value, + f: f, + } +} diff --git a/third_party/rust/itertools-0.8.0/src/tee.rs b/third_party/rust/itertools-0.8.0/src/tee.rs new file mode 100644 index 0000000000..77d261759d --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/tee.rs @@ -0,0 +1,78 @@ +use super::size_hint; + +use std::cell::RefCell; +use std::collections::VecDeque; +use std::rc::Rc; + +/// Common buffer object for the two tee halves +#[derive(Debug)] +struct TeeBuffer<A, I> { + backlog: VecDeque<A>, + iter: I, + /// The owner field indicates which id should read from the backlog + owner: bool, +} + +/// One half of an iterator pair where both return the same elements. +/// +/// See [`.tee()`](../trait.Itertools.html#method.tee) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct Tee<I> + where I: Iterator +{ + rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>, + id: bool, +} + +pub fn new<I>(iter: I) -> (Tee<I>, Tee<I>) + where I: Iterator +{ + let buffer = TeeBuffer{backlog: VecDeque::new(), iter: iter, owner: false}; + let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true}; + let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false}; + (t1, t2) +} + +impl<I> Iterator for Tee<I> + where I: Iterator, + I::Item: Clone +{ + type Item = I::Item; + fn next(&mut self) -> Option<I::Item> { + // .borrow_mut may fail here -- but only if the user has tied some kind of weird + // knot where the iterator refers back to itself. + let mut buffer = self.rcbuffer.borrow_mut(); + if buffer.owner == self.id { + match buffer.backlog.pop_front() { + None => {} + some_elt => return some_elt, + } + } + match buffer.iter.next() { + None => None, + Some(elt) => { + buffer.backlog.push_back(elt.clone()); + buffer.owner = !self.id; + Some(elt) + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let buffer = self.rcbuffer.borrow(); + let sh = buffer.iter.size_hint(); + + if buffer.owner == self.id { + let log_len = buffer.backlog.len(); + size_hint::add_scalar(sh, log_len) + } else { + sh + } + } +} + +impl<I> ExactSizeIterator for Tee<I> + where I: ExactSizeIterator, + I::Item: Clone +{} diff --git a/third_party/rust/itertools-0.8.0/src/tuple_impl.rs b/third_party/rust/itertools-0.8.0/src/tuple_impl.rs new file mode 100644 index 0000000000..0daa7800c1 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/tuple_impl.rs @@ -0,0 +1,266 @@ +//! Some iterator that produces tuples + +use std::iter::Fuse; + +/// An iterator over a incomplete tuple. +/// +/// See [`.tuples()`](../trait.Itertools.html#method.tuples) and +/// [`Tuples::into_buffer()`](struct.Tuples.html#method.into_buffer). +#[derive(Debug)] +pub struct TupleBuffer<T> + where T: TupleCollect +{ + cur: usize, + buf: T::Buffer, +} + +impl<T> TupleBuffer<T> + where T: TupleCollect +{ + fn new(buf: T::Buffer) -> Self { + TupleBuffer { + cur: 0, + buf: buf, + } + } +} + +impl<T> Iterator for TupleBuffer<T> + where T: TupleCollect +{ + type Item = T::Item; + + fn next(&mut self) -> Option<Self::Item> { + let s = self.buf.as_mut(); + if let Some(ref mut item) = s.get_mut(self.cur) { + self.cur += 1; + item.take() + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let buffer = &self.buf.as_ref()[self.cur..]; + let len = if buffer.len() == 0 { + 0 + } else { + buffer.iter() + .position(|x| x.is_none()) + .unwrap_or(buffer.len()) + }; + (len, Some(len)) + } +} + +impl<T> ExactSizeIterator for TupleBuffer<T> + where T: TupleCollect +{ +} + +/// An iterator that groups the items in tuples of a specific size. +/// +/// See [`.tuples()`](../trait.Itertools.html#method.tuples) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Tuples<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect +{ + iter: Fuse<I>, + buf: T::Buffer, +} + +/// Create a new tuples iterator. +pub fn tuples<I, T>(iter: I) -> Tuples<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect +{ + Tuples { + iter: iter.fuse(), + buf: Default::default(), + } +} + +impl<I, T> Iterator for Tuples<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect +{ + type Item = T; + + fn next(&mut self) -> Option<T> { + T::collect_from_iter(&mut self.iter, &mut self.buf) + } +} + +impl<I, T> Tuples<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect +{ + /// Return a buffer with the produced items that was not enough to be grouped in a tuple. + /// + /// ``` + /// use itertools::Itertools; + /// + /// let mut iter = (0..5).tuples(); + /// assert_eq!(Some((0, 1, 2)), iter.next()); + /// assert_eq!(None, iter.next()); + /// itertools::assert_equal(vec![3, 4], iter.into_buffer()); + /// ``` + pub fn into_buffer(self) -> TupleBuffer<T> { + TupleBuffer::new(self.buf) + } +} + + +/// An iterator over all contiguous windows that produces tuples of a specific size. +/// +/// See [`.tuple_windows()`](../trait.Itertools.html#method.tuple_windows) for more +/// information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +#[derive(Debug)] +pub struct TupleWindows<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect +{ + iter: I, + last: Option<T>, +} + +/// Create a new tuple windows iterator. +pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect, + T::Item: Clone +{ + use std::iter::once; + + let mut last = None; + if T::num_items() != 1 { + // put in a duplicate item in front of the tuple; this simplifies + // .next() function. + if let Some(item) = iter.next() { + let iter = once(item.clone()).chain(once(item)).chain(&mut iter); + last = T::collect_from_iter_no_buf(iter); + } + } + + TupleWindows { + last: last, + iter: iter, + } +} + +impl<I, T> Iterator for TupleWindows<I, T> + where I: Iterator<Item = T::Item>, + T: TupleCollect + Clone, + T::Item: Clone +{ + type Item = T; + + fn next(&mut self) -> Option<T> { + if T::num_items() == 1 { + return T::collect_from_iter_no_buf(&mut self.iter) + } + if let Some(ref mut last) = self.last { + if let Some(new) = self.iter.next() { + last.left_shift_push(new); + return Some(last.clone()); + } + } + None + } +} + +pub trait TupleCollect: Sized { + type Item; + type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>; + + fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> + where I: IntoIterator<Item = Self::Item>; + + fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self> + where I: IntoIterator<Item = Self::Item>; + + fn num_items() -> usize; + + fn left_shift_push(&mut self, item: Self::Item); +} + +macro_rules! impl_tuple_collect { + () => (); + ($N:expr; $A:ident ; $($X:ident),* ; $($Y:ident),* ; $($Y_rev:ident),*) => ( + impl<$A> TupleCollect for ($($X),*,) { + type Item = $A; + type Buffer = [Option<$A>; $N - 1]; + + #[allow(unused_assignments, unused_mut)] + fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self> + where I: IntoIterator<Item = $A> + { + let mut iter = iter.into_iter(); + $( + let mut $Y = None; + )* + + loop { + $( + $Y = iter.next(); + if $Y.is_none() { + break + } + )* + return Some(($($Y.unwrap()),*,)) + } + + let mut i = 0; + let mut s = buf.as_mut(); + $( + if i < s.len() { + s[i] = $Y; + i += 1; + } + )* + return None; + } + + #[allow(unused_assignments)] + fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self> + where I: IntoIterator<Item = $A> + { + let mut iter = iter.into_iter(); + loop { + $( + let $Y = if let Some($Y) = iter.next() { + $Y + } else { + break; + }; + )* + return Some(($($Y),*,)) + } + + return None; + } + + fn num_items() -> usize { + $N + } + + fn left_shift_push(&mut self, item: $A) { + use std::mem::replace; + + let &mut ($(ref mut $Y),*,) = self; + let tmp = item; + $( + let tmp = replace($Y_rev, tmp); + )* + drop(tmp); + } + } + ) +} + +impl_tuple_collect!(1; A; A; a; a); +impl_tuple_collect!(2; A; A, A; a, b; b, a); +impl_tuple_collect!(3; A; A, A, A; a, b, c; c, b, a); +impl_tuple_collect!(4; A; A, A, A, A; a, b, c, d; d, c, b, a); diff --git a/third_party/rust/itertools-0.8.0/src/unique_impl.rs b/third_party/rust/itertools-0.8.0/src/unique_impl.rs new file mode 100644 index 0000000000..d9e7fd3dc8 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/unique_impl.rs @@ -0,0 +1,134 @@ + +use std::collections::HashMap; +use std::collections::hash_map::{Entry}; +use std::hash::Hash; +use std::fmt; + +/// An iterator adapter to filter out duplicate elements. +/// +/// See [`.unique_by()`](../trait.Itertools.html#method.unique) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct UniqueBy<I: Iterator, V, F> { + iter: I, + // Use a hashmap for the entry API + used: HashMap<V, ()>, + f: F, +} + +impl<I, V, F> fmt::Debug for UniqueBy<I, V, F> + where I: Iterator + fmt::Debug, + V: fmt::Debug + Hash + Eq, +{ + debug_fmt_fields!(UniqueBy, iter, used); +} + +/// Create a new `UniqueBy` iterator. +pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F> + where V: Eq + Hash, + F: FnMut(&I::Item) -> V, + I: Iterator, +{ + UniqueBy { + iter: iter, + used: HashMap::new(), + f: f, + } +} + +// count the number of new unique keys in iterable (`used` is the set already seen) +fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize + where I: IntoIterator<Item=K>, + K: Hash + Eq, +{ + let iter = iterable.into_iter(); + let current_used = used.len(); + used.extend(iter.map(|key| (key, ()))); + used.len() - current_used +} + +impl<I, V, F> Iterator for UniqueBy<I, V, F> + where I: Iterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + while let Some(v) = self.iter.next() { + let key = (self.f)(&v); + if self.used.insert(key, ()).is_none() { + return Some(v); + } + } + None + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, hi) = self.iter.size_hint(); + ((low > 0 && self.used.is_empty()) as usize, hi) + } + + fn count(self) -> usize { + let mut key_f = self.f; + count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt))) + } +} + +impl<I> Iterator for Unique<I> + where I: Iterator, + I::Item: Eq + Hash + Clone +{ + type Item = I::Item; + + fn next(&mut self) -> Option<I::Item> { + while let Some(v) = self.iter.iter.next() { + if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let elt = entry.key().clone(); + entry.insert(()); + return Some(elt); + } + } + None + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let (low, hi) = self.iter.iter.size_hint(); + ((low > 0 && self.iter.used.is_empty()) as usize, hi) + } + + fn count(self) -> usize { + count_new_keys(self.iter.used, self.iter.iter) + } +} + +/// An iterator adapter to filter out duplicate elements. +/// +/// See [`.unique()`](../trait.Itertools.html#method.unique) for more information. +#[derive(Clone)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Unique<I: Iterator> { + iter: UniqueBy<I, I::Item, ()>, +} + +impl<I> fmt::Debug for Unique<I> + where I: Iterator + fmt::Debug, + I::Item: Hash + Eq + fmt::Debug, +{ + debug_fmt_fields!(Unique, iter); +} + +pub fn unique<I>(iter: I) -> Unique<I> + where I: Iterator, + I::Item: Eq + Hash, +{ + Unique { + iter: UniqueBy { + iter: iter, + used: HashMap::new(), + f: (), + } + } +} diff --git a/third_party/rust/itertools-0.8.0/src/with_position.rs b/third_party/rust/itertools-0.8.0/src/with_position.rs new file mode 100644 index 0000000000..2a7c2b8ad6 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/with_position.rs @@ -0,0 +1,90 @@ +use std::iter::{Fuse,Peekable}; + +/// An iterator adaptor that wraps each element in an [`Position`](../enum.Position.html). +/// +/// Iterator element type is `Position<I::Item>`. +/// +/// See [`.with_position()`](../trait.Itertools.html#method.with_position) for more information. +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct WithPosition<I> + where I: Iterator, +{ + handled_first: bool, + peekable: Peekable<Fuse<I>>, +} + +/// Create a new `WithPosition` iterator. +pub fn with_position<I>(iter: I) -> WithPosition<I> + where I: Iterator, +{ + WithPosition { + handled_first: false, + peekable: iter.fuse().peekable(), + } +} + +/// A value yielded by `WithPosition`. +/// Indicates the position of this element in the iterator results. +/// +/// See [`.with_position()`](trait.Itertools.html#method.with_position) for more information. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum Position<T> { + /// This is the first element. + First(T), + /// This is neither the first nor the last element. + Middle(T), + /// This is the last element. + Last(T), + /// This is the only element. + Only(T), +} + +impl<T> Position<T> { + /// Return the inner value. + pub fn into_inner(self) -> T { + match self { + Position::First(x) | + Position::Middle(x) | + Position::Last(x) | + Position::Only(x) => x, + } + } +} + +impl<I: Iterator> Iterator for WithPosition<I> { + type Item = Position<I::Item>; + + fn next(&mut self) -> Option<Self::Item> { + match self.peekable.next() { + Some(item) => { + if !self.handled_first { + // Haven't seen the first item yet, and there is one to give. + self.handled_first = true; + // Peek to see if this is also the last item, + // in which case tag it as `Only`. + match self.peekable.peek() { + Some(_) => Some(Position::First(item)), + None => Some(Position::Only(item)), + } + } else { + // Have seen the first item, and there's something left. + // Peek to see if this is the last item. + match self.peekable.peek() { + Some(_) => Some(Position::Middle(item)), + None => Some(Position::Last(item)), + } + } + } + // Iterator is finished. + None => None, + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.peekable.size_hint() + } +} + +impl<I> ExactSizeIterator for WithPosition<I> + where I: ExactSizeIterator, +{ } diff --git a/third_party/rust/itertools-0.8.0/src/zip_eq_impl.rs b/third_party/rust/itertools-0.8.0/src/zip_eq_impl.rs new file mode 100644 index 0000000000..857465da41 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/zip_eq_impl.rs @@ -0,0 +1,60 @@ +use super::size_hint; + +/// An iterator which iterates two other iterators simultaneously +/// +/// See [`.zip_eq()`](../trait.Itertools.html#method.zip_eq) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct ZipEq<I, J> { + a: I, + b: J, +} + +/// Iterate `i` and `j` in lock step. +/// +/// **Panics** if the iterators are not of the same length. +/// +/// `IntoIterator` enabled version of `i.zip_eq(j)`. +/// +/// ``` +/// use itertools::zip_eq; +/// +/// let data = [1, 2, 3, 4, 5]; +/// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) { +/// /* loop body */ +/// } +/// ``` +pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter> + where I: IntoIterator, + J: IntoIterator +{ + ZipEq { + a: i.into_iter(), + b: j.into_iter(), + } +} + +impl<I, J> Iterator for ZipEq<I, J> + where I: Iterator, + J: Iterator +{ + type Item = (I::Item, J::Item); + + fn next(&mut self) -> Option<Self::Item> { + match (self.a.next(), self.b.next()) { + (None, None) => None, + (Some(a), Some(b)) => Some((a, b)), + (None, Some(_)) | (Some(_), None) => + panic!("itertools: .zip_eq() reached end of one iterator before the other") + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::min(self.a.size_hint(), self.b.size_hint()) + } +} + +impl<I, J> ExactSizeIterator for ZipEq<I, J> + where I: ExactSizeIterator, + J: ExactSizeIterator +{} diff --git a/third_party/rust/itertools-0.8.0/src/zip_longest.rs b/third_party/rust/itertools-0.8.0/src/zip_longest.rs new file mode 100644 index 0000000000..68a381acee --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/zip_longest.rs @@ -0,0 +1,78 @@ +use std::cmp::Ordering::{Equal, Greater, Less}; +use super::size_hint; +use std::iter::Fuse; + +use either_or_both::EitherOrBoth; + +// ZipLongest originally written by SimonSapin, +// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283 + +/// An iterator which iterates two other iterators simultaneously +/// +/// This iterator is *fused*. +/// +/// See [`.zip_longest()`](../trait.Itertools.html#method.zip_longest) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct ZipLongest<T, U> { + a: Fuse<T>, + b: Fuse<U>, +} + +/// Create a new `ZipLongest` iterator. +pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U> + where T: Iterator, + U: Iterator +{ + ZipLongest { + a: a.fuse(), + b: b.fuse(), + } +} + +impl<T, U> Iterator for ZipLongest<T, U> + where T: Iterator, + U: Iterator +{ + type Item = EitherOrBoth<T::Item, U::Item>; + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + match (self.a.next(), self.b.next()) { + (None, None) => None, + (Some(a), None) => Some(EitherOrBoth::Left(a)), + (None, Some(b)) => Some(EitherOrBoth::Right(b)), + (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + size_hint::max(self.a.size_hint(), self.b.size_hint()) + } +} + +impl<T, U> DoubleEndedIterator for ZipLongest<T, U> + where T: DoubleEndedIterator + ExactSizeIterator, + U: DoubleEndedIterator + ExactSizeIterator +{ + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + match self.a.len().cmp(&self.b.len()) { + Equal => match (self.a.next_back(), self.b.next_back()) { + (None, None) => None, + (Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)), + // These can only happen if .len() is inconsistent with .next_back() + (Some(a), None) => Some(EitherOrBoth::Left(a)), + (None, Some(b)) => Some(EitherOrBoth::Right(b)), + }, + Greater => self.a.next_back().map(EitherOrBoth::Left), + Less => self.b.next_back().map(EitherOrBoth::Right), + } + } +} + +impl<T, U> ExactSizeIterator for ZipLongest<T, U> + where T: ExactSizeIterator, + U: ExactSizeIterator +{} diff --git a/third_party/rust/itertools-0.8.0/src/ziptuple.rs b/third_party/rust/itertools-0.8.0/src/ziptuple.rs new file mode 100644 index 0000000000..2dc3ea5e0b --- /dev/null +++ b/third_party/rust/itertools-0.8.0/src/ziptuple.rs @@ -0,0 +1,111 @@ +use super::size_hint; + +/// See [`multizip`](../fn.multizip.html) for more information. +#[derive(Clone, Debug)] +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct Zip<T> { + t: T, +} + +/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep. +/// +/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that +/// implement `IntoIterator`) and yields elements +/// until any of the subiterators yields `None`. +/// +/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the +/// element types of the subiterator. +/// +/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J, +/// ..)>` of each component iterator `I, J, ...`) if each component iterator is +/// nameable. +/// +/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the +/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed. +/// +/// [`izip!()`]: macro.izip.html +/// +/// ``` +/// use itertools::multizip; +/// +/// // iterate over three sequences side-by-side +/// let mut results = [0, 0, 0, 0]; +/// let inputs = [3, 7, 9, 6]; +/// +/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) { +/// *r = index * 10 + input; +/// } +/// +/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]); +/// ``` +pub fn multizip<T, U>(t: U) -> Zip<T> + where Zip<T>: From<U>, + Zip<T>: Iterator, +{ + Zip::from(t) +} + +macro_rules! impl_zip_iter { + ($($B:ident),*) => ( + #[allow(non_snake_case)] + impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> { + fn from(t: ($($B,)*)) -> Self { + let ($($B,)*) = t; + Zip { t: ($($B.into_iter(),)*) } + } + } + + #[allow(non_snake_case)] + #[allow(unused_assignments)] + impl<$($B),*> Iterator for Zip<($($B,)*)> + where + $( + $B: Iterator, + )* + { + type Item = ($($B::Item,)*); + + fn next(&mut self) -> Option<Self::Item> + { + let ($(ref mut $B,)*) = self.t; + + // NOTE: Just like iter::Zip, we check the iterators + // for None in order. We may finish unevenly (some + // iterators gave n + 1 elements, some only n). + $( + let $B = match $B.next() { + None => return None, + Some(elt) => elt + }; + )* + Some(($($B,)*)) + } + + fn size_hint(&self) -> (usize, Option<usize>) + { + let sh = (::std::usize::MAX, None); + let ($(ref $B,)*) = self.t; + $( + let sh = size_hint::min($B.size_hint(), sh); + )* + sh + } + } + + #[allow(non_snake_case)] + impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where + $( + $B: ExactSizeIterator, + )* + { } + ); +} + +impl_zip_iter!(A); +impl_zip_iter!(A, B); +impl_zip_iter!(A, B, C); +impl_zip_iter!(A, B, C, D); +impl_zip_iter!(A, B, C, D, E); +impl_zip_iter!(A, B, C, D, E, F); +impl_zip_iter!(A, B, C, D, E, F, G); +impl_zip_iter!(A, B, C, D, E, F, G, H); diff --git a/third_party/rust/itertools-0.8.0/tests/merge_join.rs b/third_party/rust/itertools-0.8.0/tests/merge_join.rs new file mode 100644 index 0000000000..41829202b8 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/merge_join.rs @@ -0,0 +1,110 @@ +extern crate itertools; + +use itertools::EitherOrBoth; +use itertools::free::merge_join_by; + +#[test] +fn empty() { + let left: Vec<u32> = vec![]; + let right: Vec<u32> = vec![]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn left_only() { + let left: Vec<u32> = vec![1,2,3]; + let right: Vec<u32> = vec![]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Left(2), + EitherOrBoth::Left(3) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn right_only() { + let left: Vec<u32> = vec![]; + let right: Vec<u32> = vec![1,2,3]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ + EitherOrBoth::Right(1), + EitherOrBoth::Right(2), + EitherOrBoth::Right(3) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn first_left_then_right() { + let left: Vec<u32> = vec![1,2,3]; + let right: Vec<u32> = vec![4,5,6]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Left(2), + EitherOrBoth::Left(3), + EitherOrBoth::Right(4), + EitherOrBoth::Right(5), + EitherOrBoth::Right(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn first_right_then_left() { + let left: Vec<u32> = vec![4,5,6]; + let right: Vec<u32> = vec![1,2,3]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ + EitherOrBoth::Right(1), + EitherOrBoth::Right(2), + EitherOrBoth::Right(3), + EitherOrBoth::Left(4), + EitherOrBoth::Left(5), + EitherOrBoth::Left(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn interspersed_left_and_right() { + let left: Vec<u32> = vec![1,3,5]; + let right: Vec<u32> = vec![2,4,6]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Right(2), + EitherOrBoth::Left(3), + EitherOrBoth::Right(4), + EitherOrBoth::Left(5), + EitherOrBoth::Right(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} + +#[test] +fn overlapping_left_and_right() { + let left: Vec<u32> = vec![1,3,4,6]; + let right: Vec<u32> = vec![2,3,4,5]; + let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![ + EitherOrBoth::Left(1), + EitherOrBoth::Right(2), + EitherOrBoth::Both(3, 3), + EitherOrBoth::Both(4, 4), + EitherOrBoth::Right(5), + EitherOrBoth::Left(6) + ]; + let actual_result = merge_join_by(left, right, |l, r| l.cmp(r)) + .collect::<Vec<_>>(); + assert_eq!(expected_result, actual_result); +} diff --git a/third_party/rust/itertools-0.8.0/tests/peeking_take_while.rs b/third_party/rust/itertools-0.8.0/tests/peeking_take_while.rs new file mode 100644 index 0000000000..45c76c2d5c --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/peeking_take_while.rs @@ -0,0 +1,53 @@ + +extern crate itertools; + +use itertools::Itertools; +use itertools::{put_back, put_back_n}; + +#[test] +fn peeking_take_while_peekable() { + let mut r = (0..10).peekable(); + r.peeking_take_while(|x| *x <= 3).count(); + assert_eq!(r.next(), Some(4)); +} + +#[test] +fn peeking_take_while_put_back() { + let mut r = put_back(0..10); + r.peeking_take_while(|x| *x <= 3).count(); + assert_eq!(r.next(), Some(4)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} + +#[test] +fn peeking_take_while_put_back_n() { + let mut r = put_back_n(6..10); + for elt in (0..6).rev() { + r.put_back(elt); + } + r.peeking_take_while(|x| *x <= 3).count(); + assert_eq!(r.next(), Some(4)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} + +#[test] +fn peeking_take_while_slice_iter() { + let v = [1, 2, 3, 4, 5, 6]; + let mut r = v.iter(); + r.peeking_take_while(|x| **x <= 3).count(); + assert_eq!(r.next(), Some(&4)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} + +#[test] +fn peeking_take_while_slice_iter_rev() { + let v = [1, 2, 3, 4, 5, 6]; + let mut r = v.iter().rev(); + r.peeking_take_while(|x| **x >= 3).count(); + assert_eq!(r.next(), Some(&2)); + r.peeking_take_while(|_| true).count(); + assert_eq!(r.next(), None); +} diff --git a/third_party/rust/itertools-0.8.0/tests/quick.rs b/third_party/rust/itertools-0.8.0/tests/quick.rs new file mode 100644 index 0000000000..e0c61b47de --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/quick.rs @@ -0,0 +1,1017 @@ +//! The purpose of these tests is to cover corner cases of iterators +//! and adaptors. +//! +//! In particular we test the tedious size_hint and exact size correctness. + +#[macro_use] extern crate itertools; + +extern crate quickcheck; +extern crate rand; + +use std::default::Default; + +use quickcheck as qc; +use std::ops::Range; +use std::cmp::Ordering; +use itertools::Itertools; +use itertools::{ + multizip, + EitherOrBoth, +}; +use itertools::free::{ + cloned, + enumerate, + multipeek, + put_back, + put_back_n, + rciter, + zip, + zip_eq, +}; + +use rand::Rng; +use rand::seq::SliceRandom; +use quickcheck::TestResult; + +/// Trait for size hint modifier types +trait HintKind: Copy + Send + qc::Arbitrary { + fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>); +} + +/// Exact size hint variant that leaves hints unchanged +#[derive(Clone, Copy, Debug)] +struct Exact {} + +impl HintKind for Exact { + fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) { + org_hint + } +} + +impl qc::Arbitrary for Exact { + fn arbitrary<G: qc::Gen>(_: &mut G) -> Self { + Exact {} + } +} + +/// Inexact size hint variant to simulate imprecise (but valid) size hints +/// +/// Will always decrease the lower bound and increase the upper bound +/// of the size hint by set amounts. +#[derive(Clone, Copy, Debug)] +struct Inexact { + underestimate: usize, + overestimate: usize, +} + +impl HintKind for Inexact { + fn loosen_bounds(&self, org_hint: (usize, Option<usize>)) -> (usize, Option<usize>) { + let (org_lower, org_upper) = org_hint; + (org_lower.saturating_sub(self.underestimate), + org_upper.and_then(move |x| x.checked_add(self.overestimate))) + } +} + +impl qc::Arbitrary for Inexact { + fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { + let ue_value = usize::arbitrary(g); + let oe_value = usize::arbitrary(g); + // Compensate for quickcheck using extreme values too rarely + let ue_choices = &[0, ue_value, usize::max_value()]; + let oe_choices = &[0, oe_value, usize::max_value()]; + Inexact { + underestimate: *ue_choices.choose(g).unwrap(), + overestimate: *oe_choices.choose(g).unwrap(), + } + } + + fn shrink(&self) -> Box<Iterator<Item=Self>> { + let underestimate_value = self.underestimate; + let overestimate_value = self.overestimate; + Box::new( + underestimate_value.shrink().flat_map(move |ue_value| + overestimate_value.shrink().map(move |oe_value| + Inexact { + underestimate: ue_value, + overestimate: oe_value, + } + ) + ) + ) + } +} + +/// Our base iterator that we can impl Arbitrary for +/// +/// By default we'll return inexact bounds estimates for size_hint +/// to make tests harder to pass. +/// +/// NOTE: Iter is tricky and is not fused, to help catch bugs. +/// At the end it will return None once, then return Some(0), +/// then return None again. +#[derive(Clone, Debug)] +struct Iter<T, SK: HintKind = Inexact> { + iterator: Range<T>, + // fuse/done flag + fuse_flag: i32, + hint_kind: SK, +} + +impl<T, HK> Iter<T, HK> where HK: HintKind +{ + fn new(it: Range<T>, hint_kind: HK) -> Self { + Iter { + iterator: it, + fuse_flag: 0, + hint_kind: hint_kind + } + } +} + +impl<T, HK> Iterator for Iter<T, HK> + where Range<T>: Iterator, + <Range<T> as Iterator>::Item: Default, + HK: HintKind, +{ + type Item = <Range<T> as Iterator>::Item; + + fn next(&mut self) -> Option<Self::Item> + { + let elt = self.iterator.next(); + if elt.is_none() { + self.fuse_flag += 1; + // check fuse flag + if self.fuse_flag == 2 { + return Some(Default::default()) + } + } + elt + } + + fn size_hint(&self) -> (usize, Option<usize>) + { + let org_hint = self.iterator.size_hint(); + self.hint_kind.loosen_bounds(org_hint) + } +} + +impl<T, HK> DoubleEndedIterator for Iter<T, HK> + where Range<T>: DoubleEndedIterator, + <Range<T> as Iterator>::Item: Default, + HK: HintKind +{ + fn next_back(&mut self) -> Option<Self::Item> { self.iterator.next_back() } +} + +impl<T> ExactSizeIterator for Iter<T, Exact> where Range<T>: ExactSizeIterator, + <Range<T> as Iterator>::Item: Default, +{ } + +impl<T, HK> qc::Arbitrary for Iter<T, HK> + where T: qc::Arbitrary, + HK: HintKind, +{ + fn arbitrary<G: qc::Gen>(g: &mut G) -> Self + { + Iter::new(T::arbitrary(g)..T::arbitrary(g), HK::arbitrary(g)) + } + + fn shrink(&self) -> Box<Iterator<Item=Iter<T, HK>>> + { + let r = self.iterator.clone(); + let hint_kind = self.hint_kind; + Box::new( + r.start.shrink().flat_map(move |a| + r.end.shrink().map(move |b| + Iter::new(a.clone()..b, hint_kind) + ) + ) + ) + } +} + +/// A meta-iterator which yields `Iter<i32>`s whose start/endpoints are +/// increased or decreased linearly on each iteration. +#[derive(Clone, Debug)] +struct ShiftRange<HK = Inexact> { + range_start: i32, + range_end: i32, + start_step: i32, + end_step: i32, + iter_count: u32, + hint_kind: HK, +} + +impl<HK> Iterator for ShiftRange<HK> where HK: HintKind { + type Item = Iter<i32, HK>; + + fn next(&mut self) -> Option<Self::Item> { + if self.iter_count == 0 { + return None; + } + + let iter = Iter::new(self.range_start..self.range_end, self.hint_kind); + + self.range_start += self.start_step; + self.range_end += self.end_step; + self.iter_count -= 1; + + Some(iter) + } +} + +impl ExactSizeIterator for ShiftRange<Exact> { } + +impl<HK> qc::Arbitrary for ShiftRange<HK> + where HK: HintKind +{ + fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { + const MAX_STARTING_RANGE_DIFF: i32 = 32; + const MAX_STEP_MODULO: i32 = 8; + const MAX_ITER_COUNT: u32 = 3; + + let range_start = qc::Arbitrary::arbitrary(g); + let range_end = range_start + g.gen_range(0, MAX_STARTING_RANGE_DIFF + 1); + let start_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); + let end_step = g.gen_range(-MAX_STEP_MODULO, MAX_STEP_MODULO + 1); + let iter_count = g.gen_range(0, MAX_ITER_COUNT + 1); + let hint_kind = qc::Arbitrary::arbitrary(g); + + ShiftRange { + range_start: range_start, + range_end: range_end, + start_step: start_step, + end_step: end_step, + iter_count: iter_count, + hint_kind: hint_kind + } + } +} + +fn correct_size_hint<I: Iterator>(mut it: I) -> bool { + // record size hint at each iteration + let initial_hint = it.size_hint(); + let mut hints = Vec::with_capacity(initial_hint.0 + 1); + hints.push(initial_hint); + while let Some(_) = it.next() { + hints.push(it.size_hint()) + } + + let mut true_count = hints.len(); // start off +1 too much + + // check all the size hints + for &(low, hi) in &hints { + true_count -= 1; + if low > true_count || + (hi.is_some() && hi.unwrap() < true_count) + { + println!("True size: {:?}, size hint: {:?}", true_count, (low, hi)); + //println!("All hints: {:?}", hints); + return false + } + } + true +} + +fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool { + // check every iteration + let (mut low, mut hi) = it.size_hint(); + if Some(low) != hi { return false; } + while let Some(_) = it.next() { + let (xlow, xhi) = it.size_hint(); + if low != xlow + 1 { return false; } + low = xlow; + hi = xhi; + if Some(low) != hi { return false; } + } + let (low, hi) = it.size_hint(); + low == 0 && hi == Some(0) +} + +// Exact size for this case, without ExactSizeIterator +fn exact_size_for_this<I: Iterator>(mut it: I) -> bool { + // check every iteration + let (mut low, mut hi) = it.size_hint(); + if Some(low) != hi { return false; } + while let Some(_) = it.next() { + let (xlow, xhi) = it.size_hint(); + if low != xlow + 1 { return false; } + low = xlow; + hi = xhi; + if Some(low) != hi { return false; } + } + let (low, hi) = it.size_hint(); + low == 0 && hi == Some(0) +} + +/* + * NOTE: Range<i8> is broken! + * (all signed ranges are) +#[quickcheck] +fn size_range_i8(a: Iter<i8>) -> bool { + exact_size(a) +} + +#[quickcheck] +fn size_range_i16(a: Iter<i16>) -> bool { + exact_size(a) +} + +#[quickcheck] +fn size_range_u8(a: Iter<u8>) -> bool { + exact_size(a) +} + */ + +macro_rules! quickcheck { + // accept several property function definitions + // The property functions can use pattern matching and `mut` as usual + // in the function arguments, but the functions can not be generic. + {$($(#$attr:tt)* fn $fn_name:ident($($arg:tt)*) -> $ret:ty { $($code:tt)* })*} => ( + $( + #[test] + $(#$attr)* + fn $fn_name() { + fn prop($($arg)*) -> $ret { + $($code)* + } + ::quickcheck::quickcheck(quickcheck!(@fn prop [] $($arg)*)); + } + )* + ); + // parse argument list (with patterns allowed) into prop as fn(_, _) -> _ + (@fn $f:ident [$($t:tt)*]) => { + $f as fn($($t),*) -> _ + }; + (@fn $f:ident [$($p:tt)*] : $($tail:tt)*) => { + quickcheck!(@fn $f [$($p)* _] $($tail)*) + }; + (@fn $f:ident [$($p:tt)*] $t:tt $($tail:tt)*) => { + quickcheck!(@fn $f [$($p)*] $($tail)*) + }; +} + +quickcheck! { + + fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool { + correct_size_hint(a.cartesian_product(b)) + } + fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool { + correct_size_hint(iproduct!(a, b, c)) + } + + fn correct_cartesian_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>, + take_manual: usize) -> () + { + // test correctness of iproduct through regular iteration (take) + // and through fold. + let ac = a.clone(); + let br = &b.clone(); + let cr = &c.clone(); + let answer: Vec<_> = ac.flat_map(move |ea| br.clone().flat_map(move |eb| cr.clone().map(move |ec| (ea, eb, ec)))).collect(); + let mut product_iter = iproduct!(a, b, c); + let mut actual = Vec::new(); + + actual.extend((&mut product_iter).take(take_manual)); + if actual.len() == take_manual { + product_iter.fold((), |(), elt| actual.push(elt)); + } + assert_eq!(answer, actual); + } + + fn size_multi_product(a: ShiftRange) -> bool { + correct_size_hint(a.multi_cartesian_product()) + } + fn correct_multi_product3(a: ShiftRange, take_manual: usize) -> () { + // Fix no. of iterators at 3 + let a = ShiftRange { iter_count: 3, ..a }; + + // test correctness of MultiProduct through regular iteration (take) + // and through fold. + let mut iters = a.clone(); + let i0 = iters.next().unwrap(); + let i1r = &iters.next().unwrap(); + let i2r = &iters.next().unwrap(); + let answer: Vec<_> = i0.flat_map(move |ei0| i1r.clone().flat_map(move |ei1| i2r.clone().map(move |ei2| vec![ei0, ei1, ei2]))).collect(); + let mut multi_product = a.clone().multi_cartesian_product(); + let mut actual = Vec::new(); + + actual.extend((&mut multi_product).take(take_manual)); + if actual.len() == take_manual { + multi_product.fold((), |(), elt| actual.push(elt)); + } + assert_eq!(answer, actual); + + assert_eq!(answer.into_iter().last(), a.clone().multi_cartesian_product().last()); + } + + #[allow(deprecated)] + fn size_step(a: Iter<i16, Exact>, s: usize) -> bool { + let mut s = s; + if s == 0 { + s += 1; // never zero + } + let filt = a.clone().dedup(); + correct_size_hint(filt.step(s)) && + exact_size(a.step(s)) + } + + #[allow(deprecated)] + fn equal_step(a: Iter<i16>, s: usize) -> bool { + let mut s = s; + if s == 0 { + s += 1; // never zero + } + let mut i = 0; + itertools::equal(a.clone().step(s), a.filter(|_| { + let keep = i % s == 0; + i += 1; + keep + })) + } + + #[allow(deprecated)] + fn equal_step_vec(a: Vec<i16>, s: usize) -> bool { + let mut s = s; + if s == 0 { + s += 1; // never zero + } + let mut i = 0; + itertools::equal(a.iter().step(s), a.iter().filter(|_| { + let keep = i % s == 0; + i += 1; + keep + })) + } + + fn size_multipeek(a: Iter<u16, Exact>, s: u8) -> bool { + let mut it = multipeek(a); + // peek a few times + for _ in 0..s { + it.peek(); + } + exact_size(it) + } + + fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool { + let mut sa = a.clone(); + let mut sb = b.clone(); + sa.sort(); + sb.sort(); + let mut merged = sa.clone(); + merged.extend(sb.iter().cloned()); + merged.sort(); + itertools::equal(&merged, sa.iter().merge(&sb)) + } + fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool { + correct_size_hint(a.merge(b)) + } + fn size_zip(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool { + let filt = a.clone().dedup(); + correct_size_hint(multizip((filt, b.clone(), c.clone()))) && + exact_size(multizip((a, b, c))) + } + fn size_zip_rc(a: Iter<i16>, b: Iter<i16>) -> bool { + let rc = rciter(a.clone()); + correct_size_hint(multizip((&rc, &rc, b))) + } + + fn size_zip_macro(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool { + let filt = a.clone().dedup(); + correct_size_hint(izip!(filt, b.clone(), c.clone())) && + exact_size(izip!(a, b, c)) + } + fn equal_kmerge(a: Vec<i16>, b: Vec<i16>, c: Vec<i16>) -> bool { + use itertools::free::kmerge; + let mut sa = a.clone(); + let mut sb = b.clone(); + let mut sc = c.clone(); + sa.sort(); + sb.sort(); + sc.sort(); + let mut merged = sa.clone(); + merged.extend(sb.iter().cloned()); + merged.extend(sc.iter().cloned()); + merged.sort(); + itertools::equal(merged.into_iter(), kmerge(vec![sa, sb, sc])) + } + + // Any number of input iterators + fn equal_kmerge_2(mut inputs: Vec<Vec<i16>>) -> bool { + use itertools::free::kmerge; + // sort the inputs + for input in &mut inputs { + input.sort(); + } + let mut merged = inputs.concat(); + merged.sort(); + itertools::equal(merged.into_iter(), kmerge(inputs)) + } + + // Any number of input iterators + fn equal_kmerge_by_ge(mut inputs: Vec<Vec<i16>>) -> bool { + // sort the inputs + for input in &mut inputs { + input.sort(); + input.reverse(); + } + let mut merged = inputs.concat(); + merged.sort(); + merged.reverse(); + itertools::equal(merged.into_iter(), + inputs.into_iter().kmerge_by(|x, y| x >= y)) + } + + // Any number of input iterators + fn equal_kmerge_by_lt(mut inputs: Vec<Vec<i16>>) -> bool { + // sort the inputs + for input in &mut inputs { + input.sort(); + } + let mut merged = inputs.concat(); + merged.sort(); + itertools::equal(merged.into_iter(), + inputs.into_iter().kmerge_by(|x, y| x < y)) + } + + // Any number of input iterators + fn equal_kmerge_by_le(mut inputs: Vec<Vec<i16>>) -> bool { + // sort the inputs + for input in &mut inputs { + input.sort(); + } + let mut merged = inputs.concat(); + merged.sort(); + itertools::equal(merged.into_iter(), + inputs.into_iter().kmerge_by(|x, y| x <= y)) + } + fn size_kmerge(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool { + use itertools::free::kmerge; + correct_size_hint(kmerge(vec![a, b, c])) + } + fn equal_zip_eq(a: Vec<i32>, b: Vec<i32>) -> bool { + let len = std::cmp::min(a.len(), b.len()); + let a = &a[..len]; + let b = &b[..len]; + itertools::equal(zip_eq(a, b), zip(a, b)) + } + fn size_zip_longest(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool { + let filt = a.clone().dedup(); + let filt2 = b.clone().dedup(); + correct_size_hint(filt.zip_longest(b.clone())) && + correct_size_hint(a.clone().zip_longest(filt2)) && + exact_size(a.zip_longest(b)) + } + fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool { + let it = a.clone().zip_longest(b.clone()); + let jt = a.clone().zip_longest(b.clone()); + itertools::equal(a.clone(), + it.filter_map(|elt| match elt { + EitherOrBoth::Both(x, _) => Some(x), + EitherOrBoth::Left(x) => Some(x), + _ => None, + } + )) + && + itertools::equal(b.clone(), + jt.filter_map(|elt| match elt { + EitherOrBoth::Both(_, y) => Some(y), + EitherOrBoth::Right(y) => Some(y), + _ => None, + } + )) + } + fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool { + correct_size_hint(a.interleave(b)) + } + fn exact_interleave(a: Iter<i16, Exact>, b: Iter<i16, Exact>) -> bool { + exact_size_for_this(a.interleave(b)) + } + fn size_interleave_shortest(a: Iter<i16>, b: Iter<i16>) -> bool { + correct_size_hint(a.interleave_shortest(b)) + } + fn exact_interleave_shortest(a: Vec<()>, b: Vec<()>) -> bool { + exact_size_for_this(a.iter().interleave_shortest(&b)) + } + fn size_intersperse(a: Iter<i16>, x: i16) -> bool { + correct_size_hint(a.intersperse(x)) + } + fn equal_intersperse(a: Vec<i32>, x: i32) -> bool { + let mut inter = false; + let mut i = 0; + for elt in a.iter().cloned().intersperse(x) { + if inter { + if elt != x { return false } + } else { + if elt != a[i] { return false } + i += 1; + } + inter = !inter; + } + true + } + + fn equal_combinations_2(a: Vec<u8>) -> bool { + let mut v = Vec::new(); + for (i, x) in enumerate(&a) { + for y in &a[i + 1..] { + v.push((x, y)); + } + } + itertools::equal(a.iter().tuple_combinations::<(_, _)>(), v) + } + + fn collect_tuple_matches_size(a: Iter<i16>) -> bool { + let size = a.clone().count(); + a.collect_tuple::<(_, _, _)>().is_some() == (size == 3) + } +} + +quickcheck! { + fn equal_dedup(a: Vec<i32>) -> bool { + let mut b = a.clone(); + b.dedup(); + itertools::equal(&b, a.iter().dedup()) + } +} + +quickcheck! { + fn size_dedup(a: Vec<i32>) -> bool { + correct_size_hint(a.iter().dedup()) + } +} + +quickcheck! { + fn exact_repeatn((n, x): (usize, i32)) -> bool { + let it = itertools::repeat_n(x, n); + exact_size(it) + } +} + +quickcheck! { + fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool { + let mut it = put_back(a.into_iter()); + match x { + Some(t) => it.put_back(t), + None => {} + } + correct_size_hint(it) + } +} + +quickcheck! { + fn size_put_backn(a: Vec<u8>, b: Vec<u8>) -> bool { + let mut it = put_back_n(a.into_iter()); + for elt in b { + it.put_back(elt) + } + correct_size_hint(it) + } +} + +quickcheck! { + fn size_tee(a: Vec<u8>) -> bool { + let (mut t1, mut t2) = a.iter().tee(); + t1.next(); + t1.next(); + t2.next(); + exact_size(t1) && exact_size(t2) + } +} + +quickcheck! { + fn size_tee_2(a: Vec<u8>) -> bool { + let (mut t1, mut t2) = a.iter().dedup().tee(); + t1.next(); + t1.next(); + t2.next(); + correct_size_hint(t1) && correct_size_hint(t2) + } +} + +quickcheck! { + fn size_take_while_ref(a: Vec<u8>, stop: u8) -> bool { + correct_size_hint(a.iter().take_while_ref(|x| **x != stop)) + } +} + +quickcheck! { + fn equal_partition(a: Vec<i32>) -> bool { + let mut a = a; + let mut ap = a.clone(); + let split_index = itertools::partition(&mut ap, |x| *x >= 0); + let parted = (0..split_index).all(|i| ap[i] >= 0) && + (split_index..a.len()).all(|i| ap[i] < 0); + + a.sort(); + ap.sort(); + parted && (a == ap) + } +} + +quickcheck! { + fn size_combinations(it: Iter<i16>) -> bool { + correct_size_hint(it.tuple_combinations::<(_, _)>()) + } +} + +quickcheck! { + fn equal_combinations(it: Iter<i16>) -> bool { + let values = it.clone().collect_vec(); + let mut cmb = it.tuple_combinations(); + for i in 0..values.len() { + for j in i+1..values.len() { + let pair = (values[i], values[j]); + if pair != cmb.next().unwrap() { + return false; + } + } + } + cmb.next() == None + } +} + +quickcheck! { + fn size_pad_tail(it: Iter<i8>, pad: u8) -> bool { + correct_size_hint(it.clone().pad_using(pad as usize, |_| 0)) && + correct_size_hint(it.dropping(1).rev().pad_using(pad as usize, |_| 0)) + } +} + +quickcheck! { + fn size_pad_tail2(it: Iter<i8, Exact>, pad: u8) -> bool { + exact_size(it.pad_using(pad as usize, |_| 0)) + } +} + +quickcheck! { + fn size_unique(it: Iter<i8>) -> bool { + correct_size_hint(it.unique()) + } + + fn count_unique(it: Vec<i8>, take_first: u8) -> () { + let answer = { + let mut v = it.clone(); + v.sort(); v.dedup(); + v.len() + }; + let mut iter = cloned(&it).unique(); + let first_count = (&mut iter).take(take_first as usize).count(); + let rest_count = iter.count(); + assert_eq!(answer, first_count + rest_count); + } +} + +quickcheck! { + fn fuzz_group_by_lazy_1(it: Iter<u8>) -> bool { + let jt = it.clone(); + let groups = it.group_by(|k| *k); + let res = itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x)); + res + } +} + +quickcheck! { + fn fuzz_group_by_lazy_2(data: Vec<u8>) -> bool { + let groups = data.iter().group_by(|k| *k / 10); + let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); + res + } +} + +quickcheck! { + fn fuzz_group_by_lazy_3(data: Vec<u8>) -> bool { + let grouper = data.iter().group_by(|k| *k / 10); + let groups = grouper.into_iter().collect_vec(); + let res = itertools::equal(data.iter(), groups.into_iter().flat_map(|(_, x)| x)); + res + } +} + +quickcheck! { + fn fuzz_group_by_lazy_duo(data: Vec<u8>, order: Vec<(bool, bool)>) -> bool { + let grouper = data.iter().group_by(|k| *k / 3); + let mut groups1 = grouper.into_iter(); + let mut groups2 = grouper.into_iter(); + let mut elts = Vec::<&u8>::new(); + let mut old_groups = Vec::new(); + + let tup1 = |(_, b)| b; + for &(ord, consume_now) in &order { + let iter = &mut [&mut groups1, &mut groups2][ord as usize]; + match iter.next() { + Some((_, gr)) => if consume_now { + for og in old_groups.drain(..) { + elts.extend(og); + } + elts.extend(gr); + } else { + old_groups.push(gr); + }, + None => break, + } + } + for og in old_groups.drain(..) { + elts.extend(og); + } + for gr in groups1.map(&tup1) { elts.extend(gr); } + for gr in groups2.map(&tup1) { elts.extend(gr); } + itertools::assert_equal(&data, elts); + true + } +} + +quickcheck! { + fn equal_chunks_lazy(a: Vec<u8>, size: u8) -> bool { + let mut size = size; + if size == 0 { + size += 1; + } + let chunks = a.iter().chunks(size as usize); + let it = a.chunks(size as usize); + for (a, b) in chunks.into_iter().zip(it) { + if !itertools::equal(a, b) { + return false; + } + } + true + } +} + +quickcheck! { + fn equal_tuple_windows_1(a: Vec<u8>) -> bool { + let x = a.windows(1).map(|s| (&s[0], )); + let y = a.iter().tuple_windows::<(_,)>(); + itertools::equal(x, y) + } + + fn equal_tuple_windows_2(a: Vec<u8>) -> bool { + let x = a.windows(2).map(|s| (&s[0], &s[1])); + let y = a.iter().tuple_windows::<(_, _)>(); + itertools::equal(x, y) + } + + fn equal_tuple_windows_3(a: Vec<u8>) -> bool { + let x = a.windows(3).map(|s| (&s[0], &s[1], &s[2])); + let y = a.iter().tuple_windows::<(_, _, _)>(); + itertools::equal(x, y) + } + + fn equal_tuple_windows_4(a: Vec<u8>) -> bool { + let x = a.windows(4).map(|s| (&s[0], &s[1], &s[2], &s[3])); + let y = a.iter().tuple_windows::<(_, _, _, _)>(); + itertools::equal(x, y) + } + + fn equal_tuples_1(a: Vec<u8>) -> bool { + let x = a.chunks(1).map(|s| (&s[0], )); + let y = a.iter().tuples::<(_,)>(); + itertools::equal(x, y) + } + + fn equal_tuples_2(a: Vec<u8>) -> bool { + let x = a.chunks(2).filter(|s| s.len() == 2).map(|s| (&s[0], &s[1])); + let y = a.iter().tuples::<(_, _)>(); + itertools::equal(x, y) + } + + fn equal_tuples_3(a: Vec<u8>) -> bool { + let x = a.chunks(3).filter(|s| s.len() == 3).map(|s| (&s[0], &s[1], &s[2])); + let y = a.iter().tuples::<(_, _, _)>(); + itertools::equal(x, y) + } + + fn equal_tuples_4(a: Vec<u8>) -> bool { + let x = a.chunks(4).filter(|s| s.len() == 4).map(|s| (&s[0], &s[1], &s[2], &s[3])); + let y = a.iter().tuples::<(_, _, _, _)>(); + itertools::equal(x, y) + } + + fn exact_tuple_buffer(a: Vec<u8>) -> bool { + let mut iter = a.iter().tuples::<(_, _, _, _)>(); + (&mut iter).last(); + let buffer = iter.into_buffer(); + assert_eq!(buffer.len(), a.len() % 4); + exact_size(buffer) + } +} + +// with_position +quickcheck! { + fn with_position_exact_size_1(a: Vec<u8>) -> bool { + exact_size_for_this(a.iter().with_position()) + } + fn with_position_exact_size_2(a: Iter<u8, Exact>) -> bool { + exact_size_for_this(a.with_position()) + } +} + +quickcheck! { + fn correct_group_map_modulo_key(a: Vec<u8>, modulo: u8) -> () { + let modulo = if modulo == 0 { 1 } else { modulo }; // Avoid `% 0` + let count = a.len(); + let lookup = a.into_iter().map(|i| (i % modulo, i)).into_group_map(); + + assert_eq!(lookup.values().flat_map(|vals| vals.iter()).count(), count); + + for (&key, vals) in lookup.iter() { + assert!(vals.iter().all(|&val| val % modulo == key)); + } + } +} + +/// A peculiar type: Equality compares both tuple items, but ordering only the +/// first item. This is so we can check the stability property easily. +#[derive(Clone, Debug, PartialEq, Eq)] +struct Val(u32, u32); + +impl PartialOrd<Val> for Val { + fn partial_cmp(&self, other: &Val) -> Option<Ordering> { + self.0.partial_cmp(&other.0) + } +} + +impl Ord for Val { + fn cmp(&self, other: &Val) -> Ordering { + self.0.cmp(&other.0) + } +} + +impl qc::Arbitrary for Val { + fn arbitrary<G: qc::Gen>(g: &mut G) -> Self { + let (x, y) = <(u32, u32)>::arbitrary(g); + Val(x, y) + } + fn shrink(&self) -> Box<Iterator<Item = Self>> { + Box::new((self.0, self.1).shrink().map(|(x, y)| Val(x, y))) + } +} + +quickcheck! { + fn minmax(a: Vec<Val>) -> bool { + use itertools::MinMaxResult; + + + let minmax = a.iter().minmax(); + let expected = match a.len() { + 0 => MinMaxResult::NoElements, + 1 => MinMaxResult::OneElement(&a[0]), + _ => MinMaxResult::MinMax(a.iter().min().unwrap(), + a.iter().max().unwrap()), + }; + minmax == expected + } +} + +quickcheck! { + fn minmax_f64(a: Vec<f64>) -> TestResult { + use itertools::MinMaxResult; + + if a.iter().any(|x| x.is_nan()) { + return TestResult::discard(); + } + + let min = cloned(&a).fold1(f64::min); + let max = cloned(&a).fold1(f64::max); + + let minmax = cloned(&a).minmax(); + let expected = match a.len() { + 0 => MinMaxResult::NoElements, + 1 => MinMaxResult::OneElement(min.unwrap()), + _ => MinMaxResult::MinMax(min.unwrap(), max.unwrap()), + }; + TestResult::from_bool(minmax == expected) + } +} + +quickcheck! { + #[allow(deprecated)] + fn tree_fold1_f64(mut a: Vec<f64>) -> TestResult { + fn collapse_adjacent<F>(x: Vec<f64>, mut f: F) -> Vec<f64> + where F: FnMut(f64, f64) -> f64 + { + let mut out = Vec::new(); + for i in (0..x.len()).step(2) { + if i == x.len()-1 { + out.push(x[i]) + } else { + out.push(f(x[i], x[i+1])); + } + } + out + } + + if a.iter().any(|x| x.is_nan()) { + return TestResult::discard(); + } + + let actual = a.iter().cloned().tree_fold1(f64::atan2); + + while a.len() > 1 { + a = collapse_adjacent(a, f64::atan2); + } + let expected = a.pop(); + + TestResult::from_bool(actual == expected) + } +} diff --git a/third_party/rust/itertools-0.8.0/tests/test_core.rs b/third_party/rust/itertools-0.8.0/tests/test_core.rs new file mode 100644 index 0000000000..cf97abd360 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/test_core.rs @@ -0,0 +1,246 @@ +//! Licensed under the Apache License, Version 2.0 +//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license +//! http://opensource.org/licenses/MIT, at your +//! option. This file may not be copied, modified, or distributed +//! except according to those terms. +#![no_std] + +#[macro_use] extern crate itertools as it; + +use core::iter; + +use it::Itertools; +use it::interleave; +use it::multizip; +use it::free::put_back; + +#[test] +fn product2() { + let s = "αβ"; + + let mut prod = iproduct!(s.chars(), 0..2); + assert!(prod.next() == Some(('α', 0))); + assert!(prod.next() == Some(('α', 1))); + assert!(prod.next() == Some(('β', 0))); + assert!(prod.next() == Some(('β', 1))); + assert!(prod.next() == None); +} + +#[test] +fn product_temporary() { + for (_x, _y, _z) in iproduct!( + [0, 1, 2].iter().cloned(), + [0, 1, 2].iter().cloned(), + [0, 1, 2].iter().cloned()) + { + // ok + } +} + + +#[test] +fn izip_macro() { + let mut zip = izip!(2..3); + assert!(zip.next() == Some(2)); + assert!(zip.next().is_none()); + + let mut zip = izip!(0..3, 0..2, 0..2i8); + for i in 0..2 { + assert!((i as usize, i, i as i8) == zip.next().unwrap()); + } + assert!(zip.next().is_none()); + + let xs: [isize; 0] = []; + let mut zip = izip!(0..3, 0..2, 0..2i8, &xs); + assert!(zip.next().is_none()); +} + +#[test] +fn izip2() { + let _zip1: iter::Zip<_, _> = izip!(1.., 2..); + let _zip2: iter::Zip<_, _> = izip!(1.., 2.., ); +} + +#[test] +fn izip3() { + let mut zip: iter::Map<iter::Zip<_, _>, _> = izip!(0..3, 0..2, 0..2i8); + for i in 0..2 { + assert!((i as usize, i, i as i8) == zip.next().unwrap()); + } + assert!(zip.next().is_none()); +} + +#[test] +fn multizip3() { + let mut zip = multizip((0..3, 0..2, 0..2i8)); + for i in 0..2 { + assert!((i as usize, i, i as i8) == zip.next().unwrap()); + } + assert!(zip.next().is_none()); + + let xs: [isize; 0] = []; + let mut zip = multizip((0..3, 0..2, 0..2i8, xs.iter())); + assert!(zip.next().is_none()); + + for (_, _, _, _, _) in multizip((0..3, 0..2, xs.iter(), &xs, xs.to_vec())) { + /* test compiles */ + } +} + +#[test] +fn write_to() { + let xs = [7, 9, 8]; + let mut ys = [0; 5]; + let cnt = ys.iter_mut().set_from(xs.iter().map(|x| *x)); + assert!(cnt == xs.len()); + assert!(ys == [7, 9, 8, 0, 0]); + + let cnt = ys.iter_mut().set_from(0..10); + assert!(cnt == ys.len()); + assert!(ys == [0, 1, 2, 3, 4]); +} + +#[test] +fn test_interleave() { + let xs: [u8; 0] = []; + let ys = [7u8, 9, 8, 10]; + let zs = [2u8, 77]; + let it = interleave(xs.iter(), ys.iter()); + it::assert_equal(it, ys.iter()); + + let rs = [7u8, 2, 9, 77, 8, 10]; + let it = interleave(ys.iter(), zs.iter()); + it::assert_equal(it, rs.iter()); +} + +#[allow(deprecated)] +#[test] +fn foreach() { + let xs = [1i32, 2, 3]; + let mut sum = 0; + xs.iter().foreach(|elt| sum += *elt); + assert!(sum == 6); +} + +#[test] +fn dropping() { + let xs = [1, 2, 3]; + let mut it = xs.iter().dropping(2); + assert_eq!(it.next(), Some(&3)); + assert!(it.next().is_none()); + let mut it = xs.iter().dropping(5); + assert!(it.next().is_none()); +} + +#[test] +fn batching() { + let xs = [0, 1, 2, 1, 3]; + let ys = [(0, 1), (2, 1)]; + + // An iterator that gathers elements up in pairs + let pit = xs.iter().cloned().batching(|it| { + match it.next() { + None => None, + Some(x) => match it.next() { + None => None, + Some(y) => Some((x, y)), + } + } + }); + it::assert_equal(pit, ys.iter().cloned()); +} + +#[test] +fn test_put_back() { + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let mut pb = put_back(xs.iter().cloned()); + pb.next(); + pb.put_back(1); + pb.put_back(0); + it::assert_equal(pb, xs.iter().cloned()); +} + +#[allow(deprecated)] +#[test] +fn step() { + it::assert_equal((0..10).step(1), 0..10); + it::assert_equal((0..10).step(2), (0..10).filter(|x: &i32| *x % 2 == 0)); + it::assert_equal((0..10).step(10), 0..1); +} + +#[allow(deprecated)] +#[test] +fn merge() { + it::assert_equal((0..10).step(2).merge((1..10).step(2)), 0..10); +} + + +#[test] +fn repeatn() { + let s = "α"; + let mut it = it::repeat_n(s, 3); + assert_eq!(it.len(), 3); + assert_eq!(it.next(), Some(s)); + assert_eq!(it.next(), Some(s)); + assert_eq!(it.next(), Some(s)); + assert_eq!(it.next(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn count_clones() { + // Check that RepeatN only clones N - 1 times. + + use core::cell::Cell; + #[derive(PartialEq, Debug)] + struct Foo { + n: Cell<usize> + } + + impl Clone for Foo + { + fn clone(&self) -> Self + { + let n = self.n.get(); + self.n.set(n + 1); + Foo { n: Cell::new(n + 1) } + } + } + + + for n in 0..10 { + let f = Foo{n: Cell::new(0)}; + let it = it::repeat_n(f, n); + // drain it + let last = it.last(); + if n == 0 { + assert_eq!(last, None); + } else { + assert_eq!(last, Some(Foo{n: Cell::new(n - 1)})); + } + } +} + +#[test] +fn part() { + let mut data = [7, 1, 1, 9, 1, 1, 3]; + let i = it::partition(&mut data, |elt| *elt >= 3); + assert_eq!(i, 3); + assert_eq!(data, [7, 3, 9, 1, 1, 1, 1]); + + let i = it::partition(&mut data, |elt| *elt == 1); + assert_eq!(i, 4); + assert_eq!(data, [1, 1, 1, 1, 9, 3, 7]); + + let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + let i = it::partition(&mut data, |elt| *elt % 3 == 0); + assert_eq!(i, 3); + assert_eq!(data, [9, 6, 3, 4, 5, 2, 7, 8, 1]); +} + +#[test] +fn tree_fold1() { + for i in 0..100 { + assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y)); + } +} diff --git a/third_party/rust/itertools-0.8.0/tests/test_std.rs b/third_party/rust/itertools-0.8.0/tests/test_std.rs new file mode 100644 index 0000000000..b587f44706 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/test_std.rs @@ -0,0 +1,735 @@ + +#[macro_use] extern crate itertools as it; +extern crate permutohedron; + +use it::Itertools; +use it::multizip; +use it::multipeek; +use it::free::rciter; +use it::free::put_back_n; +use it::FoldWhile; +use it::cloned; + +#[test] +fn product3() { + let prod = iproduct!(0..3, 0..2, 0..2); + assert_eq!(prod.size_hint(), (12, Some(12))); + let v = prod.collect_vec(); + for i in 0..3 { + for j in 0..2 { + for k in 0..2 { + assert!((i, j, k) == v[(i * 2 * 2 + j * 2 + k) as usize]); + } + } + } + for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) { + /* test compiles */ + } +} + +#[test] +fn interleave_shortest() { + let v0: Vec<i32> = vec![0, 2, 4]; + let v1: Vec<i32> = vec![1, 3, 5, 7]; + let it = v0.into_iter().interleave_shortest(v1.into_iter()); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]); + + let v0: Vec<i32> = vec![0, 2, 4, 6, 8]; + let v1: Vec<i32> = vec![1, 3, 5]; + let it = v0.into_iter().interleave_shortest(v1.into_iter()); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]); + + let i0 = ::std::iter::repeat(0); + let v1: Vec<_> = vec![1, 3, 5]; + let it = i0.interleave_shortest(v1.into_iter()); + assert_eq!(it.size_hint(), (7, Some(7))); + + let v0: Vec<_> = vec![0, 2, 4]; + let i1 = ::std::iter::repeat(1); + let it = v0.into_iter().interleave_shortest(i1); + assert_eq!(it.size_hint(), (6, Some(6))); +} + + +#[test] +fn unique_by() { + let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; + let ys = ["aaa", "bbbbb", "ccc"]; + it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string())); +} + +#[test] +fn unique() { + let xs = [0, 1, 2, 3, 2, 1, 3]; + let ys = [0, 1, 2, 3]; + it::assert_equal(ys.iter(), xs.iter().unique()); + let xs = [0, 1]; + let ys = [0, 1]; + it::assert_equal(ys.iter(), xs.iter().unique()); +} + +#[test] +fn intersperse() { + let xs = ["a", "", "b", "c"]; + let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect(); + let text: String = v.concat(); + assert_eq!(text, "a, , b, c".to_string()); + + let ys = [0, 1, 2, 3]; + let mut it = ys[..0].iter().map(|x| *x).intersperse(1); + assert!(it.next() == None); +} + +#[test] +fn dedup() { + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let ys = [0, 1, 2, 1, 3]; + it::assert_equal(ys.iter(), xs.iter().dedup()); + let xs = [0, 0, 0, 0, 0]; + let ys = [0]; + it::assert_equal(ys.iter(), xs.iter().dedup()); + + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let ys = [0, 1, 2, 1, 3]; + let mut xs_d = Vec::new(); + xs.iter().dedup().fold((), |(), &elt| xs_d.push(elt)); + assert_eq!(&xs_d, &ys); +} + +#[test] +fn all_equal() { + assert!(!"AABBCCC".chars().all_equal()); + assert!("AAAAAAA".chars().all_equal()); + for (_key, mut sub) in &"AABBCCC".chars().group_by(|&x| x) { + assert!(sub.all_equal()); + } +} + +#[test] +fn test_put_back_n() { + let xs = [0, 1, 1, 1, 2, 1, 3, 3]; + let mut pb = put_back_n(xs.iter().cloned()); + pb.next(); + pb.next(); + pb.put_back(1); + pb.put_back(0); + it::assert_equal(pb, xs.iter().cloned()); +} + +#[test] +fn tee() { + let xs = [0, 1, 2, 3]; + let (mut t1, mut t2) = xs.iter().cloned().tee(); + assert_eq!(t1.next(), Some(0)); + assert_eq!(t2.next(), Some(0)); + assert_eq!(t1.next(), Some(1)); + assert_eq!(t1.next(), Some(2)); + assert_eq!(t1.next(), Some(3)); + assert_eq!(t1.next(), None); + assert_eq!(t2.next(), Some(1)); + assert_eq!(t2.next(), Some(2)); + assert_eq!(t1.next(), None); + assert_eq!(t2.next(), Some(3)); + assert_eq!(t2.next(), None); + assert_eq!(t1.next(), None); + assert_eq!(t2.next(), None); + + let (t1, t2) = xs.iter().cloned().tee(); + it::assert_equal(t1, xs.iter().cloned()); + it::assert_equal(t2, xs.iter().cloned()); + + let (t1, t2) = xs.iter().cloned().tee(); + it::assert_equal(t1.zip(t2), xs.iter().cloned().zip(xs.iter().cloned())); +} + + +#[test] +fn test_rciter() { + let xs = [0, 1, 1, 1, 2, 1, 3, 5, 6]; + + let mut r1 = rciter(xs.iter().cloned()); + let mut r2 = r1.clone(); + assert_eq!(r1.next(), Some(0)); + assert_eq!(r2.next(), Some(1)); + let mut z = r1.zip(r2); + assert_eq!(z.next(), Some((1, 1))); + assert_eq!(z.next(), Some((2, 1))); + assert_eq!(z.next(), Some((3, 5))); + assert_eq!(z.next(), None); + + // test intoiterator + let r1 = rciter(0..5); + let mut z = izip!(&r1, r1); + assert_eq!(z.next(), Some((0, 1))); +} + +#[allow(deprecated)] +#[test] +fn trait_pointers() { + struct ByRef<'r, I: ?Sized>(&'r mut I) where I: 'r; + + impl<'r, X, I: ?Sized> Iterator for ByRef<'r, I> where + I: 'r + Iterator<Item=X> + { + type Item = X; + fn next(&mut self) -> Option<X> + { + self.0.next() + } + } + + let mut it = Box::new(0..10) as Box<Iterator<Item=i32>>; + assert_eq!(it.next(), Some(0)); + + { + /* make sure foreach works on non-Sized */ + let jt: &mut Iterator<Item = i32> = &mut *it; + assert_eq!(jt.next(), Some(1)); + + { + let mut r = ByRef(jt); + assert_eq!(r.next(), Some(2)); + } + + assert_eq!(jt.find_position(|x| *x == 4), Some((1, 4))); + jt.foreach(|_| ()); + } +} + +#[test] +fn merge_by() { + let odd : Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")]; + let even = vec![(2, "foo"), (4, "bar"), (6, "baz")]; + let expected = vec![(1, "hello"), (2, "foo"), (3, "world"), (4, "bar"), (5, "!"), (6, "baz")]; + let results = odd.iter().merge_by(even.iter(), |a, b| a.0 <= b.0); + it::assert_equal(results, expected.iter()); +} + +#[test] +fn merge_by_btree() { + use std::collections::BTreeMap; + let mut bt1 = BTreeMap::new(); + bt1.insert("hello", 1); + bt1.insert("world", 3); + let mut bt2 = BTreeMap::new(); + bt2.insert("foo", 2); + bt2.insert("bar", 4); + let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0 ); + let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)]; + it::assert_equal(results, expected.into_iter()); +} + +#[allow(deprecated)] +#[test] +fn kmerge() { + let its = (0..4).map(|s| (s..10).step(4)); + + it::assert_equal(its.kmerge(), 0..10); +} + +#[allow(deprecated)] +#[test] +fn kmerge_2() { + let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step(4)); + + it::assert_equal(its.kmerge(), 0..10); +} + +#[test] +fn kmerge_empty() { + let its = (0..4).map(|_| 0..0); + assert_eq!(its.kmerge().next(), None); +} + +#[test] +fn kmerge_size_hint() { + let its = (0..5).map(|_| (0..10)); + assert_eq!(its.kmerge().size_hint(), (50, Some(50))); +} + +#[test] +fn kmerge_empty_size_hint() { + let its = (0..5).map(|_| (0..0)); + assert_eq!(its.kmerge().size_hint(), (0, Some(0))); +} + +#[test] +fn join() { + let many = [1, 2, 3]; + let one = [1]; + let none: Vec<i32> = vec![]; + + assert_eq!(many.iter().join(", "), "1, 2, 3"); + assert_eq!( one.iter().join(", "), "1"); + assert_eq!(none.iter().join(", "), ""); +} + +#[test] +fn sorted_by() { + let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| { + a.cmp(&b) + }); + it::assert_equal(sc, vec![1, 2, 3, 4]); + + let v = (0..5).sorted_by(|&a, &b| a.cmp(&b).reverse()); + it::assert_equal(v, vec![4, 3, 2, 1, 0]); +} + +#[test] +fn sorted_by_key() { + let sc = [3, 4, 1, 2].iter().cloned().sorted_by_key(|&x| x); + it::assert_equal(sc, vec![1, 2, 3, 4]); + + let v = (0..5).sorted_by_key(|&x| -x); + it::assert_equal(v, vec![4, 3, 2, 1, 0]); +} + +#[test] +fn test_multipeek() { + let nums = vec![1u8,2,3,4,5]; + + let mp = multipeek(nums.iter().map(|&x| x)); + assert_eq!(nums, mp.collect::<Vec<_>>()); + + let mut mp = multipeek(nums.iter().map(|&x| x)); + assert_eq!(mp.peek(), Some(&1)); + assert_eq!(mp.next(), Some(1)); + assert_eq!(mp.peek(), Some(&2)); + assert_eq!(mp.peek(), Some(&3)); + assert_eq!(mp.next(), Some(2)); + assert_eq!(mp.peek(), Some(&3)); + assert_eq!(mp.peek(), Some(&4)); + assert_eq!(mp.peek(), Some(&5)); + assert_eq!(mp.peek(), None); + assert_eq!(mp.next(), Some(3)); + assert_eq!(mp.next(), Some(4)); + assert_eq!(mp.peek(), Some(&5)); + assert_eq!(mp.peek(), None); + assert_eq!(mp.next(), Some(5)); + assert_eq!(mp.next(), None); + assert_eq!(mp.peek(), None); + +} + +#[test] +fn test_multipeek_reset() { + let data = [1, 2, 3, 4]; + + let mut mp = multipeek(cloned(&data)); + assert_eq!(mp.peek(), Some(&1)); + assert_eq!(mp.next(), Some(1)); + assert_eq!(mp.peek(), Some(&2)); + assert_eq!(mp.peek(), Some(&3)); + mp.reset_peek(); + assert_eq!(mp.peek(), Some(&2)); + assert_eq!(mp.next(), Some(2)); +} + +#[test] +fn test_multipeek_peeking_next() { + use it::PeekingNext; + let nums = vec![1u8,2,3,4,5,6,7]; + + let mut mp = multipeek(nums.iter().map(|&x| x)); + assert_eq!(mp.peeking_next(|&x| x != 0), Some(1)); + assert_eq!(mp.next(), Some(2)); + assert_eq!(mp.peek(), Some(&3)); + assert_eq!(mp.peek(), Some(&4)); + assert_eq!(mp.peeking_next(|&x| x == 3), Some(3)); + assert_eq!(mp.peek(), Some(&4)); + assert_eq!(mp.peeking_next(|&x| x != 4), None); + assert_eq!(mp.peeking_next(|&x| x == 4), Some(4)); + assert_eq!(mp.peek(), Some(&5)); + assert_eq!(mp.peek(), Some(&6)); + assert_eq!(mp.peeking_next(|&x| x != 5), None); + assert_eq!(mp.peek(), Some(&7)); + assert_eq!(mp.peeking_next(|&x| x == 5), Some(5)); + assert_eq!(mp.peeking_next(|&x| x == 6), Some(6)); + assert_eq!(mp.peek(), Some(&7)); + assert_eq!(mp.peek(), None); + assert_eq!(mp.next(), Some(7)); + assert_eq!(mp.peek(), None); +} + +#[test] +fn pad_using() { + it::assert_equal((0..0).pad_using(1, |_| 1), 1..2); + + let v: Vec<usize> = vec![0, 1, 2]; + let r = v.into_iter().pad_using(5, |n| n); + it::assert_equal(r, vec![0, 1, 2, 3, 4]); + + let v: Vec<usize> = vec![0, 1, 2]; + let r = v.into_iter().pad_using(1, |_| panic!()); + it::assert_equal(r, vec![0, 1, 2]); +} + +#[test] +fn group_by() { + for (ch1, sub) in &"AABBCCC".chars().group_by(|&x| x) { + for ch2 in sub { + assert_eq!(ch1, ch2); + } + } + + for (ch1, sub) in &"AAABBBCCCCDDDD".chars().group_by(|&x| x) { + for ch2 in sub { + assert_eq!(ch1, ch2); + if ch1 == 'C' { + break; + } + } + } + + let toupper = |ch: &char| ch.to_uppercase().nth(0).unwrap(); + + // try all possible orderings + for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) { + let groups = "AaaBbbccCcDDDD".chars().group_by(&toupper); + let mut subs = groups.into_iter().collect_vec(); + + for &idx in &indices[..] { + let (key, text) = match idx { + 0 => ('A', "Aaa".chars()), + 1 => ('B', "Bbb".chars()), + 2 => ('C', "ccCc".chars()), + 3 => ('D', "DDDD".chars()), + _ => unreachable!(), + }; + assert_eq!(key, subs[idx].0); + it::assert_equal(&mut subs[idx].1, text); + } + } + + let groups = "AAABBBCCCCDDDD".chars().group_by(|&x| x); + let mut subs = groups.into_iter().map(|(_, g)| g).collect_vec(); + + let sd = subs.pop().unwrap(); + let sc = subs.pop().unwrap(); + let sb = subs.pop().unwrap(); + let sa = subs.pop().unwrap(); + for (a, b, c, d) in multizip((sa, sb, sc, sd)) { + assert_eq!(a, 'A'); + assert_eq!(b, 'B'); + assert_eq!(c, 'C'); + assert_eq!(d, 'D'); + } + + // check that the key closure is called exactly n times + { + let mut ntimes = 0; + let text = "AABCCC"; + for (_, sub) in &text.chars().group_by(|&x| { ntimes += 1; x}) { + for _ in sub { + } + } + assert_eq!(ntimes, text.len()); + } + + { + let mut ntimes = 0; + let text = "AABCCC"; + for _ in &text.chars().group_by(|&x| { ntimes += 1; x}) { + } + assert_eq!(ntimes, text.len()); + } + + { + let text = "ABCCCDEEFGHIJJKK"; + let gr = text.chars().group_by(|&x| x); + it::assert_equal(gr.into_iter().flat_map(|(_, sub)| sub), text.chars()); + } +} + +#[test] +fn group_by_lazy_2() { + let data = vec![0, 1]; + let groups = data.iter().group_by(|k| *k); + let gs = groups.into_iter().collect_vec(); + it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g)); + + let data = vec![0, 1, 1, 0, 0]; + let groups = data.iter().group_by(|k| *k); + let mut gs = groups.into_iter().collect_vec(); + gs[1..].reverse(); + it::assert_equal(&[0, 0, 0, 1, 1], gs.into_iter().flat_map(|(_, g)| g)); + + let grouper = data.iter().group_by(|k| *k); + let mut groups = Vec::new(); + for (k, group) in &grouper { + if *k == 1 { + groups.push(group); + } + } + it::assert_equal(&mut groups[0], &[1, 1]); + + let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let grouper = data.iter().group_by(|k| *k); + let mut groups = Vec::new(); + for (i, (_, group)) in grouper.into_iter().enumerate() { + if i < 2 { + groups.push(group); + } else if i < 4 { + for _ in group { + } + } else { + groups.push(group); + } + } + it::assert_equal(&mut groups[0], &[0, 0, 0]); + it::assert_equal(&mut groups[1], &[1, 1]); + it::assert_equal(&mut groups[2], &[3, 3]); + + // use groups as chunks + let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let mut i = 0; + let grouper = data.iter().group_by(move |_| { let k = i / 3; i += 1; k }); + for (i, group) in &grouper { + match i { + 0 => it::assert_equal(group, &[0, 0, 0]), + 1 => it::assert_equal(group, &[1, 1, 0]), + 2 => it::assert_equal(group, &[0, 2, 2]), + 3 => it::assert_equal(group, &[3, 3]), + _ => unreachable!(), + } + } +} + +#[test] +fn group_by_lazy_3() { + // test consuming each group on the lap after it was produced + let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2]; + let grouper = data.iter().group_by(|elt| *elt); + let mut last = None; + for (key, group) in &grouper { + if let Some(gr) = last.take() { + for elt in gr { + assert!(elt != key && i32::abs(elt - key) == 1); + } + } + last = Some(group); + } +} + +#[test] +fn chunks() { + let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3]; + let grouper = data.iter().chunks(3); + for (i, chunk) in grouper.into_iter().enumerate() { + match i { + 0 => it::assert_equal(chunk, &[0, 0, 0]), + 1 => it::assert_equal(chunk, &[1, 1, 0]), + 2 => it::assert_equal(chunk, &[0, 2, 2]), + 3 => it::assert_equal(chunk, &[3, 3]), + _ => unreachable!(), + } + } +} + +#[test] +fn concat_empty() { + let data: Vec<Vec<()>> = Vec::new(); + assert_eq!(data.into_iter().concat(), Vec::new()) +} + +#[test] +fn concat_non_empty() { + let data = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]]; + assert_eq!(data.into_iter().concat(), vec![1,2,3,4,5,6,7,8,9]) +} + +#[test] +fn combinations() { + assert!((1..3).combinations(5).next().is_none()); + + let it = (1..3).combinations(2); + it::assert_equal(it, vec![ + vec![1, 2], + ]); + + let it = (1..5).combinations(2); + it::assert_equal(it, vec![ + vec![1, 2], + vec![1, 3], + vec![1, 4], + vec![2, 3], + vec![2, 4], + vec![3, 4], + ]); + + it::assert_equal((0..0).tuple_combinations::<(_, _)>(), <Vec<_>>::new()); + it::assert_equal((0..1).tuple_combinations::<(_, _)>(), <Vec<_>>::new()); + it::assert_equal((0..2).tuple_combinations::<(_, _)>(), vec![(0, 1)]); + + it::assert_equal((0..0).combinations(2), <Vec<Vec<_>>>::new()); + it::assert_equal((0..1).combinations(1), vec![vec![0]]); + it::assert_equal((0..2).combinations(1), vec![vec![0], vec![1]]); + it::assert_equal((0..2).combinations(2), vec![vec![0, 1]]); +} + +#[test] +fn combinations_of_too_short() { + for i in 1..10 { + assert!((0..0).combinations(i).next().is_none()); + assert!((0..i - 1).combinations(i).next().is_none()); + } +} + + +#[test] +fn combinations_zero() { + it::assert_equal((1..3).combinations(0), vec![vec![]]); +} + +#[test] +fn diff_mismatch() { + let a = vec![1, 2, 3, 4]; + let b = vec![1.0, 5.0, 3.0, 4.0]; + let b_map = b.into_iter().map(|f| f as i32); + let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); + + assert!(match diff { + Some(it::Diff::FirstMismatch(1, _, from_diff)) => + from_diff.collect::<Vec<_>>() == vec![5, 3, 4], + _ => false, + }); +} + +#[test] +fn diff_longer() { + let a = vec![1, 2, 3, 4]; + let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; + let b_map = b.into_iter().map(|f| f as i32); + let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); + + assert!(match diff { + Some(it::Diff::Longer(_, remaining)) => + remaining.collect::<Vec<_>>() == vec![5, 6], + _ => false, + }); +} + +#[test] +fn diff_shorter() { + let a = vec![1, 2, 3, 4]; + let b = vec![1.0, 2.0]; + let b_map = b.into_iter().map(|f| f as i32); + let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b); + + assert!(match diff { + Some(it::Diff::Shorter(len, _)) => len == 2, + _ => false, + }); +} + +#[test] +fn minmax() { + use std::cmp::Ordering; + use it::MinMaxResult; + + // A peculiar type: Equality compares both tuple items, but ordering only the + // first item. This is so we can check the stability property easily. + #[derive(Clone, Debug, PartialEq, Eq)] + struct Val(u32, u32); + + impl PartialOrd<Val> for Val { + fn partial_cmp(&self, other: &Val) -> Option<Ordering> { + self.0.partial_cmp(&other.0) + } + } + + impl Ord for Val { + fn cmp(&self, other: &Val) -> Ordering { + self.0.cmp(&other.0) + } + } + + assert_eq!(None::<Option<u32>>.iter().minmax(), MinMaxResult::NoElements); + + assert_eq!(Some(1u32).iter().minmax(), MinMaxResult::OneElement(&1)); + + let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)]; + + let minmax = data.iter().minmax(); + assert_eq!(minmax, MinMaxResult::MinMax(&Val(0, 1), &Val(2, 1))); + + let (min, max) = data.iter().minmax_by_key(|v| v.1).into_option().unwrap(); + assert_eq!(min, &Val(2, 0)); + assert_eq!(max, &Val(0, 2)); + + let (min, max) = data.iter().minmax_by(|x, y| x.1.cmp(&y.1)).into_option().unwrap(); + assert_eq!(min, &Val(2, 0)); + assert_eq!(max, &Val(0, 2)); +} + +#[test] +fn format() { + let data = [0, 1, 2, 3]; + let ans1 = "0, 1, 2, 3"; + let ans2 = "0--1--2--3"; + + let t1 = format!("{}", data.iter().format(", ")); + assert_eq!(t1, ans1); + let t2 = format!("{:?}", data.iter().format("--")); + assert_eq!(t2, ans2); + + let dataf = [1.1, 2.71828, -22.]; + let t3 = format!("{:.2e}", dataf.iter().format(", ")); + assert_eq!(t3, "1.10e0, 2.72e0, -2.20e1"); +} + +#[test] +fn while_some() { + let ns = (1..10).map(|x| if x % 5 != 0 { Some(x) } else { None }) + .while_some(); + it::assert_equal(ns, vec![1, 2, 3, 4]); +} + +#[allow(deprecated)] +#[test] +fn fold_while() { + let mut iterations = 0; + let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let sum = vec.into_iter().fold_while(0, |acc, item| { + iterations += 1; + let new_sum = acc.clone() + item; + if new_sum <= 20 { + FoldWhile::Continue(new_sum) + } else { + FoldWhile::Done(acc) + } + }).into_inner(); + assert_eq!(iterations, 6); + assert_eq!(sum, 15); +} + +#[test] +fn tree_fold1() { + let x = [ + "", + "0", + "0 1 x", + "0 1 x 2 x", + "0 1 x 2 3 x x", + "0 1 x 2 3 x x 4 x", + "0 1 x 2 3 x x 4 5 x x", + "0 1 x 2 3 x x 4 5 x 6 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 x x x", + "0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x", + ]; + for (i, &s) in x.iter().enumerate() { + let expected = if s == "" { None } else { Some(s.to_string()) }; + let num_strings = (0..i).map(|x| x.to_string()); + let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b)); + assert_eq!(actual, expected); + } +} diff --git a/third_party/rust/itertools-0.8.0/tests/tuples.rs b/third_party/rust/itertools-0.8.0/tests/tuples.rs new file mode 100644 index 0000000000..07dba57fe6 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/tuples.rs @@ -0,0 +1,88 @@ +extern crate itertools; + +use itertools::Itertools; + +#[test] +fn tuples() { + let v = [1, 2, 3, 4, 5]; + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1,)), iter.next()); + assert_eq!(Some((2,)), iter.next()); + assert_eq!(Some((3,)), iter.next()); + assert_eq!(Some((4,)), iter.next()); + assert_eq!(Some((5,)), iter.next()); + assert_eq!(None, iter.next()); + assert_eq!(None, iter.into_buffer().next()); + + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1, 2)), iter.next()); + assert_eq!(Some((3, 4)), iter.next()); + assert_eq!(None, iter.next()); + itertools::assert_equal(vec![5], iter.into_buffer()); + + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1, 2, 3)), iter.next()); + assert_eq!(None, iter.next()); + itertools::assert_equal(vec![4, 5], iter.into_buffer()); + + let mut iter = v.iter().cloned().tuples(); + assert_eq!(Some((1, 2, 3, 4)), iter.next()); + assert_eq!(None, iter.next()); + itertools::assert_equal(vec![5], iter.into_buffer()); +} + +#[test] +fn tuple_windows() { + let v = [1, 2, 3, 4, 5]; + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1,)), iter.next()); + assert_eq!(Some((2,)), iter.next()); + assert_eq!(Some((3,)), iter.next()); + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1, 2)), iter.next()); + assert_eq!(Some((2, 3)), iter.next()); + assert_eq!(Some((3, 4)), iter.next()); + assert_eq!(Some((4, 5)), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1, 2, 3)), iter.next()); + assert_eq!(Some((2, 3, 4)), iter.next()); + assert_eq!(Some((3, 4, 5)), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = v.iter().cloned().tuple_windows(); + assert_eq!(Some((1, 2, 3, 4)), iter.next()); + assert_eq!(Some((2, 3, 4, 5)), iter.next()); + assert_eq!(None, iter.next()); + + let v = [1, 2, 3]; + let mut iter = v.iter().cloned().tuple_windows::<(_, _, _, _)>(); + assert_eq!(None, iter.next()); +} + +#[test] +fn next_tuple() { + let v = [1, 2, 3, 4, 5]; + let mut iter = v.iter(); + assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((1, 2))); + assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((3, 4))); + assert_eq!(iter.next_tuple::<(_, _)>(), None); +} + +#[test] +fn collect_tuple() { + let v = [1, 2]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_tuple(), Some((1, 2))); + + let v = [1]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_tuple::<(_, _)>(), None); + + let v = [1, 2, 3]; + let iter = v.iter().cloned(); + assert_eq!(iter.collect_tuple::<(_, _)>(), None); +} diff --git a/third_party/rust/itertools-0.8.0/tests/zip.rs b/third_party/rust/itertools-0.8.0/tests/zip.rs new file mode 100644 index 0000000000..c5c51899b8 --- /dev/null +++ b/third_party/rust/itertools-0.8.0/tests/zip.rs @@ -0,0 +1,65 @@ +extern crate itertools; + +use itertools::Itertools; +use itertools::EitherOrBoth::{Both, Left, Right}; +use itertools::free::zip_eq; + +#[test] +fn zip_longest_fused() { + let a = [Some(1), None, Some(3), Some(4)]; + let b = [1, 2, 3]; + + let unfused = a.iter().batching(|it| *it.next().unwrap()) + .zip_longest(b.iter().cloned()); + itertools::assert_equal(unfused, + vec![Both(1, 1), Right(2), Right(3)]); +} + +#[test] +fn test_zip_longest_size_hint() { + let c = (1..10).cycle(); + let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let v2 = &[10, 11, 12]; + + assert_eq!(c.zip_longest(v.iter()).size_hint(), (std::usize::MAX, None)); + + assert_eq!(v.iter().zip_longest(v2.iter()).size_hint(), (10, Some(10))); +} + +#[test] +fn test_double_ended_zip_longest() { + let xs = [1, 2, 3, 4, 5, 6]; + let ys = [1, 2, 3, 7]; + let a = xs.iter().map(|&x| x); + let b = ys.iter().map(|&x| x); + let mut it = a.zip_longest(b); + assert_eq!(it.next(), Some(Both(1, 1))); + assert_eq!(it.next(), Some(Both(2, 2))); + assert_eq!(it.next_back(), Some(Left(6))); + assert_eq!(it.next_back(), Some(Left(5))); + assert_eq!(it.next_back(), Some(Both(4, 7))); + assert_eq!(it.next(), Some(Both(3, 3))); + assert_eq!(it.next(), None); +} + + +#[should_panic] +#[test] +fn zip_eq_panic1() +{ + let a = [1, 2]; + let b = [1, 2, 3]; + + zip_eq(&a, &b).count(); +} + +#[should_panic] +#[test] +fn zip_eq_panic2() +{ + let a: [i32; 0] = []; + let b = [1, 2, 3]; + + zip_eq(&a, &b).count(); +} + |