nonempty-collections-1.1.0/.cargo_vcs_info.json0000644000000001360000000000100152200ustar { "git": { "sha1": "8c8e3a1b3dc8417d74b97005d52314b91d6952dd" }, "path_in_vcs": "" }nonempty-collections-1.1.0/.github/workflows/ci.yml000064400000000000000000000005051046102023000205230ustar 00000000000000--- name: Tests on: push: branches: [master] pull_request: env: CARGO_TERM_COLOR: always jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Cache Dependencies uses: Swatinem/rust-cache@v2 - name: Run tests run: cargo test --all-features nonempty-collections-1.1.0/.gitignore000064400000000000000000000000241046102023000157740ustar 00000000000000target/* **/*.rs.bk nonempty-collections-1.1.0/CHANGELOG.md000064400000000000000000000163621046102023000156310ustar 00000000000000# `nonempty-collections` ## 1.1.0 (2025-10-16) #### Added - The `Singleton` trait. - `NonEmptyIterator::unzip`. - `Extend` impls for `NESet`, `NEMap`, and `NEIndexMap`. ## 1.0.1 (2025-09-06) #### Added - Various `AsRef` impls. #### Fixed - Overly restrictive bounds on the `PartialEq` impl for `NEMap`. ## 1.0.0 (2025-06-30) Five months since the big changes and no major issues. If there are, we can now fix them in the normal Semver way. #### Added - `nev![a; n]` syntax (similar to `vec![a; n]`) #### Changed - Bumped the Rust Edition to 2024. ## 0.3.1 (2025-06-14) #### Added - `iter_mut()` to `NEVec`, `NEMap`, and `NEIndexMap` - `peekable()` to `NonEmptyIterator` - `remove()`, `swap_remove()`, `retain()`, and `retain_mut()` to `NEVec`. - `AsRef<[T]>` for `NESlice`. ## 0.3.0 (2025-02-15) #### Changed - **BREAKING:** Redesign of `NonEmptyIterator`: - `NonEmptyIterator` is now bounded by `IntoIterator` and has default implementations of all methods (i.e. it is a marker trait). - `NonEmptyIterator::first()` is renamed to `next()` and the old implementation of `next()` is removed. - `NonEmptyIterator::all()` now consumes self - `NonEmptyIterator::any()` now consumes self - `NonEmptyIterator::nth()` now consumes self - `NonEmptyIterator::take(usize)` -> `NonEmptyIterator::take(NonZeroUsize)` and doesn't panic anymore - **BREAKING:** `NEVec::truncate(usize)` -> `NEVec::truncate(NonZeroUsize)` and doesn't panic anymore - **BREAKING:** Capacities for all collections now use `NonZeroUsize` instead of `usize`: - `with_capacity(NonZeroUsize)` - `with_capacity_and_hasher(NonZeroUsize)` - `capacity() -> NonZeroUsize` - **BREAKING:** All fields are now private for `NEVec`, `NEMap`, `NESet`, and `NESlice` - **BREAKING:** Removed: - `NESlice::new(&T, &[T])` - `IntoIteratorProxy` - **BREAKING:** Methods that are no longer `const`: - `NEVec::new()` - `NEVec::first()` - **BREAKING:** non-empty maps and sets now behave similarly to their possibly empty counter parts: when created from an iterator with duplicates, the last occurence is kept. - **BREAKING:** Consistent API, new naming to align with Rust's naming conventions and indicate the fallibility of the function: - `from_vec` to `try_from_vec` - `from_map` to `try_from_map` - `from_slice` to `try_from_slice` - `from_set` to `try_from_set`. - **BREAKING:** `IteratorExt` is removed in favor of `IntoIteratorExt`. Now it's possible to call `try_into_nonempty_iter()` instead of `to_nonempty_iter()` on all regular iterators because regular iterators also implement `IntoIterator`. - **BREAKING:** `.iter()`, `.iter_mut()`, etc, are now prefixed with `nonempty_` - `FromNonEmptyIterator` is now implemented for `HashSet` instead of `HashSet` (with the default hasher). #### Fixed - Fixes bug in `PartialEq for NEIndexMap`, previously, maps with unequal lengths would be considered equal if the shorter map would contain the same values as the longer map. - Fixes bug in `NEMap::with_capacity()` and `NESet::with_capacity()`, it wasn't possible to call this method without explicitly specifying the type for `S` (the hasher). For this method it is assumed that it always uses the default hasher (just like in `std`), in case the user wants to specify the hasher `with_capacity_and_hasher()` can be used. The fix moved the method into the proper `impl` block. #### Added - New feature `either`: adds `NEEither` an extension to `either::Either`. - New feature `itertools`: adds a new `NonEmptyItertools` trait that is an extension of the `NonEmptyIterator` similar to how `Itertools` extends `Iterator`. So far, `cartesian_product()`, `sorted_by_key()`, and `all_unique()` are implemented. - `NonEmptyIterator::find()` the equivalent of `Iterator::find()`. - `IntoNonEmptyIterator for &NEVec`, `&NEIndexMap`, `&NEMap`, `&NESet`, `&NESlice`, `&[T; $i] where $i > 0` (these previously only existed for their owned equivalents) - `NESlice::from_slice()` is now `const` - `Index for NESlice` - All public types now implement `Debug` - Aliases `ne_vec` for `nev`, `ne_hashset` for `nes`, and `ne_hashmap` for `nem`. - Strict lint configuration - The rust version to which the library is build is now pinned, to avoid accidental breakage. - A [`justfile`](https://github.com/casey/just) that allows to run pre-configured commands to check the codebase. E.g. `just lint` or `just test`. - Benchmarks for `Vec` versus `NEVec`. - Added `.iter()` methods to all collections returning a regular `Iterator`. ## 0.2.9 (2024-08-26) #### Added - `NonEmptyIterator::group_by`. - `NVec::sort_by` and `NEVec::sort_by_key`. - An impl of `Extend` for `NEVec`. #### Fixed - `NEVec::sort` avoids a second internal `sort`. ## 0.2.8 (2024-08-19) #### Added - Missing `FromNonEmptyIterator` for `HashMap`. ## 0.2.7 (2024-07-22) #### Added - `serde` support for `NEMap` and `NESet`. ## 0.2.6 (2024-06-27) #### Fixed - Ownership issues in `nem!` when using non-Copy types. ## 0.2.5 (2024-04-09) #### Added - Implementation of `NonEmptyIterator` for fixed-sized stdlib Arrays. ## 0.2.4 (2024-04-04) #### Added - Added `NEVec::partition_point` to match the function of the same name in `std`. #### Fixed - Render feature-gated types on `docs.rs`. ## 0.2.3 (2024-03-19) #### Fixed - More edge cases involving `NEChunks`. ## 0.2.2 (2024-03-18) #### Fixed - `IntoIterator` for `NEChunks` yielding the wrong type. - `NonEmptyIterator` for `NEChunks` missing a cutoff condition. ## 0.2.1 (2024-03-15) #### Added - The missing `IntoIterator` impl for `NEChunks`. - `IntoIteratorExt` for direct conversion from anything that implements `IntoIterator`. Thanks to Rinde van Lon. #### Fixed - A bug involving repeated keys in `NEMap` and `NEIndexedMap`. Thanks to Rinde van Lon. ## 0.2.0 (2024-03-14) #### Added - `NEIndexMap`, thanks to [Rinde van Lon](https://github.com/rinde/). - `NonEmptyIterator::max_by_key` and `NonEmptyIterator::min_by_key`, also thanks to Rinde. - `NEVec::with_capacity` - `NEVec::nonempty_chunks` and `NESlice::nonempty_chunks` #### Changed - **BREAKING:** All `len` implementations and `NonEmptyIterator::count` have had their return type changed to `NonZeroUsize`. ## 0.1.5 (2024-01-12) #### Added - `NonEmptyIterator::reduce`, which yields a concrete `Self::Item` instead of an `Option`. - `IteratorExt::to_nonempty_iter` for converting any given `Iterator` into a non-empty one (if possible). - The `NEVec::dedup*` series for removing duplicate items in-place. #### Fixed - Account for potentially duplicated `head` value when converting into an `NESet` from other nonempty iterators. ## 0.1.4 (2023-11-02) #### Added - `FromNonEmptyIterator` impls for `NEMap` and `NESet`. - `Debug`, `Clone`, `PartialEq`, and `Eq` for `NEMap`. ## 0.1.3 (2023-09-15) #### Added - `NESlice` for when what you have on hand is already borrowed. Thanks again to Greg Shuflin. ## 0.1.2 (2023-09-05) #### Added - A `FromNonEmptyIterator` instance for `Result`, meaning you can `collect` into a guaranteed `Result, Error>` (or other nonempty type). Thanks to Greg Shuflin. ## 0.1.1 (2023-04-08) #### Added - Missing `IntoNonEmptyIterator` instances. - Missing `Intoiterator` instance for `FlatMap`. #### Fixed - Incorrect `IntoIterator` for `Take`. nonempty-collections-1.1.0/Cargo.lock0000644000000234550000000000100132040ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "anstyle" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "bitflags" version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "clap" version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" dependencies = [ "anstyle", "clap_lex", "terminal_size", ] [[package]] name = "clap_lex" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "condtype" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" [[package]] name = "divan" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a405457ec78b8fe08b0e32b4a3570ab5dff6dd16eb9e76a5ee0a9d9cbd898933" dependencies = [ "cfg-if", "clap", "condtype", "divan-macros", "libc", "regex-lite", ] [[package]] name = "divan-macros" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9556bc800956545d6420a640173e5ba7dfa82f38d3ea5a167eb555bc69ac3323" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys 0.61.2", ] [[package]] name = "hashbrown" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "indexmap" version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "itertools" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "linux-raw-sys" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "memchr" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "nonempty-collections" version = "1.1.0" dependencies = [ "divan", "either", "indexmap", "itertools", "maplit", "serde", "serde_json", ] [[package]] name = "proc-macro2" version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] [[package]] name = "regex-lite" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" [[package]] name = "rustix" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.61.2", ] [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", "serde_core", ] [[package]] name = "syn" version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "terminal_size" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ "rustix", "windows-sys 0.60.2", ] [[package]] name = "unicode-ident" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] [[package]] name = "windows-targets" version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" nonempty-collections-1.1.0/Cargo.toml0000644000000030040000000000100132130ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2024" name = "nonempty-collections" version = "1.1.0" authors = ["Colin Woodbury "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Correct-by-construction non-empty collections." readme = "README.md" keywords = [ "nonempty", "vector", "set", "map", ] categories = ["data-structures"] license = "MIT" repository = "https://github.com/fosskers/nonempty-collections" [package.metadata.docs.rs] all-features = true [lib] name = "nonempty_collections" path = "src/lib.rs" [[bench]] name = "vec" path = "benches/vec.rs" harness = false [dependencies.either] version = "1.0" optional = true [dependencies.indexmap] version = "2.7" optional = true [dependencies.itertools] version = "0.14" features = ["use_alloc"] optional = true [dependencies.serde] version = "1.0" features = ["serde_derive"] optional = true [dev-dependencies.divan] version = "0.1" [dev-dependencies.maplit] version = "1.0" [dev-dependencies.serde_json] version = "1.0" nonempty-collections-1.1.0/Cargo.toml.orig0000644000000014210000000000100141530ustar [package] name = "nonempty-collections" version = "1.1.0" description = "Correct-by-construction non-empty collections." authors = ["Colin Woodbury "] edition = "2024" license = "MIT" repository = "https://github.com/fosskers/nonempty-collections" readme = "README.md" keywords = ["nonempty", "vector", "set", "map"] categories = ["data-structures"] [dependencies] serde = { version = "1.0", features = ["serde_derive"], optional = true } indexmap = { version = "2.7", optional = true } either = { version = "1.0", optional = true } itertools = { version = "0.14", optional = true, features = ["use_alloc"] } [dev-dependencies] serde_json = "1.0" divan = "0.1" maplit = "1.0" [[bench]] name = "vec" harness = false [package.metadata.docs.rs] all-features = true nonempty-collections-1.1.0/Cargo.toml.orig000064400000000000000000000014211046102023000166750ustar 00000000000000[package] name = "nonempty-collections" version = "1.1.0" description = "Correct-by-construction non-empty collections." authors = ["Colin Woodbury "] edition = "2024" license = "MIT" repository = "https://github.com/fosskers/nonempty-collections" readme = "README.md" keywords = ["nonempty", "vector", "set", "map"] categories = ["data-structures"] [dependencies] serde = { version = "1.0", features = ["serde_derive"], optional = true } indexmap = { version = "2.7", optional = true } either = { version = "1.0", optional = true } itertools = { version = "0.14", optional = true, features = ["use_alloc"] } [dev-dependencies] serde_json = "1.0" divan = "0.1" maplit = "1.0" [[bench]] name = "vec" harness = false [package.metadata.docs.rs] all-features = true nonempty-collections-1.1.0/LICENSE000064400000000000000000000020421046102023000150130ustar 00000000000000Copyright (c) 2021 Colin Woodbury 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. nonempty-collections-1.1.0/README.md000064400000000000000000000117741046102023000153010ustar 00000000000000# Correct-by-Construction Collections Non-empty variants of the standard collections. Non-emptiness can be a powerful guarantee. If your main use of `Vec` is as an `Iterator`, then you may not need to distinguish on emptiness. But there are indeed times when the `Vec` you receive as a function argument needs to be non-empty or your function can't proceed. Similarly, there are times when the `Vec` you return to a calling user needs to promise it actually contains something. With `NEVec`, you're freed from the boilerplate of constantly needing to check `is_empty()` or pattern matching before proceeding, or erroring if you can't. So overall, code, type signatures, and logic become cleaner. Consider that unlike `Vec`, [`NEVec::first()`] and [`NEVec::last()`] don't return in `Option`; they always succeed. Alongside [`NEVec`](https://docs.rs/nonempty-collections/latest/nonempty_collections/vector/struct.NEVec.html) are its cousins [`NESlice`](https://docs.rs/nonempty-collections/latest/nonempty_collections/slice/struct.NESlice.html), [`NEMap`](https://docs.rs/nonempty-collections/latest/nonempty_collections/map/struct.NEMap.html), and [`NESet`](https://docs.rs/nonempty-collections/latest/nonempty_collections/set/struct.NESet.html), which are all guaranteed to contain at least one item. ## Examples The simplest way to construct these non-empty collections is via their macros: [`nev!`], [`nes!`], and [`nem!`]: ```rust use nonempty_collections::*; let v: NEVec = nev![1, 2, 3]; let s: NESet = nes![1, 2, 2, 3]; // 1 2 3 let m: NEMap<&str, bool> = nem!["a" => true, "b" => false]; assert_eq!(&1, v.first()); assert_eq!(3, s.len().get()); assert!(m.get("a").unwrap()); ``` Unlike the familiar `vec!` macro, `nev!` and friends require at least one element: ```rust use nonempty_collections::nev; let v = nev![1]; ``` A value must be provided: ```rust let v = nev![]; // Doesn't compile! ``` Like `Vec`, you can also construct a [`NEVec`](https://docs.rs/nonempty-collections/latest/nonempty_collections/vector/struct.NEVec.html) the old fashioned way with [`NEVec::new()`] or its constructor: ```rust use nonempty_collections::NEVec; let mut l = NEVec::try_from_vec(vec![42, 36, 58]).unwrap(); assert_eq!(&42, l.first()); l.push(9001); assert_eq!(l.last(), &9001); ``` And if necessary, you're free to convert to and from `Vec`: ```rust use nonempty_collections::nev; use nonempty_collections::NEVec; let l: NEVec = nev![42, 36, 58, 9001]; let v: Vec = l.into(); assert_eq!(v, vec![42, 36, 58, 9001]); let u: Option> = NEVec::try_from_vec(v); assert_eq!(Some(nev![42, 36, 58, 9001]), u); ``` ## Iterators This library extends the notion of non-emptiness to iterators, and provides the [`NonEmptyIterator`](https://docs.rs/nonempty-collections/latest/nonempty_collections/iter/trait.NonEmptyIterator.html) trait. This has some interesting consequences: - Functions like `map` preserve non-emptiness. - Functions like `max` always have a result. - A non-empty iterator chain can be `collect`ed back into a non-empty structure. - You can chain many operations together without having to double-check for emptiness. ```rust use nonempty_collections::*; let v: NEVec<_> = nev![1, 2, 3].into_nonempty_iter().map(|n| n + 1).collect(); assert_eq!(&2, v.first()); ``` Consider also [`IntoIteratorExt::try_into_nonempty_iter`] for converting any given [`Iterator`] and [`IntoIterator`] into a non-empty one, if it contains at least one item. ## Arrays Since fixed-size arrays are by definition already not empty, they aren't given a special wrapper type like [`NEVec`](https://docs.rs/nonempty-collections/latest/nonempty_collections/vector/struct.NEVec.html). Instead, we enable them to be easily iterated over in a compatible way: ```rust use nonempty_collections::*; let a: [u32; 4] = [1, 2, 3, 4]; let v: NEVec<_> = a.into_nonempty_iter().map(|n| n + 1).collect(); assert_eq!(nev![2, 3, 4, 5], v); ``` See [`NonEmptyArrayExt`](https://docs.rs/nonempty-collections/latest/nonempty_collections/array/trait.NonEmptyArrayExt.html) for more conversions. ## Caveats Since `NEVec`, `NEMap`, and `NESet` must have a least one element, it is not possible to implement the [`FromIterator`] trait for them. We can't know, in general, if any given standard-library [`Iterator`] actually contains something. ## Features * `serde`: `serde` support. * `indexmap`: adds [`NEIndexMap`](https://docs.rs/nonempty-collections/latest/nonempty_collections/index_map/struct.NEIndexMap.html) a non-empty [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/). * `itertools`: adds [`NonEmptyItertools`](https://docs.rs/nonempty-collections/latest/nonempty_collections/itertools/trait.NonEmptyItertools.html) a non-empty variant of [`itertools`](https://docs.rs/itertools/latest/itertools/). * `either`: adds [`NEEither`](https://docs.rs/nonempty-collections/latest/nonempty_collections/either/enum.NEEither.html) a non-empty variant of `Either` from the [`either` crate](https://docs.rs/either/latest/either/). nonempty-collections-1.1.0/src/array.rs000064400000000000000000000132611046102023000162660ustar 00000000000000//! Extends non-zero length arrays with conversion methods to non-empty //! collections. //! //! Since fixed-size arrays are by definition already not empty, they aren't //! given a special wrapper type like [`crate::NEVec`]. Instead, we enable them //! to be easily iterated over in a compatible way: //! //! ``` //! use nonempty_collections::*; //! //! let a: [u32; 4] = [1, 2, 3, 4]; //! let v: NEVec<_> = a.into_nonempty_iter().map(|n| n + 1).collect(); //! assert_eq!(nev![2, 3, 4, 5], v); //! ``` //! //! See [`NonEmptyArrayExt`] for more conversions. //! //! # Caveats //! //! These extensions are only provided for arrays up to size 32. use core::fmt; use std::num::NonZeroUsize; use crate::impl_nonempty_iter_for_arrays; use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; /// Provides extension methods for non-empty arrays. /// /// # Examples /// /// Create a non-empty slice of an array: /// /// ``` /// # use nonempty_collections::*; /// assert_eq!( /// NESlice::try_from_slice(&[1, 2]), /// Some([1, 2].as_nonempty_slice()) /// ); /// ``` /// /// Get the length of an array as a [`NonZeroUsize`]: /// /// ``` /// # use nonempty_collections::NonEmptyArrayExt; /// # use std::num::NonZeroUsize; /// assert_eq!(NonZeroUsize::MIN, [1].nonzero_len()); /// ``` /// /// Convert array into a non-empty vec: /// /// ``` /// # use nonempty_collections::*; /// assert_eq!(nev![4], [4].into_nonempty_vec()); /// ``` pub trait NonEmptyArrayExt { /// Create a `NESlice` that borrows the contents of `self`. fn as_nonempty_slice(&self) -> crate::NESlice<'_, T>; /// Returns the length of this array as a [`NonZeroUsize`]. fn nonzero_len(&self) -> NonZeroUsize; /// Moves `self` into a new [`crate::NEVec`]. fn into_nonempty_vec(self) -> crate::NEVec; } /// Non-empty iterator for arrays with length > 0. /// /// # Examples /// /// Use non-zero length arrays anywhere an [`IntoNonEmptyIterator`] is expected. /// /// ``` /// use std::num::NonZeroUsize; /// /// use nonempty_collections::*; /// /// fn is_one(iter: impl IntoNonEmptyIterator) { /// assert_eq!(NonZeroUsize::MIN, iter.into_nonempty_iter().count()); /// } /// /// is_one([0]); /// ``` /// /// Only compiles for non-empty arrays: /// /// ```compile_fail /// use nonempty_collections::*; /// /// fn is_one(iter: impl IntoNonEmptyIterator) {} /// /// is_one([]); // Doesn't compile because it is empty. /// ``` #[derive(Clone)] pub struct ArrayNonEmptyIterator { iter: core::array::IntoIter, } impl IntoIterator for ArrayNonEmptyIterator { type Item = T; type IntoIter = core::array::IntoIter; fn into_iter(self) -> Self::IntoIter { self.iter } } impl NonEmptyIterator for ArrayNonEmptyIterator {} impl fmt::Debug for ArrayNonEmptyIterator { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } // NOTE 2024-04-05 This must never be implemented for 0. // // Also, happy birthday Dad. impl_nonempty_iter_for_arrays!( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ); #[doc(hidden)] #[macro_export] macro_rules! impl_nonempty_iter_for_arrays { ($($i:literal),+ $(,)?) => { $( impl IntoNonEmptyIterator for [T; $i] { type IntoNEIter = ArrayNonEmptyIterator; fn into_nonempty_iter(self) -> Self::IntoNEIter { ArrayNonEmptyIterator { iter: self.into_iter(), } } } impl<'a, T> IntoNonEmptyIterator for &'a [T; $i] { type IntoNEIter = $crate::slice::Iter<'a,T>; fn into_nonempty_iter(self) -> Self::IntoNEIter { self.as_nonempty_slice().into_nonempty_iter() } } impl NonEmptyArrayExt for [T; $i] { fn as_nonempty_slice(&self) -> $crate::NESlice<'_, T> { // This should never panic because a slice with length > 0 // is non-empty by definition. $crate::NESlice::try_from_slice(self).unwrap() } fn nonzero_len(&self) -> NonZeroUsize { // This should be fine because $i is always > 0. unsafe { NonZeroUsize::new_unchecked($i) } } fn into_nonempty_vec(self) -> $crate::NEVec { self.into_nonempty_iter().collect() } } )+ }; } #[cfg(test)] mod test { use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; #[test] fn test_iter() { let iter = [1, 2, 3, 4].into_nonempty_iter(); let (first, rest) = iter.next(); assert_eq!(1, first); assert_eq!(vec![2, 3, 4], rest.into_iter().collect::>()); let iter = [1].into_nonempty_iter(); let (first, rest) = iter.next(); assert_eq!(1, first); assert_eq!(0, rest.into_iter().count()); assert_eq!(33, [1, -2, 33, 4].into_nonempty_iter().max()); } #[test] fn test_iter_ref() { let iter = (&[1, 2, 3, 4]).into_nonempty_iter(); let (first, rest) = iter.next(); assert_eq!(&1, first); assert_eq!(vec![&2, &3, &4], rest.into_iter().collect::>()); let iter = (&[1]).into_nonempty_iter(); let (first, rest) = iter.next(); assert_eq!(&1, first); assert_eq!(0, rest.into_iter().count()); assert_eq!(&33, (&[1, -2, 33, 4]).into_nonempty_iter().max()); } } nonempty-collections-1.1.0/src/either.rs000064400000000000000000000056461046102023000164400ustar 00000000000000//! Extension of [`either::Either`] to provide support for [`NonEmptyIterator`]. //! //! ``` //! use nonempty_collections::*; //! fn get_data(input: usize) -> NEEither<[usize; 1], [usize; 3]> { //! if input == 0 { //! NEEither::Left([0]) //! } else { //! NEEither::Right([2, 1, 4]) //! } //! } //! //! assert_eq!( //! nev![0], //! get_data(0).into_nonempty_iter().collect::>() //! ); //! ``` // Implementation note: // In an ideal world there is no need for `NEEither` and we could just implement // `NonEmptyIterator` for `Either`. However, the following holds: // - `NonEmptyIterator` requires an implementation of `IntoIterator` // - `Either` conditionally implements `Iterator` // - Rust has blanket implementation `impl IntoIterator for I` // Therefore we cannot implement (`Into`)`NonEmptyIterator` for `Either` // except if we add bounds similar to `L: NonEmptyIterator + Iterator` and `R: // NonEmptyIterator + Iterator`, which our implementations of `NonEmptyIterator` // don't satisfy as that would break encapsulation. use either::Either; use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; /// Non-empty variant of [`either::Either`] that implements /// [`NonEmptyIterator`]. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub enum NEEither { /// A value of type `L`. Left(L), /// A value of type `R`. Right(R), } impl NEEither { /// Convert the inner value to a `NonEmptyIterator`. /// /// This requires the `Left` and `Right` non-empty iterators to have the /// same item type. /// /// ``` /// use nonempty_collections::*; /// let left: NEEither<_, NESet> = NEEither::Left(nev![1, 2, 3]); /// let right: NEEither, _> = NEEither::Right(nes![4]); /// /// let combined = left.into_nonempty_iter().chain(right).collect::>(); /// let expected = nev![1, 2, 3, 4]; /// assert_eq!(expected, combined); /// ``` pub fn into_nonempty_iter(self) -> NEEither where L: IntoNonEmptyIterator, R: IntoNonEmptyIterator, { match self { NEEither::Left(left) => NEEither::Left(left.into_nonempty_iter()), NEEither::Right(right) => NEEither::Right(right.into_nonempty_iter()), } } } impl NonEmptyIterator for NEEither where L: NonEmptyIterator + IntoIterator, R: NonEmptyIterator + IntoIterator, { } impl IntoIterator for NEEither where L: IntoIterator, R: IntoIterator, { type Item = L::Item; type IntoIter = Either; fn into_iter(self) -> Self::IntoIter { match self { NEEither::Left(left) => Either::Left(left.into_iter()), NEEither::Right(right) => Either::Right(right.into_iter()), } } } nonempty-collections-1.1.0/src/index_map.rs000064400000000000000000000541301046102023000171140ustar 00000000000000//! [`NEIndexMap`] is a non-empty variant of [`IndexMap`]. //! //! Unlike `HashMap` and [`crate::NEMap`], these feature a predictable iteration //! order. use crate::FromNonEmptyIterator; use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; use crate::Singleton; use indexmap::indexmap; use indexmap::Equivalent; use indexmap::IndexMap; use std::fmt; use std::fmt::Debug; use std::fmt::Formatter; use std::hash::BuildHasher; use std::hash::Hash; use std::num::NonZeroUsize; /// Short-hand for constructing [`NEIndexMap`] values. /// /// ``` /// use nonempty_collections::ne_indexmap; /// /// let m = ne_indexmap! {"elves" => 3000, "orcs" => 10000}; /// assert_eq!(2, m.len().get()); /// ``` #[macro_export] macro_rules! ne_indexmap { ($hk:expr => $hv:expr, $( $xk:expr => $xv:expr,)+) => { $crate::ne_indexmap!{$hk => $hv, $($xk => $xv),+} }; ($hk:expr => $hv:expr, $( $xk:expr => $xv:expr ),*) => {{ const CAP: core::num::NonZeroUsize = core::num::NonZeroUsize::MIN.saturating_add(<[()]>::len(&[$({ stringify!($xk); }),*])); let mut map = $crate::index_map::NEIndexMap::with_capacity(CAP, $hk, $hv); $( map.insert($xk, $xv); )* map }}; ($hk:expr => $hv:expr) => { $crate::index_map::NEIndexMap::new($hk, $hv) } } /// A non-empty, growable [`IndexMap`]. /// /// Unlike `HashMap` and [`crate::NEMap`], these feature a predictable iteration /// order. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"Netherlands" => 18, "Canada" => 40}; /// assert_eq!(2, m.len().get()); /// ``` #[derive(Clone)] pub struct NEIndexMap { inner: IndexMap, } impl NEIndexMap { /// Returns the number of elements the map can hold without reallocating. #[must_use] pub fn capacity(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.capacity()) } } /// Returns a reference to the map's `BuildHasher`. #[must_use] pub fn hasher(&self) -> &S { self.inner.hasher() } /// Returns a regular iterator over the entries in this non-empty index map. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter()`. pub fn iter(&self) -> indexmap::map::Iter<'_, K, V> { self.inner.iter() } /// Returns a regular mutable iterator over the entries in this non-empty /// index map. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter_mut()`. pub fn iter_mut(&mut self) -> indexmap::map::IterMut<'_, K, V> { self.inner.iter_mut() } /// An iterator visiting all elements in their order. pub fn nonempty_iter(&self) -> Iter<'_, K, V> { Iter { iter: self.inner.iter(), } } /// An iterator visiting all elements in their order. pub fn nonempty_iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut { iter: self.inner.iter_mut(), } } /// An iterator visiting all keys in arbitrary order. The iterator element /// type is `&'a K`. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"Duke" => "Leto", "Doctor" => "Yueh", "Planetologist" => "Kynes"}; /// let v = m.keys().collect::>(); /// assert_eq!(nev![&"Duke", &"Doctor", &"Planetologist"], v); /// ``` pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.inner.keys(), } } /// Returns the number of elements in the map. Always 1 or more. /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"a" => 1, "b" => 2}; /// assert_eq!(2, m.len().get()); /// ``` #[must_use] pub fn len(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.len()) } } /// A `NEIndexMap` is never empty. #[deprecated(note = "A NEIndexMap is never empty.")] #[must_use] pub const fn is_empty(&self) -> bool { false } /// An iterator visiting all values in order. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap!["Caladan" => "Atreides", "Giedi Prime" => "Harkonnen", "Kaitain" => "Corrino"]; /// assert_eq!(vec![&"Atreides", &"Harkonnen", &"Corrino"], m.values().collect::>()); /// ``` pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.inner.values(), } } /// Return an iterator visiting all mutable values in order. /// /// ``` /// use nonempty_collections::*; /// /// let mut m = ne_indexmap![0 => "Fremen".to_string(), 1 => "Crysknife".to_string(), 2 => "Water of Life".to_string()]; /// m.values_mut().into_iter().for_each(|v| v.truncate(3)); /// /// assert_eq!(vec![&mut "Fre".to_string(), &mut "Cry".to_string(),&mut "Wat".to_string()], m.values_mut().collect::>()); /// ``` pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { ValuesMut { inner: self.inner.values_mut(), } } /// Get the first element. Never fails. #[allow(clippy::missing_panics_doc)] // the invariant of NEIndexMap is that its non-empty #[must_use] pub fn first(&self) -> (&K, &V) { self.inner.first().unwrap() } /// Get the last element. Never fails. #[allow(clippy::missing_panics_doc)] // the invariant of NEIndexMap is that its non-empty #[must_use] pub fn last(&self) -> (&K, &V) { self.inner.last().unwrap() } } impl Debug for NEIndexMap { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.nonempty_iter()).finish() } } impl NEIndexMap where K: Eq + Hash, { /// Creates a new `NEIndexMap` with a single element. #[must_use] pub fn new(k: K, v: V) -> Self { Self { inner: indexmap! {k => v}, } } /// Creates a new `NEIndexMap` with a single element and specified /// heap capacity. #[must_use] pub fn with_capacity(capacity: NonZeroUsize, k: K, v: V) -> NEIndexMap { let mut inner = IndexMap::with_capacity(capacity.get()); inner.insert(k, v); Self { inner } } } impl NEIndexMap where K: Eq + Hash, S: BuildHasher, { /// Attempt a conversion from [`IndexMap`], consuming the given `IndexMap`. /// Will return `None` if the `IndexMap` is empty. /// /// ``` /// use indexmap::*; /// use nonempty_collections::*; /// /// assert_eq!( /// Some(ne_indexmap! {"a" => 1, "b" => 2}), /// NEIndexMap::try_from_map(indexmap! {"a" => 1, "b" => 2}) /// ); /// let m: IndexMap<(), ()> = indexmap! {}; /// assert_eq!(None, NEIndexMap::try_from_map(m)); /// ``` #[must_use] pub fn try_from_map(map: IndexMap) -> Option { if map.is_empty() { None } else { Some(Self { inner: map }) } } /// Returns true if the map contains a value. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"Paul" => ()}; /// assert!(m.contains_key("Paul")); /// assert!(!m.contains_key("Atreides")); /// ``` #[must_use] pub fn contains_key(&self, k: &Q) -> bool where Q: Hash + Equivalent + ?Sized, { self.inner.contains_key(k) } /// Return a reference to the value stored for `key`, if it is present, /// else `None`. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"Arrakis" => 3}; /// assert_eq!(Some(&3), m.get("Arrakis")); /// assert_eq!(None, m.get("Caladan")); /// ``` #[must_use] pub fn get(&self, k: &Q) -> Option<&V> where Q: Hash + Equivalent + ?Sized, { self.inner.get(k) } /// Return references to the key-value pair stored for `key`, /// if it is present, else `None`. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"Year" => 1963, "Pages" => 896}; /// assert_eq!(Some((&"Year", &1963)), m.get_key_value(&"Year")); /// assert_eq!(Some((&"Pages", &896)), m.get_key_value(&"Pages")); /// assert_eq!(None, m.get_key_value(&"Title")); /// ``` #[must_use] pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> where Q: Hash + Equivalent + ?Sized, { self.inner.get_key_value(key) } /// Return a mutable reference to the value stored for `key`, if it is /// present, else `None`. /// /// ``` /// use nonempty_collections::*; /// /// let mut m = ne_indexmap! {"Mentat" => 3, "Bene Gesserit" => 14}; /// let v = m.get_mut(&"Mentat"); /// assert_eq!(Some(&mut 3), v); /// *v.unwrap() += 1; /// assert_eq!(Some(&mut 4), m.get_mut(&"Mentat")); /// /// let v = m.get_mut(&"Bene Gesserit"); /// assert_eq!(Some(&mut 14), v); /// *v.unwrap() -= 1; /// assert_eq!(Some(&mut 13), m.get_mut(&"Bene Gesserit")); /// /// assert_eq!(None, m.get_mut(&"Sandworm")); /// ``` pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where Q: Hash + Equivalent + ?Sized, { self.inner.get_mut(key) } /// Return item index, if it exists in the map. /// /// ``` /// use nonempty_collections::*; /// let m = ne_indexmap! {"Title" => "Dune", "Author" => "Frank Herbert", "Language" => "English"}; /// /// assert_eq!(Some(0), m.get_index_of(&"Title")); /// assert_eq!(Some(1), m.get_index_of(&"Author")); /// assert_eq!(None, m.get_index_of(&"Genre")); /// ```` #[must_use] pub fn get_index_of(&self, key: &Q) -> Option where Q: Hash + Equivalent + ?Sized, { self.inner.get_index_of(key) } /// Insert a key-value pair into the map. /// /// If an equivalent key already exists in the map: the key remains and /// retains in its place in the order, its corresponding value is updated /// with `value`, and the older value is returned inside `Some(_)`. /// /// If no equivalent key existed in the map: the new key-value pair is /// inserted, last in order, and `None` is returned. /// ``` /// use nonempty_collections::*; /// /// let mut m = ne_indexmap! {"Duke" => "Leto", "Doctor" => "Yueh"}; /// assert_eq!(None, m.insert("Lady", "Jessica")); /// assert_eq!( /// vec!["Duke", "Doctor", "Lady"], /// m.keys().copied().collect::>() /// ); /// /// // Spoiler alert: there is a different duke at some point /// assert_eq!(Some("Leto"), m.insert("Duke", "Paul")); /// assert_eq!( /// vec!["Paul", "Yueh", "Jessica"], /// m.values().copied().collect::>() /// ); /// ``` pub fn insert(&mut self, k: K, v: V) -> Option { self.inner.insert(k, v) } /// Shrink the capacity of the map as much as possible. pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit(); } /// Creates a new `NEIndexMap` with a single element and specified /// heap capacity and hasher. #[must_use] pub fn with_capacity_and_hasher( capacity: NonZeroUsize, hasher: S, k: K, v: V, ) -> NEIndexMap { let mut inner = IndexMap::with_capacity_and_hasher(capacity.get(), hasher); inner.insert(k, v); Self { inner } } /// See [`IndexMap::with_hasher`]. #[must_use] pub fn with_hasher(hasher: S, k: K, v: V) -> NEIndexMap { let mut inner = IndexMap::with_hasher(hasher); inner.insert(k, v); Self { inner } } /// Swaps the position of two key-value pairs in the map. /// /// # Panics /// If `a` or `b` are out of bounds. pub fn swap_indices(&mut self, a: usize, b: usize) { self.inner.swap_indices(a, b); } } impl AsRef> for NEIndexMap { fn as_ref(&self) -> &IndexMap { &self.inner } } impl AsMut> for NEIndexMap { fn as_mut(&mut self) -> &mut IndexMap { &mut self.inner } } impl PartialEq for NEIndexMap where K: Eq + Hash, V: Eq, S: BuildHasher, { fn eq(&self, other: &Self) -> bool { self.inner.eq(&other.inner) } } impl Eq for NEIndexMap where K: Eq + Hash, V: Eq, S: BuildHasher, { } impl From> for IndexMap where K: Eq + Hash, S: BuildHasher, { /// ``` /// use indexmap::IndexMap; /// use nonempty_collections::*; /// /// let m: IndexMap<&str, usize> = ne_indexmap! {"population" => 1000}.into(); /// assert!(m.contains_key("population")); /// ``` fn from(m: NEIndexMap) -> Self { m.inner } } impl IntoNonEmptyIterator for NEIndexMap { type IntoNEIter = IntoIter; fn into_nonempty_iter(self) -> Self::IntoNEIter { IntoIter { iter: self.inner.into_iter(), } } } impl<'a, K, V, S> IntoNonEmptyIterator for &'a NEIndexMap { type IntoNEIter = Iter<'a, K, V>; fn into_nonempty_iter(self) -> Self::IntoNEIter { self.nonempty_iter() } } impl IntoIterator for NEIndexMap { type Item = (K, V); type IntoIter = indexmap::map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl<'a, K, V, S> IntoIterator for &'a NEIndexMap { type Item = (&'a K, &'a V); type IntoIter = indexmap::map::Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, K, V, S> IntoIterator for &'a mut NEIndexMap { type Item = (&'a K, &'a mut V); type IntoIter = indexmap::map::IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } /// ``` /// use nonempty_collections::*; /// /// let v = nev![('a', 1), ('b', 2), ('c', 3), ('a', 4)]; /// let m0 = v.into_nonempty_iter().collect::>(); /// let m1 = ne_indexmap! {'a' => 4, 'b' => 2, 'c' => 3}; /// assert_eq!(m0, m1); /// ``` impl FromNonEmptyIterator<(K, V)> for NEIndexMap where K: Eq + Hash, S: BuildHasher + Default, { fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { Self { inner: iter.into_nonempty_iter().into_iter().collect(), } } } impl std::ops::Index for NEIndexMap { type Output = V; fn index(&self, index: usize) -> &V { self.inner.index(index) } } /// A non-empty iterator over the entries of an [`NEIndexMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, K: 'a, V: 'a> { iter: indexmap::map::Iter<'a, K, V>, } impl NonEmptyIterator for Iter<'_, K, V> {} impl<'a, K, V> IntoIterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); type IntoIter = indexmap::map::Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter } } // FIXME: Remove in favor of `#[derive(Clone)]` (see https://github.com/rust-lang/rust/issues/26925 for more info) impl Clone for Iter<'_, K, V> { fn clone(&self) -> Self { Iter { iter: self.iter.clone(), } } } impl Debug for Iter<'_, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } /// A mutable non-empty iterator over the entries of an [`NEIndexMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, K: 'a, V: 'a> { iter: indexmap::map::IterMut<'a, K, V>, } impl NonEmptyIterator for IterMut<'_, K, V> {} impl<'a, K, V> IntoIterator for IterMut<'a, K, V> { type Item = (&'a K, &'a mut V); type IntoIter = indexmap::map::IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter } } impl Debug for IterMut<'_, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator over the entries of an [`NEIndexMap`]. pub struct IntoIter { iter: indexmap::map::IntoIter, } impl NonEmptyIterator for IntoIter {} impl IntoIterator for IntoIter { type Item = (K, V); type IntoIter = indexmap::map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.iter } } impl Debug for IntoIter { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator over the keys of an [`NEIndexMap`]. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"elves" => 3000, "orcs" => 10000}; /// let v = m.keys().copied().collect::>(); /// assert_eq!(nev!["elves", "orcs"], v); /// ``` #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Keys<'a, K: 'a, V: 'a> { inner: indexmap::map::Keys<'a, K, V>, } impl NonEmptyIterator for Keys<'_, K, V> {} impl<'a, K, V> IntoIterator for Keys<'a, K, V> { type Item = &'a K; type IntoIter = indexmap::map::Keys<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.inner } } // FIXME: Remove in favor of `#[derive(Clone)]` (see https://github.com/rust-lang/rust/issues/26925 for more info) impl Clone for Keys<'_, K, V> { fn clone(&self) -> Self { Keys { inner: self.inner.clone(), } } } impl Debug for Keys<'_, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } /// A non-empty iterator over the values of an [`NEIndexMap`]. /// /// ``` /// use nonempty_collections::*; /// /// let m = ne_indexmap! {"elves" => 3000, "orcs" => 10000}; /// let mut v = m.values().copied().collect::>(); /// v.sort(); /// assert_eq!(nev![3000, 10000], v); /// ``` #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Values<'a, K: 'a, V: 'a> { inner: indexmap::map::Values<'a, K, V>, } impl NonEmptyIterator for Values<'_, K, V> {} impl<'a, K, V> IntoIterator for Values<'a, K, V> { type Item = &'a V; type IntoIter = indexmap::map::Values<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.inner } } // FIXME: Remove in favor of `#[derive(Clone)]` (see https://github.com/rust-lang/rust/issues/26925 for more info) impl Clone for Values<'_, K, V> { fn clone(&self) -> Self { Values { inner: self.inner.clone(), } } } impl Debug for Values<'_, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() } } /// A non-empty iterator over the mutable values of an [`NEIndexMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: indexmap::map::ValuesMut<'a, K, V>, } impl NonEmptyIterator for ValuesMut<'_, K, V> {} impl<'a, K, V> IntoIterator for ValuesMut<'a, K, V> { type Item = &'a mut V; type IntoIter = indexmap::map::ValuesMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.inner } } impl Debug for ValuesMut<'_, K, V> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl Singleton for NEIndexMap where K: Eq + Hash, { type Item = (K, V); /// ``` /// use nonempty_collections::{NEIndexMap, Singleton, ne_indexmap}; /// /// let m = NEIndexMap::singleton(('a', 1)); /// assert_eq!(ne_indexmap!['a' => 1], m); /// ``` fn singleton((k, v): Self::Item) -> Self { NEIndexMap::new(k, v) } } impl Extend<(K, V)> for NEIndexMap where K: Eq + Hash, { fn extend>(&mut self, iter: I) { self.inner.extend(iter); } } #[cfg(test)] mod test { use super::*; #[test] fn test_swap_indices() { let mut map = ne_indexmap! { 0 => (), 1 => () }; assert_eq!(vec![0, 1], map.keys().copied().collect::>()); map.swap_indices(0, 1); assert_eq!(vec![1, 0], map.keys().copied().collect::>()); map.swap_indices(1, 0); assert_eq!(vec![0, 1], map.keys().copied().collect::>()); let mut map = ne_indexmap! { 0 => (), 1 => (), 2 => () }; assert_eq!(vec![0, 1, 2], map.keys().copied().collect::>()); map.swap_indices(0, 1); assert_eq!(vec![1, 0, 2], map.keys().copied().collect::>()); map.swap_indices(1, 0); assert_eq!(vec![0, 1, 2], map.keys().copied().collect::>()); map.swap_indices(0, 2); assert_eq!(vec![2, 1, 0], map.keys().copied().collect::>()); map.swap_indices(1, 2); assert_eq!(vec![2, 0, 1], map.keys().copied().collect::>()); let mut map = ne_indexmap! { 0 => (), 1 => (), 2 => (), 3 => (), 4 => (), 5 => () }; assert_eq!( vec![0, 1, 2, 3, 4, 5], map.keys().copied().collect::>() ); map.swap_indices(1, 2); assert_eq!( vec![0, 2, 1, 3, 4, 5], map.keys().copied().collect::>() ); map.swap_indices(0, 3); assert_eq!( vec![3, 2, 1, 0, 4, 5], map.keys().copied().collect::>() ); } #[test] fn debug_impl() { let expected = format!("{:?}", indexmap! {0 => 10, 1 => 11, 2 => 12}); let actual = format!("{:?}", ne_indexmap! {0 => 10, 1 => 11, 2 => 12}); assert_eq!(expected, actual); } #[test] fn iter_mut() { let mut v = ne_indexmap! {"a" => 0, "b" => 1, "c" => 2}; v.iter_mut().for_each(|(_k, v)| { *v += 1; }); assert_eq!(ne_indexmap! {"a" => 1, "b" => 2, "c" => 3}, v); for (_k, v) in &mut v { *v -= 1; } assert_eq!(ne_indexmap! {"a" => 0, "b" => 1, "c" => 2}, v); } } nonempty-collections-1.1.0/src/iter.rs000064400000000000000000001234371046102023000161220ustar 00000000000000//! Non-empty iterators. use crate::nev; use crate::NEVec; use crate::Singleton; use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashMap; use std::collections::HashSet; use std::hash::BuildHasher; use std::hash::Hash; use std::iter::Product; use std::iter::Sum; use std::num::NonZeroUsize; use std::rc::Rc; use std::result::Result; // Iterator structs which _always_ have something if the source iterator is // non-empty: // // - [x] Chain (if one, the other, or both are nonempty) // - [x] Cloned // - [x] Copied // - [ ] Cycle // - [x] Enumerate // - [x] Map // - [x] Once // - [ ] Scan // - [x] Take // - [x] Zip (if both are nonempty) /// Creates an iterator that yields an element exactly once. /// /// See also [`std::iter::once`]. pub fn once(value: T) -> Once { Once::new(value) } /// An [`Iterator`] that is guaranteed to have at least one item. /// /// By implementing `NonEmptyIterator` for a type the implementor is responsible /// for ensuring that non-emptiness holds. Violating this invariant may lead to /// panics and/or undefined behavior. pub trait NonEmptyIterator: IntoIterator { /// Advances this non-empty iterator, consuming its ownership. Yields the /// first item and a possibly empty iterator containing the rest of the /// elements. #[must_use] fn next(self) -> (Self::Item, Self::IntoIter) where Self: Sized, { let mut iter = self.into_iter(); (iter.next().unwrap(), iter) } /// Creates an iterator which can use the [`peek`] and [`peek_mut`] methods /// to look at the next element of the iterator without consuming it. See /// their documentation for more information. /// /// Note that the underlying iterator is still advanced when this method is /// called. In order to retrieve the next element, [`next`] is called on the /// underlying iterator, hence any side effects (i.e. anything other than /// fetching the next value) of the [`next`] method will occur. /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![0, 1, 2, 3]; /// let iter = v.into_nonempty_iter().peekable(); /// assert_eq!(&0, iter.peek()); /// ``` /// /// [`peek`]: Peekable::peek /// [`peek_mut`]: Peekable::peek_mut /// [`next`]: Iterator::next fn peekable(self) -> Peekable where Self: Sized, { let mut iter = self.into_iter(); Peekable { first: iter.next().unwrap(), rest: iter, } } /// Tests if every element of the iterator matches a predicate. /// /// Because this function always advances the iterator at least once, the /// non-empty guarantee is invalidated. Therefore, this function consumes /// this `NonEmptyIterator`. /// /// See also [`Iterator::all`]. /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![2, 2, 2]; /// assert!(n.nonempty_iter().all(|n| n % 2 == 0)); /// assert!(n.iter().all(|n| n % 2 == 0)); /// ``` #[must_use] fn all(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, { self.into_iter().all(f) } /// Tests if any element of the iterator matches a predicate. /// /// Because this function always advances the iterator at least once, the /// non-empty guarantee is invalidated. Therefore, this function consumes /// this `NonEmptyIterator`. /// /// See also [`Iterator::any`]. /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![1, 1, 1, 2, 1, 1]; /// assert!(n.nonempty_iter().any(|n| n % 2 == 0)); /// assert!(!n.nonempty_iter().any(|n| n % 3 == 0)); /// ``` #[must_use] fn any(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool, { self.into_iter().any(f) } /// Takes two iterators and creates a new non-empty iterator over both in /// sequence. /// /// Note that the second iterator need not be empty. /// /// See also [`Iterator::chain`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3]; /// let s = nes![4, 5, 6]; /// let mut r: Vec<_> = v.into_nonempty_iter().chain(s).collect(); /// r.sort(); /// /// assert_eq!(vec![1, 2, 3, 4, 5, 6], r); /// ``` fn chain(self, other: U) -> Chain where Self: Sized, U: IntoIterator, { Chain { inner: self.into_iter().chain(other), } } /// Creates a non-empty iterator which clones all of its elements. /// /// This is useful when you have an iterator over `&T`, but you need an /// iterator over `T`. /// /// See also [`Iterator::cloned`]. /// /// ``` /// use nonempty_collections::NEVec; /// use nonempty_collections::*; /// /// #[derive(Debug, Clone, PartialEq, Eq)] /// enum Foo { /// A, /// B, /// C, /// } /// /// let v0 = nev![Foo::A, Foo::B, Foo::C]; /// let v1: NEVec<_> = v0.nonempty_iter().collect(); /// let v2: NEVec<_> = v0.nonempty_iter().cloned().collect(); /// /// assert_eq!(nev![&Foo::A, &Foo::B, &Foo::C], v1); /// assert_eq!(nev![Foo::A, Foo::B, Foo::C], v2); /// ``` fn cloned<'a, T>(self) -> Cloned where Self: Sized + NonEmptyIterator, T: Clone + 'a, { Cloned { iter: self } } /// Transforms an iterator into a collection, or some other concrete value. /// /// See also [`Iterator::collect`]. /// /// ``` /// use nonempty_collections::*; /// /// let n0 = nev![1, 2, 3, 4]; /// let n1 = n0.into_nonempty_iter().collect(); /// assert_eq!(nev![1, 2, 3, 4], n1); /// ``` #[must_use] fn collect(self) -> B where Self: Sized, B: FromNonEmptyIterator, { FromNonEmptyIterator::from_nonempty_iter(self) } /// Creates a non-empty iterator which copies all of its elements. /// /// See also [`Iterator::copied`]. /// /// ``` /// use nonempty_collections::*; /// /// let n0 = nev![1, 2, 3, 4]; /// let n1 = n0.nonempty_iter().copied().collect(); /// assert_eq!(n0, n1); /// ``` fn copied<'a, T>(self) -> Copied where Self: Sized + NonEmptyIterator, T: Copy + 'a, { Copied { iter: self.into_iter().copied(), } } /// Consumes the non-empty iterator, counting the number of iterations and /// returning it. /// /// See also [`Iterator::count`]. /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![1]; /// assert_eq!(1, n.nonempty_iter().count().get()); /// /// let n = nev![1, 2, 3, 4, 5, 6]; /// assert_eq!(6, n.nonempty_iter().count().get()); /// ```` #[must_use] fn count(self) -> NonZeroUsize where Self: Sized, { unsafe { NonZeroUsize::new_unchecked(self.into_iter().count()) } } /// Creates a non-empty iterator which gives the current iteration count as /// well as the next value. /// /// See also [`Iterator::enumerate`]. /// /// ``` /// use nonempty_collections::*; /// /// let s = nes!["Doriath", "Gondolin", "Nargothrond"]; /// let total: usize = s.nonempty_iter().enumerate().map(|(c, _)| c).sum(); /// assert_eq!(3, total); /// ``` fn enumerate(self) -> Enumerate where Self: Sized, { Enumerate { iter: self } } /// Creates an iterator which uses a closure to determine if an element /// should be yielded. /// /// **Note:** The iterator returned by this method is **not** a /// `NonEmptyIterator`, since there is never a guarantee that any element /// will pass the predicate. /// /// See also [`Iterator::filter`]. /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![1, 2, 3, 4, 5, 6]; /// let v: Vec<_> = n /// .nonempty_iter() /// .map(|x| x * 2) /// .filter(|&x| x % 3 == 0) /// .collect(); /// assert_eq!(vec![6, 12], v); /// ``` fn filter

