1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use quote::{__private::TokenStream, format_ident, quote}; #[derive(Clone, Debug)] pub struct Enum { pub id: TokenStream, pub ice_id: String, variants: Vec<TokenStream>, next_value: i32 } impl Enum { pub fn empty() -> Enum { Enum { id: TokenStream::new(), ice_id: String::new(), variants: vec![], next_value: 0 } } pub fn add_variant(&mut self, name: &str, value: Option<i32>) { let value = match value { Some(value) => { self.next_value = value + 1; value }, None => { let value = self.next_value; self.next_value = value + 1; value } }; let id = format_ident!("{}", name); self.variants.push(quote! { #id = #value }); } pub fn generate(&self) -> Result<TokenStream, Box<dyn std::error::Error>> { let id_token = &self.id; let variant_tokens = self.variants.iter().map(|variant| { quote! { #variant } }).collect::<Vec<_>>(); Ok(quote! { #[derive(Debug, Copy, Clone, TryFromPrimitive, PartialEq)] #[repr(i32)] pub enum #id_token { #(#variant_tokens),* } impl OptionalType for #id_token { fn optional_type() -> u8 { 4 } } impl ToBytes for #id_token { fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> { let mut bytes = Vec::new(); bytes.extend(IceSize{size: *self as i32}.to_bytes()?); Ok(bytes) } } impl FromBytes for #id_token { fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> where Self: Sized { let mut read = 0; let enum_value = IceSize::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?.size; *read_bytes = *read_bytes + read; match #id_token::try_from(enum_value) { Ok(enum_type) => Ok(enum_type), _ => Err(Box::new(ProtocolError::new(&format!("Cannot convert int {} to enum", enum_value)))) } } } }) } }