Search code examples
rustiteratorflatbuffers

What's the common API for both `Vec<String>` and flatbuffers' vector of String in Rust?


I'd like to be able to iterate over Rust vector of String (Vec<String>) and flatbuffers' vector of strings: IDL as follows:

table Sitekeys {
  domains: [string];
}

Here is how the file is generated (with flatc --rust ...):

  #[inline]
  pub fn domains(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> {
    ...
  }

I can't figure the signature of the function that can accept both vectors. I believe it should be the most base possible interface (trait in Rust). Coming from J2EE/Android i think about smth similar to java.util.List or java.util.Iterator.

What would be the suitable signature in Rust?

PS. Obviously i can extract some new common interface with adapter for each case, but i'd prefer to operate with just base interface.

PPS. I forgot to mention that performance matters, so i'd prefer to avoid creating of new instances (if it's used behind the scenes in into_iter() or smth) if possible.


Solution

  • flatbuffers::Vector does not implement AsRef<[T]> but it does implement IntoIterator, so you can make your function signature use that.

    fn take_iterator<'a>(iter: impl IntoIterator<Item=&'a str>) {}
    

    Also, your flatbuffer object actually uses &str not String, you can match both and use a Vec<&str>:

    fn main() {
        let flatbuffer_v: flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>> = flatbuffers::Vector::default();
        let std_v: Vec<&str> = Vec::new();
        take_iterator(flatbuffer_v);
        take_iterator(std_v);
    }
    

    or, if you have a Vec<String> just take the references:

    fn main() {
        let flatbuffer_v: flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>> = flatbuffers::Vector::default();
        let std_v: Vec<String> = Vec::new();
        take_iterator(flatbuffer_v);
        take_iterator(std_v.iter().map(AsRef::as_ref));
    }