(self, predicate: P) -> std::iter::Filter<::IntoIter, P> where Self: Sized, P: FnMut(&::Item) -> bool, { self.into_iter().filter(predicate) } /// Creates an iterator that both filters and maps. /// /// **Note:** The iterator returned by this method is **not** a /// `NonEmptyIterator`, since there is never a guarantee that any element /// will yield `Some` from the given function. /// /// See also [`Iterator::filter_map`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev!["Frodo", "Sam", "", "Peregrin", "Meriadoc"]; /// let firsts: Vec = v /// .into_nonempty_iter() /// .filter_map(|s| s.chars().next()) /// .collect(); /// assert_eq!(vec!['F', 'S', 'P', 'M'], firsts); /// ``` fn filter_map(self, f: F) -> std::iter::FilterMap<::IntoIter, F> where Self: Sized, F: FnMut(::Item) -> Option, { self.into_iter().filter_map(f) } /// Searches for an element of an iterator that satisfies a predicate. /// /// Because this function always advances the iterator at least once, the /// non-empty guarantee is invalidated. Therefore, this function consumes /// this `NonEmptyIterator`. /// /// See also [`Iterator::find`]. /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![1, 3, 5, 7, 9, 10]; /// assert_eq!(Some(&10), n.iter().find(|n| *n % 2 == 0)); /// assert_eq!(None, n.iter().find(|n| **n > 10)); /// ``` #[must_use] fn find

