2016-08-08 79 views
0

Ich habe den folgenden Code, die einen Vektor von Bytes aus dem übergebenen Vektor von ENUM-Werte erzeugt:Convert Vektor von Enum-Werte in eine andere Vektor

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

Aber beim Kompilieren, ich mit Iterieren einen Fehler erhalten, um 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`. 

Wie kann ich dieses Problem mit std::iter::FromIterator beheben?

Antwort

2

Das Problem ist, dass enum_value_to_binary eine Vec<u8> für jedes Element in values zurückgibt. Sie enden also mit einem Iterator<Item=Vec<u8>> und Sie rufen collect::<Vec<u8>>() darauf, aber es kann nicht die verschachtelten Vektoren glätten. Wenn Sie die Werte alle wollen in einer Vec<u8> abgeflacht werden, dann sollten Sie flat_map statt map verwenden:

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

Oder etwas mehr idiomatische und performant, können Sie einfach direkt enum_value_to_binary Rückkehr einen Iterator haben.

Auch die iter-Methode gibt eine Iterator<Item=&'a T> zurück, was bedeutet, dass Sie nur die Elemente ausleihen, aber self.enum_value_to_binary will Besitz über den Wert übernehmen. Es gibt ein paar Möglichkeiten, das zu beheben. Eine Option wäre into_iter anstelle von iter, die Ihnen die Elemente nach Wert gibt. Wenn Sie das tun, werden Sie die Variable arity vor die Variable binary verschieben, da das Erstellen der binary-Variable Besitz (Verschieben) data.values übernehmen wird.

Die andere Möglichkeit wäre, self.enum_value_to_binary zu ändern, um sein Argument als Referenz zu nehmen.

Auch möglich, dass Sie für den Typ binary eigentlich Vec<Vec<u8>> sein wollten.

+0

Nein, in meinem Beispiel möchte ich einen Vektor von Bytes zurückgeben. Der Compiler hat 'Fehler aus ausgeliehenem Inhalt [E0507]' für den Ausdruck '| & item |' erzeugt. – Relrin