#iterator #dynamic #traits #trait-object #dyn #wrap #box-dyn

dyn-iter

Wrapper around Box<dyn Iterator<Item = V> + 'iter> to simplify your code

4 releases (2 stable)

1.0.1 May 23, 2023
1.0.0 May 22, 2023
0.2.0 Sep 28, 2020
0.1.0 Sep 22, 2020

#926 in Rust patterns

Download history 538/week @ 2024-07-21 353/week @ 2024-07-28 417/week @ 2024-08-04 468/week @ 2024-08-11 456/week @ 2024-08-18 373/week @ 2024-08-25 488/week @ 2024-09-01 456/week @ 2024-09-08 467/week @ 2024-09-15 473/week @ 2024-09-22 465/week @ 2024-09-29 455/week @ 2024-10-06 575/week @ 2024-10-13 443/week @ 2024-10-20 482/week @ 2024-10-27 466/week @ 2024-11-03

2,021 downloads per month
Used in cargo-sonar

MIT license

16KB
124 lines

dyn-iter

continuous-integration-badge code-coverage-badge crates.io-badge license-badge documentation-badge

This tiny crate should help you simplify your code when you need to wrap Iterator as trait-object.

Imagine for example a trait like the following.

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Color {
    Red,
    Green,
    Blue,
    White,
    Black,
}
trait Colors<'a> {
    type ColorsIter: Iterator<Item = Color> + 'a;
    fn colors(&'a self) -> Self::ColorsIter;
}

As an implementor, you have a struct Flag that looks like this.

# use std::collections::HashSet;
# #[derive(Debug, Clone, Copy, PartialEq, Eq)]
# enum Color {
#     Red,
#     Green,
#     Blue,
#     White,
#     Black,
# }
struct Flag {
    pub primary_colors: HashSet<Color>,
    pub secondary_colors: HashSet<Color>,
}

you might implement Colors that look like this

# use std::collections::HashSet;
# use dyn_iter::{DynIter, IntoDynIterator as _};
# #[derive(Debug, Clone, Copy, PartialEq, Eq)]
# enum Color {
#     Red,
#     Green,
#     Blue,
#     White,
#     Black,
# }
# struct Flag {
#     pub primary_colors: HashSet<Color>,
#     pub secondary_colors: HashSet<Color>,
# }
# trait Colors<'a> {
#     type ColorsIter: Iterator<Item = Color> + 'a;
#     fn colors(&'a self) -> Self::ColorsIter;
# }
impl<'a> Colors<'a> for Flag {
    type ColorsIter = ???;
    fn colors(&'a self) -> Self::ColorsIter {
        self.primary_colors
            .iter()
            .chain(&self.secondary_colors)
            .filter(|color| **color != Color::Black)
            .copied()
    }
}

With the above implementation, defining the associated type ColorsIter might be difficult. DynIter should simplify your life because you can just write the following implementation.

# use std::collections::HashSet;
# use dyn_iter::{DynIter, IntoDynIterator as _};
# #[derive(Debug, Clone, Copy, PartialEq, Eq)]
# enum Color {
#     Red,
#     Green,
#     Blue,
#     White,
#     Black,
# }
# struct Flag {
#     pub primary_colors: HashSet<Color>,
#     pub secondary_colors: HashSet<Color>,
# }
# trait Colors<'a> {
#     type ColorsIter: Iterator<Item = Color> + 'a;
#     fn colors(&'a self) -> Self::ColorsIter;
# }
impl<'a> Colors<'a> for Flag {
    type ColorsIter = DynIter<'a, Color>;
    fn colors(&'a self) -> Self::ColorsIter {
        self.primary_colors
            .iter()
            .chain(&self.secondary_colors)
            .filter(|color| **color != Color::Black)
            .copied()
            .into_dyn_iter()
    }
}

Behind the scene, DynIter<'iter, V> is only providing a wrapper around a Box<dyn Iterator<Item = V> + 'iter>.

For more details about why this crate exists, read this blog post.

No runtime deps