(self, predicate: P) -> Option where Self: Sized, P: FnMut(&Self::Item) -> bool, { self.into_iter().find(predicate) } /// Creates an iterator that works like `map`, but flattens nested, /// non-empty structure. /// /// See also [`Iterator::flat_map`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3]; /// let r = v.into_nonempty_iter().flat_map(|n| nev![n]).collect(); /// assert_eq!(nev![1, 2, 3], r); /// ``` #[inline] fn flat_map(self, f: F) -> FlatMap where Self: Sized, F: FnMut(Self::Item) -> U, U: IntoNonEmptyIterator, { FlatMap { inner: self.into_iter().flat_map(f), } } // fn flatten(self) -> FlatMap // where // Self: Sized, // Self::Item: IntoNonEmptyIterator, // V: NonEmptyIterator, // { // self.flat_map(|ne| ne) // } /// Folds every element into an accumulator by applying an operation, /// returning the final result. /// /// See also [`Iterator::fold`]. /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![1, 2, 3, 4]; /// let r = n.into_nonempty_iter().fold(0, |acc, x| acc + x); /// assert_eq!(10, r); /// ``` #[must_use] fn fold(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { self.into_iter().fold(init, f) } /// Group the non-empty input stream into concrete, non-empty subsections /// via a given function. The cutoff criterion is whether the return value /// of `f` changes between two consecutive elements. /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![1, 1, 2, 3, 3]; /// let r: NEVec<_> = n.into_nonempty_iter().group_by(|n| *n).collect(); /// assert_eq!(r, nev![nev![1, 1], nev![2], nev![3, 3]]); /// /// let n = nev![2, 4, 6, 7, 9, 1, 2, 4, 6, 3]; /// let r: NEVec<_> = n.into_nonempty_iter().group_by(|n| n % 2 == 0).collect(); /// assert_eq!( /// r, /// nev![nev![2, 4, 6], nev![7, 9, 1], nev![2, 4, 6], nev![3]] /// ); /// ``` fn group_by(self, f: F) -> NEGroupBy where Self: Sized, F: FnMut(&Self::Item) -> K, K: PartialEq, { NEGroupBy { iter: self, f } } /// Takes a closure and creates a non-empty iterator which calls that /// closure on each element. /// /// If `self` is a `NonEmptyIterator`, then so is [`Map`]. /// /// See also [`Iterator::map`]. /// /// ``` /// use nonempty_collections::NEVec; /// use nonempty_collections::*; /// /// let s = nes![1, 2, 3]; /// let mut v: NEVec<_> = s.nonempty_iter().map(|n| n * 2).collect(); /// v.sort(); /// assert_eq!(nev![2, 4, 6], v); /// ``` #[inline] fn map(self, f: F) -> Map where Self: Sized, F: FnMut(Self::Item) -> U, { Map { iter: self.into_iter().map(f), } } /// Returns the maximum element of a non-empty iterator. /// /// Unlike [`Iterator::max`], this always yields a value. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![1, 1000, 2, 3]; /// assert_eq!(1000, v.into_nonempty_iter().max()); /// ``` #[must_use] fn max(self) -> Self::Item where Self: Sized, Self::Item: Ord, { self.max_by(Ord::cmp) } /// Returns the element that gives the maximum value with respect to the /// given comparison function. /// /// Unlike [`Iterator::max_by`], this always yields a value. #[must_use] fn max_by(self, compare: F) -> Self::Item where Self: Sized, F: Fn(&Self::Item, &Self::Item) -> Ordering, { let (first, iter) = self.next(); iter.into_iter() .fold(first, |acc, item| match compare(&acc, &item) { Ordering::Less => item, _ => acc, }) } /// Returns the element that gives the maximum value from the /// specified function. /// /// There are two differences with [`Iterator::max_by_key`]: /// - this function always yields a value while [`Iterator::max_by_key`] /// yields an `Option`. /// - if several elements are equally maximum, the *first* element is /// returned (unlike [`Iterator::max_by_key`] which returns the last /// element). /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// let max = nev!["hi", "hey", "rust", "yolo"] /// .into_nonempty_iter() /// .max_by_key(|item| item.len()); /// assert_eq!("rust", max); /// ``` #[must_use] fn max_by_key(self, mut key: F) -> Self::Item where Self: Sized, B: Ord, F: FnMut(&Self::Item) -> B, { self.map(|item| (key(&item), item)) .max_by(|(left_key, _), (right_key, _)| left_key.cmp(right_key)) .1 } /// Returns the minimum element of a non-empty iterator. /// /// Unlike [`Iterator::min`], this always yields a value. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![1000, 1, 2000, 3000]; /// assert_eq!(1, v.into_nonempty_iter().min()); /// ``` #[must_use] fn min(self) -> Self::Item where Self: Sized, Self::Item: Ord, { self.min_by(Ord::cmp) } /// Returns the element that gives the minimum value with respect to the /// given comparison function. /// /// Unlike [`Iterator::min_by`], this always yields a value. #[must_use] fn min_by(self, compare: F) -> Self::Item where Self: Sized, F: Fn(&Self::Item, &Self::Item) -> Ordering, { let (first, iter) = self.next(); iter.into_iter() .fold(first, |acc, item| match compare(&acc, &item) { Ordering::Greater => item, _ => acc, }) } /// Returns the element that gives the minimum value from the /// specified function. /// /// There are two differences with [`Iterator::min_by_key`]: /// - this function always yields a value while [`Iterator::min_by_key`] /// yields an `Option`. /// - if several elements are equally minimum, the *first* element is /// returned (unlike [`Iterator::min_by_key`] which returns the last /// element). /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// let min = nev!["hi", "hello", "greetings", "hy"] /// .into_nonempty_iter() /// .min_by_key(|item| item.len()); /// assert_eq!("hi", min); /// ``` #[must_use] fn min_by_key(self, mut key: F) -> Self::Item where Self: Sized, B: Ord, F: FnMut(&Self::Item) -> B, { self.map(|item| (key(&item), item)) .min_by(|(left_key, _), (right_key, _)| left_key.cmp(right_key)) .1 } /// Sort all iterator elements into a new non-empty iterator in ascending /// order. /// /// **Note:** This consumes the entire iterator, uses the /// [`NEVec::sort_by_key`] method and returns the result as a new iterator /// that owns its elements. /// /// This sort is stable (i.e., does not reorder equal elements). /// /// The sorted iterator, if directly collected to a `NEVec`, is converted /// without any extra copying or allocation cost. /// /// ``` /// use nonempty_collections::*; /// /// // sort people in descending order by age /// let people = nev![("Jane", 20), ("John", 18), ("Jill", 30), ("Jack", 30)]; /// /// let oldest_people_first = people /// .into_nonempty_iter() /// .sorted_by_key(|x| -x.1) /// .map(|(person, _age)| person) /// .collect::>(); /// /// assert_eq!(nev!["Jill", "Jack", "Jane", "John"], oldest_people_first); /// ``` fn sorted_by_key(self, f: F) -> crate::vector::IntoIter where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K, { let mut v = NEVec::from_nonempty_iter(self); v.sort_by_key(f); v.into_nonempty_iter() } /// Returns the `n`th element of the iterator. /// /// This function consumes this `NonEmptyIterator`. [`Self::next()`] can be /// used for getting the first element and a reference to an iterator /// over the remaining elements. /// /// See also [`Iterator::nth`]. /// /// ``` /// use nonempty_collections::*; /// /// let n = nev![0, 1, 2, 3, 4, 5, 6]; /// assert_eq!(Some(&0), n.nonempty_iter().nth(0)); /// /// let n = nev![0, 1, 2, 3, 4, 5, 6]; /// assert_eq!(Some(&6), n.nonempty_iter().nth(6)); /// /// let n = nev![0, 1, 2, 3, 4, 5, 6]; /// assert_eq!(None, n.nonempty_iter().nth(100)); /// ``` fn nth(self, n: usize) -> Option where Self: Sized, { self.into_iter().nth(n) } /// Skip the first `n` elements. /// /// Note that the result will not be non-empty. /// /// See also [`Iterator::skip`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3]; /// assert_eq!(Some(&3), v.nonempty_iter().skip(2).next()); /// ``` fn skip(self, n: usize) -> std::iter::Skip<::IntoIter> where Self: Sized, { self.into_iter().skip(n) } /// Skips over all initial elements that pass a given predicate. /// /// **Note**: This does not yield a non-empty iterator, since there is no /// guarantee that anything will fail the predicate. /// /// See also [`Iterator::skip_while`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![2, 4, 6, 7, 8]; /// let r: Vec<_> = v.into_nonempty_iter().skip_while(|n| n % 2 == 0).collect(); /// assert_eq!(vec![7, 8], r); /// ``` fn skip_while

