Trait for iterator that was implemented for a reference

⚓ Rust    📅 2025-06-01    👤 surdeus    👁️ 3      

surdeus

Warning

This post was published 71 days ago. The information described in this article may have changed.

Hi folks,

Could you please tell me if the following is possible?

(the commented code doesn't work)

Thank you :wink:

#[derive(Debug, PartialEq)]
pub struct Content {
    number: i32,
}
#[derive(Debug, PartialEq)]
pub struct Thing {
    content: Content,
}
#[derive(Debug, PartialEq)]
pub struct ManyThings {
    things: Vec<Thing>,
}

pub struct ManyThingsIterator {
    things_reversed: Vec<Thing>,
}
pub struct ManyThingsIteratorSlice<'a> {
    things: &'a [Thing],
}
impl Iterator for ManyThingsIterator {
    type Item = Thing;

    fn next(&mut self) -> Option<Self::Item> {
        self.things_reversed.pop()
    }
}
impl<'a> Iterator for ManyThingsIteratorSlice<'a> {
    type Item = &'a Thing;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some((out, rest)) = self.things.split_first() {
            self.things = rest;
            Some(out)
        } else {
            None
        }
    }
}

impl IntoIterator for ManyThings {
    type Item = Thing;
    type IntoIter = ManyThingsIterator;

    fn into_iter(self) -> Self::IntoIter {
        let mut things_reversed = self.things;
        things_reversed.reverse();
        ManyThingsIterator { things_reversed }
    }
}
impl<'a> IntoIterator for &'a ManyThings {
    type Item = &'a Thing;
    type IntoIter = ManyThingsIteratorSlice<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ManyThingsIteratorSlice {
            things: self.things.as_slice(),
        }
    }
}

pub trait GetContent {
    fn move_it_out(self) -> Content;
    fn get_it(&self) -> &Content;
}
pub trait GetContentMultiple {
    fn move_it_out_multiple<T>(self) -> Vec<Content>
    where
        Self: Sized + IntoIterator<Item = T>,
        T: GetContent,
    {
        self.into_iter().map(|inp| inp.move_it_out()).collect()
    }
    fn get_it_multiple<'a, T>(self) -> Vec<&'a Content>
    where
        Self: Sized + IntoIterator<Item = &'a T>,
        T: GetContent + 'a,
    {
        self.into_iter().map(|inp| inp.get_it()).collect()
    }
}

impl GetContent for Thing {
    fn move_it_out(self) -> Content {
        self.content
    }
    fn get_it(&self) -> &Content {
        &self.content
    }
}
impl GetContentMultiple for ManyThings {}

#[test]
fn test_move_it_out_multiple() {
    let a = ManyThings {
        things: vec![
            Thing {
                content: Content { number: 0 },
            },
            Thing {
                content: Content { number: 1 },
            },
            Thing {
                content: Content { number: 2 },
            },
        ],
    };
    assert_eq!(
        a.move_it_out_multiple(),
        vec![Content { number: 0 }, Content { number: 1 }, Content { number: 2 }]
    )
}
#[test]
fn test_get_it_multiple() {
    let a = ManyThings {
        things: vec![
            Thing {
                content: Content { number: 0 },
            },
            Thing {
                content: Content { number: 1 },
            },
            Thing {
                content: Content { number: 2 },
            },
        ],
    };
    let b = &a;
    // assert_eq!(
    //     b.get_it_multiple(),
    //     vec![&Content { number: 0 }, &Content { number: 1 }, &Content { number: 2 }]
    // )
}

4 posts - 2 participants

Read full topic

🏷️ rust_feed