Reputation: 790
I have the following code which generates a vector of bytes from the passed vector of enum values:
#[derive(Debug, PartialEq)]
pub enum BertType {
SmallInteger(u8),
Integer(i32),
Float(f64),
String(String),
Boolean(bool),
Tuple(BertTuple),
}
#[derive(Debug, PartialEq)]
pub struct BertTuple {
pub values: Vec<BertType>
}
pub struct Serializer;
pub trait Serialize<T> {
fn to_bert(&self, data: T) -> Vec<u8>;
}
impl Serializer {
fn enum_value_to_binary(&self, enum_value: BertType) -> Vec<u8> {
match enum_value {
BertType::SmallInteger(value_u8) => self.to_bert(value_u8),
BertType::Integer(value_i32) => self.to_bert(value_i32),
BertType::Float(value_f64) => self.to_bert(value_f64),
BertType::String(string) => self.to_bert(string),
BertType::Boolean(boolean) => self.to_bert(boolean),
BertType::Tuple(tuple) => self.to_bert(tuple),
}
}
}
// some functions for serialize bool/integer/etc. into Vec<u8>
// ...
impl Serialize<BertTuple> for Serializer {
fn to_bert(&self, data: BertTuple) -> Vec<u8> {
let mut binary: Vec<u8> = data.values
.iter()
.map(|&item| self.enum_value_to_binary(item)) // <-- what the issue there?
.collect();
let arity = data.values.len();
match arity {
0...255 => self.get_small_tuple(arity as u8, binary),
_ => self.get_large_tuple(arity as i32, binary),
}
}
}
But when compiling, I receive an error with iterating around map
:
error: the trait bound `std::vec::Vec<u8>: std::iter::FromIterator<std::vec::Vec<u8>>` is not satisfied [E0277]
.collect();
^~~~~~~
help: run `rustc --explain E0277` to see a detailed explanation
note: a collection of type `std::vec::Vec<u8>` cannot be built from an iterator over elements of type `std::vec::Vec<u8>`
error: aborting due to previous error
error: Could not compile `bert-rs`.
How can I fix this issue with std::iter::FromIterator
?
Upvotes: 1
Views: 1846
Reputation: 1240
The problem is that enum_value_to_binary
returns a Vec<u8>
for each element in values
. So you end up with an Iterator<Item=Vec<u8>>
and you call collect::<Vec<u8>>()
on that, but it doesn't know how to flatten the nested vectors. If you want all the values to be flattened into one Vec<u8>
, then you should use flat_map
instead of map
:
let mut binary: Vec<u8> = data.values
.iter()
.flat_map(|item| self.enum_value_to_binary(item).into_iter())
.collect();
Or, slightly more idiomatic and performant, you can just have enum_value_to_binary
return an iterator directly.
Also, the iter
method returns an Iterator<Item=&'a T>
, which means you are just borrowing the elements, but self.enum_value_to_binary
wants to take ownership over the value. There's a couple of ways to fix that. One option would be to use into_iter
instead of iter
, which will give you the elements by value. If you do that, you'll move the arity
variable up to before the binary
variable, since creating the binary
variable will take ownership (move) data.values
.
The other option would be to change self.enum_value_to_binary
to take it's argument by reference.
Also possible that you meant for the type of binary
to actually be Vec<Vec<u8>>
.
Upvotes: 2