enum-iterator-2.1.0/.cargo_vcs_info.json0000644000000001530000000000100136260ustar { "git": { "sha1": "2b1aaefe6de0ccea827b1376ebad12f3476662a9" }, "path_in_vcs": "enum-iterator" }enum-iterator-2.1.0/Cargo.toml0000644000000020220000000000100116210ustar # 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 = "enum-iterator" version = "2.1.0" authors = ["Stephane Raux "] description = "Tools to iterate over all values of a type (e.g. all variants of an enumeration)" homepage = "https://github.com/stephaneyfx/enum-iterator" documentation = "https://docs.rs/enum-iterator" readme = "README.md" keywords = [ "enum", "variants", "iterator", "enumerate", "cardinality", ] license = "0BSD" repository = "https://github.com/stephaneyfx/enum-iterator.git" [dependencies.enum-iterator-derive] version = "1.4.0" enum-iterator-2.1.0/Cargo.toml.orig000064400000000000000000000010731046102023000153070ustar 00000000000000[package] name = "enum-iterator" version = "2.1.0" authors = ["Stephane Raux "] edition = "2021" description = "Tools to iterate over all values of a type (e.g. all variants of an enumeration)" license = "0BSD" homepage = "https://github.com/stephaneyfx/enum-iterator" repository = "https://github.com/stephaneyfx/enum-iterator.git" documentation = "https://docs.rs/enum-iterator" keywords = ["enum", "variants", "iterator", "enumerate", "cardinality"] [dependencies] enum-iterator-derive = { path = "../enum-iterator-derive", version = "1.4.0" } enum-iterator-2.1.0/LICENSE000064400000000000000000000012321046102023000134220ustar 00000000000000BSD Zero Clause License Copyright (c) 2018 Stephane Raux Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. enum-iterator-2.1.0/README.md000064400000000000000000000032431046102023000137000ustar 00000000000000 # Overview - [📦 crates.io](https://crates.io/crates/enum-iterator) - [📖 Documentation](https://docs.rs/enum-iterator) - [⚖ 0BSD license](https://spdx.org/licenses/0BSD.html) Tools to iterate over the values of a type. # Examples ```rust use enum_iterator::{all, cardinality, first, last, next, previous, reverse_all, Sequence}; #[derive(Debug, PartialEq, Sequence)] enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } assert_eq!(cardinality::(), 7); assert_eq!(all::().collect::>(), [ Day::Monday, Day::Tuesday, Day::Wednesday, Day::Thursday, Day::Friday, Day::Saturday, Day::Sunday, ]); assert_eq!(first::(), Some(Day::Monday)); assert_eq!(last::(), Some(Day::Sunday)); assert_eq!(next(&Day::Tuesday), Some(Day::Wednesday)); assert_eq!(previous(&Day::Wednesday), Some(Day::Tuesday)); assert_eq!(reverse_all::().collect::>(), [ Day::Sunday, Day::Saturday, Day::Friday, Day::Thursday, Day::Wednesday, Day::Tuesday, Day::Monday, ]); ``` ```rust use enum_iterator::{cardinality, first, last, Sequence}; #[derive(Debug, PartialEq, Sequence)] struct Foo { a: bool, b: u8, } assert_eq!(cardinality::(), 512); assert_eq!(first::(), Some(Foo { a: false, b: 0 })); assert_eq!(last::(), Some(Foo { a: true, b: 255 })); ``` # Rust version This crate tracks stable Rust. Minor releases may require a newer Rust version. Patch releases must not require a newer Rust version. # Contribute All contributions shall be licensed under the [0BSD license](https://spdx.org/licenses/0BSD.html). enum-iterator-2.1.0/src/lib.rs000064400000000000000000000674501046102023000143360ustar 00000000000000// Copyright (c) 2018-2022 Stephane Raux. Distributed under the 0BSD license. //! # Overview //! - [📦 crates.io](https://crates.io/crates/enum-iterator) //! - [📖 Documentation](https://docs.rs/enum-iterator) //! - [⚖ 0BSD license](https://spdx.org/licenses/0BSD.html) //! //! Tools to iterate over the values of a type. //! //! # Examples //! ``` //! use enum_iterator::{all, cardinality, first, last, next, previous, reverse_all, Sequence}; //! //! #[derive(Debug, PartialEq, Sequence)] //! enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } //! //! assert_eq!(cardinality::(), 7); //! assert_eq!(all::().collect::>(), [ //! Day::Monday, //! Day::Tuesday, //! Day::Wednesday, //! Day::Thursday, //! Day::Friday, //! Day::Saturday, //! Day::Sunday, //! ]); //! assert_eq!(first::(), Some(Day::Monday)); //! assert_eq!(last::(), Some(Day::Sunday)); //! assert_eq!(next(&Day::Tuesday), Some(Day::Wednesday)); //! assert_eq!(previous(&Day::Wednesday), Some(Day::Tuesday)); //! assert_eq!(reverse_all::().collect::>(), [ //! Day::Sunday, //! Day::Saturday, //! Day::Friday, //! Day::Thursday, //! Day::Wednesday, //! Day::Tuesday, //! Day::Monday, //! ]); //! ``` //! //! ``` //! use enum_iterator::{cardinality, first, last, Sequence}; //! //! #[derive(Debug, PartialEq, Sequence)] //! struct Foo { //! a: bool, //! b: u8, //! } //! //! assert_eq!(cardinality::(), 512); //! assert_eq!(first::(), Some(Foo { a: false, b: 0 })); //! assert_eq!(last::(), Some(Foo { a: true, b: 255 })); //! ``` //! //! # Rust version //! This crate tracks stable Rust. Minor releases may require a newer Rust version. Patch releases //! must not require a newer Rust version. //! //! # Contribute //! All contributions shall be licensed under the [0BSD license](https://spdx.org/licenses/0BSD.html). #![deny(missing_docs)] #![deny(warnings)] #![no_std] use core::{cmp::Ordering, iter::FusedIterator, ops::ControlFlow, task::Poll}; pub use enum_iterator_derive::Sequence; /// Returns the cardinality (number of values) of `T` /// /// # Example /// ``` /// use enum_iterator::{cardinality, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Color { Red, Green, Blue } /// /// assert_eq!(cardinality::(), 3); /// ``` pub const fn cardinality() -> usize { T::CARDINALITY } /// Returns an iterator over all values of type `T`. /// /// Values are yielded in the order defined by [`Sequence::next`], starting with /// [`Sequence::first`]. /// /// # Example /// ``` /// use enum_iterator::{all, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Color { Red, Green, Blue } /// /// assert_eq!( /// all::().collect::>(), /// [Color::Red, Color::Green, Color::Blue], /// ); /// ``` pub fn all() -> All { All(T::first()) } /// Returns an iterator over all values of type `T` in the reverse order of [`all`]. /// /// # Example /// ``` /// use enum_iterator::{reverse_all, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Color { Red, Green, Blue } /// /// assert_eq!( /// reverse_all::().collect::>(), /// [Color::Blue, Color::Green, Color::Red], /// ); /// ``` pub fn reverse_all() -> ReverseAll { ReverseAll(T::last()) } /// Returns the next value of type `T` or `None` if this was the end. /// /// Same as [`Sequence::next`]. /// /// # Example /// ``` /// use enum_iterator::{next, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(next(&Day::Friday), Some(Day::Saturday)); /// ``` pub fn next(x: &T) -> Option { x.next() } /// Returns the next value of type `T` or [`first()`](first) if this was the end. /// /// # Example /// ``` /// use enum_iterator::{next_cycle, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(next_cycle(&Day::Sunday), Day::Monday); /// ``` pub fn next_cycle(x: &T) -> T { next(x) .or_else(first) .expect("Sequence::first returned None for inhabited type") } /// Returns the previous value of type `T` or `None` if this was the beginning. /// /// Same as [`Sequence::previous`]. /// /// # Example /// ``` /// use enum_iterator::{previous, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(previous(&Day::Saturday), Some(Day::Friday)); /// ``` pub fn previous(x: &T) -> Option { x.previous() } /// Returns the previous value of type `T` or [`last()`](last) if this was the beginning. /// /// # Example /// ``` /// use enum_iterator::{previous_cycle, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(previous_cycle(&Day::Monday), Day::Sunday); /// ``` pub fn previous_cycle(x: &T) -> T { previous(x) .or_else(last) .expect("Sequence::last returned None for inhabited type") } /// Returns the first value of type `T`. /// /// Same as [`Sequence::first`]. /// /// # Example /// ``` /// use enum_iterator::{first, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(first::(), Some(Day::Monday)); /// ``` pub fn first() -> Option { T::first() } /// Returns the last value of type `T`. /// /// Same as [`Sequence::last`]. /// /// # Example /// ``` /// use enum_iterator::{last, Sequence}; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(last::(), Some(Day::Sunday)); /// ``` pub fn last() -> Option { T::last() } /// Iterator over the values of type `T`. /// /// Returned by [`all`]. #[derive(Clone, Debug)] pub struct All(Option); impl Iterator for All { type Item = T; fn next(&mut self) -> Option { let item = self.0.take()?; self.0 = item.next(); Some(item) } } impl FusedIterator for All {} /// Iterator over the values of type `T` in reverse order. /// /// Returned by [`reverse_all`]. #[derive(Clone, Debug)] pub struct ReverseAll(Option); impl Iterator for ReverseAll { type Item = T; fn next(&mut self) -> Option { let item = self.0.take()?; self.0 = item.previous(); Some(item) } } impl FusedIterator for ReverseAll {} /// Trait to iterate over the values of a type. /// /// The [crate root](crate) defines useful functions to work with types implementing `Sequence`. /// /// # Derivation /// /// `Sequence` can be derived for `enum` and `struct` types. Specifically, it can be derived /// for: /// - Enumerations whose variants meet one of the following criteria: /// - The variant does not have fields. /// - The variant has fields meeting all these conditions: /// - Every field has a type that implements `Sequence`. /// - Every field but the last one has a type that implements `Clone`. /// - Enumerations without variants. /// - Structures whose fields meet all these conditions: /// - Every field has a type that implements `Sequence`. /// - Every field but the last one has a type that implements `Clone`. /// - Unit structures (i.e. without fields). /// /// The cardinality (number of values) of the type must not exceed `usize::MAX`. /// /// # Laws /// /// `T: Sequence` implies the following assertions: /// - `T::first().and_then(|x| x.previous()).is_none()` /// - `T::last().and_then(|x| x.next()).is_none()` /// - `T::first().is_none()` ⇔ `T::last().is_none()` /// - `std::iter::successors(T::first(), T::next)` must eventually yield `T::last()`. /// - If `T` is inhabited, `T::first().is_some()`. /// /// If a manual implementation of `Sequence` violates any of these laws, the functions at the crate root may misbehave, including panicking. /// /// # Examples /// ## C-like enumeration /// /// ``` /// use enum_iterator::{all, cardinality, Sequence}; /// /// #[derive(Clone, Copy, Debug, PartialEq, Sequence)] /// enum Direction { North, South, West, East } /// /// assert_eq!(cardinality::(), 4); /// assert_eq!(all::().collect::>(), [ /// Direction::North, /// Direction::South, /// Direction::West, /// Direction::East, /// ]); /// ``` /// /// ## Enumeration with data /// /// ``` /// use enum_iterator::{all, cardinality, Sequence}; /// /// #[derive(Clone, Copy, Debug, PartialEq, Sequence)] /// enum Direction { North, South, West, East } /// /// #[derive(Clone, Copy, Debug, PartialEq, Sequence)] /// enum Greeting { /// Hi, /// Bye, /// } /// /// #[derive(Clone, Copy, Debug, PartialEq, Sequence)] /// enum Action { /// Move(Direction), /// Jump, /// Talk { greeting: Greeting, loud: bool }, /// } /// /// assert_eq!(cardinality::(), 4 + 1 + 2 * 2); /// assert_eq!(all::().collect::>(), [ /// Action::Move(Direction::North), /// Action::Move(Direction::South), /// Action::Move(Direction::West), /// Action::Move(Direction::East), /// Action::Jump, /// Action::Talk { greeting: Greeting::Hi, loud: false }, /// Action::Talk { greeting: Greeting::Hi, loud: true }, /// Action::Talk { greeting: Greeting::Bye, loud: false }, /// Action::Talk { greeting: Greeting::Bye, loud: true }, /// ]); /// ``` /// /// ## Structure /// /// ``` /// use enum_iterator::{all, cardinality, Sequence}; /// /// #[derive(Clone, Copy, Debug, PartialEq, Sequence)] /// enum Side { /// Left, /// Right, /// } /// /// #[derive(Clone, Copy, Debug, PartialEq, Sequence)] /// enum LimbKind { /// Arm, /// Leg, /// } /// /// #[derive(Debug, PartialEq, Sequence)] /// struct Limb { /// kind: LimbKind, /// side: Side, /// } /// /// assert_eq!(cardinality::(), 4); /// assert_eq!(all::().collect::>(), [ /// Limb { kind: LimbKind::Arm, side: Side::Left }, /// Limb { kind: LimbKind::Arm, side: Side::Right }, /// Limb { kind: LimbKind::Leg, side: Side::Left }, /// Limb { kind: LimbKind::Leg, side: Side::Right }, /// ]); /// ``` pub trait Sequence: Sized { /// Number of values of type `Self`. /// /// # Example /// ``` /// use enum_iterator::Sequence; /// /// #[derive(Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(Day::CARDINALITY, 7); /// ``` const CARDINALITY: usize; /// Returns value following `*self` or `None` if this was the end. /// /// Values are yielded in the following order. Comparisons between values are based on their /// relative order as yielded by `next`; an element yielded after another is considered greater. /// /// - For primitive types, in increasing order (same as `Ord`). /// - For arrays and tuples, in lexicographic order of the sequence of their elements. /// - When derived for an enumeration, in variant definition order. /// - When derived for a structure, in lexicographic order of the sequence of its fields taken /// in definition order. /// /// The order described above is the same as `Ord` if any custom `Sequence` implementation /// follows `Ord` and any enumeration has its variants defined in increasing order of /// discriminant. /// /// # Example /// ``` /// use enum_iterator::Sequence; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(Day::Tuesday.next(), Some(Day::Wednesday)); /// ``` fn next(&self) -> Option; /// Returns value preceding `*self` or `None` if this was the beginning. /// /// # Example /// ``` /// use enum_iterator::Sequence; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(Day::Wednesday.previous(), Some(Day::Tuesday)); /// ``` fn previous(&self) -> Option; /// Returns the first value of type `Self`. /// /// # Example /// ``` /// use enum_iterator::Sequence; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(Day::first(), Some(Day::Monday)); /// ``` fn first() -> Option; /// Returns the last value of type `Self`. /// /// # Example /// ``` /// use enum_iterator::Sequence; /// /// #[derive(Debug, PartialEq, Sequence)] /// enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } /// /// assert_eq!(Day::last(), Some(Day::Sunday)); /// ``` fn last() -> Option; } impl Sequence for bool { const CARDINALITY: usize = 2; fn next(&self) -> Option { (!*self).then_some(true) } fn previous(&self) -> Option { (*self).then_some(false) } fn first() -> Option { Some(false) } fn last() -> Option { Some(true) } } macro_rules! impl_sequence_for_int { ($ty:ty) => { impl Sequence for $ty { const CARDINALITY: usize = 1 << <$ty>::BITS; fn next(&self) -> Option { self.checked_add(1) } fn previous(&self) -> Option { self.checked_sub(1) } fn first() -> Option { Some(Self::MIN) } fn last() -> Option { Some(Self::MAX) } } }; } impl_sequence_for_int!(i8); impl_sequence_for_int!(u8); impl_sequence_for_int!(i16); impl_sequence_for_int!(u16); impl Sequence for () { const CARDINALITY: usize = 1; fn next(&self) -> Option { None } fn previous(&self) -> Option { None } fn first() -> Option { Some(()) } fn last() -> Option { Some(()) } } impl Sequence for core::convert::Infallible { const CARDINALITY: usize = 0; fn next(&self) -> Option { None } fn previous(&self) -> Option { None } fn first() -> Option { None } fn last() -> Option { None } } impl Sequence for Ordering { const CARDINALITY: usize = 3; fn next(&self) -> Option { int_to_ordering(*self as i8 + 1) } fn previous(&self) -> Option { int_to_ordering(*self as i8 - 1) } fn first() -> Option { Some(Ordering::Less) } fn last() -> Option { Some(Ordering::Greater) } } fn int_to_ordering(i: i8) -> Option { match i { -1 => Some(Ordering::Less), 0 => Some(Ordering::Equal), 1 => Some(Ordering::Greater), _ => None, } } impl Sequence for Option { const CARDINALITY: usize = T::CARDINALITY + 1; fn next(&self) -> Option { match self { None => T::first().map(Some), Some(x) => x.next().map(Some), } } fn previous(&self) -> Option { self.as_ref().map(T::previous) } fn first() -> Option { Some(None) } fn last() -> Option { Some(T::last()) } } impl Sequence for Poll { const CARDINALITY: usize = T::CARDINALITY + 1; fn next(&self) -> Option { match self { Poll::Ready(x) => x.next().map(Poll::Ready).or(Some(Poll::Pending)), Poll::Pending => None, } } fn previous(&self) -> Option { match self { Poll::Ready(x) => x.previous().map(Poll::Ready), Poll::Pending => T::last().map(Poll::Ready), } } fn first() -> Option { T::first().map(Poll::Ready).or(Some(Poll::Pending)) } fn last() -> Option { Some(Poll::Pending) } } impl Sequence for [T; N] { const CARDINALITY: usize = { let tc = T::CARDINALITY; let mut c = 1; let mut i = 0; loop { if i == N { break c; } c *= tc; i += 1; } }; fn next(&self) -> Option { advance_for_array(self, T::first) } fn previous(&self) -> Option { advance_for_array(self, T::last) } fn first() -> Option { if N == 0 { Some(core::array::from_fn(|_| unreachable!())) } else { let x = T::first()?; Some(core::array::from_fn(|_| x.clone())) } } fn last() -> Option { if N == 0 { Some(core::array::from_fn(|_| unreachable!())) } else { let x = T::last()?; Some(core::array::from_fn(|_| x.clone())) } } } fn advance_for_array(a: &[T; N], reset: R) -> Option<[T; N]> where T: Sequence + Clone, R: Fn() -> Option, { let mut a = a.clone(); let keep = a.iter_mut().rev().try_fold((), |_, x| match x.next() { Some(new_x) => { *x = new_x; ControlFlow::Break(true) } None => match reset() { Some(new_x) => { *x = new_x; ControlFlow::Continue(()) } None => ControlFlow::Break(false), }, }); Some(a).filter(|_| matches!(keep, ControlFlow::Break(true))) } macro_rules! impl_seq_advance_for_tuple { ( $this:ident, $advance:ident, $reset:ident, $carry:ident @ $($values:expr,)* @ @ $($placeholders:pat,)* ) => { Some(($($values,)*)).filter(|_| !$carry) }; ( $this:ident, $advance:ident, $reset:ident, $carry:ident @ $($values:expr,)* @ $ty:ident, $($types:ident,)* @ $($placeholders:pat,)* ) => {{ let (.., item, $($placeholders,)*) = $this; let (x, new_carry) = if $carry { match Sequence::$advance(item) { Some(x) => (x, false), None => (Sequence::$reset()?, true), } } else { (item.clone(), false) }; impl_seq_advance_for_tuple!( $this, $advance, $reset, new_carry @ x, $($values,)* @ $($types,)* @ _, $($placeholders,)* ) }}; ($this:ident, $advance:ident, $reset:ident @ $($types:ident,)*) => {{ let (.., item) = $this; let (x, carry) = match Sequence::$advance(item) { Some(x) => (x, false), None => (Sequence::$reset()?, true), }; impl_seq_advance_for_tuple!($this, $advance, $reset, carry @ x, @ $($types,)* @ _,) }}; } macro_rules! impl_sequence_for_tuple { ($($types:ident,)* @ $last:ident) => { impl<$($types,)* $last> Sequence for ($($types,)* $last,) where $($types: Sequence + Clone,)* $last: Sequence, { const CARDINALITY: usize = $(<$types as Sequence>::CARDINALITY *)* <$last as Sequence>::CARDINALITY; fn next(&self) -> Option { impl_seq_advance_for_tuple!(self, next, first @ $($types,)*) } fn previous(&self) -> Option { impl_seq_advance_for_tuple!(self, previous, last @ $($types,)*) } fn first() -> Option { Some(( $(<$types as Sequence>::first()?,)* <$last as Sequence>::first()?, )) } fn last() -> Option { Some(( $(<$types as Sequence>::last()?,)* <$last as Sequence>::last()?, )) } } }; } macro_rules! impl_sequence_for_tuples { ($($types:ident,)*) => { impl_sequence_for_tuples!(@ $($types,)*); }; ($($types:ident,)* @ $head:ident, $($tail:ident,)*) => { impl_sequence_for_tuple!($($types,)* @ $head); impl_sequence_for_tuples!($($types,)* $head, @ $($tail,)*); }; ($($types:ident,)* @) => {}; } impl_sequence_for_tuples!( T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, ); #[cfg(test)] mod tests { use crate::{all, cardinality, reverse_all, Sequence}; use core::{cmp::Ordering, convert::Infallible, task::Poll}; fn cardinality_equals_item_count() { assert_eq!(cardinality::(), all::().count()); } #[test] fn cardinality_equals_item_count_for_bool() { cardinality_equals_item_count::(); } #[test] fn all_bool_values_are_yielded() { assert!(all::().eq([false, true])); } #[test] fn all_bool_values_are_yielded_in_reverse() { assert!(reverse_all::().eq([true, false])); } #[test] fn cardinality_equals_item_count_for_i8() { cardinality_equals_item_count::(); } #[test] fn all_i8_values_are_yielded() { assert!(all::().eq(i8::MIN..=i8::MAX)); } #[test] fn all_i8_values_are_yielded_in_reverse() { assert!(reverse_all::().eq((i8::MIN..=i8::MAX).rev())); } #[test] fn cardinality_equals_item_count_for_u8() { cardinality_equals_item_count::(); } #[test] fn all_u8_values_are_yielded() { assert!(all::().eq(u8::MIN..=u8::MAX)); } #[test] fn all_u8_values_are_yielded_in_reverse() { assert!(reverse_all::().eq((u8::MIN..=u8::MAX).rev())); } #[test] fn cardinality_equals_item_count_for_i16() { cardinality_equals_item_count::(); } #[test] fn all_i16_values_are_yielded() { assert!(all::().eq(i16::MIN..=i16::MAX)); } #[test] fn all_i16_values_are_yielded_in_reverse() { assert!(reverse_all::().eq((i16::MIN..=i16::MAX).rev())); } #[test] fn cardinality_equals_item_count_for_u16() { cardinality_equals_item_count::(); } #[test] fn all_u16_values_are_yielded() { assert!(all::().eq(u16::MIN..=u16::MAX)); } #[test] fn all_u16_values_are_yielded_in_reverse() { assert!(reverse_all::().eq((u16::MIN..=u16::MAX).rev())); } #[test] fn cardinality_equals_item_count_for_unit() { cardinality_equals_item_count::<()>(); } #[test] fn all_unit_values_are_yielded() { assert!(all::<()>().eq([()])); } #[test] fn all_unit_values_are_yielded_in_reverse() { assert!(reverse_all::<()>().eq([()])); } #[test] fn cardinality_equals_item_count_for_infallible() { cardinality_equals_item_count::(); } #[test] fn all_infallible_values_are_yielded() { assert!(all::().next().is_none()); } #[test] fn all_infallible_values_are_yielded_in_reverse() { assert!(reverse_all::().next().is_none()); } #[test] fn cardinality_equals_item_count_for_tuple_with_infallible() { cardinality_equals_item_count::<(bool, Infallible)>(); } #[test] fn all_tuple_with_infallible_values_are_yielded() { assert!(all::<(bool, Infallible)>().next().is_none()); } #[test] fn all_tuple_with_infallible_values_are_yielded_in_reverse() { assert!(reverse_all::<(bool, Infallible)>().next().is_none()); } #[test] fn cardinality_equals_item_count_for_singleton() { cardinality_equals_item_count::<(u8,)>(); } #[test] fn cardinality_equals_item_count_for_pair() { cardinality_equals_item_count::<(u8, bool)>(); } #[test] fn cardinality_equals_item_count_for_triple() { cardinality_equals_item_count::<(bool, u8, bool)>(); } #[test] fn cardinality_equals_item_count_for_option() { cardinality_equals_item_count::>(); } #[test] fn all_bool_option_items_are_yielded() { assert!(all::>().eq([None, Some(false), Some(true)])); } #[test] fn all_bool_option_items_are_yielded_in_reverse() { assert!(reverse_all::>().eq([Some(true), Some(false), None])); } #[test] fn all_infallible_option_items_are_yielded() { assert!(all::>().eq([None])); } #[test] fn all_infallible_option_items_are_yielded_in_reverse() { assert!(reverse_all::>().eq([None])); } #[test] fn cardinality_equals_item_count_for_ordering() { cardinality_equals_item_count::(); } #[test] fn all_ordering_values_are_yielded() { assert!(all::().eq([Ordering::Less, Ordering::Equal, Ordering::Greater])); } #[test] fn all_ordering_values_are_yielded_in_reverse() { assert!(reverse_all::().eq([Ordering::Greater, Ordering::Equal, Ordering::Less])); } #[test] fn cardinality_equals_item_count_for_poll() { cardinality_equals_item_count::>(); } #[test] fn all_bool_poll_items_are_yielded() { assert!(all::>().eq([Poll::Ready(false), Poll::Ready(true), Poll::Pending])); } #[test] fn all_bool_poll_items_are_yielded_in_reverse() { assert!(reverse_all::>().eq([ Poll::Pending, Poll::Ready(true), Poll::Ready(false), ])); } #[test] fn all_infallible_poll_items_are_yielded() { assert!(all::>().eq([Poll::Pending])); } #[test] fn all_infallible_poll_items_are_yielded_in_reverse() { assert!(reverse_all::>().eq([Poll::Pending])); } #[test] fn tuple_fields_vary_from_right_to_left() { assert!(all::<(Option, bool)>().eq([ (None, false), (None, true), (Some(false), false), (Some(false), true), (Some(true), false), (Some(true), true), ])); } #[test] fn cardinality_of_empty_array_is_one() { assert_eq!(cardinality::<[u8; 0]>(), 1); } #[test] fn cardinality_equals_item_count_for_empty_array() { cardinality_equals_item_count::<[u8; 0]>(); } #[test] fn cardinality_equals_item_count_for_array() { cardinality_equals_item_count::<[u8; 3]>(); } #[test] fn array_items_vary_from_right_to_left() { assert!(all::<[Option; 2]>().eq([ [None, None], [None, Some(false)], [None, Some(true)], [Some(false), None], [Some(false), Some(false)], [Some(false), Some(true)], [Some(true), None], [Some(true), Some(false)], [Some(true), Some(true)], ])); } #[test] fn all_empty_array_items_are_yielded() { assert!(all::<[bool; 0]>().eq([[]])); } #[test] fn cardinality_of_empty_infallible_array_is_one() { assert_eq!(cardinality::<[Infallible; 0]>(), 1); } #[test] fn cardinality_of_non_empty_infallible_array_is_zero() { assert_eq!(cardinality::<[Infallible; 1]>(), 0); } #[test] fn all_empty_infallible_array_items_are_yielded() { assert!(all::<[Infallible; 0]>().eq([[]])); } #[test] fn all_non_empty_infallible_array_items_are_yielded() { assert!(all::<[Infallible; 1]>().next().is_none()); } } enum-iterator-2.1.0/tests/derive.rs000064400000000000000000000103331046102023000154050ustar 00000000000000// Copyright (c) 2018-2022 Stephane Raux. Distributed under the 0BSD license. use enum_iterator::{all, cardinality, reverse_all, Sequence}; use std::{convert::Infallible, iter::once}; #[derive(Clone, Copy, Debug, PartialEq, Sequence)] enum Direction { North, South, West, East, } #[derive(Clone, Debug, PartialEq, Sequence)] enum Either { Left(L), Right(R), } #[test] fn all_values_of_generic_type_are_yielded() { assert_eq!(cardinality::>(), 6); assert_eq!( all::>().collect::>(), [ Either::Left(false), Either::Left(true), Either::Right(Direction::North), Either::Right(Direction::South), Either::Right(Direction::West), Either::Right(Direction::East), ] ); } #[derive(Clone, Debug, PartialEq, Sequence)] struct Foo { x: T, } #[test] fn all_values_of_generic_type_with_trait_bound_are_yielded() { assert_eq!(cardinality::>(), 2); assert_eq!( all::>().collect::>(), [Foo { x: false }, Foo { x: true }], ); } #[test] fn all_values_of_enum_type_with_empty_variant_are_yielded() { assert_eq!(cardinality::>(), 2); assert_eq!( all::>().collect::>(), [Either::Right(false), Either::Right(true)], ); } #[derive(Debug, PartialEq, Sequence)] struct Impossible { a: bool, b: Infallible, } #[test] fn all_values_of_impossible_are_yielded() { assert_eq!(cardinality::(), 0); assert!(all::().next().is_none()); } #[derive(Debug, PartialEq, Sequence)] enum Move { Stay, Basic(Direction), Fancy(FancyMove), Jump { direction: Direction, somersault: bool, }, Swim(Direction, SwimmingStyle), } #[derive(Debug, PartialEq, Sequence)] struct FancyMove { direction: Direction, fast: bool, } #[derive(Debug, PartialEq, Sequence)] enum SwimmingStyle { Breaststroke, FrontCrawl, } fn all_moves() -> Vec { let directions = [ Direction::North, Direction::South, Direction::West, Direction::East, ]; once(Move::Stay) .chain(directions.into_iter().map(Move::Basic)) .chain( directions .into_iter() .flat_map(|d| [(d, false), (d, true)]) .map(|(direction, fast)| FancyMove { direction, fast }) .map(Move::Fancy), ) .chain( directions .into_iter() .flat_map(|d| [(d, false), (d, true)]) .map(|(direction, somersault)| Move::Jump { direction, somersault, }), ) .chain( directions .into_iter() .flat_map(|d| { [ (d, SwimmingStyle::Breaststroke), (d, SwimmingStyle::FrontCrawl), ] }) .map(|(direction, style)| Move::Swim(direction, style)), ) .collect() } #[test] fn all_works() { assert_eq!(all::().collect::>(), all_moves()); } #[test] fn reverse_all_works() { let expected = { let mut moves = all_moves(); moves.reverse(); moves }; assert_eq!(reverse_all::().collect::>(), expected); } #[derive(Debug, PartialEq, Sequence)] enum Empty {} #[test] fn empty_cadinality_is_zero() { assert_eq!(cardinality::(), 0); } #[test] fn all_values_of_empty_are_yielded() { assert_eq!(all::().collect::>(), Vec::new()); } #[test] fn all_values_of_empty_are_yielded_in_reverse() { assert_eq!(reverse_all::().collect::>(), Vec::new()); } #[derive(Debug, PartialEq, Sequence)] struct Unit; #[test] fn unit_cardinality_is_one() { assert_eq!(cardinality::(), 1); } #[test] fn all_values_of_unit_are_yielded() { assert_eq!(all::().collect::>(), vec![Unit]); } #[test] fn all_values_of_unit_are_yielded_in_reverse() { assert_eq!(reverse_all::().collect::>(), vec![Unit]); }