Wrapping a `HashSet` and implementing `Iterator`

Hey folks,

I have the following struct:

use std::collections::HashSet;
use tantivy::tokenizer::{SimpleTokenizer, TokenStream, Tokenizer};

pub struct Vocabulary {
    #[allow(dead_code)]
    tokens: HashSet<String>,
}

impl Default for Vocabulary {
    fn default() -> Self {
        Self::new()
    }
}

impl Vocabulary {
    #[allow(dead_code)]
    pub fn new() -> Self {
        Self { tokens: HashSet::new() }
    }

    pub fn add_text(& mut self, text: &str) {
        let mut tokenizer = SimpleTokenizer::default();
        let mut stream = tokenizer.token_stream(text);
        stream.process(&mut |token| {
            self.tokens.insert(token.text.clone());
        });
    }
}

I'd like to implement std::iter::Iterator to produce an iterator of Strings from the HashSet. I understand that I need to implement the from() method of the trait, but I'm a little confused as to how to wrap the HashSet's own iterator.

Any help is greatly appreciated.

Oh hang on... maybe this is the answer?

Yes, as a general rule, collections and iterators are different types, and IntoIterator is used to go from a collection (or a reference to a collection) to an iterator. There are a few reasons for this, but one of them is that the data representation that is good for lookups is not the same as the data representation that is good for iteration.

This would be your by-value IntoIterator implementation:

impl IntoIterator for Vocabulary {
    type Item = String;
    type IntoIter = std::collections::hash_set::IntoIter<String>;
    fn into_iter(self) -> Self::IntoIter {
        self.tokens.into_iter()
    }
}

This one reuses the iterator type already defined for HashSet, but you can also provide your own iterator that wraps the HashSet iterator.

Also called iterables in other languages (except C# that weirdly calls iterators "enumerators" and then iterables are "enumerables").

Indeed! I'm a huge fan of Python iterators. Much of what I'm learning now is how to do similar things in Rust.