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 #(#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}