nonempty-0.8.1/.cargo_vcs_info.json0000644000000001360000000000100127130ustar { "git": { "sha1": "cdf611bab2bc37ff9c443067638324fb32a21f2e" }, "path_in_vcs": "" }nonempty-0.8.1/.github/workflows/actions.yml000064400000000000000000000024211046102023000172620ustar 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 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 env: RUSTFLAGS: -D warnings - name: Check formating uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check nonempty-0.8.1/.gitignore000064400000000000000000000000361046102023000134720ustar 00000000000000/target **/*.rs.bk Cargo.lock nonempty-0.8.1/Cargo.toml0000644000000015650000000000100107200ustar # 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 = "2018" name = "nonempty" version = "0.8.1" authors = ["Alexis Sellier "] description = "Correct by construction non-empty vector" readme = "README.md" license = "MIT" repository = "https://github.com/cloudhead/nonempty" [dependencies.serde] version = "1" features = ["serde_derive"] optional = true [dev-dependencies.serde_json] version = "1" [features] serialize = ["serde"] nonempty-0.8.1/Cargo.toml.orig000064400000000000000000000006151046102023000143740ustar 00000000000000[package] name = "nonempty" version = "0.8.1" description = "Correct by construction non-empty vector" authors = ["Alexis Sellier "] edition = "2018" license = "MIT" repository = "https://github.com/cloudhead/nonempty" [dependencies] serde = { features = ["serde_derive"], optional = true, version = "1" } [features] serialize = ["serde"] [dev-dependencies] serde_json = "1" nonempty-0.8.1/LICENSE000064400000000000000000000020421046102023000125060ustar 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.8.1/README.md000064400000000000000000000007141046102023000127640ustar 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.8.1/src/lib.rs000064400000000000000000001012511046102023000134060ustar 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: //! //! ``` //! 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: //! //! ``` //! 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: //! //! ``` //! 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 `FromInterator` trait for it. We can't know, in general, if //! any given `Iterator` actually contains something. //! //! # Features //! //! * `serialize`: `serde` support. #[cfg(feature = "serialize")] use serde::{ ser::{SerializeSeq, Serializer}, Deserialize, Serialize, }; use std::cmp::Ordering; use std::mem; use std::{iter, vec}; pub mod nonzero; /// Like the `vec!` macro, but enforces at least one argument. A nice short-hand /// for constructing [`NonEmpty`] values. /// /// ``` /// 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() }); /// /// // 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: Vec::new(), } }; } /// Non-empty vector. #[cfg_attr(feature = "serialize", derive(Deserialize))] #[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<'a, T> DoubleEndedIterator for Iter<'a, 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<'a, T> ExactSizeIterator for Iter<'a, T> { fn len(&self) -> usize { self.tail.len() + self.head.map_or(0, |_| 1) } } impl<'a, T> core::iter::FusedIterator for Iter<'a, T> {} impl NonEmpty { /// Alias for [`NonEmpty::singleton`]. pub const fn new(e: T) -> Self { Self::singleton(e) } /// 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 } /// 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 Iterator + '_ { 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 guranteed /// 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 first == last. /// /// # Example Use /// /// ``` /// use nonempty::NonEmpty; /// /// let mut non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// /// // Guaranteed to have the last element and the elements /// // preceding it. /// assert_eq!(non_empty.split(), (&1, &[2, 3, 4][..], &5)); /// /// let non_empty = NonEmpty::new(1); /// /// // Guaranteed to have the last element. /// assert_eq!(non_empty.split(), (&1, &[][..], &1)); /// ``` pub fn split(&self) -> (&T, &[T], &T) { match self.tail.split_last() { None => (&self.head, &[], &self.head), Some((last, middle)) => (&self.head, middle, 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, compare: F) -> &T where F: Fn(&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, compare: F) -> &T where F: Fn(&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)); /// ``` pub fn maximum_by_key(&self, f: F) -> &T where U: Ord, F: Fn(&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)); /// ``` pub fn minimum_by_key(&self, f: F) -> &T where U: Ord, F: Fn(&T) -> &U, { self.minimum_by(|i, j| f(i).cmp(f(j))) } } 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, std::slice::Iter<'a, T>>; fn into_iter(self) -> Self::IntoIter { iter::once(&self.head).chain(self.tail.iter()) } } impl std::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 std::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 std::{convert::TryFrom, fmt}; 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 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 nonempty = NonEmpty::from((0, vec![1, 2, 3])); assert_eq!( nonempty.iter().cloned().collect::>(), vec![0, 1, 2, 3] ); assert_eq!( nonempty.iter().rev().cloned().collect::>(), vec![3, 2, 1, 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 std::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") ); } #[cfg(feature = "serialize")] mod serialize { use crate::NonEmpty; 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(()) } } } nonempty-0.8.1/src/nonzero.rs000064400000000000000000000030531046102023000143330ustar 00000000000000use std::num::NonZeroUsize; /// A non-empty list which statically guarantees certain operations /// cannot return zero, using [`std::num::NonZeroUsize`]. /// /// *Experimental* /// #[repr(transparent)] #[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 std::ops::Deref for NonEmpty { type Target = super::NonEmpty; fn deref(&self) -> &Self::Target { &self.0 } } impl std::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 std::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()); } }