ice_rs/slice/
class.rs

1use crate::slice::types::IceType;
2use quote::{__private::TokenStream, quote};
3
4use super::struct_member::StructMember;
5
6
7#[derive(Clone, Debug)]
8pub struct Class {
9    pub id: TokenStream,
10    pub ice_id: String,
11    pub members: Vec<StructMember>,
12    pub extends: Option<IceType>,
13}
14
15impl Class {
16    pub fn empty() -> Class {
17        Class {
18            id: TokenStream::new(),
19            ice_id: String::new(),
20            members: Vec::new(),
21            extends: None
22        }
23    }
24
25    pub fn add_member(&mut self, member: StructMember) {
26        self.members.push(member);
27    }
28
29    pub fn generate(&self, mod_path: &str) -> Result<TokenStream, Box<dyn std::error::Error>> {
30        let id_token = &self.id;
31        let type_id_token = format!("{}::{}", mod_path, self.ice_id);
32        let mut member_tokens = self.members.iter().map(|member| {
33            member.declare()
34        }).collect::<Vec<_>>();
35        let member_from_bytes_tokens = self.members.iter().map(|member| {
36            let id_token = &member.id;
37            let var_token = &member.r#type.token_from();
38            match member.r#type {
39                IceType::Optional(_, _) => {
40                    quote! {
41                        let mut #id_token = None
42                    }
43                }
44                _ => {
45                    quote! {
46                        let #id_token = #var_token::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?
47                    }
48                }
49            }
50        }).collect::<Vec<_>>();
51
52        let member_to_bytes_tokens = self.members.iter().map(|member| {
53            let id_token = &member.id;
54            match member.r#type {
55                IceType::Optional(_, tag) => {
56                    quote! {
57                        bytes.extend(OptionalWrapper::new(#tag, self.#id_token.clone()).to_bytes()?);
58                    }
59                }
60                _ => {
61                    quote! {
62                        bytes.extend(self.#id_token.to_bytes()?);
63                    }
64                }
65            }
66        }).collect::<Vec<_>>();
67
68        let mut member_to_struct = self.members.iter().map(|member| {
69            let id_token = &member.id;
70            quote! {
71                #id_token: #id_token
72            }
73        }).collect::<Vec<_>>();
74
75        if self.extends.is_some() { 
76            let token = self.extends.as_ref().unwrap().token();
77            member_tokens.push(quote!{
78                extends: #token
79            });
80            member_to_struct.push(quote!{
81                extends: #token::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?
82            });
83        }
84
85        let has_optionals = self.members.iter().any(|member| {
86            match member.r#type {
87                IceType::Optional(_, _) => { true },
88                _ => false
89            }
90        });
91
92        let optional_tokens = self.members.iter()
93        .filter_map(|member| {
94            let id_token = &member.id;            
95            match &member.r#type {
96                IceType::Optional(option_type, tag) => {
97                    let var_token = option_type.token();
98                    Some(quote! {
99                        #tag => {
100                            #id_token = Some(#var_token::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?);
101                        }
102                    })
103                },
104                _ => None
105            }
106        }).collect::<Vec<_>>();
107
108        let optional_from = if has_optionals {
109            Some(quote! {
110                while read < bytes.len() as i32 {
111                    let flag_byte = bytes[read as usize..bytes.len()].first().unwrap();
112                    if *flag_byte == 0xFF {
113                        break;
114                    }
115                    let flag = OptionalFlag::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
116                    match flag.tag {
117                        #(#optional_tokens),*
118                        _ => {
119                            if flags.last_slice {
120                                return Err(Box::new(ProtocolError::new("Last slice not expected")));
121                            } else {
122                                read = read - 1;
123                                break;
124                            }
125                        }
126                    }
127                }
128            })
129        } else {
130            None
131        };
132
133        Ok(quote! {
134            #[derive(Debug, Clone, PartialEq)]
135            pub struct #id_token {
136                #(#member_tokens),*
137            }
138
139            impl ToBytes for #id_token {
140                fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
141                    let mut bytes = Vec::new();
142                    let slice_flags = SliceFlags {
143                        type_id: SliceFlagsTypeEncoding::StringTypeId,
144                        optional_members: #has_optionals,
145                        indirection_table: false,
146                        slice_size: false,
147                        last_slice: true
148                    };
149                    bytes.extend(1u8.to_bytes()?);
150                    bytes.extend(slice_flags.to_bytes()?);                    
151                    bytes.extend(#type_id_token.to_bytes()?);
152                    // TODO: split non optional and optional members as optionals must go last
153                    #(#member_to_bytes_tokens);*;
154                    bytes.extend(255u8.to_bytes()?);
155                    Ok(bytes)
156                }
157            }
158
159            impl FromBytes for #id_token {
160                fn from_bytes(bytes: &[u8], read_bytes: &mut i32) -> Result<Self, Box<dyn std::error::Error + Send + Sync>>
161                where Self: Sized {
162                    let mut read = 0;
163                    let marker = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
164                    if marker != 1 && marker != 255 {
165                        read = 0;
166                    }
167                    let flags = SliceFlags::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
168                    match flags.type_id {
169                        SliceFlagsTypeEncoding::StringTypeId => {
170                            let _slice_name = String::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;
171                        }
172                        SliceFlagsTypeEncoding::CompactTypeId => {
173                            todo!()
174                        }
175                        SliceFlagsTypeEncoding::IndexTypeId => {
176                            todo!()
177                        }
178                        SliceFlagsTypeEncoding::NoTypeId => {}
179                    }
180
181                    #(#member_from_bytes_tokens);*;
182                    #optional_from
183
184                    let obj = Self{
185                        #(#member_to_struct),*
186                    };
187                    *read_bytes = *read_bytes + read;
188                    Ok(obj)
189                }
190            }
191        })
192    }
193}