Skip to content

Commit

Permalink
iter() and try_iter()
Browse files Browse the repository at this point in the history
  • Loading branch information
wilson committed Nov 27, 2024
1 parent e78d806 commit 8c9d8d4
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "enumeration"
version = "3.0.0"
version = "3.1.0"
edition = "2021"
license = "MIT"
description = "An extension to rust enum"
Expand Down
12 changes: 12 additions & 0 deletions src/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ where
fn to_usize(self) -> usize where Self::Index: Into<usize> {
self.to_index().into()
}

#[inline(always)]
/// Iterate through all variants
fn iter() -> impl Iterator<Item = Self> where Self::Index: Into<usize> + From<usize> {
(0..Self::len()).map(|i| unsafe { Self::variant_unchecked(i.into()) })
}

#[inline(always)]
/// iter() but when `Index` only implements `TryFrom<usize>` as opposed to `From<usize>`
fn try_iter() -> impl Iterator<Item = Self> where Self::Index: Into<usize> + TryFrom<usize> {
(0..Self::len()).map(|i| unsafe { Self::variant_unchecked(i.try_into().unwrap_or_else(|_| unreachable!()) ) })
}
}

/// This macro helps to create enum with trait [Enumeration].
Expand Down
106 changes: 75 additions & 31 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,89 @@ use std::any::{Any, TypeId};
use enumeration::prelude::*;
use enumeration::variant::*;

