ice_rs/slice/
enumeration.rs

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