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))))
}
}
}
})
}
}