(self, pred: P) -> std::iter::SkipWhile<::IntoIter, P> where Self: Sized, P: FnMut(&::Item) -> bool, { self.into_iter().skip_while(pred) } /// Sums the elements of a non-empty iterator. /// /// See also [`Iterator::sum`]. /// /// ``` /// use nonempty_collections::*; /// /// let sum: u32 = nev![1, 2, 3, 4].nonempty_iter().sum(); /// assert_eq!(10, sum); /// ``` #[must_use] fn sum(self) -> S where Self: Sized + IntoIterator, S: Sum<::Item>, { Sum::sum(self.into_iter()) } /// Iterates over the first `n` elements, or fewer if the underlying /// iterator ends sooner. /// /// See also [`Iterator::take`]. /// /// # Panics /// /// Panics if `n == 0`. /// /// # Examples /// /// ``` /// use core::num::NonZeroUsize; /// /// use nonempty_collections::*; /// /// let n: NEVec<_> = nev![1, 2, 3] /// .nonempty_iter() /// .map(|n| n * 2) /// .take(NonZeroUsize::new(2).unwrap()) /// .collect(); /// assert_eq!(nev![2, 4], n); /// ``` fn take(self, n: NonZeroUsize) -> Take where Self: Sized, { Take { iter: self.into_iter().take(n.get()), } } /// Iterates over all initial elements that pass a given predicate. /// /// **Note**: This does not yield a non-empty iterator, since there is no /// guarantee that anything will pass the predicate. /// /// See also [`Iterator::take_while`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![2, 4, 6, 7, 8]; /// let r: Vec<_> = v.into_nonempty_iter().take_while(|n| n % 2 == 0).collect(); /// assert_eq!(vec![2, 4, 6], r); /// ``` fn take_while

(self, pred: P) -> std::iter::TakeWhile<::IntoIter, P> where Self: Sized, P: FnMut(&::Item) -> bool, { self.into_iter().take_while(pred) } /// Iterates over the entire non-empty iterator, multiplying all the /// elements. /// /// See also [`Iterator::product`]. /// /// ``` /// use nonempty_collections::*; /// /// let prod: u32 = nev![1, 2, 3, 4].nonempty_iter().product(); /// assert_eq!(24, prod); /// ``` #[must_use] fn product

