Hi everybody,
I successfully implemented IntoIterator for a few custom types but now I need to implement it for a refence and I couldn't find any examples how this is usually done. All examples I found are consuming the custom type. So I came up with my own idea that works. Could you please look at the code of IntoIterBorrow
and tell me if this is the way how it's usually done?
Thank you.
struct IntoIterBorrow<'a> {
items: &'a Vec<FooBar>,
index: usize,
}
impl<'a> Iterator for IntoIterBorrow<'a> {
type Item = &'a FooBar;
fn next(&mut self) -> Option<Self::Item> {
self.items.get(self.index).map(|item| {
self.index += 1;
item
})
}
}
struct IntoIterMoved {
items: Vec<FooBar>,
}
impl Iterator for IntoIterMoved {
type Item = FooBar;
fn next(&mut self) -> Option<Self::Item> {
self.items.pop()
}
}
#[derive(Debug)]
struct FooBar {
name: String,
number: i32,
}
impl FooBar {
fn new(name: &str, number: i32) -> Self {
Self {
name: name.to_owned(),
number,
}
}
fn get_name(&self) -> String {
format!("{}{}", self.name, self.number)
}
}
#[derive(Debug)]
struct MyStruct {
items: Vec<FooBar>,
}
impl MyStruct {
fn new(items: Vec<FooBar>) -> Self {
Self { items }
}
}
impl IntoIterator for MyStruct {
type Item = FooBar;
type IntoIter = IntoIterMoved;
fn into_iter(self) -> Self::IntoIter {
let mut items = self.items;
items.reverse();
IntoIterMoved { items }
}
}
impl<'a> IntoIterator for &'a MyStruct {
type Item = &'a FooBar;
type IntoIter = IntoIterBorrow<'a>;
fn into_iter(self) -> Self::IntoIter {
IntoIterBorrow {
items: &self.items,
index: 0,
}
}
}
fn main() {
let x = MyStruct::new(vec![
FooBar::new("abc", 1),
FooBar::new("def", 2),
FooBar::new("ghi", 3),
]);
let y: Vec<_> = x.into_iter().map(|x| x.get_name()).collect();
println!("{:?}", y);
// println!("{:?}", x); // as expected - error
let x = MyStruct::new(vec![
FooBar::new("abc", 1),
FooBar::new("def", 2),
FooBar::new("ghi", 3),
]);
let y: Vec<_> = (&x).into_iter().map(|x| x.get_name()).collect();
println!("{:?}", y);
println!("{:?}", x); // as expected - ok
}