enumerate!(Test(u8; i32 = 99)
X = 111
Y
Z = 777
enumerate!(pub TestPub(u8)
Foo
);

enumerate!(enum TestEnum(u8)
Foo
);

enumerate!(pub enum TestPubEnum(u8)
Foo
);

const DEFAULT_STR: &'static str = "default";
const FOO_STR: &'static str = "foo";
const BAZ_STR: &'static str = "baz";

enumerate!(Test(u8; &'static str = DEFAULT_STR)
Foo = FOO_STR
Bar
Baz = BAZ_STR
);

enumerate!(TestUnitType(u8; () = ())
Foo
Bar = { assert!(true); }
);

enumerate!(Str(u8; &'static str)
HelloWorld = "Hello world!"
const HELLO_WORLD_STR: &'static str = "Hello world!";

enumerate!(TestString(u8; &'static str)
HelloWorld = HELLO_WORLD_STR
);

#[test]
fn test_index() {
assert_eq!(Test::X.to_index(), 0);
assert_eq!(Test::Y.to_index(), 1);
assert_eq!(Test::Z.to_index(), 2);
assert_eq!(Test::Foo.to_index(), 0);
assert_eq!(Test::Bar.to_index(), 1);
assert_eq!(Test::Baz.to_index(), 2);
}

#[test]
fn test_cast() {
assert_eq!(Test::variant(0).unwrap(), Test::X);
assert_eq!(Test::variant(1).unwrap(), Test::Y);
assert_eq!(Test::variant(2).unwrap(), Test::Z);
assert_eq!(Test::variant(0).unwrap(), Test::Foo);
assert_eq!(Test::variant(1).unwrap(), Test::Bar);
assert_eq!(Test::variant(2).unwrap(), Test::Baz);
}

#[test]
fn test_associated_constant_values() {
assert_eq!(*Test::X.value(), 111);
assert_eq!(*Test::Y.value(), 99);
assert_eq!(*Test::Z.value(), 777);
assert_eq!(*Test::Foo.value(), FOO_STR);
assert_eq!(*Test::Bar.value(), DEFAULT_STR);
assert_eq!(*Test::Baz.value(), BAZ_STR);
}

#[test]
fn test_string() {
assert_eq!(*Str::HelloWorld.value(), "Hello world!");
assert_eq!(*TestString::HelloWorld.value(), HELLO_WORLD_STR);
}

#[test]
fn test_variant() {
let vec: Vec<Variant<_>> = vec![Test::X.into(), Str::HelloWorld.into()];
let vec: Vec<Variant<_>> = vec![Test::Foo.into(), TestString::HelloWorld.into()];

assert_eq!(vec[0].cast::<Test>(), Ok(Test::X));
assert_eq!(vec[1].cast::<Str>(), Ok(Str::HelloWorld));
assert_eq!(vec[0].cast::<Test>(), Ok(Test::Foo));
assert_eq!(vec[1].cast::<TestString>(), Ok(TestString::HelloWorld));
assert!(vec[1].cast::<Test>().is_err());
}

#[test]
fn test_variant_with() {
let vec: Vec<VariantWith<_, _>> = vec![Test::X.into(), Test::Z.into()];
let vec: Vec<VariantWith<_, _>> = vec![Test::Foo.into(), Test::Baz.into()];

assert_eq!(*vec[0].value(), 111);
assert_eq!(*vec[1].value(), 777);
assert_eq!(*vec[0].value(), FOO_STR);
assert_eq!(*vec[1].value(), BAZ_STR);
}

#[test]
fn test_iter() {
let mut iter = (0..Test::VARIANT_COUNT).variants();

assert_eq!(iter.next(), Some(Ok(Test::X)));
assert_eq!(iter.next(), Some(Ok(Test::Y)));
assert_eq!(iter.next(), Some(Ok(Test::Z)));
assert_eq!(iter.next(), Some(Ok(Test::Foo)));
assert_eq!(iter.next(), Some(Ok(Test::Bar)));
assert_eq!(iter.next(), Some(Ok(Test::Baz)));
assert_eq!(iter.next(), None);

let mut iter = (Test::VARIANT_COUNT..=Test::VARIANT_COUNT).variants::<Test>();
Expand All @@ -79,9 +97,9 @@ fn test_iter() {
fn test_iter_unchecked() {
let mut iter = unsafe { (0..Test::VARIANT_COUNT).variants_unchecked() };

assert_eq!(iter.next(), Some(Test::X));
assert_eq!(iter.next(), Some(Test::Y));
assert_eq!(iter.next(), Some(Test::Z));
assert_eq!(iter.next(), Some(Test::Foo));
assert_eq!(iter.next(), Some(Test::Bar));
assert_eq!(iter.next(), Some(Test::Baz));
assert_eq!(iter.next(), None);
}

Expand All @@ -96,9 +114,9 @@ fn test_iter_unchecked_fail() {
fn test_iter_unwrap() {
let mut iter = (0..Test::VARIANT_COUNT).variants_unwrap();

assert_eq!(iter.next(), Some(Test::X));
assert_eq!(iter.next(), Some(Test::Y));
assert_eq!(iter.next(), Some(Test::Z));
assert_eq!(iter.next(), Some(Test::Foo));
assert_eq!(iter.next(), Some(Test::Bar));
assert_eq!(iter.next(), Some(Test::Baz));
assert_eq!(iter.next(), None);
}

Expand All @@ -114,3 +132,29 @@ fn test_len() {
assert_eq!(Test::len(), Test::count() as usize);
assert_eq!(Test::len().type_id(), TypeId::of::<usize>())
}

#[test]
fn test_try_iter() {
let mut iter = Test::try_iter();

assert_eq!(iter.next(), Some(Test::Foo));
assert_eq!(iter.next(), Some(Test::Bar));
assert_eq!(iter.next(), Some(Test::Baz));
assert_eq!(iter.next(), None);
}

enumerate!(TestUsize(usize)
Foo
Bar
Baz
);

#[test]
fn test_iter_usize() {
let mut iter = TestUsize::iter();

assert_eq!(iter.next(), Some(TestUsize::Foo));
assert_eq!(iter.next(), Some(TestUsize::Bar));
assert_eq!(iter.next(), Some(TestUsize::Baz));
assert_eq!(iter.next(), None);
}

0 comments on commit 8c9d8d4

Please sign in to comment.