2016-08-08 3 views
0

Я следующий код, который генерирует вектор байт из переданного вектора значений перечислений:Преобразовать вектор значений перечислений в другом вектор

#[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), 
     } 
    } 
} 

Но компилирования, я получаю ошибку перебора вокруг 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`. 

Как исправить эту проблему с помощью std::iter::FromIterator?

ответ

2

Проблема заключается в том, что enum_value_to_binary возвращает Vec<u8> для каждого элемента в values. Таким образом, вы получаете Iterator<Item=Vec<u8>>, и вы вызываете collect::<Vec<u8>>(), но он не знает, как сгладить вложенные векторы. Если вы хотите, чтобы все значения должны быть уплощенными в один Vec<u8>, то вы должны использовать flat_map вместо map:

let mut binary: Vec<u8> = data.values 
      .iter() 
      .flat_map(|item| self.enum_value_to_binary(item).into_iter()) 
      .collect(); 

Или, чуть более идиоматическими и производительный, вы можете просто enum_value_to_binary возвращать итератор непосредственно.

Кроме того, метод iter возвращает Iterator<Item=&'a T>, что означает, что вы просто заимствуете элементы, но self.enum_value_to_binary хочет взять на себя ответственность над стоимостью. Есть несколько способов исправить это. Один из вариантов заключается в использовании into_iter вместо iter, который даст вам элементы по стоимости. Если вы это сделаете, вы переместите переменную arity до переменной binary, так как при создании переменной binary вы получите право собственности (переместить) data.values.

Другой вариант - изменить self.enum_value_to_binary, чтобы принять его аргумент по ссылке.

Возможно также, что вы имели в виду тип binary на самом деле Vec<Vec<u8>>.

+0

Нет, в моем примере я хочу вернуть вектор байтов. Компилятор генерирует 'не может выйти из заимствованного содержимого [E0507]' error для выражения '| & item |'. – Relrin

Смежные вопросы