2017-09-06 31 views
1

所以我正在製作一個基於simplecs的ECS。錯誤`不能命名爲一個元組變量`是什麼意思?

我有一個生成一個實體結構,看起來像這樣一個宏:

($($name:ident : $component:ty,)*) => { 
     /// A collection of pointers to components 
     #[derive(Clone, Debug, Deserialize, PartialEq)] 
     pub struct Entity { 
      $(
      pub $name: Option<($component)>, 
      )* 
      children: Vec<Entity> 
     } 
} 

這是我的目標是用SERDE序列化的實體,而是留下了一堆難看的無值,該組件應是。所以,我想實現一個自定義序列,看起來像這樣:

impl Serialize for Entity { 
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 
     where S: Serializer 
    { 
     let mut num_fields = 0; 
     $(
      match self.$name { 
       Some => num_fields += 1, 
       None => {} 
      }; 
     )* 
      let mut state = serializer.serialize_struct("Entity", num_fields)?; 
      // do serialize 
      state.end() 
    } 
} 

串行器嘗試通過宏參數($name)提供的名稱來訪問現場,但是當我去編譯,我得到這個錯誤

error[E0530]: match bindings cannot shadow tuple variants 
    | 
    |   Some => {} 
    |   ^^^^ cannot be named the same as a tuple variant 
+2

您正在使用'Some'而不是'Some(pattern)'。如果您不關心內容,請在if條件中使用'self。$ name.is_some()'而不是使用匹配。 –

回答

3

語法self.$name訪問成員變量是正確的。正如@ oli_obk-ker在問題評論中所說的,錯誤是由於使用Some而不是Some(pattern)

  match self.$name { 
      Some(_) => num_fields += 1, 
//    ^~~ 
      None => {} 
     }; 
// 
// even better, use `if self.$name.is_some() { num_fields += 1; }`. 

但是,您甚至不需要編寫自己的serialize。您可以在字段上使用#[serde(skip_serializing_if = "f") attribute,如果f(&self.field)返回true,則可以避免將生成的代碼寫出。

($($name:ident : $component:ty,)*) => { 
    /// A collection of pointers to components 
    #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] 
    pub struct Entity { 
     $(
      #[serde(skip_serializing_if = "Option::is_none")] // <-- add this 
      pub $name: Option<($component)>, 
     )* 
     children: Vec<Entity> 
    } 
}