nonempty-0.11.0/.cargo_vcs_info.json0000644000000001610000000000100127620ustar { "git": { "sha1": "99130f7e1486d117e65f5722d8d4c1de2b2704dd", "dirty": true }, "path_in_vcs": "" }nonempty-0.11.0/.envrc000064400000000000000000000000121046102023000126630ustar 00000000000000use flake nonempty-0.11.0/.github/workflows/actions.yml000064400000000000000000000032661046102023000173430ustar 00000000000000name: Cargo on: push: branches: [master] pull_request: branches: [master] jobs: build: name: Build and test strategy: matrix: os: ['ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - name: Build run: cargo build --verbose env: RUSTFLAGS: -D warnings - name: Run tests run: cargo test --all --verbose --features serialize,arbitrary no-std: name: no-std build and test strategy: matrix: os: ['ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - name: Build run: cargo build --verbose --no-default-features env: RUSTFLAGS: -D warnings - name: Run tests run: cargo test --all --verbose --no-default-features rustfmt_and_clippy: name: Check rustfmt style && run clippy runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal components: clippy, rustfmt override: true - name: Cache cargo registry uses: actions/cache@v1 with: path: ~/.cargo/registry key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - name: Run clippy uses: actions-rs/cargo@v1 with: command: clippy args: --all --tests --features serialize,arbitrary env: RUSTFLAGS: -D warnings - name: Check formating uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check nonempty-0.11.0/.gitignore000064400000000000000000000000441046102023000135420ustar 00000000000000/target **/*.rs.bk Cargo.lock .idea nonempty-0.11.0/CHANGELOG.md000064400000000000000000000012531046102023000133660ustar 00000000000000# Changelog All notable changes to this library will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## 0.11.0 ### Added - `std` feature flag; building with `--no-default-features` now enables `no_std` use. - `NonEmpty::sort` was added. - `NonEmpty::as_ref` added for converting a `&NonEmpty` to `NonEmpty<&T>`. ### Changed - MSRV is now 1.56 (this is a semver-breaking change). - `NonEmpty::split` now returns `Option<&T>` for last element. - `cargo clippy` and `cargo doc` failures are fixed. ## [Unreleased] nonempty-0.11.0/Cargo.toml0000644000000022770000000000100107720ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "nonempty" version = "0.11.0" authors = ["Alexis Sellier "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Correct by construction non-empty vector" readme = "README.md" license = "MIT" repository = "https://github.com/cloudhead/nonempty" [lib] name = "nonempty" path = "src/lib.rs" [dependencies.arbitrary] version = "1" features = ["derive"] optional = true [dependencies.serde] version = "1" features = [ "derive", "alloc", ] optional = true default-features = false [dev-dependencies.serde_json] version = "1" [features] arbitrary = ["dep:arbitrary"] default = ["std"] serialize = ["dep:serde"] std = [] nonempty-0.11.0/Cargo.toml.orig000064400000000000000000000010561046102023000144450ustar 00000000000000[package] name = "nonempty" version = "0.11.0" description = "Correct by construction non-empty vector" authors = ["Alexis Sellier "] edition = "2021" license = "MIT" repository = "https://github.com/cloudhead/nonempty" [dependencies] serde = { features = ["derive", "alloc"], default-features = false, optional = true, version = "1" } arbitrary = { features = ["derive"], optional = true, version = "1" } [features] default = ["std"] std = [] serialize = ["dep:serde"] arbitrary = ["dep:arbitrary"] [dev-dependencies] serde_json = "1" nonempty-0.11.0/LICENSE000064400000000000000000000020421046102023000125570ustar 00000000000000Copyright (c) 2019 Alexis Sellier 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-0.11.0/README.md000064400000000000000000000007141046102023000130350ustar 00000000000000# Correct by Construction Non-Empty List This package exposes a type `NonEmpty` with a data representation that guarantees non-emptiness statically: struct NonEmpty(T, Vec) The library is meant to have an interface similar to `std::vec::Vec`: use nonempty::NonEmpty; let mut l = NonEmpty::new(42); assert_eq!(l.first(), &42); l.push(36); l.push(58); let v: Vec = l.into(); assert_eq!(v, vec![42, 36, 58]); nonempty-0.11.0/flake.lock000064400000000000000000000000001046102023000134760ustar 00000000000000nonempty-0.11.0/flake.nix000064400000000000000000000102321046102023000133540ustar 00000000000000{ description = "Build a cargo project"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/release-24.11"; crane.url = "github:ipetkov/crane"; flake-utils.url = "github:numtide/flake-utils"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs = { nixpkgs.follows = "nixpkgs"; flake-utils.follows = "flake-utils"; }; }; advisory-db = { url = "github:rustsec/advisory-db"; flake = false; }; }; outputs = { self, nixpkgs, crane, rust-overlay, flake-utils, advisory-db, ... }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; overlays = [(import rust-overlay)]; }; rustToolChain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; craneLib = (crane.mkLib pkgs).overrideToolchain rustToolChain; inherit (pkgs) lib; src = craneLib.cleanCargoSource ./.; # Common arguments can be set here to avoid repeating them later commonArgs = { inherit src; strictDeps = true; buildInputs = [ # Add additional build inputs here ] ++ lib.optionals pkgs.stdenv.isDarwin [ # Additional darwin specific inputs can be set here pkgs.libiconv ]; # Additional environment variables can be set directly # MY_CUSTOM_VAR = "some value"; }; # Build *just* the cargo dependencies, so we can reuse # all of that work (e.g. via cachix) when running in CI cargoArtifacts = craneLib.buildDepsOnly commonArgs; # Build the actual crate itself, reusing the dependency # artifacts from above. my-crate = craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); in { checks = { # Build the crate as part of `nix flake check` for convenience inherit my-crate; # Run clippy (and deny all warnings) on the crate source, # again, reusing the dependency artifacts from above. # # Note that this is done as a separate derivation so that # we can block the CI if there are issues here, but not # prevent downstream consumers from building our crate by itself. my-crate-clippy = craneLib.cargoClippy (commonArgs // { inherit cargoArtifacts; cargoClippyExtraArgs = "--all-targets -- --deny warnings"; }); my-crate-doc = craneLib.cargoDoc (commonArgs // { inherit cargoArtifacts; }); # Check formatting my-crate-fmt = craneLib.cargoFmt { inherit src; }; my-crate-toml-fmt = craneLib.taploFmt { src = pkgs.lib.sources.sourceFilesBySuffices src [ ".toml" ]; # taplo arguments can be further customized below as needed # taploExtraArgs = "--config ./taplo.toml"; }; # Audit dependencies my-crate-audit = craneLib.cargoAudit { inherit src advisory-db; }; # Audit licenses my-crate-deny = craneLib.cargoDeny { inherit src; }; # Run tests with cargo-nextest # Consider setting `doCheck = false` on `my-crate` if you do not want # the tests to run twice my-crate-nextest = craneLib.cargoNextest (commonArgs // { inherit cargoArtifacts; partitions = 1; partitionType = "count"; }); }; packages = { default = my-crate; }; apps.default = flake-utils.lib.mkApp { drv = my-crate; }; devShells.default = craneLib.devShell { # Inherit inputs from checks. checks = self.checks.${system}; # Additional dev-shell environment variables can be set directly # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; # Extra inputs can be added here; cargo and rustc are provided by default. packages = [ pkgs.cargo-watch pkgs.cargo-nextest # pkgs.ripgrep ]; }; }); } nonempty-0.11.0/rust-toolchain.toml000064400000000000000000000001141046102023000154200ustar 00000000000000[toolchain] channel = "1.83" profile = "default" components = [ "rust-src" ]nonempty-0.11.0/src/lib.rs000064400000000000000000001137131046102023000134650ustar 00000000000000//! A Non-empty growable vector. //! //! 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 as 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 `NonEmpty`, 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`, [`NonEmpty::first`] and [`NonEmpty::last`] don't //! return in `Option`, they always succeed. //! //! # Examples //! //! The simplest way to construct a [`NonEmpty`] is via the [`nonempty`] macro: //! //! ``` //! # extern crate alloc; //! # use alloc::vec::Vec; //! use nonempty::{NonEmpty, nonempty}; //! //! let l: NonEmpty = nonempty![1, 2, 3]; //! assert_eq!(l.head, 1); //! ``` //! //! Unlike the familiar `vec!` macro, `nonempty!` requires at least one element: //! //! ``` //! # extern crate alloc; //! # use alloc::vec::Vec; //! use nonempty::nonempty; //! //! let l = nonempty![1]; //! //! // Doesn't compile! //! // let l = nonempty![]; //! ``` //! //! Like `Vec`, you can also construct a [`NonEmpty`] the old fashioned way with //! [`NonEmpty::new`] or its constructor: //! //! ``` //! # extern crate alloc; //! # use alloc::vec::Vec; //! use nonempty::NonEmpty; //! //! let mut l = NonEmpty { head: 42, tail: vec![36, 58] }; //! assert_eq!(l.head, 42); //! //! l.push(9001); //! assert_eq!(l.last(), &9001); //! ``` //! //! And if necessary, you're free to convert to and from `Vec`: //! //! ``` //! use nonempty::{NonEmpty, nonempty}; //! //! let l: NonEmpty = nonempty![42, 36, 58, 9001]; //! let v: Vec = l.into(); //! assert_eq!(v, vec![42, 36, 58, 9001]); //! //! let u: Option> = NonEmpty::from_vec(v); //! assert_eq!(Some(nonempty![42, 36, 58, 9001]), u); //! ``` //! //! # Caveats //! //! Since `NonEmpty` must have a least one element, it is not possible to //! implement the `FromIterator` trait for it. We can't know, in general, if //! any given `Iterator` actually contains something. #![no_std] //! # Features //! //! * `serialize`: `serde` support. //! * `arbitrary`: `arbitrary` support. #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; #[cfg(feature = "serialize")] use serde::{ ser::{SerializeSeq, Serializer}, Deserialize, Serialize, }; use core::iter; use core::mem; use core::{cmp::Ordering, num::NonZeroUsize}; #[cfg(feature = "std")] extern crate std; #[cfg_attr(test, macro_use)] extern crate alloc; use alloc::vec::{self, Vec}; pub mod nonzero; /// Like the `vec!` macro, but enforces at least one argument. A nice short-hand /// for constructing [`NonEmpty`] values. /// /// ``` /// # extern crate alloc; /// # use alloc::vec::Vec; /// use nonempty::{NonEmpty, nonempty}; /// /// let v = nonempty![1, 2, 3]; /// assert_eq!(v, NonEmpty { head: 1, tail: vec![2, 3] }); /// /// let v = nonempty![1]; /// assert_eq!(v, NonEmpty { head: 1, tail: Vec::new() }); /// /// // Accepts trailing commas /// let v = nonempty![1,]; /// assert_eq!(v, NonEmpty { head: 1, tail: Vec::new() }); /// /// // Doesn't compile! /// // let v = nonempty![]; /// ``` #[macro_export] macro_rules! nonempty { ($h:expr, $( $x:expr ),* $(,)?) => {{ let tail = vec![$($x),*]; $crate::NonEmpty { head: $h, tail } }}; ($h:expr) => { $crate::NonEmpty { head: $h, tail: alloc::vec::Vec::new(), } }; } /// Non-empty vector. #[cfg_attr(feature = "serialize", derive(Deserialize))] #[cfg_attr(feature = "arbitrary", derive(Arbitrary))] #[cfg_attr(feature = "serialize", serde(try_from = "Vec"))] #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct NonEmpty { pub head: T, pub tail: Vec, } // Nb. `Serialize` is implemented manually, as serde's `into` container attribute // requires a `T: Clone` bound which we'd like to avoid. #[cfg(feature = "serialize")] impl Serialize for NonEmpty where T: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut seq = serializer.serialize_seq(Some(self.len()))?; for e in self { seq.serialize_element(e)?; } seq.end() } } pub struct Iter<'a, T> { head: Option<&'a T>, tail: &'a [T], } impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { if let Some(value) = self.head.take() { Some(value) } else if let Some((first, rest)) = self.tail.split_first() { self.tail = rest; Some(first) } else { None } } } impl DoubleEndedIterator for Iter<'_, T> { fn next_back(&mut self) -> Option { if let Some((last, rest)) = self.tail.split_last() { self.tail = rest; Some(last) } else if let Some(first_value) = self.head.take() { Some(first_value) } else { None } } } impl ExactSizeIterator for Iter<'_, T> { fn len(&self) -> usize { self.tail.len() + self.head.map_or(0, |_| 1) } } impl core::iter::FusedIterator for Iter<'_, T> {} impl NonEmpty { /// Alias for [`NonEmpty::singleton`]. pub const fn new(e: T) -> Self { Self::singleton(e) } /// Converts from `&NonEmpty` to `NonEmpty<&T>`. pub fn as_ref(&self) -> NonEmpty<&T> { NonEmpty { head: &self.head, tail: self.tail.iter().collect(), } } /// Attempt to convert an iterator into a `NonEmpty` vector. /// Returns `None` if the iterator was empty. pub fn collect(iter: I) -> Option> where I: IntoIterator, { let mut iter = iter.into_iter(); let head = iter.next()?; Some(Self { head, tail: iter.collect(), }) } /// Create a new non-empty list with an initial element. pub const fn singleton(head: T) -> Self { NonEmpty { head, tail: Vec::new(), } } /// Always returns false. pub const fn is_empty(&self) -> bool { false } /// Get the first element. Never fails. pub const fn first(&self) -> &T { &self.head } /// Get the mutable reference to the first element. Never fails. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let mut non_empty = NonEmpty::new(42); /// let head = non_empty.first_mut(); /// *head += 1; /// assert_eq!(non_empty.first(), &43); /// /// let mut non_empty = NonEmpty::from((1, vec![4, 2, 3])); /// let head = non_empty.first_mut(); /// *head *= 42; /// assert_eq!(non_empty.first(), &42); /// ``` pub fn first_mut(&mut self) -> &mut T { &mut self.head } /// Get the possibly-empty tail of the list. /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new(42); /// assert_eq!(non_empty.tail(), &[]); /// /// let non_empty = NonEmpty::from((1, vec![4, 2, 3])); /// assert_eq!(non_empty.tail(), &[4, 2, 3]); /// ``` pub fn tail(&self) -> &[T] { &self.tail } /// Push an element to the end of the list. pub fn push(&mut self, e: T) { self.tail.push(e) } /// Pop an element from the end of the list. pub fn pop(&mut self) -> Option { self.tail.pop() } /// 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::NonEmpty; /// /// let mut non_empty = NonEmpty::from((1, vec![2, 3])); /// non_empty.insert(1, 4); /// assert_eq!(non_empty, NonEmpty::from((1, vec![4, 2, 3]))); /// non_empty.insert(4, 5); /// assert_eq!(non_empty, NonEmpty::from((1, vec![4, 2, 3, 5]))); /// non_empty.insert(0, 42); /// assert_eq!(non_empty, NonEmpty::from((42, vec![1, 4, 2, 3, 5]))); /// ``` pub fn insert(&mut self, index: usize, element: T) { let len = self.len(); assert!(index <= len); if index == 0 { let head = mem::replace(&mut self.head, element); self.tail.insert(0, head); } else { self.tail.insert(index - 1, element); } } /// Get the length of the list. pub fn len(&self) -> usize { self.tail.len() + 1 } /// Gets the length of the list as a NonZeroUsize. pub fn len_nonzero(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.tail.len().saturating_add(1)) } } /// Get the capacity of the list. pub fn capacity(&self) -> usize { self.tail.capacity() + 1 } /// Get the last element. Never fails. pub fn last(&self) -> &T { match self.tail.last() { None => &self.head, Some(e) => e, } } /// Get the last element mutably. pub fn last_mut(&mut self) -> &mut T { match self.tail.last_mut() { None => &mut self.head, Some(e) => e, } } /// Check whether an element is contained in the list. /// /// ``` /// use nonempty::NonEmpty; /// /// let mut l = NonEmpty::from((42, vec![36, 58])); /// /// assert!(l.contains(&42)); /// assert!(!l.contains(&101)); /// ``` pub fn contains(&self, x: &T) -> bool where T: PartialEq, { self.iter().any(|e| e == x) } /// Get an element by index. pub fn get(&self, index: usize) -> Option<&T> { if index == 0 { Some(&self.head) } else { self.tail.get(index - 1) } } /// Get an element by index, mutably. pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { if index == 0 { Some(&mut self.head) } else { self.tail.get_mut(index - 1) } } /// Truncate the list to a certain size. Must be greater than `0`. pub fn truncate(&mut self, len: usize) { assert!(len >= 1); self.tail.truncate(len - 1); } /// ``` /// use nonempty::NonEmpty; /// /// let mut l = NonEmpty::from((42, vec![36, 58])); /// /// let mut l_iter = l.iter(); /// /// assert_eq!(l_iter.len(), 3); /// assert_eq!(l_iter.next(), Some(&42)); /// assert_eq!(l_iter.next(), Some(&36)); /// assert_eq!(l_iter.next(), Some(&58)); /// assert_eq!(l_iter.next(), None); /// ``` pub fn iter(&self) -> Iter { Iter { head: Some(&self.head), tail: &self.tail, } } /// ``` /// use nonempty::NonEmpty; /// /// let mut l = NonEmpty::new(42); /// l.push(36); /// l.push(58); /// /// for i in l.iter_mut() { /// *i *= 10; /// } /// /// let mut l_iter = l.iter(); /// /// assert_eq!(l_iter.next(), Some(&420)); /// assert_eq!(l_iter.next(), Some(&360)); /// assert_eq!(l_iter.next(), Some(&580)); /// assert_eq!(l_iter.next(), None); /// ``` pub fn iter_mut(&mut self) -> impl DoubleEndedIterator + '_ { iter::once(&mut self.head).chain(self.tail.iter_mut()) } /// Often we have a `Vec` (or slice `&[T]`) but want to ensure that it is `NonEmpty` before /// proceeding with a computation. Using `from_slice` will give us a proof /// that we have a `NonEmpty` in the `Some` branch, otherwise it allows /// the caller to handle the `None` case. /// /// # Example Use /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty_vec = NonEmpty::from_slice(&[1, 2, 3, 4, 5]); /// assert_eq!(non_empty_vec, Some(NonEmpty::from((1, vec![2, 3, 4, 5])))); /// /// let empty_vec: Option> = NonEmpty::from_slice(&[]); /// assert!(empty_vec.is_none()); /// ``` pub fn from_slice(slice: &[T]) -> Option> where T: Clone, { slice.split_first().map(|(h, t)| NonEmpty { head: h.clone(), tail: t.into(), }) } /// Often we have a `Vec` (or slice `&[T]`) but want to ensure that it is `NonEmpty` before /// proceeding with a computation. Using `from_vec` will give us a proof /// that we have a `NonEmpty` 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 `NonEmpty::from_slice`. /// /// # Example Use /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty_vec = NonEmpty::from_vec(vec![1, 2, 3, 4, 5]); /// assert_eq!(non_empty_vec, Some(NonEmpty::from((1, vec![2, 3, 4, 5])))); /// /// let empty_vec: Option> = NonEmpty::from_vec(vec![]); /// assert!(empty_vec.is_none()); /// ``` pub fn from_vec(mut vec: Vec) -> Option> { if vec.is_empty() { None } else { let head = vec.remove(0); Some(NonEmpty { head, tail: vec }) } } /// Deconstruct a `NonEmpty` into its head and tail. /// This operation never fails since we are guaranteed /// to have a head element. /// /// # Example Use /// /// ``` /// use nonempty::NonEmpty; /// /// let mut non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// // Guaranteed to have the head and we also get the tail. /// assert_eq!(non_empty.split_first(), (&1, &[2, 3, 4, 5][..])); /// /// let non_empty = NonEmpty::new(1); /// /// // Guaranteed to have the head element. /// assert_eq!(non_empty.split_first(), (&1, &[][..])); /// ``` pub fn split_first(&self) -> (&T, &[T]) { (&self.head, &self.tail) } /// Deconstruct a `NonEmpty` into its first, last, and /// middle elements, in that order. /// /// If there is only one element then last is `None`. /// /// # Example Use /// /// ``` /// use nonempty::NonEmpty; /// /// let mut non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// // When there are two or more elements, the last element is represented /// // as a `Some`. Elements preceding it, except for the first, are returned /// // in the middle. /// assert_eq!(non_empty.split(), (&1, &[2, 3, 4][..], Some(&5))); /// /// let non_empty = NonEmpty::new(1); /// /// // The last element is `None` when there's only one element. /// assert_eq!(non_empty.split(), (&1, &[][..], None)); /// ``` pub fn split(&self) -> (&T, &[T], Option<&T>) { match self.tail.split_last() { None => (&self.head, &[], None), Some((last, middle)) => (&self.head, middle, Some(last)), } } /// Append a `Vec` to the tail of the `NonEmpty`. /// /// # Example Use /// /// ``` /// use nonempty::NonEmpty; /// /// let mut non_empty = NonEmpty::new(1); /// let mut vec = vec![2, 3, 4, 5]; /// non_empty.append(&mut vec); /// /// let mut expected = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// assert_eq!(non_empty, expected); /// ``` pub fn append(&mut self, other: &mut Vec) { self.tail.append(other) } /// A structure preserving `map`. This is useful for when /// we wish to keep the `NonEmpty` structure guaranteeing /// that there is at least one element. Otherwise, we can /// use `nonempty.iter().map(f)`. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// let squares = non_empty.map(|i| i * i); /// /// let expected = NonEmpty::from((1, vec![4, 9, 16, 25])); /// /// assert_eq!(squares, expected); /// ``` pub fn map(self, mut f: F) -> NonEmpty where F: FnMut(T) -> U, { NonEmpty { head: f(self.head), tail: self.tail.into_iter().map(f).collect(), } } /// A structure preserving, fallible mapping function. pub fn try_map(self, mut f: F) -> Result, E> where F: FnMut(T) -> Result, { Ok(NonEmpty { head: f(self.head)?, tail: self.tail.into_iter().map(f).collect::>()?, }) } /// When we have a function that goes from some `T` to a `NonEmpty`, /// we may want to apply it to a `NonEmpty` but keep the structure flat. /// This is where `flat_map` shines. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// let windows = non_empty.flat_map(|i| { /// let mut next = NonEmpty::new(i + 5); /// next.push(i + 6); /// next /// }); /// /// let expected = NonEmpty::from((6, vec![7, 7, 8, 8, 9, 9, 10, 10, 11])); /// /// assert_eq!(windows, expected); /// ``` pub fn flat_map(self, mut f: F) -> NonEmpty where F: FnMut(T) -> NonEmpty, { let mut heads = f(self.head); let mut tails = self .tail .into_iter() .flat_map(|t| f(t).into_iter()) .collect(); heads.append(&mut tails); heads } /// Flatten nested `NonEmpty`s into a single one. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::from(( /// NonEmpty::from((1, vec![2, 3])), /// vec![NonEmpty::from((4, vec![5]))], /// )); /// /// let expected = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// assert_eq!(NonEmpty::flatten(non_empty), expected); /// ``` pub fn flatten(full: NonEmpty>) -> Self { full.flat_map(|n| n) } /// 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. /// /// 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::NonEmpty; /// /// let non_empty = NonEmpty::from((0, vec![1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55])); /// assert_eq!(non_empty.binary_search(&0), Ok(0)); /// assert_eq!(non_empty.binary_search(&13), Ok(9)); /// assert_eq!(non_empty.binary_search(&4), Err(7)); /// assert_eq!(non_empty.binary_search(&100), Err(13)); /// let r = non_empty.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::NonEmpty; /// /// let mut non_empty = NonEmpty::from((0, vec![1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55])); /// let num = 42; /// let idx = non_empty.binary_search(&num).unwrap_or_else(|x| x); /// non_empty.insert(idx, num); /// assert_eq!(non_empty, NonEmpty::from((0, vec![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. /// 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 in `[1,4]`. /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::from((0, vec![1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55])); /// let seek = 0; /// assert_eq!(non_empty.binary_search_by(|probe| probe.cmp(&seek)), Ok(0)); /// let seek = 13; /// assert_eq!(non_empty.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); /// let seek = 4; /// assert_eq!(non_empty.binary_search_by(|probe| probe.cmp(&seek)), Err(7)); /// let seek = 100; /// assert_eq!(non_empty.binary_search_by(|probe| probe.cmp(&seek)), Err(13)); /// let seek = 1; /// let r = non_empty.binary_search_by(|probe| probe.cmp(&seek)); /// assert!(match r { Ok(1..=4) => true, _ => false, }); /// ``` pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result where F: FnMut(&'a T) -> Ordering, { match f(&self.head) { Ordering::Equal => Ok(0), Ordering::Greater => Err(0), Ordering::Less => self .tail .binary_search_by(f) .map(|index| index + 1) .map_err(|index| index + 1), } } /// 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. 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::NonEmpty; /// /// let non_empty = NonEmpty::from(( /// (0, 0), /// vec![(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!(non_empty.binary_search_by_key(&0, |&(a,b)| b), Ok(0)); /// assert_eq!(non_empty.binary_search_by_key(&13, |&(a,b)| b), Ok(9)); /// assert_eq!(non_empty.binary_search_by_key(&4, |&(a,b)| b), Err(7)); /// assert_eq!(non_empty.binary_search_by_key(&100, |&(a,b)| b), Err(13)); /// let r = non_empty.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)) } /// Returns the maximum element in the non-empty vector. /// /// This will return the first item in the vector if the tail is empty. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new(42); /// assert_eq!(non_empty.maximum(), &42); /// /// let non_empty = NonEmpty::from((1, vec![-34, 42, 76, 4, 5])); /// assert_eq!(non_empty.maximum(), &76); /// ``` pub fn maximum(&self) -> &T where T: Ord, { self.maximum_by(|i, j| i.cmp(j)) } /// Returns the minimum element in the non-empty vector. /// /// This will return the first item in the vector if the tail is empty. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new(42); /// assert_eq!(non_empty.minimum(), &42); /// /// let non_empty = NonEmpty::from((1, vec![-34, 42, 76, 4, 5])); /// assert_eq!(non_empty.minimum(), &-34); /// ``` pub fn minimum(&self) -> &T where T: Ord, { self.minimum_by(|i, j| i.cmp(j)) } /// Returns the element that gives the maximum value with respect to the specified comparison function. /// /// This will return the first item in the vector if the tail is empty. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new((0, 42)); /// assert_eq!(non_empty.maximum_by(|(k, _), (l, _)| k.cmp(l)), &(0, 42)); /// /// let non_empty = NonEmpty::from(((2, 1), vec![(2, -34), (4, 42), (0, 76), (1, 4), (3, 5)])); /// assert_eq!(non_empty.maximum_by(|(k, _), (l, _)| k.cmp(l)), &(4, 42)); /// ``` pub fn maximum_by(&self, mut compare: F) -> &T where F: FnMut(&T, &T) -> Ordering, { let mut max = &self.head; for i in self.tail.iter() { max = match compare(max, i) { Ordering::Equal => max, Ordering::Less => i, Ordering::Greater => max, }; } max } /// Returns the element that gives the minimum value with respect to the specified comparison function. /// /// This will return the first item in the vector if the tail is empty. /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new((0, 42)); /// assert_eq!(non_empty.minimum_by(|(k, _), (l, _)| k.cmp(l)), &(0, 42)); /// /// let non_empty = NonEmpty::from(((2, 1), vec![(2, -34), (4, 42), (0, 76), (1, 4), (3, 5)])); /// assert_eq!(non_empty.minimum_by(|(k, _), (l, _)| k.cmp(l)), &(0, 76)); /// ``` pub fn minimum_by(&self, mut compare: F) -> &T where F: FnMut(&T, &T) -> Ordering, { self.maximum_by(|a, b| compare(a, b).reverse()) } /// Returns the element that gives the maximum value with respect to the specified function. /// /// This will return the first item in the vector if the tail is empty. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new((0, 42)); /// assert_eq!(non_empty.maximum_by_key(|(k, _)| *k), &(0, 42)); /// /// let non_empty = NonEmpty::from(((2, 1), vec![(2, -34), (4, 42), (0, 76), (1, 4), (3, 5)])); /// assert_eq!(non_empty.maximum_by_key(|(k, _)| *k), &(4, 42)); /// assert_eq!(non_empty.maximum_by_key(|(k, _)| -k), &(0, 76)); /// ``` pub fn maximum_by_key(&self, mut f: F) -> &T where U: Ord, F: FnMut(&T) -> U, { self.maximum_by(|i, j| f(i).cmp(&f(j))) } /// Returns the element that gives the minimum value with respect to the specified function. /// /// This will return the first item in the vector if the tail is empty. /// /// # Examples /// /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::new((0, 42)); /// assert_eq!(non_empty.minimum_by_key(|(k, _)| *k), &(0, 42)); /// /// let non_empty = NonEmpty::from(((2, 1), vec![(2, -34), (4, 42), (0, 76), (1, 4), (3, 5)])); /// assert_eq!(non_empty.minimum_by_key(|(k, _)| *k), &(0, 76)); /// assert_eq!(non_empty.minimum_by_key(|(k, _)| -k), &(4, 42)); /// ``` pub fn minimum_by_key(&self, mut f: F) -> &T where U: Ord, F: FnMut(&T) -> U, { self.minimum_by(|i, j| f(i).cmp(&f(j))) } /// Sorts the nonempty. /// /// The implementation uses [`slice::sort`](slice::sort) for the tail and then checks where the /// head belongs. If the head is already the smallest element, this should be as fast as sorting a /// slice. However, if the head needs to be inserted, then it incurs extra cost for removing /// the new head from the tail and adding the old head at the correct index. /// /// # Examples /// /// ``` /// use nonempty::nonempty; /// /// let mut non_empty = nonempty![-5, 4, 1, -3, 2]; /// /// non_empty.sort(); /// assert!(non_empty == nonempty![-5, -3, 1, 2, 4]); /// ``` pub fn sort(&mut self) where T: Ord, { self.tail.sort(); let index = match self.tail.binary_search(&self.head) { Ok(index) => index, Err(index) => index, }; if index != 0 { let new_head = self.tail.remove(0); let head = mem::replace(&mut self.head, new_head); self.tail.insert(index - 1, head); } } } impl Default for NonEmpty { fn default() -> Self { Self::new(T::default()) } } impl From> for Vec { /// Turns a non-empty list into a Vec. fn from(nonempty: NonEmpty) -> Vec { iter::once(nonempty.head).chain(nonempty.tail).collect() } } impl From> for (T, Vec) { /// Turns a non-empty list into a Vec. fn from(nonempty: NonEmpty) -> (T, Vec) { (nonempty.head, nonempty.tail) } } impl From<(T, Vec)> for NonEmpty { /// Turns a pair of an element and a Vec into /// a NonEmpty. fn from((head, tail): (T, Vec)) -> Self { NonEmpty { head, tail } } } impl IntoIterator for NonEmpty { type Item = T; type IntoIter = iter::Chain, vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { iter::once(self.head).chain(self.tail) } } impl<'a, T> IntoIterator for &'a NonEmpty { type Item = &'a T; type IntoIter = iter::Chain, core::slice::Iter<'a, T>>; fn into_iter(self) -> Self::IntoIter { iter::once(&self.head).chain(self.tail.iter()) } } impl core::ops::Index for NonEmpty { type Output = T; /// ``` /// use nonempty::NonEmpty; /// /// let non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// assert_eq!(non_empty[0], 1); /// assert_eq!(non_empty[1], 2); /// assert_eq!(non_empty[3], 4); /// ``` fn index(&self, index: usize) -> &T { if index > 0 { &self.tail[index - 1] } else { &self.head } } } impl core::ops::IndexMut for NonEmpty { fn index_mut(&mut self, index: usize) -> &mut T { if index > 0 { &mut self.tail[index - 1] } else { &mut self.head } } } impl Extend for NonEmpty { fn extend>(&mut self, iter: T) { self.tail.extend(iter) } } #[cfg(feature = "serialize")] pub mod serialize { use core::{convert::TryFrom, fmt}; use alloc::vec::Vec; use super::NonEmpty; #[derive(Debug)] pub enum Error { Empty, } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Empty => f.write_str( "the vector provided was empty, NonEmpty needs at least one element", ), } } } impl TryFrom> for NonEmpty { type Error = Error; fn try_from(vec: Vec) -> Result { NonEmpty::from_vec(vec).ok_or(Error::Empty) } } } #[cfg(test)] mod tests { use alloc::{string::String, vec::Vec}; use crate::NonEmpty; #[test] fn test_from_conversion() { let result = NonEmpty::from((1, vec![2, 3, 4, 5])); let expected = NonEmpty { head: 1, tail: vec![2, 3, 4, 5], }; assert_eq!(result, expected); } #[test] fn test_into_iter() { let nonempty = NonEmpty::from((0, vec![1, 2, 3])); for (i, n) in nonempty.into_iter().enumerate() { assert_eq!(i as i32, n); } } #[test] fn test_iter_syntax() { let nonempty = NonEmpty::from((0, vec![1, 2, 3])); for n in &nonempty { let _ = *n; // Prove that we're dealing with references. } for _ in nonempty {} } #[test] fn test_iter_both_directions() { let mut nonempty = NonEmpty::from((0, vec![1, 2, 3])); assert_eq!(nonempty.iter().cloned().collect::>(), [0, 1, 2, 3]); assert_eq!( nonempty.iter().rev().cloned().collect::>(), [3, 2, 1, 0] ); assert_eq!( nonempty.iter_mut().rev().collect::>(), [&mut 3, &mut 2, &mut 1, &mut 0] ); } #[test] fn test_iter_both_directions_at_once() { let nonempty = NonEmpty::from((0, vec![1, 2, 3])); let mut i = nonempty.iter(); assert_eq!(i.next(), Some(&0)); assert_eq!(i.next_back(), Some(&3)); assert_eq!(i.next(), Some(&1)); assert_eq!(i.next_back(), Some(&2)); assert_eq!(i.next(), None); assert_eq!(i.next_back(), None); } #[test] fn test_mutate_head() { let mut non_empty = NonEmpty::new(42); non_empty.head += 1; assert_eq!(non_empty.head, 43); let mut non_empty = NonEmpty::from((1, vec![4, 2, 3])); non_empty.head *= 42; assert_eq!(non_empty.head, 42); } #[test] fn test_to_nonempty() { use core::iter::{empty, once}; assert_eq!(NonEmpty::<()>::collect(empty()), None); assert_eq!(NonEmpty::<()>::collect(once(())), Some(NonEmpty::new(()))); assert_eq!( NonEmpty::::collect(once(1).chain(once(2))), Some(nonempty!(1, 2)) ); } #[test] fn test_try_map() { assert_eq!( nonempty!(1, 2, 3, 4).try_map(Ok::<_, String>), Ok(nonempty!(1, 2, 3, 4)) ); assert_eq!( nonempty!(1, 2, 3, 4).try_map(|i| if i % 2 == 0 { Ok(i) } else { Err("not even") }), Err("not even") ); } #[test] fn test_nontrivial_minimum_by_key() { #[derive(Debug, Clone, Copy, PartialEq, Eq)] struct Position { x: i32, y: i32, } impl Position { pub fn distance_squared(&self, other: Position) -> u32 { let dx = self.x - other.x; let dy = self.y - other.y; (dx * dx + dy * dy) as u32 } } let positions = nonempty![ Position { x: 1, y: 1 }, Position { x: 0, y: 0 }, Position { x: 3, y: 4 } ]; let target = Position { x: 1, y: 2 }; let closest = positions.minimum_by_key(|position| position.distance_squared(target)); assert_eq!(closest, &Position { x: 1, y: 1 }); } #[test] fn test_sort() { let mut numbers = nonempty![1]; numbers.sort(); assert_eq!(numbers, nonempty![1]); let mut numbers = nonempty![2, 1, 3]; numbers.sort(); assert_eq!(numbers, nonempty![1, 2, 3]); let mut numbers = nonempty![1, 3, 2]; numbers.sort(); assert_eq!(numbers, nonempty![1, 2, 3]); let mut numbers = nonempty![3, 2, 1]; numbers.sort(); assert_eq!(numbers, nonempty![1, 2, 3]); } #[cfg(feature = "serialize")] mod serialize { use crate::NonEmpty; use alloc::boxed::Box; use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct SimpleSerializable(pub i32); #[test] fn test_simple_round_trip() -> Result<(), Box> { // Given let mut non_empty = NonEmpty::new(SimpleSerializable(42)); non_empty.push(SimpleSerializable(777)); // When let res = serde_json::from_str::<'_, NonEmpty>( &serde_json::to_string(&non_empty)?, )?; // Then assert_eq!(res, non_empty); Ok(()) } #[test] fn test_serialization() -> Result<(), Box> { let ne = nonempty![1, 2, 3, 4, 5]; let ve = vec![1, 2, 3, 4, 5]; assert_eq!(serde_json::to_string(&ne)?, serde_json::to_string(&ve)?); Ok(()) } } #[cfg(feature = "arbitrary")] mod arbitrary { use crate::NonEmpty; use arbitrary::{Arbitrary, Unstructured}; #[test] fn test_arbitrary_empty_tail() -> arbitrary::Result<()> { let mut u = Unstructured::new(&[1, 2, 3, 4]); let ne = NonEmpty::::arbitrary(&mut u)?; assert!(!ne.is_empty()); assert_eq!( ne, NonEmpty { head: 67305985, tail: vec![], } ); Ok(()) } #[test] fn test_arbitrary_with_tail() -> arbitrary::Result<()> { let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8]); let ne = NonEmpty::::arbitrary(&mut u)?; assert!(!ne.is_empty()); assert_eq!( ne, NonEmpty { head: 67305985, tail: vec![526086], } ); Ok(()) } #[test] fn test_arbitrary_with_split() -> arbitrary::Result<()> { let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8]); let ne = NonEmpty::::arbitrary(&mut u)?; let (head, middle, last) = ne.split(); let mut tail = middle.to_vec(); tail.extend(last); assert_eq!(ne, NonEmpty { head: *head, tail }); Ok(()) } } } nonempty-0.11.0/src/nonzero.rs000064400000000000000000000052051046102023000144050ustar 00000000000000#[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; use core::num::NonZeroUsize; /// A non-empty list which statically guarantees certain operations /// cannot return zero, using [`core::num::NonZeroUsize`]. /// /// *Experimental* /// #[repr(transparent)] #[cfg_attr(feature = "arbitrary", derive(Arbitrary))] #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct NonEmpty(super::NonEmpty); impl NonEmpty { /// Get the length of the list. pub fn len(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.0.tail.len() + 1) } } /// Get the capacity of the list. pub fn capacity(&self) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(self.0.tail.capacity() + 1) } } /// Truncate the list to a certain size. pub fn truncate(&mut self, len: NonZeroUsize) { self.tail.truncate(usize::from(len) - 1); } } impl From> for NonEmpty { fn from(other: super::NonEmpty) -> NonEmpty { NonEmpty(other) } } impl core::ops::Deref for NonEmpty { type Target = super::NonEmpty; fn deref(&self) -> &Self::Target { &self.0 } } impl core::ops::DerefMut for NonEmpty { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } #[cfg(test)] mod tests { use crate::nonzero; use crate::NonEmpty; use core::convert::TryInto; #[test] fn test_nonzero() { let nonempty: nonzero::NonEmpty<_> = NonEmpty::from((0, vec![1, 2, 3])).into(); assert_eq!(nonempty.len(), 4.try_into().unwrap()); assert_eq!(nonempty.capacity(), 4.try_into().unwrap()); } #[cfg(feature = "arbitrary")] mod arbitrary { use crate::nonzero; use arbitrary::{Arbitrary, Unstructured}; use core::convert::TryInto; #[test] fn test_nonzero_arbitrary_empty_tail() -> arbitrary::Result<()> { let mut u = Unstructured::new(&[1, 2, 3, 4]); let nonempty: nonzero::NonEmpty<_> = nonzero::NonEmpty::::arbitrary(&mut u)?; assert_eq!(nonempty.len(), 1.try_into().unwrap()); assert_eq!(nonempty.capacity(), 1.try_into().unwrap()); Ok(()) } #[test] fn test_nonzero_arbitrary_with_tail() -> arbitrary::Result<()> { let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8]); let nonempty: nonzero::NonEmpty<_> = nonzero::NonEmpty::::arbitrary(&mut u)?; assert_eq!(nonempty.len(), 2.try_into().unwrap()); assert_eq!(nonempty.capacity(), 5.try_into().unwrap()); Ok(()) } } } nonempty-0.11.0/taplo.toml000064400000000000000000000004631046102023000135730ustar 00000000000000# Sorts `Cargo.toml` dependencies. All other `.toml` files are formatted with the default config. # # https://taplo.tamasfe.dev/configuration/file.html#configuration-file [formatting] reorder_keys = false [[rule]] include = ["**/Cargo.toml"] keys = ["dependencies"] [rule.formatting] reorder_keys = true