Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(variadics): add iter_any_ref and iter_any_mut to VariadicsExt #1245

Merged
merged 2 commits into from
Jun 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions variadics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//! ## [`var_args!`]
#![doc = include_str!("../var_args.md")]

use std::any::Any;

use sealed::sealed;

#[doc = include_str!("../var_expr.md")]
Expand Down Expand Up @@ -138,6 +140,24 @@ pub trait VariadicExt: Variadic {
/// Convert an exclusive (`mut`) reference to this variadic into a variadic of exclusive
/// (`mut`) references.
fn as_mut_var(&mut self) -> Self::AsMutVar<'_>;

/// Iterator type returned by [`Self::iter_any_ref`].
type IterAnyRef<'a>: Iterator<Item = &'a dyn Any>
where
Self: 'static;
/// Iterate this variadic as `&dyn Any` references.
fn iter_any_ref(&self) -> Self::IterAnyRef<'_>
where
Self: 'static;

/// Iterator type returned by [`Self::iter_any_mut`].
type IterAnyMut<'a>: Iterator<Item = &'a mut dyn Any>
where
Self: 'static;
/// Iterate this variadic as `&mut dyn Any` exclusive references.
fn iter_any_mut(&mut self) -> Self::IterAnyMut<'_>
where
Self: 'static;
}
#[sealed]
impl<Item, Rest> VariadicExt for (Item, Rest)
Expand Down Expand Up @@ -176,6 +196,30 @@ where
let (item, rest) = self;
(item, rest.as_mut_var())
}

type IterAnyRef<'a> = std::iter::Chain<std::iter::Once<&'a dyn Any>, Rest::IterAnyRef<'a>>
where
Self: 'static;
fn iter_any_ref(&self) -> Self::IterAnyRef<'_>
where
Self: 'static,
{
let var_args!(item, ...rest) = self;
let item: &dyn Any = item;
std::iter::once(item).chain(rest.iter_any_ref())
}

type IterAnyMut<'a> = std::iter::Chain<std::iter::Once<&'a mut dyn Any>, Rest::IterAnyMut<'a>>
where
Self: 'static;
fn iter_any_mut(&mut self) -> Self::IterAnyMut<'_>
where
Self: 'static,
{
let var_args!(item, ...rest) = self;
let item: &mut dyn Any = item;
std::iter::once(item).chain(rest.iter_any_mut())
}
}
#[sealed]
impl VariadicExt for () {
Expand All @@ -197,6 +241,26 @@ impl VariadicExt for () {

type AsMutVar<'a> = ();
fn as_mut_var(&mut self) -> Self::AsMutVar<'_> {}

type IterAnyRef<'a> = std::iter::Empty<&'a dyn Any>
where
Self: 'static;
fn iter_any_ref(&self) -> Self::IterAnyRef<'_>
where
Self: 'static,
{
std::iter::empty()
}

type IterAnyMut<'a> = std::iter::Empty<&'a mut dyn Any>
where
Self: 'static;
fn iter_any_mut(&mut self) -> Self::IterAnyMut<'_>
where
Self: 'static,
{
std::iter::empty()
}
}

/// Convert from a variadic of references back into the original variadic. The inverse of
Expand Down Expand Up @@ -372,4 +436,38 @@ mod test {

assert_eq!(var_expr!("Hello World".to_owned(), Box::new(6)), my_owned);
}

#[test]
fn test_iter_any() {
let mut var = var_expr!(1_i32, false, "Hello".to_owned());

let mut mut_iter = var.iter_any_mut();
*mut_iter.next().unwrap().downcast_mut::<i32>().unwrap() += 1;
*mut_iter.next().unwrap().downcast_mut::<bool>().unwrap() |= true;
*mut_iter.next().unwrap().downcast_mut::<String>().unwrap() += " World";
assert!(mut_iter.next().is_none());

let mut ref_iter = var.iter_any_ref();
assert_eq!(
Some(&2),
ref_iter
.next()
.map(<dyn Any>::downcast_ref)
.map(Option::unwrap)
);
assert_eq!(
Some(&true),
ref_iter
.next()
.map(<dyn Any>::downcast_ref)
.map(Option::unwrap)
);
assert_eq!(
Some("Hello World"),
ref_iter
.next()
.map(|any| &**any.downcast_ref::<String>().unwrap())
);
assert!(ref_iter.next().is_none());
}
}
Loading