Ensure Methods Implemented for NewType(Vec<Type>) Also Work for NewType(Vec<&Type>)

I have the following code:

pub struct Emails (
    Vec<Email>
);

impl Emails {
    pub fn print(&self) {
        println!("      Inbox");
        println!("=================\n");

        self.0.iter()
            .for_each(|email| {
                println!("{:#?}\n", email);
            });
    }

    pub fn filter(&self /*, some_predicate: implement later */, show_amount: Option<usize>) /* -> Need Maybe a New Type */ {
        let filtered_emails = self.0.iter()
            .filter(...)
            .collect::<Vec<&Email>>();

            // Problem is print method only works for Emails, which is a Vec<Email>

            // I tried creating a new type for Vec<&Email> called EmailsSlice
    }
}

This means I write redundant code:

pub struct Emails (
    Vec<Email>,
);

impl Emails {
    pub fn print(&self) {
        EmailsSlice (
            self.0.iter().collect()
        ).print()
    }
}

pub struct EmailsSlice<'emails> (
    Vec<&'emails Email>,
);

impl<'emails> EmailsSlice<'emails> {
    pub fn print(&self) {
        println!("      Inbox");
        println!("=================\n");

        self.0.iter()
            .for_each(|email| {
                println!("{:#?}\n", email);
            });
    }
}

I would like to use it like this:

match arguments.first() {
    Some(argument) => {
        let show_amount = argument.parse::<usize>().ok();

        if let Some(filter) = arguments.get(1) {
            user.inbox.filter(filter, show_amount)
                .print();
        }
    },
    None => {
        user.inbox.print();
    },
}

Here's one approach.

impl Emails {
    fn print_iter<'i, I: IntoIterator<Item = &'i Email>>(iter: I) {
        // Or take an optional title or leave this part up to
        // the caller or whatever
        println!("      Inbox");
        println!("=================\n");
        iter.into_iter().for_each(|email| {
                println!("{:#?}\n", email);
        })
    }

    pub fn print(&self) {
        Self::print_iter(&self.0);
    }

    pub fn filter(&self /*, some_predicate: implement later */, show_amount: Option<usize>) /* -> Need Maybe a New Type */ {
        let iter = self.0.iter() /* .filter(..) */ ;         
        Self::print_iter(iter);
    }
}
1 Like

Ended up going with this to satisfy how I wanted it to be used:

pub struct EmailsSlice<'emails> (
    Vec<&'emails Email>,
);

impl<'emails> EmailsSlice<'emails> {
    pub fn print(&self) {
        println!("      Inbox");
        println!("=================\n");

        self.0.iter()
            .for_each(|email| {
                println!("{:#?}\n", email);
            });
    }
}

#[derive(Deserialize, Debug)]
pub struct Emails (
    Vec<Email>,
);

impl Emails {
    pub fn parse_filter(input: &str) -> MailFilter {
        ...
    }

    pub fn print(&self) {
        EmailsSlice (
            self.0.iter().collect()
        ).print();
    }

    pub fn filter(&self, filters: MailFilter, show_amount: Option<usize>) -> EmailsSlice {
        let all_emails = self.0.len();

        let show_amount = show_amount.unwrap_or(all_emails);

        let filtered_emails = self.0.iter()
            .filter(|email| {
                filters.matches(email)
            })
            .take(show_amount)
            .collect();

        EmailsSlice (
            filtered_emails,
        )
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.