4

I am writing a container implementing the prefix tree in a generic way (key and value are generic parameters). Due to the nature of this data structure I need the key to have an iterator.

Essentially in accordance to this question the IntoIterator trait is responsible for this possibility but not all the structures implement it. For example &str and String do not implement it.

What should I do in this case when IntoIterator isn't implemented by the standard type?

An expected API is

let mut t1 = Trie::new();
t1.insert(String::from("this"), 1);

let mut t2 = Trie::new();
t2.insert(vec![1, 2, 3], 1);
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Alex
  • 9,891
  • 11
  • 53
  • 87

2 Answers2

7

The problem with String and str is that they have two types of iterators - chars() - iterator over UTF-8 chars and bytes() - iterator over bytes. That's why it's impossible to implement IntoIterator for these types. You have to create two wrappers (or pick one of them)

struct ByteString(String)
struct Utf8String(String)

and implement IntoIterator for them.

AlexeyKarasev
  • 490
  • 3
  • 13
  • I think it would be a sensible default for `.into_iter()` to yield UTF-8 chars. You are still able to call `.bytes()` but 90% of the time you are using `&str` as UTF-8 text. – stimulate Dec 30 '21 at 02:57
4

The easiest solution, as stated in the comments, is to create a wrapper type:

use ::std::iter::IntoIterator;

struct StringWrapper<'a>(&'a str);

impl<'a> IntoIterator for StringWrapper<'a> {
    type Item = char;
    type IntoIter = ::std::str::Chars<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.chars()
    }
}

fn main() {
    // Raw str
    let wr = StringWrapper("test 1");
    for c in wr {
        println!("{}", c);
    }
    println!("-----");

    // Reference to raw str 
    let s = "test 2";
    let wr_s = StringWrapper(s);
    for c in wr_s {
        println!("{}", c);
    }
    println!("-----");

    // reference to String
    let owned_s = "test 3";
    let wr_s_owned = StringWrapper(&owned_s);
    for c in wr_s_owned {
        println!("{}", c);
    }
}
MutantOctopus
  • 3,431
  • 4
  • 22
  • 31