(self) -> P where Self: Sized + IntoIterator, P: Product<::Item>, { Product::product(self.into_iter()) } /// "Zips up" two non-empty iterators into a single one, while preserving /// non-emptiness. /// /// See also [`Iterator::zip`]. /// /// ``` /// use nonempty_collections::*; /// /// let a = nev![1, 2, 3]; /// let b = nev![4, 5, 6, 7]; /// let r = a /// .into_nonempty_iter() /// .zip(b) /// .map(|(av, bv)| av + bv) /// .collect(); /// assert_eq!(nev![5, 7, 9], r); /// ``` fn zip(self, other: U) -> Zip where Self: Sized, U: IntoNonEmptyIterator, { Zip { inner: self.into_iter().zip(other), } } /// Reduce a non-empty iterator of pairs into a pair of concrete containers. /// /// See also [`Iterator::unzip`]. /// /// ``` /// use nonempty_collections::*; /// /// let v = nev![('a', 1), ('b', 2), ('c', 3)]; /// let (a, b): (NEVec, NEVec) = v.into_nonempty_iter().unzip(); /// /// assert_eq!(a, nev!['a', 'b', 'c']); /// assert_eq!(b, nev![1, 2, 3]); /// ``` /// /// Fortunately, the [`Extend`] impl of [`crate::NEMap`] naturally fits /// this, thus you can split keys and values cleanly: /// /// ``` /// use nonempty_collections::*; /// /// let m = nem!['a' => 1, 'b' => 2, 'c' => 3]; /// let (a, b): (NESet, NESet) = m.into_nonempty_iter().unzip(); /// /// assert_eq!(a, nes!['a', 'b', 'c']); /// assert_eq!(b, nes![1, 2, 3]); /// ``` fn unzip(self) -> (FromA, FromB) where FromA: Singleton + Extend, FromB: Singleton + Extend, Self: Sized + NonEmptyIterator, { let ((a, b), iter) = self.next(); let from_a = Singleton::singleton(a); let from_b = Singleton::singleton(b); let mut fused = (from_a, from_b); fused.extend(iter); fused } /// Reduces the elements to a single one, by repeatedly applying a reducing /// operation. /// /// See also [`Iterator::reduce`]. /// /// ``` /// use nonempty_collections::*; /// /// let a = nev![1, 2, 3, 4]; /// let b = a.clone(); /// /// let x = a.into_nonempty_iter().reduce(|acc, v| acc + v); /// assert_eq!(x, 10); /// /// let y = b.into_nonempty_iter().reduce(|acc, v| acc * v); /// assert_eq!(y, 24); /// ``` #[must_use] fn reduce(self, f: F) -> Self::Item where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item, { self.into_iter().reduce(f).unwrap() } } /// Conversion from a [`NonEmptyIterator`]. pub trait FromNonEmptyIterator: Sized { /// Creates a value from a [`NonEmptyIterator`]. fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator; } impl FromNonEmptyIterator for Vec { fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { iter.into_nonempty_iter().into_iter().collect() } } impl FromNonEmptyIterator<(K, V)> for HashMap where K: Eq + Hash, S: BuildHasher + Default, { fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { iter.into_nonempty_iter().into_iter().collect() } } impl FromNonEmptyIterator for HashSet where T: Eq + Hash, S: BuildHasher + Default, { fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { iter.into_nonempty_iter().into_iter().collect() } } impl FromNonEmptyIterator> for Result where V: FromNonEmptyIterator, { fn from_nonempty_iter(iter: I) -> Result where I: IntoNonEmptyIterator>, { let (head, rest) = iter.into_nonempty_iter().next(); let head: A = head?; let mut buf = NEVec::new(head); for item in rest { let item: A = item?; buf.push(item); } let new_iter = buf.into_nonempty_iter(); let output: V = FromNonEmptyIterator::from_nonempty_iter(new_iter); Ok(output) } } /// Conversion into a [`NonEmptyIterator`]. pub trait IntoNonEmptyIterator: IntoIterator { /// Which kind of [`NonEmptyIterator`] are we turning this into? type IntoNEIter: NonEmptyIterator; /// Creates a [`NonEmptyIterator`] from a value. fn into_nonempty_iter(self) -> Self::IntoNEIter; } impl IntoNonEmptyIterator for I { type IntoNEIter = I; fn into_nonempty_iter(self) -> Self::IntoNEIter { self } } /// Similar to [`std::iter::Map`], but with additional non-emptiness guarantees. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Map { iter: std::iter::Map, } impl NonEmptyIterator for Map where I: NonEmptyIterator, F: FnMut(I::Item) -> U, { } /// ``` /// use nonempty_collections::*; /// /// let v: Vec<_> = nev![1, 2, 3].nonempty_iter().map(|n| n * 2).collect(); /// ``` impl IntoIterator for Map where I: NonEmptyIterator, F: FnMut(I::Item) -> U, { type Item = U; type IntoIter = std::iter::Map; fn into_iter(self) -> Self::IntoIter { self.iter } } impl std::fmt::Debug for Map where I: NonEmptyIterator, I::IntoIter: std::fmt::Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.iter.fmt(f) } } /// An iterator that clones the elements of an underlying iterator. /// /// See also [`std::iter::Cloned`]. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Cloned { iter: I, } impl<'a, I, T: 'a> NonEmptyIterator for Cloned where I: NonEmptyIterator, T: Clone, { } impl<'a, I, T: 'a> IntoIterator for Cloned where I: IntoIterator, T: Clone, { type Item = T; type IntoIter = std::iter::Cloned; fn into_iter(self) -> Self::IntoIter { self.iter.into_iter().cloned() } } impl std::fmt::Debug for Cloned { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.iter.fmt(f) } } /// An iterator that yields the current count and the element during iteration. /// /// See also [`std::iter::Enumerate`]. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Enumerate { iter: I, } impl NonEmptyIterator for Enumerate where I: NonEmptyIterator {} impl IntoIterator for Enumerate where I: IntoIterator, { type Item = (usize, I::Item); type IntoIter = std::iter::Enumerate; fn into_iter(self) -> Self::IntoIter { self.iter.into_iter().enumerate() } } impl std::fmt::Debug for Enumerate { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator that only iterates over the first `n` iterations. /// /// See also [`Iterator::take`]. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Take { iter: std::iter::Take, } impl NonEmptyIterator for Take where I: NonEmptyIterator {} /// ``` /// use core::num::NonZeroUsize; /// /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3]; /// let r = v /// .nonempty_iter() /// .take(NonZeroUsize::new(1).unwrap()) /// .into_iter() /// .count(); /// assert_eq!(1, r); /// ``` impl IntoIterator for Take where I: NonEmptyIterator, { type Item = I::Item; type IntoIter = std::iter::Take; fn into_iter(self) -> Self::IntoIter { self.iter } } impl std::fmt::Debug for Take where I: NonEmptyIterator, I::IntoIter: std::fmt::Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator that links two iterators together, in a chain. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Chain { inner: std::iter::Chain, } impl NonEmptyIterator for Chain where A: Iterator, B: Iterator, { } impl IntoIterator for Chain where A: Iterator, B: Iterator, { type Item = A::Item; type IntoIter = std::iter::Chain; fn into_iter(self) -> Self::IntoIter { self.inner } } impl std::fmt::Debug for Chain where A: std::fmt::Debug, B: std::fmt::Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.fmt(f) } } /// A non-empty iterator that yields an element exactly once. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Once { inner: std::iter::Once, } impl Once { pub(crate) fn new(value: T) -> Once { Once { inner: std::iter::once(value), } } } impl NonEmptyIterator for Once {} impl IntoIterator for Once { type Item = T; type IntoIter = std::iter::Once; fn into_iter(self) -> Self::IntoIter { self.inner } } impl std::fmt::Debug for Once { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.fmt(f) } } /// A non-empty iterator that copies the elements of an underlying non-empty /// iterator. /// /// See also [`std::iter::Copied`]. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Copied { iter: std::iter::Copied, } impl<'a, I, T: 'a> NonEmptyIterator for Copied where I: Iterator, T: Copy, { } impl<'a, I, T: 'a> IntoIterator for Copied where I: Iterator, T: Copy, { type Item = T; type IntoIter = std::iter::Copied; fn into_iter(self) -> Self::IntoIter { self.iter } } impl<'a, I, T: 'a> std::fmt::Debug for Copied where I: Iterator + std::fmt::Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator that "zips up" its sources. /// /// See also [`std::iter::Zip`]. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Zip { inner: std::iter::Zip, } impl NonEmptyIterator for Zip where A: Iterator, B: Iterator, { } impl IntoIterator for Zip where A: Iterator, B: Iterator, { type Item = (A::Item, B::Item); type IntoIter = std::iter::Zip; fn into_iter(self) -> Self::IntoIter { self.inner } } impl std::fmt::Debug for Zip where A: std::fmt::Debug, B: std::fmt::Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.fmt(f) } } /// Wrapper struct for powering [`NonEmptyIterator::group_by`]. #[derive(Debug)] pub struct NEGroupBy { iter: I, f: F, } impl NonEmptyIterator for NEGroupBy where I: NonEmptyIterator, F: FnMut(&I::Item) -> K, K: PartialEq, { } impl IntoIterator for NEGroupBy where I: IntoIterator, F: FnMut(&I::Item) -> K, K: PartialEq, { type Item = NEVec; type IntoIter = GroupBy<::IntoIter, K, I::Item, F>; fn into_iter(self) -> Self::IntoIter { GroupBy { iter: self.iter.into_iter(), f: Rc::new(RefCell::new(self.f)), prev: None, curr: None, } } } /// A (possibly empty) definition of the group-by operation that enables /// [`NEGroupBy`] to be written. You aren't expected to use this directly, thus /// there is no way to construct one. #[derive(Debug)] pub struct GroupBy { iter: I, f: Rc>, prev: Option, curr: Option>, } impl Iterator for GroupBy where I: Iterator, F: FnMut(&I::Item) -> K, K: PartialEq, { type Item = NEVec; fn next(&mut self) -> Option { loop { match self.iter.next() { None => return self.curr.take(), Some(v) => { let k = { let mut f = self.f.borrow_mut(); f(&v) }; match (self.prev.as_ref(), &mut self.curr) { // Continue some run of similar values. (Some(p), Some(c)) if p == &k => { c.push(v); } // We found a break; finally yield an NEVec. (Some(_), Some(_)) => { let curr = self.curr.take(); self.curr = Some(nev![v]); self.prev = Some(k); return curr; } // Very first iteration. (_, _) => { self.prev = Some(k); self.curr = Some(nev![v]); } } } } } } } /// Flatten nested, non-empty structures. /// /// See also [`std::iter::FlatMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct FlatMap { inner: std::iter::FlatMap, } impl U> NonEmptyIterator for FlatMap {} /// ``` /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3]; /// let r: Vec<_> = v /// .into_nonempty_iter() /// .flat_map(|n| nev![n]) /// .into_iter() /// .collect(); /// assert_eq!(vec![1, 2, 3], r); /// ``` impl U> IntoIterator for FlatMap { type Item = U::Item; type IntoIter = std::iter::FlatMap; fn into_iter(self) -> Self::IntoIter { self.inner } } impl std::fmt::Debug for FlatMap where U: IntoIterator, U::IntoIter: std::fmt::Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.fmt(f) } } impl Clone for FlatMap where U: Clone + IntoIterator, U::IntoIter: Clone, { fn clone(&self) -> Self { FlatMap { inner: self.inner.clone(), } } } /// An adapter for regular iterators that are known to be non-empty. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct NonEmptyIterAdapter { inner: I, } impl NonEmptyIterator for NonEmptyIterAdapter {} impl IntoIterator for NonEmptyIterAdapter where I: Iterator, { type Item = I::Item; type IntoIter = I; fn into_iter(self) -> Self::IntoIter { self.inner } } impl std::fmt::Debug for NonEmptyIterAdapter { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.fmt(f) } } /// Convenience trait extending [`IntoIterator`]. pub trait IntoIteratorExt { /// The type of the elements being iterated over. type Item; /// Which kind of [`NonEmptyIterator`] are we turning this into? type IntoIter: NonEmptyIterator; /// Tries to convert `self` into a [`NonEmptyIterator`]. /// /// ``` /// use nonempty_collections::*; /// /// let a = vec![1]; /// let x = a.try_into_nonempty_iter(); /// assert!(x.is_some()); /// /// let y = x.unwrap().collect::>(); /// assert_eq!(y.len().get(), 1); /// ``` /// /// ``` /// use nonempty_collections::*; /// /// let b: Vec = vec![]; /// let x = b.try_into_nonempty_iter(); /// /// assert!(x.is_none()); /// ``` /// /// To construct non-empty collections directly, consider macros like /// [`crate::nev!`]. fn try_into_nonempty_iter(self) -> Option; } impl IntoIteratorExt for T where T: IntoIterator, { type Item = T::Item; type IntoIter = NonEmptyIterAdapter>; /// Converts `self` into a non-empty iterator or returns `None` if /// the iterator is empty. fn try_into_nonempty_iter(self) -> Option { let mut iter = self.into_iter().peekable(); iter.peek() .is_some() .then_some(NonEmptyIterAdapter { inner: iter }) } } /// A non-empty iterator with a `peek()` that returns a reference to the first /// element. /// /// This `struct` is created by the [`peekable`] method on [`NonEmptyIterator`]. /// See its documentation for more. /// /// [`peekable`]: NonEmptyIterator::peekable #[derive(Debug, Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Peekable { first: I::Item, rest: I, } impl Peekable { /// Returns a reference to the first value without advancing or consuming /// the iterator. pub const fn peek(&self) -> &I::Item { &self.first } /// Returns a mutable reference to the first value without advancing or /// consuming the iterator. pub fn peek_mut(&mut self) -> &mut I::Item { &mut self.first } } impl NonEmptyIterator for Peekable {} impl IntoIterator for Peekable { type Item = I::Item; type IntoIter = std::iter::Chain, I>; fn into_iter(self) -> Self::IntoIter { std::iter::once(self.first).chain(self.rest) } } #[cfg(test)] mod tests { use super::*; use crate::nem; use crate::NEMap; #[test] fn into_hashset() { let m = nem!['a' => 1, 'b' => 2, 'c' => 3]; let _: HashSet<_> = m.values().collect(); } #[test] fn into_hashmap() { let m = nem!['a' => 1, 'b' => 2, 'c' => 3]; let h: HashMap<_, _> = m.iter().map(|(k, v)| (*k, *v)).collect(); let n = NEMap::try_from(h).unwrap(); assert_eq!(m, n); } #[test] fn peekable() { let v = nev![0, 1, 2, 3]; let iter = v.into_nonempty_iter().peekable(); assert_eq!(&0, iter.peek()); let all = iter.collect::>(); assert_eq!(nev![0, 1, 2, 3], all); let mut iter = all.into_nonempty_iter().peekable(); *iter.peek_mut() = 7; let (first, rest) = iter.next(); assert_eq!(7, first); assert_eq!(vec![1, 2, 3], rest.collect::>()); let u = nev![0, 1, 2]; let p: NEVec<_> = u .into_nonempty_iter() .map(|n| n + 1) .peekable() .map(|n| n * 2) .collect(); assert_eq!(nev![2, 4, 6], p); } } nonempty-collections-1.1.0/src/itertools.rs000064400000000000000000000066321046102023000172000ustar 00000000000000//! Extra non-empty iterator adaptors, functions and macros. //! //! To extend [`NonEmptyIterator`] with methods in this crate, import //! the [`NonEmptyItertools`] trait: //! //! ``` //! use nonempty_collections::NonEmptyItertools; //! ``` use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; use core::fmt; use itertools::Itertools; use std::fmt::Debug; /// A [`NonEmptyIterator`] blanket implementation that provides extra adaptors /// and methods, similar to [`Itertools`](https://docs.rs/itertools/) for `Iterator`. pub trait NonEmptyItertools: NonEmptyIterator { /// Return a non-empty iterator adaptor that iterates over the non-empty /// cartesian product of the element sets of two iterators `self` and /// `J`. /// /// `NonEmptyIterator`element type is `(Self::Item, J::Item)`. /// /// ``` /// use nonempty_collections::*; /// /// let product = nev![0, 1] /// .nonempty_iter() /// .copied() /// .cartesian_product("αβ".chars().try_into_nonempty_iter().unwrap()) /// .collect::>(); /// assert_eq!(nev![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')], product); /// ``` fn cartesian_product(self, other: J) -> Product where Self: Sized, Self::Item: Clone, J: IntoNonEmptyIterator, ::IntoIter: Clone, { Product { inner: Itertools::cartesian_product(self.into_iter(), other.into_nonempty_iter()), } } /// Check whether all elements are unique (non equal). /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// /// let data = nev![1, 2, 3, 4, 1, 5]; /// assert!(!nev![1, 2, 3, 4, 1, 5].nonempty_iter().all_unique()); /// assert!(nev![2, 3, 4, 1, 5].nonempty_iter().all_unique()); /// ``` #[must_use] fn all_unique(self) -> bool where Self: Sized, Self::Item: Eq + std::hash::Hash, { self.into_iter().all_unique() } } impl NonEmptyItertools for T where T: NonEmptyIterator + ?Sized {} /// A non-empty 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()`](crate::itertools::Itertools::cartesian_product) /// for more information. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct Product where I: NonEmptyIterator, J: NonEmptyIterator, { inner: itertools::Product, } impl NonEmptyIterator for Product where I: NonEmptyIterator, J: NonEmptyIterator, J::Item: Clone, I::Item: Clone, J::IntoIter: Clone, I::IntoIter: Clone, { } impl IntoIterator for Product where I: NonEmptyIterator, J: NonEmptyIterator, J::Item: Clone, I::Item: Clone, J::IntoIter: Clone, I::IntoIter: Clone, { type Item = (I::Item, J::Item); type IntoIter = itertools::Product; fn into_iter(self) -> Self::IntoIter { self.inner } } impl Debug for Product where I: NonEmptyIterator, J: NonEmptyIterator, I::Item: Debug, J::Item: Debug, I::IntoIter: Debug, J::IntoIter: Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Debug::fmt(&self.inner, f) } } nonempty-collections-1.1.0/src/lib.rs000064400000000000000000000137041046102023000157200ustar 00000000000000#![allow(rustdoc::redundant_explicit_links)] // the explicit links are needed for cargo rdme //! Non-empty variants of the standard collections. //! //! Non-emptiness can be a powerful guarantee. If your main use of `Vec` is as //! an `Iterator`, then you may not need to distinguish on emptiness. But there //! are indeed times when the `Vec` you receive as a function argument needs to //! be non-empty or your function can't proceed. Similarly, there are times when //! the `Vec` you return to a calling user needs to promise it actually contains //! something. //! //! With `NEVec`, you're freed from the boilerplate of constantly needing to //! check `is_empty()` or pattern matching before proceeding, or erroring if you //! can't. So overall, code, type signatures, and logic become cleaner. //! //! Consider that unlike `Vec`, [`NEVec::first()`] and [`NEVec::last()`] don't //! return in `Option`; they always succeed. //! //! Alongside [`NEVec`](crate::vector::NEVec) are its cousins //! [`NESlice`](crate::slice::NESlice), [`NEMap`](crate::map::NEMap), and //! [`NESet`](crate::set::NESet), which are all guaranteed to contain at least //! one item. //! //! # Examples //! //! The simplest way to construct these non-empty collections is via their //! macros: [`nev!`], [`nes!`], and [`nem!`]: //! //! ``` //! use nonempty_collections::*; //! //! let v: NEVec = nev![1, 2, 3]; //! let s: NESet = nes![1, 2, 2, 3]; // 1 2 3 //! let m: NEMap<&str, bool> = nem!["a" => true, "b" => false]; //! assert_eq!(&1, v.first()); //! assert_eq!(3, s.len().get()); //! assert!(m.get("a").unwrap()); //! ``` //! //! Unlike the familiar `vec!` macro, `nev!` and friends require at least one //! element: //! //! ``` //! use nonempty_collections::nev; //! //! let v = nev![1]; //! ``` //! //! A value must be provided: //! //! ```compile_fail //! let v = nev![]; // Doesn't compile! //! ``` //! //! Like `Vec`, you can also construct a [`NEVec`](crate::vector::NEVec) the old //! fashioned way with [`NEVec::new()`] or its constructor: //! //! ``` //! use nonempty_collections::NEVec; //! //! let mut l = NEVec::try_from_vec(vec![42, 36, 58]).unwrap(); //! assert_eq!(&42, l.first()); //! //! l.push(9001); //! assert_eq!(l.last(), &9001); //! ``` //! //! And if necessary, you're free to convert to and from `Vec`: //! //! ``` //! use nonempty_collections::nev; //! use nonempty_collections::NEVec; //! //! let l: NEVec = nev![42, 36, 58, 9001]; //! let v: Vec = l.into(); //! assert_eq!(v, vec![42, 36, 58, 9001]); //! //! let u: Option> = NEVec::try_from_vec(v); //! assert_eq!(Some(nev![42, 36, 58, 9001]), u); //! ``` //! //! # Iterators //! //! This library extends the notion of non-emptiness to iterators, and provides //! the [`NonEmptyIterator`](crate::iter::NonEmptyIterator) trait. This has some //! interesting consequences: //! //! - Functions like `map` preserve non-emptiness. //! - Functions like `max` always have a result. //! - A non-empty iterator chain can be `collect`ed back into a non-empty //! structure. //! - You can chain many operations together without having to double-check for //! emptiness. //! //! ``` //! use nonempty_collections::*; //! //! let v: NEVec<_> = nev![1, 2, 3].into_nonempty_iter().map(|n| n + 1).collect(); //! assert_eq!(&2, v.first()); //! ``` //! //! Consider also [`IntoIteratorExt::try_into_nonempty_iter`] for converting any //! given [`Iterator`] and [`IntoIterator`] into a non-empty one, if it contains //! at least one item. //! //! # Arrays //! //! Since fixed-size arrays are by definition already not empty, they aren't //! given a special wrapper type like [`NEVec`](crate::vector::NEVec). Instead, //! we enable them to be easily iterated over in a compatible way: //! //! ``` //! use nonempty_collections::*; //! //! let a: [u32; 4] = [1, 2, 3, 4]; //! let v: NEVec<_> = a.into_nonempty_iter().map(|n| n + 1).collect(); //! assert_eq!(nev![2, 3, 4, 5], v); //! ``` //! See [`NonEmptyArrayExt`](crate::array::NonEmptyArrayExt) for more //! conversions. //! //! # Caveats //! //! Since `NEVec`, `NEMap`, and `NESet` must have a least one element, it is not //! possible to implement the [`FromIterator`] trait for them. We can't //! know, in general, if any given standard-library [`Iterator`] actually //! contains something. //! //! # Features //! //! * `serde`: `serde` support. //! * `indexmap`: adds [`NEIndexMap`](crate::index_map::NEIndexMap) a non-empty [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/). //! * `itertools`: adds [`NonEmptyItertools`](crate::itertools::NonEmptyItertools) a non-empty variant of [`itertools`](https://docs.rs/itertools/latest/itertools/). //! * `either`: adds [`NEEither`](crate::either::NEEither) a non-empty variant of `Either` from the [`either` crate](https://docs.rs/either/latest/either/). pub mod array; pub mod iter; pub mod map; pub mod set; pub mod slice; pub mod vector; #[cfg(feature = "either")] pub mod either; #[cfg(feature = "indexmap")] pub mod index_map; #[cfg(feature = "itertools")] pub mod itertools; pub use array::ArrayNonEmptyIterator; pub use array::NonEmptyArrayExt; #[cfg(feature = "either")] pub use either::NEEither; #[cfg(feature = "indexmap")] pub use index_map::NEIndexMap; pub use iter::FromNonEmptyIterator; pub use iter::IntoIteratorExt; pub use iter::IntoNonEmptyIterator; pub use iter::NonEmptyIterator; #[cfg(feature = "itertools")] pub use itertools::NonEmptyItertools; pub use map::NEMap; pub use set::NESet; pub use slice::NESlice; pub use vector::NEVec; /// Errors typically involving type conversions. #[derive(Debug, Clone, Copy)] pub enum Error { /// There was nothing to decode. Empty, } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::Empty => write!(f, "Given collection was empty"), } } } /// A type that can be instantiated via a single item - the kindred spirit to /// [`Default`]. pub trait Singleton { type Item; fn singleton(item: Self::Item) -> Self; } nonempty-collections-1.1.0/src/map.rs000064400000000000000000000507451046102023000157350ustar 00000000000000//! Non-empty [`HashMap`]s. use core::fmt; use std::borrow::Borrow; use std::collections::HashMap; use std::hash::BuildHasher; use std::hash::Hash; use std::num::NonZeroUsize; #[cfg(feature = "serde")] use serde::Deserialize; #[cfg(feature = "serde")] use serde::Serialize; use crate::FromNonEmptyIterator; use crate::IntoIteratorExt; use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; use crate::Singleton; /// Like the [`crate::nev!`] macro, but for Maps. A nice short-hand for /// constructing [`NEMap`] values. /// /// ``` /// use nonempty_collections::nem; /// /// let m = nem! {"elves" => 3000, "orcs" => 10000}; /// assert_eq!(2, m.len().get()); /// ``` #[macro_export] macro_rules! nem { ($hk:expr => $hv:expr, $( $xk:expr => $xv:expr ),* $(,)?) => {{ let mut map = $crate::NEMap::new($hk, $hv); $( map.insert($xk, $xv); )* map }}; ($hk:expr => $hv:expr) => { $crate::NEMap::new($hk, $hv) } } /// A non-empty, growable `HashMap`. /// /// ``` /// use nonempty_collections::nem; /// /// let m = nem!["elves" => 3000, "orcs" => 10000]; /// assert_eq!(2, m.len().get()); /// ``` #[allow(clippy::unsafe_derive_deserialize)] #[cfg_attr( feature = "serde", derive(Deserialize, Serialize), serde(bound( serialize = "K: Eq + Hash + Clone + Serialize, V: Clone + Serialize, S: Clone + BuildHasher", deserialize = "K: Eq + Hash + Clone + Deserialize<'de>, V: Deserialize<'de>, S: Default + BuildHasher" )), serde(into = "HashMap", try_from = "HashMap") )] #[derive(Clone)] pub struct NEMap { inner: HashMap, } impl NEMap where K: Eq + Hash, { /// Creates a new `NEMap` with a single element. #[must_use] pub fn new(k: K, v: V) -> NEMap { let mut inner = HashMap::new(); inner.insert(k, v); NEMap { inner } } /// Creates a new `NEMap` with a single element and specified capacity. /// ``` /// use std::num::*; /// /// use nonempty_collections::*; /// let map = NEMap::with_capacity(NonZeroUsize::MIN, 1, 1); /// assert_eq!(nem! { 1 => 1 }, map); /// assert!(map.capacity().get() >= 1); /// ``` #[must_use] pub fn with_capacity(capacity: NonZeroUsize, k: K, v: V) -> NEMap { let mut inner = HashMap::with_capacity(capacity.get()); inner.insert(k, v); NEMap { inner } } } impl NEMap { /// Attempt a conversion from [`HashMap`], consuming the given `HashMap`. /// Will return `None` if the `HashMap` is empty. /// /// ``` /// use std::collections::*; /// /// use nonempty_collections::*; /// /// let mut map = HashMap::new(); /// map.extend([("a", 1), ("b", 2)]); /// assert_eq!(Some(nem! {"a" => 1, "b" => 2}), NEMap::try_from_map(map)); /// let map: HashMap<(), ()> = HashMap::new(); /// assert_eq!(None, NEMap::try_from_map(map)); /// ``` #[must_use] pub fn try_from_map(map: HashMap) -> Option { if map.is_empty() { None } else { Some(Self { inner: map }) } } /// Returns the number of elements the map can hold without reallocating. #[must_use] pub fn capacity(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.capacity()) } } /// Returns a reference to the map's `BuildHasher`. #[must_use] pub fn hasher(&self) -> &S { self.inner.hasher() } /// Returns a regular iterator over the entries in this non-empty map. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter()`. pub fn iter(&self) -> std::collections::hash_map::Iter<'_, K, V> { self.inner.iter() } /// Returns a regular mutable iterator over the entries in this non-empty /// map. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter_mut()`. pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<'_, K, V> { self.inner.iter_mut() } /// An iterator visiting all elements in arbitrary order. The iterator /// element type is `(&'a K, &'a V)`. pub fn nonempty_iter(&self) -> Iter<'_, K, V> { Iter { iter: self.inner.iter(), } } /// An iterator visiting all elements in arbitrary order. The iterator /// element type is `(&'a K, &'a mut V)`. /// /// # Panics /// /// If you manually advance this iterator until empty and then call `first`, /// you're in for a surprise. pub fn nonempty_iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut { iter: self.inner.iter_mut(), } } /// An iterator visiting all keys in arbitrary order. The iterator element /// type is `&'a K`. /// /// ``` /// use nonempty_collections::*; /// /// let m = nem!["Valmar" => "Vanyar", "Tirion" => "Noldor", "Alqualondë" => "Teleri"]; /// let mut v: NEVec<_> = m.keys().collect(); /// v.sort(); /// assert_eq!(nev![&"Alqualondë", &"Tirion", &"Valmar"], v); /// ``` pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.inner.keys(), } } /// Returns the number of elements in the map. Always 1 or more. /// /// ``` /// use nonempty_collections::nem; /// /// let m = nem!["a" => 1, "b" => 2]; /// assert_eq!(2, m.len().get()); /// ``` #[must_use] pub fn len(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.len()) } } /// A `NEMap` is never empty. #[deprecated(since = "0.1.0", note = "A NEMap is never empty.")] #[must_use] pub const fn is_empty(&self) -> bool { false } /// An iterator visiting all values in arbitrary order. The iterator element /// type is `&'a V`. /// /// ``` /// use nonempty_collections::*; /// /// let m = nem!["Valmar" => "Vanyar", "Tirion" => "Noldor", "Alqualondë" => "Teleri"]; /// let mut v: NEVec<_> = m.values().collect(); /// v.sort(); /// assert_eq!(nev![&"Noldor", &"Teleri", &"Vanyar"], v); /// ``` pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.inner.values(), } } // /// An iterator visiting all values mutably in arbitrary order. The iterator // /// element type is `&'a mut V`. // /// // /// ``` // /// use nonempty_collections::nem; // /// // /// let mut m = nem!["Valmar" => 10000, "Tirion" => 10000, "Alqualondë" => // 10000]; /// // /// for v in m.values_mut() { // /// *v += 1000; // /// } // /// ``` // pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { // ValuesMut { // inner: self.iter_mut(), // head_val: todo!(), // } // } } impl NEMap where K: Eq + Hash, S: BuildHasher, { /// Returns true if the map contains a value. /// /// ``` /// use nonempty_collections::nem; /// /// let m = nem!["Jack" => 8]; /// assert!(m.contains_key("Jack")); /// assert!(!m.contains_key("Colin")); /// ``` #[must_use] pub fn contains_key(&self, k: &Q) -> bool where K: Borrow, Q: Eq + Hash + ?Sized, { self.inner.contains_key(k) } /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's value type, but `Hash` and /// `Eq` on the borrowed form must match those for the key type. /// /// ``` /// use nonempty_collections::nem; /// /// let m = nem!["silmarils" => 3]; /// assert_eq!(Some(&3), m.get("silmarils")); /// assert_eq!(None, m.get("arkenstone")); /// ``` #[must_use] pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, Q: Eq + Hash + ?Sized, { self.inner.get(k) } /// Returns the key-value pair corresponding to the key. /// /// The key may be any borrowed form of the map's value type, but `Hash` and /// `Eq` on the borrowed form must match those for the key type. /// /// ``` /// use nonempty_collections::nem; /// /// let m = nem!["silmarils" => 3]; /// assert_eq!(Some((&"silmarils", &3)), m.get_key_value("silmarils")); /// assert_eq!(None, m.get_key_value("arkenstone")); /// ``` #[must_use] pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Eq + Hash + ?Sized, { self.inner.get_key_value(k) } /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's value type, but `Hash` and /// `Eq` on the borrowed form must match those for the key type. /// /// ``` /// use nonempty_collections::nem; /// /// let mut m = nem!["silmarils" => 3]; /// let mut v = m.get_mut("silmarils").unwrap(); /// /// // And thus it came to pass that the Silmarils found their long homes: /// // one in the airs of heaven, and one in the fires of the heart of the /// // world, and one in the deep waters. /// *v -= 3; /// /// assert_eq!(Some(&0), m.get("silmarils")); /// ``` #[must_use] pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> where K: Borrow, Q: Eq + Hash + ?Sized, { self.inner.get_mut(k) } /// Insert a key-value pair into the map. /// /// If the map did not have this present, [`None`] is returned. /// /// If the map did have this key present, the value is updated, and the old /// value is returned. The key is not updated, though; this matters for /// types that can be `==` without being identical. See [`HashMap::insert`] /// for more. /// /// ``` /// use nonempty_collections::nem; /// /// let mut m = nem!["Vilya" => "Elrond", "Nenya" => "Galadriel"]; /// assert_eq!(None, m.insert("Narya", "Cirdan")); /// /// // The Ring of Fire was given to Gandalf upon his arrival in Middle Earth. /// assert_eq!(Some("Cirdan"), m.insert("Narya", "Gandalf")); /// ``` pub fn insert(&mut self, k: K, v: V) -> Option { self.inner.insert(k, v) } /// Shrinks the capacity of the map as much as possible. It will drop down /// as much as possible while maintaining the internal rules and possibly /// leaving some space in accordance with the resize policy. pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit(); } /// See [`HashMap::with_capacity_and_hasher`]. #[must_use] pub fn with_capacity_and_hasher( capacity: NonZeroUsize, hasher: S, k: K, v: V, ) -> NEMap { let mut inner = HashMap::with_capacity_and_hasher(capacity.get(), hasher); inner.insert(k, v); NEMap { inner } } /// See [`HashMap::with_hasher`]. #[must_use] pub fn with_hasher(hasher: S, k: K, v: V) -> NEMap { let mut inner = HashMap::with_hasher(hasher); inner.insert(k, v); NEMap { inner } } } impl AsRef> for NEMap { fn as_ref(&self) -> &HashMap { &self.inner } } impl AsMut> for NEMap { fn as_mut(&mut self) -> &mut HashMap { &mut self.inner } } impl PartialEq for NEMap where K: Eq + Hash, V: PartialEq, S: BuildHasher, { /// This is an `O(n)` comparison of each key/value pair, one by one. /// Short-circuits if any comparison fails. /// /// ``` /// use nonempty_collections::*; /// /// let m0 = nem!['a' => 1, 'b' => 2]; /// let m1 = nem!['b' => 2, 'a' => 1]; /// assert_eq!(m0, m1); /// ``` fn eq(&self, other: &Self) -> bool { self.inner.eq(&other.inner) } } impl Eq for NEMap where K: Eq + Hash, V: Eq, S: BuildHasher, { } impl From> for HashMap where K: Eq + Hash, S: BuildHasher, { /// ``` /// use nonempty_collections::nem; /// use std::collections::HashMap; /// /// let m: HashMap<&str, usize> = nem!["population" => 1000].into(); /// assert!(m.contains_key("population")); /// ``` fn from(m: NEMap) -> Self { m.inner } } impl TryFrom> for NEMap where K: Eq + Hash, S: BuildHasher + Default, { type Error = crate::Error; fn try_from(map: HashMap) -> Result { map.try_into_nonempty_iter() .map(NonEmptyIterator::collect) .ok_or(crate::Error::Empty) } } impl IntoNonEmptyIterator for NEMap { type IntoNEIter = IntoIter; fn into_nonempty_iter(self) -> Self::IntoNEIter { IntoIter { iter: self.inner.into_iter(), } } } impl<'a, K, V, S> IntoNonEmptyIterator for &'a NEMap { type IntoNEIter = Iter<'a, K, V>; fn into_nonempty_iter(self) -> Self::IntoNEIter { self.nonempty_iter() } } impl IntoIterator for NEMap { type Item = (K, V); type IntoIter = std::collections::hash_map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl<'a, K, V, S> IntoIterator for &'a NEMap { type Item = (&'a K, &'a V); type IntoIter = std::collections::hash_map::Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, K, V, S> IntoIterator for &'a mut NEMap { type Item = (&'a K, &'a mut V); type IntoIter = std::collections::hash_map::IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } /// ``` /// use nonempty_collections::*; /// /// let v = nev![('a', 1), ('b', 2), ('c', 3), ('a', 4)]; /// let m0: NEMap<_, _> = v.into_nonempty_iter().collect(); /// let m1: NEMap<_, _> = nem!['a' => 4, 'b' => 2, 'c' => 3]; /// assert_eq!(m0, m1); /// ``` impl FromNonEmptyIterator<(K, V)> for NEMap where K: Eq + Hash, S: BuildHasher + Default, { fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { NEMap { inner: iter.into_nonempty_iter().into_iter().collect(), } } } /// A non-empty iterator over the entries of an [`NEMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, K: 'a, V: 'a> { iter: std::collections::hash_map::Iter<'a, K, V>, } impl NonEmptyIterator for Iter<'_, K, V> {} impl<'a, K, V> IntoIterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); type IntoIter = std::collections::hash_map::Iter<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter } } impl fmt::Debug for Iter<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator over mutable values of an [`NEMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, K: 'a, V: 'a> { iter: std::collections::hash_map::IterMut<'a, K, V>, } impl NonEmptyIterator for IterMut<'_, K, V> {} impl<'a, K, V> IntoIterator for IterMut<'a, K, V> { type Item = (&'a K, &'a mut V); type IntoIter = std::collections::hash_map::IterMut<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.iter } } impl fmt::Debug for IterMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator over the entries of an [`NEMap`]. pub struct IntoIter { iter: std::collections::hash_map::IntoIter, } impl NonEmptyIterator for IntoIter {} impl IntoIterator for IntoIter { type Item = (K, V); type IntoIter = std::collections::hash_map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.iter } } impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator over the keys of an [`NEMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Keys<'a, K: 'a, V: 'a> { inner: std::collections::hash_map::Keys<'a, K, V>, } impl NonEmptyIterator for Keys<'_, K, V> {} impl<'a, K, V> IntoIterator for Keys<'a, K, V> { type Item = &'a K; type IntoIter = std::collections::hash_map::Keys<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.inner } } impl fmt::Debug for Keys<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } /// A non-empty iterator over the values of an [`NEMap`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Values<'a, K: 'a, V: 'a> { inner: std::collections::hash_map::Values<'a, K, V>, } impl NonEmptyIterator for Values<'_, K, V> {} impl<'a, K, V> IntoIterator for Values<'a, K, V> { type Item = &'a V; type IntoIter = std::collections::hash_map::Values<'a, K, V>; fn into_iter(self) -> Self::IntoIter { self.inner } } impl fmt::Debug for Values<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl fmt::Debug for NEMap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } // /// A non-empty iterator over mutable values of an [`NEMap`]. // pub struct ValuesMut<'a, K: 'a, V: 'a> { // inner: IterMut<'a, K, V>, // } // impl<'a, K, V> NonEmptyIterator for ValuesMut<'a, K, V> { // type Item = &'a mut V; // type Iter = Skip, // std::collections::hash_map::IterMut<'a, K, V>>>; // fn first(self) -> (Self::Item, Self::Iter) { // (self.head_val, self.inner.skip(1)) // } // fn next(&mut self) -> Option { // self.inner.next().map(|(_, v)| v) // } // } impl Singleton for NEMap where K: Eq + Hash, { type Item = (K, V); /// ``` /// use nonempty_collections::{NEMap, Singleton, nem}; /// /// let m = NEMap::singleton(('a', 1)); /// assert_eq!(nem!['a' => 1], m); /// ``` fn singleton((k, v): Self::Item) -> Self { NEMap::new(k, v) } } impl Extend<(K, V)> for NEMap where K: Eq + Hash, { fn extend>(&mut self, iter: I) { self.inner.extend(iter); } } #[cfg(test)] mod test { use std::num::NonZeroUsize; use maplit::hashmap; use crate::nem; struct Foo { user: String, } #[test] fn debug_impl() { let expected = format!("{:?}", hashmap! {0 => 10}); let actual = format!("{:?}", nem! {0 => 10}); assert_eq!(expected, actual); } #[test] fn macro_usage() { let a = Foo { user: "a".to_string(), }; let b = Foo { user: "b".to_string(), }; let map = nem![1 => a, 2 => b]; assert_eq!("a", map.get(&1).unwrap().user); assert_eq!("b", map.get(&2).unwrap().user); } #[test] fn macro_length() { let map = nem![1 => 'a', 2 => 'b', 1 => 'c']; assert_eq!(unsafe { NonZeroUsize::new_unchecked(2) }, map.len()); assert_eq!('c', *map.get(&1).unwrap()); assert_eq!('b', *map.get(&2).unwrap()); } #[test] fn iter_mut() { let mut v = nem! {"a" => 0, "b" => 1, "c" => 2}; v.iter_mut().for_each(|(_k, v)| { *v += 1; }); assert_eq!(nem! {"a" => 1, "b" => 2, "c" => 3}, v); for (_k, v) in &mut v { *v -= 1; } assert_eq!(nem! {"a" => 0, "b" => 1, "c" => 2}, v); } } #[cfg(feature = "serde")] #[cfg(test)] mod serde_tests { use std::collections::HashMap; use crate::nem; use crate::NEMap; #[test] fn json() { let map0 = nem![1 => 'a', 2 => 'b', 1 => 'c']; let j = serde_json::to_string(&map0).unwrap(); let map1 = serde_json::from_str(&j).unwrap(); assert_eq!(map0, map1); let empty: HashMap = HashMap::new(); let j = serde_json::to_string(&empty).unwrap(); let bad = serde_json::from_str::>(&j); assert!(bad.is_err()); } } nonempty-collections-1.1.0/src/set.rs000064400000000000000000000442511046102023000157460ustar 00000000000000//! Non-empty Sets. use core::fmt; use std::borrow::Borrow; use std::collections::HashSet; use std::hash::BuildHasher; use std::hash::Hash; use std::num::NonZeroUsize; #[cfg(feature = "serde")] use serde::Deserialize; #[cfg(feature = "serde")] use serde::Serialize; use crate::iter::NonEmptyIterator; use crate::FromNonEmptyIterator; use crate::IntoIteratorExt; use crate::IntoNonEmptyIterator; use crate::Singleton; /// Like the [`crate::nev!`] macro, but for Sets. A nice short-hand for /// constructing [`NESet`] values. /// /// ``` /// use nonempty_collections::nes; /// /// let s = nes![1, 2, 2, 3,]; /// assert_eq!(3, s.len().get()); /// ``` #[macro_export] macro_rules! nes { ($h:expr, $( $x:expr ),* $(,)?) => {{ let mut set = $crate::NESet::new($h); $( set.insert($x); )* set }}; ($h:expr) => { $crate::NESet::new($h) } } /// A non-empty, growable `HashSet`. /// /// # Construction and Access /// /// The [`nes`] macro is the simplest way to construct an `NESet`: /// /// ``` /// use nonempty_collections::*; /// /// let s = nes![1, 1, 2, 2, 3, 3, 4, 4]; /// let mut v: NEVec<_> = s.nonempty_iter().collect(); /// v.sort(); /// assert_eq!(nev![&1, &2, &3, &4], v); /// ``` /// /// /// ``` /// use nonempty_collections::nes; /// /// let s = nes!["Fëanor", "Fingolfin", "Finarfin"]; /// assert!(s.contains(&"Fëanor")); /// ``` /// /// # Conversion /// /// If you have a [`HashSet`] but want an `NESet`, try [`NESet::try_from_set`]. /// Naturally, this might not succeed. /// /// If you have an `NESet` but want a `HashSet`, try their corresponding /// [`From`] instance. This will always succeed. /// /// ``` /// use std::collections::HashSet; /// /// use nonempty_collections::nes; /// /// let n0 = nes![1, 2, 3]; /// let s0 = HashSet::from(n0); /// /// // Or just use `Into`. /// let n1 = nes![1, 2, 3]; /// let s1: HashSet<_> = n1.into(); /// ``` /// /// # API Differences with [`HashSet`] /// /// Note that the following methods aren't implemented for `NESet`: /// /// - `clear` /// - `drain` /// - `drain_filter` /// - `remove` /// - `retain` /// - `take` /// /// As these methods are all "mutate-in-place" style and are difficult to /// reconcile with the non-emptiness guarantee. #[allow(clippy::unsafe_derive_deserialize)] #[cfg_attr( feature = "serde", derive(Serialize, Deserialize), serde(bound( serialize = "T: Eq + Hash + Clone + Serialize, S: Clone + BuildHasher", deserialize = "T: Eq + Hash + Deserialize<'de>, S: Default + BuildHasher" )), serde(into = "HashSet", try_from = "HashSet") )] #[derive(Clone)] pub struct NESet { inner: HashSet, } impl NESet { /// Returns the number of elements the set can hold without reallocating. #[must_use] pub fn capacity(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.capacity()) } } /// Returns a reference to the set's `BuildHasher`. #[must_use] pub fn hasher(&self) -> &S { self.inner.hasher() } /// Returns a regular iterator over the values in this non-empty set. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter()`. pub fn iter(&self) -> std::collections::hash_set::Iter<'_, T> { self.inner.iter() } /// An iterator visiting all elements in arbitrary order. pub fn nonempty_iter(&self) -> Iter<'_, T> { Iter { iter: self.inner.iter(), } } /// Returns the number of elements in the set. Always 1 or more. /// /// ``` /// use nonempty_collections::nes; /// /// let s = nes![1, 2, 3]; /// assert_eq!(3, s.len().get()); /// ``` #[must_use] pub fn len(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.len()) } } /// A `NESet` is never empty. #[deprecated(since = "0.1.0", note = "A NESet is never empty.")] #[must_use] pub const fn is_empty(&self) -> bool { false } } impl NESet where T: Eq + Hash, { /// Creates a new `NESet` with a single element. #[must_use] pub fn new(value: T) -> Self { let mut inner = HashSet::new(); inner.insert(value); Self { inner } } /// Creates a new `NESet` with a single element and specified capacity. /// /// ``` /// use std::hash::RandomState; /// use std::num::NonZeroUsize; /// /// use nonempty_collections::*; /// let set = NESet::with_capacity(NonZeroUsize::MIN, "hello"); /// assert_eq!(nes! {"hello"}, set); /// assert!(set.capacity().get() >= 1); /// ``` #[must_use] pub fn with_capacity(capacity: NonZeroUsize, value: T) -> NESet { let mut inner = HashSet::with_capacity(capacity.get()); inner.insert(value); NESet { inner } } } impl NESet where T: Eq + Hash, S: BuildHasher, { /// Attempt a conversion from a [`HashSet`], consuming the given `HashSet`. /// Will return `None` if the `HashSet` is empty. /// /// ``` /// use std::collections::HashSet; /// /// use nonempty_collections::nes; /// use nonempty_collections::NESet; /// /// let mut s = HashSet::new(); /// s.extend([1, 2, 3]); /// /// let n = NESet::try_from_set(s); /// assert_eq!(Some(nes![1, 2, 3]), n); /// let s: HashSet<()> = HashSet::new(); /// assert_eq!(None, NESet::try_from_set(s)); /// ``` #[must_use] pub fn try_from_set(set: HashSet) -> Option> { if set.is_empty() { None } else { Some(NESet { inner: set }) } } /// Returns true if the set contains a value. /// /// ``` /// use nonempty_collections::nes; /// /// let s = nes![1, 2, 3]; /// assert!(s.contains(&3)); /// assert!(!s.contains(&10)); /// ``` #[must_use] pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: Eq + Hash + ?Sized, { self.inner.contains(value) } /// Visits the values representing the difference, i.e., the values that are /// in `self` but not in `other`. /// /// ``` /// use nonempty_collections::nes; /// /// let s0 = nes![1, 2, 3]; /// let s1 = nes![3, 4, 5]; /// let mut v: Vec<_> = s0.difference(&s1).collect(); /// v.sort(); /// assert_eq!(vec![&1, &2], v); /// ``` pub fn difference<'a>( &'a self, other: &'a NESet, ) -> std::collections::hash_set::Difference<'a, T, S> { self.inner.difference(&other.inner) } /// Returns a reference to the value in the set, if any, that is equal to /// the given value. /// /// The value may be any borrowed form of the set’s value type, but `Hash` /// and `Eq` on the borrowed form must match those for the value type. /// /// ``` /// use nonempty_collections::nes; /// /// let s = nes![1, 2, 3]; /// assert_eq!(Some(&3), s.get(&3)); /// assert_eq!(None, s.get(&10)); /// ``` #[must_use] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, Q: Eq + Hash, { self.inner.get(value) } /// Adds a value to the set. /// /// If the set did not have this value present, `true` is returned. /// /// If the set did have this value present, `false` is returned. /// /// ``` /// use nonempty_collections::nes; /// /// let mut s = nes![1, 2, 3]; /// assert_eq!(false, s.insert(2)); /// assert_eq!(true, s.insert(4)); /// ``` pub fn insert(&mut self, value: T) -> bool { self.inner.insert(value) } /// Visits the values representing the interesection, i.e., the values that /// are both in `self` and `other`. /// /// ``` /// use nonempty_collections::nes; /// /// let s0 = nes![1, 2, 3]; /// let s1 = nes![3, 4, 5]; /// let mut v: Vec<_> = s0.intersection(&s1).collect(); /// v.sort(); /// assert_eq!(vec![&3], v); /// ``` pub fn intersection<'a>( &'a self, other: &'a NESet, ) -> std::collections::hash_set::Intersection<'a, T, S> { self.inner.intersection(&other.inner) } /// Returns `true` if `self` has no elements in common with `other`. /// This is equivalent to checking for an empty intersection. /// /// ``` /// use nonempty_collections::nes; /// /// let s0 = nes![1, 2, 3]; /// let s1 = nes![4, 5, 6]; /// assert!(s0.is_disjoint(&s1)); /// ``` #[must_use] pub fn is_disjoint(&self, other: &NESet) -> bool { self.inner.is_disjoint(&other.inner) } /// Returns `true` if the set is a subset of another, i.e., `other` contains /// at least all the values in `self`. /// /// ``` /// use nonempty_collections::nes; /// /// let sub = nes![1, 2, 3]; /// let sup = nes![1, 2, 3, 4]; /// /// assert!(sub.is_subset(&sup)); /// assert!(!sup.is_subset(&sub)); /// ``` #[must_use] pub fn is_subset(&self, other: &NESet) -> bool { self.inner.is_subset(&other.inner) } /// Returns `true` if the set is a superset of another, i.e., `self` /// contains at least all the values in `other`. /// /// ``` /// use nonempty_collections::nes; /// /// let sub = nes![1, 2, 3]; /// let sup = nes![1, 2, 3, 4]; /// /// assert!(sup.is_superset(&sub)); /// assert!(!sub.is_superset(&sup)); /// ``` #[must_use] pub fn is_superset(&self, other: &NESet) -> bool { self.inner.is_superset(&other.inner) } /// Adds a value to the set, replacing the existing value, if any, that is /// equal to the given one. Returns the replaced value. pub fn replace(&mut self, value: T) -> Option { self.inner.replace(value) } /// Reserves capacity for at least `additional` more elements to be inserted /// in the `NESet`. The collection may reserve more space to avoid frequent /// reallocations. /// /// # Panics /// /// Panics if the new allocation size overflows `usize`. pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional); } /// Shrinks the capacity of the set as much as possible. It will drop down /// as much as possible while maintaining the internal rules and possibly /// leaving some space in accordance with the resize policy. pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit(); } /// Visits the values representing the union, i.e., all the values in `self` /// or `other`, without duplicates. /// /// Note that a Union is always non-empty. /// /// ``` /// use nonempty_collections::*; /// /// let s0 = nes![1, 2, 3]; /// let s1 = nes![3, 4, 5]; /// let mut v: NEVec<_> = s0.union(&s1).collect(); /// v.sort(); /// assert_eq!(nev![&1, &2, &3, &4, &5], v); /// ``` pub fn union<'a>(&'a self, other: &'a NESet) -> Union<'a, T, S> { Union { inner: self.inner.union(&other.inner), } } /// See [`HashSet::with_capacity_and_hasher`]. #[must_use] pub fn with_capacity_and_hasher(capacity: NonZeroUsize, hasher: S, value: T) -> NESet { let mut inner = HashSet::with_capacity_and_hasher(capacity.get(), hasher); inner.insert(value); NESet { inner } } /// See [`HashSet::with_hasher`]. #[must_use] pub fn with_hasher(hasher: S, value: T) -> NESet { let mut inner = HashSet::with_hasher(hasher); inner.insert(value); NESet { inner } } } impl AsRef> for NESet { fn as_ref(&self) -> &HashSet { &self.inner } } impl AsMut> for NESet { fn as_mut(&mut self) -> &mut HashSet { &mut self.inner } } impl PartialEq for NESet where T: Eq + Hash, S: BuildHasher, { /// ``` /// use nonempty_collections::nes; /// /// let s0 = nes![1, 2, 3]; /// let s1 = nes![1, 2, 3]; /// let s2 = nes![1, 2]; /// let s3 = nes![1, 2, 3, 4]; /// /// assert!(s0 == s1); /// assert!(s0 != s2); /// assert!(s0 != s3); /// ``` fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self.intersection(other).count() == self.len().get() } } impl Eq for NESet where T: Eq + Hash, S: BuildHasher, { } impl IntoNonEmptyIterator for NESet { type IntoNEIter = IntoIter; fn into_nonempty_iter(self) -> Self::IntoNEIter { IntoIter { iter: self.inner.into_iter(), } } } impl<'a, T, S> IntoNonEmptyIterator for &'a NESet { type IntoNEIter = Iter<'a, T>; fn into_nonempty_iter(self) -> Self::IntoNEIter { self.nonempty_iter() } } impl IntoIterator for NESet { type Item = T; type IntoIter = std::collections::hash_set::IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl<'a, T, S> IntoIterator for &'a NESet { type Item = &'a T; type IntoIter = std::collections::hash_set::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// ``` /// use nonempty_collections::*; /// /// let s0 = nes![1, 2, 3]; /// let s1: NESet<_> = s0.nonempty_iter().cloned().collect(); /// assert_eq!(s0, s1); /// ``` impl FromNonEmptyIterator for NESet where T: Eq + Hash, S: BuildHasher + Default, { /// ``` /// use nonempty_collections::*; /// /// let v = nev![1, 1, 2, 3, 2]; /// let s = NESet::from_nonempty_iter(v); /// /// assert_eq!(nes![1, 2, 3], s); /// ``` fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { NESet { inner: iter.into_nonempty_iter().into_iter().collect(), } } } /// A non-empty iterator over the values of an [`NESet`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { iter: std::collections::hash_set::Iter<'a, T>, } impl<'a, T: 'a> IntoIterator for Iter<'a, T> { type Item = &'a T; type IntoIter = std::collections::hash_set::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter } } impl NonEmptyIterator for Iter<'_, T> {} impl fmt::Debug for Iter<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// An owned non-empty iterator over the values of an [`NESet`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct IntoIter { iter: std::collections::hash_set::IntoIter, } impl IntoIterator for IntoIter { type Item = T; type IntoIter = std::collections::hash_set::IntoIter; fn into_iter(self) -> Self::IntoIter { self.iter } } impl NonEmptyIterator for IntoIter {} impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator producing elements in the union of two [`NESet`]s. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Union<'a, T: 'a, S: 'a> { inner: std::collections::hash_set::Union<'a, T, S>, } impl<'a, T, S> IntoIterator for Union<'a, T, S> where T: Eq + Hash, S: BuildHasher, { type Item = &'a T; type IntoIter = std::collections::hash_set::Union<'a, T, S>; fn into_iter(self) -> Self::IntoIter { self.inner } } impl NonEmptyIterator for Union<'_, T, S> where T: Eq + Hash, S: BuildHasher, { } impl fmt::Debug for Union<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl From> for HashSet where T: Eq + Hash, S: BuildHasher, { /// ``` /// use std::collections::HashSet; /// /// use nonempty_collections::nes; /// /// let s: HashSet<_> = nes![1, 2, 3].into(); /// let mut v: Vec<_> = s.into_iter().collect(); /// v.sort(); /// assert_eq!(vec![1, 2, 3], v); /// ``` fn from(s: NESet) -> Self { s.inner } } impl fmt::Debug for NESet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl TryFrom> for NESet where T: Eq + Hash, S: BuildHasher + Default, { type Error = crate::Error; fn try_from(set: HashSet) -> Result { let ne = set .try_into_nonempty_iter() .ok_or(crate::Error::Empty)? .collect(); Ok(ne) } } impl Singleton for NESet where T: Eq + Hash, { type Item = T; /// ``` /// use nonempty_collections::{NESet, Singleton, nes}; /// /// let s = NESet::singleton(1); /// assert_eq!(nes![1], s); /// ``` fn singleton(item: Self::Item) -> Self { NESet::new(item) } } impl Extend for NESet where T: Eq + Hash, { fn extend>(&mut self, iter: I) { self.inner.extend(iter); } } #[cfg(test)] mod test { use maplit::hashset; #[test] fn debug_impl() { let expected = format!("{:?}", hashset! {0}); let actual = format!("{:?}", nes! {0}); assert_eq!(expected, actual); } #[test] fn iter_debug_impl() { let expected = format!("{:?}", hashset! {0}.iter()); let actual = format!("{:?}", nes! {0}.nonempty_iter()); assert_eq!(expected, actual); } } #[cfg(feature = "serde")] #[cfg(test)] mod serde_tests { use std::collections::HashSet; use crate::nes; use crate::NESet; #[test] fn json() { let set0 = nes![1, 1, 2, 3, 2, 1, 4]; let j = serde_json::to_string(&set0).unwrap(); let set1 = serde_json::from_str(&j).unwrap(); assert_eq!(set0, set1); let empty: HashSet = HashSet::new(); let j = serde_json::to_string(&empty).unwrap(); let bad = serde_json::from_str::>(&j); assert!(bad.is_err()); } } nonempty-collections-1.1.0/src/slice.rs000064400000000000000000000226601046102023000162520ustar 00000000000000//! Non-empty Slices. use core::fmt; use std::iter::FilterMap; use std::num::NonZeroUsize; use std::ops::Index; use std::slice::Chunks; use crate::iter::IntoNonEmptyIterator; use crate::iter::NonEmptyIterator; /// A non-empty slice. Like [`crate::NEVec`], but guaranteed to have borrowed /// contents. /// /// [`NESlice::try_from_slice`] is the simplest way to construct this from /// borrowed data. /// /// Unfortunately there is no macro for this, but if you want one, just use /// `nev!` and handle the ownership manually. Also consider /// [`crate::NEVec::as_nonempty_slice`]. /// /// If you want access to the inner slice, use [`AsRef`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct NESlice<'a, T> { inner: &'a [T], } impl<'a, T> NESlice<'a, T> { /// Get the first element. Never fails. #[must_use] pub const fn first(&self) -> &T { &self.inner[0] } /// Using `try_from_slice` gives a proof that the input slice is non-empty /// in the `Some` branch. #[must_use] pub const fn try_from_slice(slice: &'a [T]) -> Option { if slice.is_empty() { None } else { Some(NESlice { inner: slice }) } } #[must_use] pub(crate) const unsafe fn from_slice_unchecked(slice: &'a [T]) -> Self { NESlice { inner: slice } } /// Get the length of the slice. #[must_use] pub fn len(&self) -> NonZeroUsize { debug_assert!(!self.inner.is_empty()); unsafe { NonZeroUsize::new_unchecked(self.inner.len()) } } /// No, this slice is not empty. #[deprecated(note = "A NESlice is never empty.")] #[must_use] pub const fn is_empty(&self) -> bool { false } /// Returns a regular iterator over the values in this non-empty slice. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter()`. pub fn iter(&self) -> std::slice::Iter<'_, T> { self.inner.iter() } /// Returns a non-empty iterator. pub fn nonempty_iter(&self) -> Iter<'_, T> { Iter { iter: self.inner.iter(), } } /// Returns a non-empty iterator over `chunk_size` elements of the `NESlice` /// at a time, starting at the beginning of the `NESlice`. /// /// ``` /// use std::num::NonZeroUsize; /// /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3, 4, 5, 6]; /// let s = v.as_nonempty_slice(); /// let n = NonZeroUsize::new(2).unwrap(); /// let r = s.nonempty_chunks(n).collect::>(); /// /// let a = nev![1, 2]; /// let b = nev![3, 4]; /// let c = nev![5, 6]; /// /// assert_eq!( /// r, /// nev![ /// a.as_nonempty_slice(), /// b.as_nonempty_slice(), /// c.as_nonempty_slice() /// ] /// ); /// ``` pub fn nonempty_chunks(&'a self, chunk_size: NonZeroUsize) -> NEChunks<'a, T> { NEChunks { inner: self.inner.chunks(chunk_size.get()), } } } impl AsRef<[T]> for NESlice<'_, T> { fn as_ref(&self) -> &[T] { self.inner } } impl<'a, T> IntoNonEmptyIterator for NESlice<'a, T> { type IntoNEIter = Iter<'a, T>; fn into_nonempty_iter(self) -> Self::IntoNEIter { Iter { iter: self.inner.iter(), } } } impl<'a, T> IntoNonEmptyIterator for &'a NESlice<'a, T> { type IntoNEIter = Iter<'a, T>; fn into_nonempty_iter(self) -> Self::IntoNEIter { self.nonempty_iter() } } impl<'a, T> IntoIterator for NESlice<'a, T> { type Item = &'a T; type IntoIter = std::slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.inner.iter() } } impl<'a, T> IntoIterator for &'a NESlice<'a, T> { type Item = &'a T; type IntoIter = std::slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl Index for NESlice<'_, T> { type Output = T; fn index(&self, index: usize) -> &Self::Output { &self.inner[index] } } /// A non-empty iterator over the values of an [`NESlice`]. #[derive(Debug)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { iter: std::slice::Iter<'a, T>, } impl NonEmptyIterator for Iter<'_, T> {} impl<'a, T> IntoIterator for Iter<'a, T> { type Item = &'a T; type IntoIter = std::slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter } } /// A non-empty Iterator of [`NESlice`] chunks. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct NEChunks<'a, T> { pub(crate) inner: Chunks<'a, T>, } type SliceFilter<'a, T> = fn(&'a [T]) -> Option>; impl NonEmptyIterator for NEChunks<'_, T> {} impl<'a, T> IntoIterator for NEChunks<'a, T> { type Item = NESlice<'a, T>; type IntoIter = FilterMap, SliceFilter<'a, T>>; fn into_iter(self) -> Self::IntoIter { self.inner.filter_map(|x| NESlice::try_from_slice(x)) } } impl fmt::Debug for NEChunks<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } #[cfg(test)] mod tests { use std::num::NonZeroUsize; use crate::nev; use crate::slice::NEChunks; use crate::NESlice; use crate::NEVec; use crate::NonEmptyIterator; #[test] fn test_from_conversion() { let slice = [1, 2, 3, 4, 5]; let nonempty_slice = NESlice::try_from_slice(&slice); let nonempty_slice = nonempty_slice.unwrap(); assert_eq!(nonempty_slice.inner, &[1, 2, 3, 4, 5]); } #[test] fn test_iter_syntax() { let slice = [0, 1, 2, 3]; let nonempty = NESlice::try_from_slice(&slice); if let Some(nonempty) = nonempty { for n in &nonempty { assert_eq!(*n, *n); // Prove that we're dealing with references. } } } #[test] fn test_into_nonempty_iter() { use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; let slice = [0usize, 1, 2, 3]; let nonempty = NESlice::try_from_slice(&slice).unwrap(); for (i, n) in nonempty.into_nonempty_iter().enumerate() { assert_eq!(i, *n); } } #[test] fn chunks() { let v = nev![1, 2, 3, 4, 5, 6, 7]; let n = NonZeroUsize::new(3).unwrap(); let a: Vec<_> = v.nonempty_chunks(n).collect(); assert_eq!( a, vec![ nev![1, 2, 3].as_nonempty_slice(), nev![4, 5, 6].as_nonempty_slice(), nev![7].as_nonempty_slice() ] ); let n = NonZeroUsize::new(1).unwrap(); let b: Vec<_> = v.nonempty_chunks(n).collect(); assert_eq!( b, vec![ nev![1].as_nonempty_slice(), nev![2].as_nonempty_slice(), nev![3].as_nonempty_slice(), nev![4].as_nonempty_slice(), nev![5].as_nonempty_slice(), nev![6].as_nonempty_slice(), nev![7].as_nonempty_slice(), ] ); } #[test] fn chunks_len() { let v = nev![1, 2, 3]; let n = NonZeroUsize::new(3).unwrap(); let c = v.nonempty_chunks(n).count().get(); assert_eq!(c, 1); let v = nev![1, 2, 3]; let n = NonZeroUsize::new(5).unwrap(); let c = v.nonempty_chunks(n).count().get(); assert_eq!(c, 1); let v = nev![1, 2, 3, 4]; let n = NonZeroUsize::new(3).unwrap(); let c = v.nonempty_chunks(n).count().get(); assert_eq!(c, 2); } // A test to reproduce index out of range errors // and ensure that the `NEChunks` iterator works // as expected. #[test] fn chunks_into_iter_with_chunk_size_over_len() { let v = nev![1, 2, 3]; let n = NonZeroUsize::new(4).unwrap(); let c = v.nonempty_chunks(n); // Iterating over should not produce any errors. for slice in c { let _: NESlice<'_, i32> = slice; } let v = nev![1, 2, 3]; let n = NonZeroUsize::new(4).unwrap(); let c: NEVec<_> = v.nonempty_chunks(n).collect(); assert_eq!(1, c.len().get()); assert_eq!(&v.as_nonempty_slice(), c.first()); } // A test to ensure the correctness of the `NEChunks` iterator #[test] fn chunks_into_iter_should_return_elements_exactly_once() { let v = nev![1, 2, 3, 4, 5, 6, 57]; let n = NonZeroUsize::new(3).unwrap(); let c: NEChunks<'_, i32> = v.nonempty_chunks(n); let mut r: Vec> = vec![]; for slice in c { let _: NESlice<'_, i32> = slice; r.push(slice); } assert_eq!( r, vec![ nev![1, 2, 3].as_nonempty_slice(), nev![4, 5, 6].as_nonempty_slice(), nev![57].as_nonempty_slice(), ] ); } // This test covers an edge case non supported by the `chunks` method // when the slice has only one element. #[test] fn chunks_into_iter_edge_case_single_element() { let v = nev![1]; let n = NonZeroUsize::new(3).unwrap(); let c: NEChunks<'_, i32> = v.nonempty_chunks(n); let mut iter = c.into_iter(); let next = iter.next().unwrap(); assert_eq!(1, next.len().get()); assert!(iter.next().is_none()); } } nonempty-collections-1.1.0/src/vector.rs000064400000000000000000001166061046102023000164610ustar 00000000000000//! Non-empty Vectors. use crate::iter::FromNonEmptyIterator; use crate::iter::IntoNonEmptyIterator; use crate::iter::NonEmptyIterator; use crate::slice::NEChunks; use crate::Singleton; use core::fmt; use std::cmp::Ordering; use std::fmt::Debug; use std::fmt::Formatter; use std::num::NonZeroUsize; #[cfg(feature = "serde")] use serde::Deserialize; #[cfg(feature = "serde")] use serde::Serialize; /// Like the [`vec!`] macro, but enforces at least one argument. A nice /// short-hand for constructing [`NEVec`] values. /// /// ``` /// use nonempty_collections::nev; /// use nonempty_collections::NEVec; /// /// let v = nev![1, 2, 3]; /// assert_eq!(v.into_iter().collect::>(), vec![1, 2, 3]); /// /// let v = nev![1]; /// assert_eq!(v.into_iter().collect::>(), vec![1]); /// /// let v = nev![1; 3]; /// assert_eq!(v.into_iter().collect::>(), vec![1; 3]); /// ``` /// /// This won't compile! /// ``` compile_fail /// use nonempty_collections::nev; /// let v = nev![]; /// ``` /// /// Neither will this. /// ``` compile_fail /// use nonempty_collections::nev; /// let v = nev![1; 0]; /// ``` /// /// Consider also [`crate::nem!`] and [`crate::nes!`]. #[macro_export] macro_rules! nev { () => {compile_error!("An NEVec cannot be empty")}; ($h:expr, $( $x:expr ),* $(,)?) => {{ let mut v = $crate::NEVec::new($h); $( v.push($x); )* v }}; ($h:expr) => { $crate::NEVec::new($h) }; ($elem:expr; $n:expr) => {{ let n = const { ::std::num::NonZero::new($n).expect("Length cannot be 0") }; $crate::vector::from_elem($elem, n) }}; } #[doc(hidden)] pub fn from_elem(elem: T, n: NonZeroUsize) -> NEVec { NEVec { inner: vec![elem; n.get()], } } /// A non-empty, growable Vector. /// /// The first element can always be accessed in constant time. Similarly, /// certain functions like [`NEVec::first`] and [`NEVec::last`] always succeed: /// /// ``` /// use nonempty_collections::nev; /// /// let s = nev!["Fëanor", "Fingolfin", "Finarfin"]; /// assert_eq!(&"Fëanor", s.first()); // There is always a first element. /// assert_eq!(&"Finarfin", s.last()); // There is always a last element. /// ``` #[cfg_attr( feature = "serde", derive(Deserialize, Serialize), serde(bound(serialize = "T: Clone + Serialize")), serde(into = "Vec", try_from = "Vec") )] #[allow(clippy::unsafe_derive_deserialize)] // the non-empty invariant is enforced by the deserialize implementation #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct NEVec { inner: Vec, } impl NEVec { /// Create a new non-empty list with an initial element. #[must_use] pub fn new(head: T) -> Self { NEVec { inner: vec![head] } } /// Creates a new `NEVec` with a single element and specified capacity. #[must_use] pub fn with_capacity(capacity: NonZeroUsize, head: T) -> Self { let mut inner = Vec::with_capacity(capacity.get()); inner.push(head); NEVec { inner } } /// Get the first element. Never fails. #[must_use] pub fn first(&self) -> &T { unsafe { self.inner.get_unchecked(0) } } /// Get the mutable reference to the first element. Never fails. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![42]; /// let head = v.first_mut(); /// *head += 1; /// assert_eq!(v.first(), &43); /// /// let mut v = nev![1, 4, 2, 3]; /// let head = v.first_mut(); /// *head *= 42; /// assert_eq!(v.first(), &42); /// ``` #[must_use] pub fn first_mut(&mut self) -> &mut T { unsafe { self.inner.get_unchecked_mut(0) } } /// Push an element to the end of the list. pub fn push(&mut self, e: T) { self.inner.push(e); } /// Pop an element from the end of the list. Is a no-op when [`Self::len()`] /// is 1. /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1, 2]; /// assert_eq!(Some(2), v.pop()); /// assert_eq!(None, v.pop()); /// ``` pub fn pop(&mut self) -> Option { if self.len() > NonZeroUsize::MIN { self.inner.pop() } else { None } } /// Removes and returns the element at position `index` within the vector, /// shifting all elements after it to the left. /// /// If this [`NEVec`] contains only one element, no removal takes place and /// `None` will be returned. If there are more elements, the item at the /// `index` is removed and returned. /// /// Note: Because this shifts over the remaining elements, it has a /// worst-case performance of *O*(*n*). If you don't need the order of /// elements to be preserved, use [`swap_remove`] instead. /// /// [`swap_remove`]: NEVec::swap_remove /// /// # Panics /// /// Panics if `index` is out of bounds and `self.len() > 1` /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1, 2, 3]; /// assert_eq!(v.remove(1), Some(2)); /// assert_eq!(nev![1, 3], v); /// ``` pub fn remove(&mut self, index: usize) -> Option { (self.len() > NonZeroUsize::MIN).then(|| self.inner.remove(index)) } /// Removes an element from the vector and returns it. /// /// If this [`NEVec`] contains only one element, no removal takes place and /// `None` will be returned. If there are more elements, the item at the /// `index` is removed and returned. /// /// The removed element is replaced by the last element of the vector. /// /// This does not preserve ordering of the remaining elements, but is /// *O*(1). If you need to preserve the element order, use [`remove`] /// instead. /// /// [`remove`]: NEVec::remove /// /// # Panics /// /// Panics if `index` is out of bounds and `self.len() > 1` /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1, 2, 3, 4]; /// assert_eq!(v.swap_remove(1), Some(2)); /// assert_eq!(nev![1, 4, 3], v); /// ``` pub fn swap_remove(&mut self, index: usize) -> Option { (self.len() > NonZeroUsize::MIN).then(|| self.inner.swap_remove(index)) } /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` for which `f(&e)` returns /// `false`. This method operates in place, visiting each element /// exactly once in the original order, and preserves the order of the /// retained elements. /// /// If there are one or more items retained `Ok(Self)` is returned with the /// remaining items. If all items are removed, the inner `Vec` is returned /// to allowed for reuse of the claimed memory. /// /// # Errors /// Returns `Err` if no elements are retained. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let vec = nev![1, 2, 3, 4]; /// let vec = vec.retain(|&x| x % 2 == 0); /// assert_eq!(Ok(nev![2, 4]), vec); /// ``` pub fn retain(self, mut f: F) -> Result> where F: FnMut(&T) -> bool, { self.retain_mut(|item| f(item)) } /// Retains only the elements specified by the predicate, passing a mutable /// reference to it. /// /// In other words, remove all elements `e` such that `f(&mut e)` returns /// `false`. This method operates in place, visiting each element /// exactly once in the original order, and preserves the order of the /// retained elements. /// /// If there are one or more items retained `Ok(Self)` is returned with the /// remaining items. If all items are removed, the inner `Vec` is returned /// to allowed for reuse of the claimed memory. /// /// # Errors /// Returns `Err` if no elements are retained. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let vec = nev![1, 2, 3, 4]; /// let vec = vec.retain_mut(|x| { /// if *x <= 3 { /// *x += 1; /// true /// } else { /// false /// } /// }); /// assert_eq!(Ok(nev![2, 3, 4]), vec); /// ``` pub fn retain_mut(mut self, f: F) -> Result> where F: FnMut(&mut T) -> bool, { self.inner.retain_mut(f); if self.inner.is_empty() { Err(self.inner) } else { Ok(self) } } /// Inserts an element at position index within the vector, shifting all /// elements after it to the right. /// /// # Panics /// /// Panics if index > len. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1, 2, 3]; /// v.insert(1, 4); /// assert_eq!(v, nev![1, 4, 2, 3]); /// v.insert(4, 5); /// assert_eq!(v, nev![1, 4, 2, 3, 5]); /// v.insert(0, 42); /// assert_eq!(v, nev![42, 1, 4, 2, 3, 5]); /// ``` pub fn insert(&mut self, index: usize, element: T) { self.inner.insert(index, element); } /// Get the length of the list. #[must_use] pub fn len(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.len()) } } /// A `NEVec` is never empty. #[deprecated(since = "0.1.0", note = "A NEVec is never empty.")] #[must_use] pub const fn is_empty(&self) -> bool { false } /// Get the capacity of the list. #[must_use] pub fn capacity(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.inner.capacity()) } } /// Get the last element. Never fails. #[must_use] #[allow(clippy::missing_panics_doc)] // never fails pub fn last(&self) -> &T { self.inner.last().unwrap() } /// Get the last element mutably. #[must_use] #[allow(clippy::missing_panics_doc)] // never fails pub fn last_mut(&mut self) -> &mut T { self.inner.last_mut().unwrap() } /// Check whether an element is contained in the list. /// /// ``` /// use nonempty_collections::nev; /// /// let mut l = nev![42, 36, 58]; /// /// assert!(l.contains(&42)); /// assert!(!l.contains(&101)); /// ``` #[must_use] pub fn contains(&self, x: &T) -> bool where T: PartialEq, { self.inner.contains(x) } /// Get an element by index. #[must_use] pub fn get(&self, index: usize) -> Option<&T> { self.inner.get(index) } /// Get an element by index, mutably. #[must_use] pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { self.inner.get_mut(index) } /// Truncate the list to a certain size. pub fn truncate(&mut self, len: NonZeroUsize) { self.inner.truncate(len.get()); } /// Returns a regular iterator over the values in this non-empty vector. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter()`. pub fn iter(&self) -> std::slice::Iter<'_, T> { self.inner.iter() } /// Returns a regular mutable iterator over the values in this non-empty /// vector. /// /// For a `NonEmptyIterator` see `Self::nonempty_iter_mut()`. pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { self.inner.iter_mut() } /// ``` /// use nonempty_collections::*; /// /// let mut l = nev![42, 36, 58]; /// /// let mut iter = l.nonempty_iter(); /// let (first, mut rest_iter) = iter.next(); /// /// assert_eq!(first, &42); /// assert_eq!(rest_iter.next(), Some(&36)); /// assert_eq!(rest_iter.next(), Some(&58)); /// assert_eq!(rest_iter.next(), None); /// ``` pub fn nonempty_iter(&self) -> Iter<'_, T> { Iter { iter: self.inner.iter(), } } /// Returns an iterator that allows modifying each value. /// /// # Examples /// /// ``` /// use nonempty_collections::*; /// /// let mut l = nev![42, 36, 58]; /// /// for i in l.nonempty_iter_mut() { /// *i *= 10; /// } /// /// let mut iter = l.nonempty_iter(); /// let (first, mut rest_iter) = iter.next(); /// /// assert_eq!(first, &420); /// assert_eq!(rest_iter.next(), Some(&360)); /// assert_eq!(rest_iter.next(), Some(&580)); /// assert_eq!(rest_iter.next(), None); /// ``` pub fn nonempty_iter_mut(&mut self) -> IterMut<'_, T> { IterMut { inner: self.inner.iter_mut(), } } /// Creates a new non-empty vec by cloning the elements from the slice if it /// is non-empty, returns `None` otherwise. /// /// Often we have a `Vec` (or slice `&[T]`) but want to ensure that it is /// `NEVec` before proceeding with a computation. Using `try_from_slice` /// will give us a proof that we have a `NEVec` in the `Some` branch, /// otherwise it allows the caller to handle the `None` case. /// /// # Example use /// /// ``` /// use nonempty_collections::nev; /// use nonempty_collections::NEVec; /// /// let v_vec = NEVec::try_from_slice(&[1, 2, 3, 4, 5]); /// assert_eq!(v_vec, Some(nev![1, 2, 3, 4, 5])); /// /// let empty_vec: Option> = NEVec::try_from_slice(&[]); /// assert!(empty_vec.is_none()); /// ``` #[must_use] pub fn try_from_slice(slice: &[T]) -> Option> where T: Clone, { if slice.is_empty() { None } else { Some(NEVec { inner: slice.to_vec(), }) } } /// Often we have a `Vec` (or slice `&[T]`) but want to ensure that it is /// `NEVec` before proceeding with a computation. Using `try_from_vec` will /// give us a proof that we have a `NEVec` in the `Some` branch, /// otherwise it allows the caller to handle the `None` case. /// /// This version will consume the `Vec` you pass in. If you would rather /// pass the data as a slice then use [`NEVec::try_from_slice`]. /// /// # Example Use /// /// ``` /// use nonempty_collections::nev; /// use nonempty_collections::NEVec; /// /// let v_vec = NEVec::try_from_vec(vec![1, 2, 3, 4, 5]); /// assert_eq!(v_vec, Some(nev![1, 2, 3, 4, 5])); /// /// let empty_vec: Option> = NEVec::try_from_vec(vec![]); /// assert!(empty_vec.is_none()); /// ``` #[must_use] pub fn try_from_vec(vec: Vec) -> Option> { if vec.is_empty() { None } else { Some(NEVec { inner: vec }) } } /// Deconstruct a `NEVec` into its head and tail. This operation never fails /// since we are guaranteed to have a head element. /// /// # Example Use /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1, 2, 3, 4, 5]; /// /// // Guaranteed to have the head and we also get the tail. /// assert_eq!(v.split_first(), (&1, &[2, 3, 4, 5][..])); /// /// let v = nev![1]; /// /// // Guaranteed to have the head element. /// assert_eq!(v.split_first(), (&1, &[][..])); /// ``` #[must_use] #[allow(clippy::missing_panics_doc)] // never fails pub fn split_first(&self) -> (&T, &[T]) { self.inner.split_first().unwrap() } /// Deconstruct a `NEVec` into its first, last, and /// middle elements, in that order. /// /// If there is only one element then first == last. /// /// # Example Use /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1, 2, 3, 4, 5]; /// /// // Guaranteed to have the last element and the elements /// // preceding it. /// assert_eq!(v.split(), (&1, &[2, 3, 4][..], &5)); /// /// let v = nev![1]; /// /// // Guaranteed to have the last element. /// assert_eq!(v.split(), (&1, &[][..], &1)); /// ``` #[must_use] pub fn split(&self) -> (&T, &[T], &T) { let (first, rest) = self.split_first(); if let Some((last, middle)) = rest.split_last() { (first, middle, last) } else { (first, &[], first) } } /// Append a `Vec` to the tail of the `NEVec`. /// /// # Example Use /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![1]; /// let mut vec = vec![2, 3, 4, 5]; /// v.append(&mut vec); /// /// let mut expected = nev![1, 2, 3, 4, 5]; /// assert_eq!(v, expected); /// ``` pub fn append(&mut self, other: &mut Vec) { self.inner.append(other); } /// Binary searches this sorted non-empty vector for a given element. /// /// If the value is found then `Result::Ok` is returned, containing the /// index of the matching element. If there are multiple matches, then any /// one of the matches could be returned. /// /// # Errors /// /// If the value is not found then `Result::Err` is returned, containing the /// index where a matching element could be inserted while maintaining /// sorted order. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let v = nev![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// assert_eq!(v.binary_search(&0), Ok(0)); /// assert_eq!(v.binary_search(&13), Ok(9)); /// assert_eq!(v.binary_search(&4), Err(7)); /// assert_eq!(v.binary_search(&100), Err(13)); /// let r = v.binary_search(&1); /// assert!(match r { /// Ok(1..=4) => true, /// _ => false, /// }); /// ``` /// /// If you want to insert an item to a sorted non-empty vector, while /// maintaining sort order: /// /// ``` /// use nonempty_collections::nev; /// /// let mut v = nev![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// let num = 42; /// let idx = v.binary_search(&num).unwrap_or_else(|x| x); /// v.insert(idx, num); /// assert_eq!(v, nev![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); /// ``` pub fn binary_search(&self, x: &T) -> Result where T: Ord, { self.binary_search_by(|p| p.cmp(x)) } /// Binary searches this sorted non-empty with a comparator function. /// /// The comparator function should implement an order consistent with the /// sort order of the underlying slice, returning an order code that /// indicates whether its argument is Less, Equal or Greater the desired /// target. /// /// If the value is found then `Result::Ok` is returned, containing the /// index of the matching element. If there are multiple matches, then any /// one of the matches could be returned. /// /// # Errors /// If the value is not found then `Result::Err` is returned, containing the /// index where a matching element could be inserted while maintaining /// sorted order. /// /// # Examples /// /// Looks up a series of four elements. The first is found, with a uniquely /// determined position; the second and third are not found; the fourth /// could match any position from 1 to 4. /// /// ``` /// use nonempty_collections::nev; /// /// let v = nev![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// let seek = 0; /// assert_eq!(v.binary_search_by(|probe| probe.cmp(&seek)), Ok(0)); /// let seek = 13; /// assert_eq!(v.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); /// let seek = 4; /// assert_eq!(v.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); /// let seek = 100; /// assert_eq!(v.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); /// let seek = 1; /// let r = v.binary_search_by(|probe| probe.cmp(&seek)); /// assert!(match r { /// Ok(1..=4) => true, /// _ => false, /// }); /// ``` pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result where F: FnMut(&'a T) -> Ordering, { self.inner.binary_search_by(f) } /// Binary searches this sorted non-empty vector with a key extraction /// function. /// /// Assumes that the vector is sorted by the key. /// /// If the value is found then `Result::Ok` is returned, containing the /// index of the matching element. If there are multiple matches, then any /// one of the matches could be returned. /// /// # Errors /// If the value is not found then `Result::Err` is returned, containing the /// index where a matching element could be inserted while maintaining /// sorted order. /// /// # Examples /// /// Looks up a series of four elements in a non-empty vector of pairs sorted /// by their second elements. The first is found, with a uniquely determined /// position; the second and third are not found; the fourth could match any /// position in [1, 4]. /// /// ``` /// use nonempty_collections::nev; /// /// let v = nev![ /// (0, 0), /// (2, 1), /// (4, 1), /// (5, 1), /// (3, 1), /// (1, 2), /// (2, 3), /// (4, 5), /// (5, 8), /// (3, 13), /// (1, 21), /// (2, 34), /// (4, 55) /// ]; /// /// assert_eq!(v.binary_search_by_key(&0, |&(a, b)| b), Ok(0)); /// assert_eq!(v.binary_search_by_key(&13, |&(a, b)| b), Ok(9)); /// assert_eq!(v.binary_search_by_key(&4, |&(a, b)| b), Err(7)); /// assert_eq!(v.binary_search_by_key(&100, |&(a, b)| b), Err(13)); /// let r = v.binary_search_by_key(&1, |&(a, b)| b); /// assert!(match r { /// Ok(1..=4) => true, /// _ => false, /// }); /// ``` pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result where B: Ord, F: FnMut(&'a T) -> B, { self.binary_search_by(|k| f(k).cmp(b)) } /// Sorts the `NEVec` in place. /// /// See also [`slice::sort`]. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// /// let mut n = nev![5, 4, 3, 2, 1]; /// n.sort(); /// assert_eq!(nev![1, 2, 3, 4, 5], n); /// /// // Naturally, sorting a sorted result should remain the same. /// n.sort(); /// assert_eq!(nev![1, 2, 3, 4, 5], n); /// ``` pub fn sort(&mut self) where T: Ord, { self.inner.sort(); } /// Like [`NEVec::sort`], but sorts the `NEVec` with a given comparison /// function. /// /// See also [`slice::sort_by`]. /// /// ``` /// use nonempty_collections::nev; /// /// let mut n = nev!["Sirion", "Gelion", "Narog"]; /// n.sort_by(|a, b| b.cmp(&a)); /// assert_eq!(nev!["Sirion", "Narog", "Gelion"], n); /// ``` pub fn sort_by(&mut self, f: F) where F: FnMut(&T, &T) -> Ordering, { self.inner.sort_by(f); } /// Like [`NEVec::sort`], but sorts the `NEVec` after first transforming /// each element into something easily comparable. Beware of expensive key /// functions, as the results of each call are not cached. /// /// See also [`slice::sort_by_key`]. /// /// ``` /// use nonempty_collections::nev; /// /// let mut n = nev![-5, 4, -3, 2, 1]; /// n.sort_by_key(|x| x * x); /// assert_eq!(nev![1, 2, -3, 4, -5], n); /// /// // Naturally, sorting a sorted result should remain the same. /// n.sort_by_key(|x| x * x); /// assert_eq!(nev![1, 2, -3, 4, -5], n); /// ``` pub fn sort_by_key(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord, { self.inner.sort_by_key(f); } /// Yields a `NESlice`. #[must_use] pub fn as_nonempty_slice(&self) -> crate::NESlice<'_, T> { // SAFETY: `self.inner` is non-empty by the invariant of `NEVec` unsafe { crate::NESlice::from_slice_unchecked(self.inner.as_slice()) } } /// Removes all but the first of consecutive elements in the vector that /// resolve to the same key. /// /// If the vector is sorted, this removes all duplicates. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// let mut v = nev![10, 20, 21, 30, 20]; /// /// v.dedup_by_key(|i| *i / 10); /// /// assert_eq!(nev![10, 20, 30, 20], v); /// ``` pub fn dedup_by_key(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K: PartialEq, { self.dedup_by(|a, b| key(a) == key(b)); } /// Removes all but the first of consecutive elements in the vector /// satisfying a given equality relation. /// /// The `same_bucket` function is passed references to two elements from the /// vector and must determine if the elements compare equal. The /// elements are passed in opposite order from their order in the slice, /// so if `same_bucket(a, b)` returns `true`, `a` is removed. /// /// If the vector is sorted, this removes all duplicates. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// let mut v = nev!["foo", "Foo", "foo", "bar", "Bar", "baz", "bar"]; /// /// v.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); /// /// assert_eq!(nev!["foo", "bar", "baz", "bar"], v); /// ``` pub fn dedup_by(&mut self, same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool, { self.inner.dedup_by(same_bucket); } /// Returns a non-empty iterator over `chunk_size` elements of the `NEVec` /// at a time, starting at the beginning of the `NEVec`. /// /// ``` /// use std::num::NonZeroUsize; /// /// use nonempty_collections::*; /// /// let v = nev![1, 2, 3, 4, 5, 6]; /// let n = NonZeroUsize::new(2).unwrap(); /// let r = v.nonempty_chunks(n).collect::>(); /// /// let a = nev![1, 2]; /// let b = nev![3, 4]; /// let c = nev![5, 6]; /// /// assert_eq!( /// r, /// nev![ /// a.as_nonempty_slice(), /// b.as_nonempty_slice(), /// c.as_nonempty_slice() /// ] /// ); /// ``` pub fn nonempty_chunks(&self, chunk_size: NonZeroUsize) -> NEChunks<'_, T> { NEChunks { inner: self.inner.chunks(chunk_size.get()), } } /// Returns the index of the partition point according to the given /// predicate (the index of the first element of the second partition). /// /// The vector is assumed to be partitioned according to the given /// predicate. This means that all elements for which the predicate /// returns true are at the start of the vector and all elements for /// which the predicate returns false are at the end. For example, `[7, /// 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0` /// (all odd numbers are at the start, all even at the end). /// /// If this vector is not partitioned, the returned result is unspecified /// and meaningless, as this method performs a kind of binary search. /// /// See also [`NEVec::binary_search`], [`NEVec::binary_search_by`], and /// [`NEVec::binary_search_by_key`]. /// /// # Examples /// /// ``` /// # use nonempty_collections::*; /// # /// let v = nev![1, 2, 3, 3, 5, 6, 7]; /// let i = v.partition_point(|&x| x < 5); /// /// assert_eq!(i, 4); /// ``` /// /// If all elements of the non-empty vector match the predicate, then the /// length of the vector will be returned: /// /// ``` /// # use nonempty_collections::*; /// # /// let a = nev![2, 4, 8]; /// assert_eq!(a.partition_point(|&x| x < 100), a.len().get()); /// ``` /// /// If you want to insert an item to a sorted vector, while maintaining /// sort order: /// /// ``` /// # use nonempty_collections::*; /// # /// let mut s = nev![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; /// let num = 42; /// let idx = s.partition_point(|&x| x < num); /// s.insert(idx, num); /// assert_eq!(s, nev![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); /// ``` #[must_use] pub fn partition_point

