I want to define a trait that has a method operating on sequences of strings. At the same time, I want to avoid having generic methods, a.k.a. static dispatch, in the trait, so that I can use this trait as a trait object. The best solution I was given till now was to do it like below:
pub trait Store {
fn query_valid_paths(&mut self, paths: &mut dyn Iterator<Item = &str>) -> Vec<String>;
}
Unfortunately, it's not perfect:
It works out of the box only for iterators of
&str
; for iterators ofString
, e.g.Vec<String>
, I have to call it with the following magicmap
incantation, which is really ugly, and I'd never invent it as a newbie without help:// `vec` is a std::vec::Vec<String> store.query_valid_paths(&mut vec.iter().map(|s| &**s));
It takes an
Iterator
, but I'd love if I could take anIntoIterator
. In other words, I'd like to be able to call it just like this:store.query_valid_paths(&vec);
Is it possible?
Failed Attempt 1
Based on a simpler question about functions taking string iterators, I'd imagine something like this could work:
pub trait Store {
fn query_valid_paths<S>(&mut self, paths: impl IntoIterator<Item = S>) -> Vec<String>
where
S: AsRef<str>;
}
but this seems to make it a "generic method", triggering static dispatch...
Failed Attempt 2
I was suggested another idea on Rust discord, specifically:
pub trait Store {
fn query_valid_paths_inner(&mut self, paths: &mut dyn Iterator<Item = &str>) -> Vec<String>;
}
impl dyn Store {
pub fn query_valid_paths<'a>(&mut self, paths: impl IntoIterator<Item = &'a str>) -> Vec<String> {
let mut it = paths.into_iter();
self.query_valid_paths_inner(&mut it)
}
}
— but when I try to add AsRef<str>
to it, I'm getting lifetime errors, and cannot seem to make it work for both String
and &str
iterators...