(&self, mut pred: P) -> usize where P: FnMut(&T) -> bool, { self.binary_search_by(|x| { if pred(x) { Ordering::Less } else { Ordering::Greater } }) .unwrap_or_else(|i| i) } } impl NEVec { /// Removes consecutive repeated elements in the vector according to the /// [`PartialEq`] trait implementation. /// /// If the vector is sorted, this removes all duplicates. /// /// # Examples /// /// ``` /// use nonempty_collections::nev; /// let mut v = nev![1, 1, 1, 2, 3, 2, 2, 1]; /// v.dedup(); /// assert_eq!(nev![1, 2, 3, 2, 1], v); /// ``` pub fn dedup(&mut self) { self.dedup_by(|a, b| a == b); } } impl From> for Vec { /// Turns a non-empty list into a `Vec`. fn from(nonempty: NEVec) -> Vec { nonempty.inner } } impl From<(T, Vec)> for NEVec { /// Turns a pair of an element and a `Vec` into /// a `NEVec`. fn from((head, tail): (T, Vec)) -> Self { let mut vec = vec![head]; vec.extend(tail); NEVec { inner: vec } } } impl AsRef> for NEVec { fn as_ref(&self) -> &Vec { self.inner.as_ref() } } impl AsMut> for NEVec { fn as_mut(&mut self) -> &mut Vec { self.inner.as_mut() } } /// ``` /// use nonempty_collections::*; /// /// let v0 = nev![1, 2, 3]; /// let v1: NEVec<_> = v0.nonempty_iter().cloned().collect(); /// assert_eq!(v0, v1); /// ``` impl FromNonEmptyIterator for NEVec { fn from_nonempty_iter(iter: I) -> Self where I: IntoNonEmptyIterator, { NEVec { inner: iter.into_nonempty_iter().into_iter().collect(), } } } /// A non-empty iterator over the values of an [`NEVec`]. #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { iter: std::slice::Iter<'a, T>, } impl NonEmptyIterator for Iter<'_, T> {} impl<'a, T> IntoIterator for Iter<'a, T> { type Item = &'a T; type IntoIter = std::slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter } } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` (see https://github.com/rust-lang/rust/issues/26925 for more info) impl Clone for Iter<'_, T> { fn clone(&self) -> Self { Iter { iter: self.iter.clone(), } } } impl Debug for Iter<'_, T> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.iter.fmt(f) } } /// A non-empty iterator over mutable values from an [`NEVec`]. #[derive(Debug)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, T: 'a> { inner: std::slice::IterMut<'a, T>, } impl NonEmptyIterator for IterMut<'_, T> {} impl<'a, T> IntoIterator for IterMut<'a, T> { type Item = &'a mut T; type IntoIter = std::slice::IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { self.inner } } /// An owned non-empty iterator over values from an [`NEVec`]. #[derive(Clone)] #[must_use = "non-empty iterators are lazy and do nothing unless consumed"] pub struct IntoIter { inner: std::vec::IntoIter, } impl NonEmptyIterator for IntoIter {} impl IntoIterator for IntoIter { type Item = T; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner } } impl Debug for IntoIter { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl IntoNonEmptyIterator for NEVec { type IntoNEIter = IntoIter; fn into_nonempty_iter(self) -> Self::IntoNEIter { IntoIter { inner: self.inner.into_iter(), } } } impl<'a, T> IntoNonEmptyIterator for &'a NEVec { type IntoNEIter = Iter<'a, T>; fn into_nonempty_iter(self) -> Self::IntoNEIter { self.nonempty_iter() } } impl IntoIterator for NEVec { type Item = T; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl<'a, T> IntoIterator for &'a NEVec { type Item = &'a T; type IntoIter = std::slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, T> IntoIterator for &'a mut NEVec { type Item = &'a mut T; type IntoIter = std::slice::IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } impl std::ops::Index for NEVec { type Output = T; /// ``` /// use nonempty_collections::nev; /// /// let v = nev![1, 2, 3, 4, 5]; /// /// assert_eq!(v[0], 1); /// assert_eq!(v[1], 2); /// assert_eq!(v[3], 4); /// ``` fn index(&self, index: usize) -> &T { self.inner.index(index) } } impl std::ops::IndexMut for NEVec { fn index_mut(&mut self, index: usize) -> &mut T { self.inner.index_mut(index) } } impl Debug for NEVec { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl TryFrom> for NEVec { type Error = crate::Error; fn try_from(vec: Vec) -> Result { NEVec::try_from_vec(vec).ok_or(crate::Error::Empty) } } impl Extend for NEVec { fn extend(&mut self, iter: I) where I: IntoIterator, { self.inner.extend(iter); } } impl Singleton for NEVec { type Item = T; /// ``` /// use nonempty_collections::{NEVec, Singleton, nev}; /// /// let v = NEVec::singleton(1); /// assert_eq!(nev![1], v); /// ``` fn singleton(item: T) -> NEVec { NEVec::new(item) } } #[cfg(test)] mod tests { use crate::nev; use crate::NEVec; #[derive(Debug, Clone, PartialEq)] struct Foo { user: String, } #[test] fn macro_usage() { let a = Foo { user: "a".to_string(), }; let b = Foo { user: "b".to_string(), }; let v = nev![a, b]; assert_eq!("a", v.first().user); } #[test] fn macro_semicolon() { let a = Foo { user: "a".to_string(), }; let v = nev![a.clone(); 3]; let expected = NEVec { inner: vec![a; 3] }; assert_eq!(v, expected); } #[test] fn test_from_conversion() { let result = NEVec::from((1, vec![2, 3, 4, 5])); let expected = NEVec { inner: vec![1, 2, 3, 4, 5], }; assert_eq!(result, expected); } #[test] fn test_into_iter() { let nonempty = NEVec::from((0usize, vec![1, 2, 3])); for (i, n) in nonempty.into_iter().enumerate() { assert_eq!(i, n); } } #[test] fn test_iter_syntax() { let nonempty = NEVec::from((0, vec![1, 2, 3])); for n in &nonempty { assert_eq!(*n, *n); // Prove that we're dealing with references. } for _ in nonempty {} } #[cfg(feature = "serde")] mod serialize { use serde::Deserialize; use serde::Serialize; use crate::NEVec; #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] struct SimpleSerializable(i32); #[test] fn test_simple_round_trip() -> Result<(), Box> { // Given let mut v = NEVec::new(SimpleSerializable(42)); v.push(SimpleSerializable(777)); let expected_value = v.clone(); // When let res = serde_json::from_str::<'_, NEVec>(&serde_json::to_string(&v)?)?; // Then assert_eq!(res, expected_value); Ok(()) } } #[test] fn test_result_collect() { use crate::IntoNonEmptyIterator; use crate::NonEmptyIterator; let nonempty = nev![2, 4, 8]; let output = nonempty .into_nonempty_iter() .map(|n| { if n % 2 == 0 { Ok(n) } else { Err("odd number!") } }) .collect::, &'static str>>(); assert_eq!(output, Ok(nev![2, 4, 8])); let nonempty = nev![2, 1, 8]; let output = nonempty .into_nonempty_iter() .map(|n| { if n % 2 == 0 { Ok(n) } else { Err("odd number!") } }) .collect::, &'static str>>(); assert_eq!(output, Err("odd number!")); } #[test] fn test_as_slice() { let nonempty = NEVec::from((0, vec![1, 2, 3])); assert_eq!( crate::NESlice::try_from_slice(&[0, 1, 2, 3]).unwrap(), nonempty.as_nonempty_slice(), ); } #[test] fn debug_impl() { let actual = format!("{:?}", nev![0, 1, 2, 3]); let expected = format!("{:?}", vec![0, 1, 2, 3]); assert_eq!(expected, actual); } #[test] fn sorting() { let mut n = nev![1, 5, 4, 3, 2, 1]; n.sort(); assert_eq!(nev![1, 1, 2, 3, 4, 5], n); let mut m = nev![1]; m.sort(); assert_eq!(nev![1], m); } #[test] fn extend() { let mut n = nev![1, 2, 3]; let v = vec![4, 5, 6]; n.extend(v); assert_eq!(n, nev![1, 2, 3, 4, 5, 6]); } #[test] fn iter_mut() { let mut v = nev![0, 1, 2, 3]; v.iter_mut().for_each(|x| { *x += 1; }); assert_eq!(nev![1, 2, 3, 4], v); for x in &mut v { *x -= 1; } assert_eq!(nev![0, 1, 2, 3], v); } #[test] fn retain() { // retain all let v = nev![0, 1, 2, 3]; let result = v.retain(|_| true); assert_eq!( Ok(nev![0, 1, 2, 3]), result, "retaining all values should not change anything" ); // retain none let v = nev![0, 1, 2, 3]; let result = v.retain(|_| false); assert_eq!( Err(vec![]), result, "removing all values should return a regular vec" ); // retain one let v = nev![3, 7]; let result = v.retain_mut(|x| *x == 3); assert_eq!(Ok(nev![3]), result, "only 3 should remain"); } #[test] fn retain_mut() { // retain all let v = nev![0, 1, 2, 3]; let result = v.retain_mut(|x| { *x += 1; true }); assert_eq!( Ok(nev![1, 2, 3, 4]), result, "each value must be incremented by 1" ); let v = nev![0, 1, 2, 3]; // retain none let result = v.retain_mut(|x| { *x += 1; false }); assert_eq!( Err(vec![]), result, "removing all values should return a regular vec" ); // retain one let v = nev![3, 7]; let result = v.retain_mut(|x| { if *x == 3 { *x += 1; true } else { false } }); assert_eq!(Ok(nev![4]), result, "only 3+1 = 4 should remain"); } }