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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::slice::types::IceType;
use crate::slice::writer;
use crate::slice::escape::escape;
use inflector::cases::{snakecase, pascalcase};
use writer::Writer;
#[derive(Clone, Debug)]
pub struct Class {
pub name: String,
members: Vec<(String, IceType)>
}
impl Class {
pub fn empty() -> Class {
Class {
name: String::from(""),
members: Vec::new()
}
}
pub fn new(name: &str) -> Class {
Class {
name: String::from(name),
members: Vec::new()
}
}
pub fn add_member(&mut self, name: &str, var_type: IceType) {
self.members.push((String::from(name), var_type));
}
pub fn class_name(&self) -> String {
pascalcase::to_pascal_case(&self.name)
}
pub fn generate(&self, writer: &mut Writer) -> Result<(), Box<dyn std::error::Error>> {
writer.generate_derive(vec!["Debug", "Clone", "PartialEq"], 0)?;
writer.generate_struct_open(&self.class_name(), 0)?;
for (type_name, var_type) in &self.members {
writer.generate_struct_member(&escape(&snakecase::to_snake_case(type_name)), &var_type.rust_type(), 1)?;
}
writer.generate_close_block(0)?;
writer.blank_line()?;
let mut lines = Vec::new();
for (key, _) in &self.members {
lines.push(format!("bytes.extend(self.{}.to_bytes()?);", &escape(&snakecase::to_snake_case(key))));
}
writer.generate_to_bytes_impl(&self.class_name(), lines, 0)?;
writer.generate_impl(Some("FromBytes"), &self.class_name(), 0)?;
writer.generate_fn(false, None, "from_bytes", vec![String::from("bytes: &[u8]"), String::from("read_bytes: &mut i32")], Some("Result<Self, Box<dyn std::error::Error>>"), true, 1)?;
writer.write("let mut read = 0;\n", 2)?;
writer.write("let _marker = u8::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;\n", 2)?;
writer.write("let _flags = SliceFlags::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;\n", 2)?;
writer.write("let _slice_name = String::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;\n", 2)?;
let mut has_optionals = false;
for (key, var_type) in &self.members {
match var_type {
IceType::Optional(_, _) => {
has_optionals = true;
writer.write(&format!("let mut {} = None;\n", &escape(&snakecase::to_snake_case(key))), 2)?;
}
_ => {
writer.write(&format!("let {} = {}::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;\n", &escape(&snakecase::to_snake_case(key)), var_type.rust_from()), 2)?;
}
};
}
if has_optionals {
writer.write("let mut flag_byte = bytes[read as usize..bytes.len()].first().unwrap();\n", 2)?;
writer.write("while *flag_byte != 0xFF as u8 {\n", 2)?;
writer.write("let flag = OptionalFlag::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?;\n", 3)?;
writer.write("match flag.tag {\n", 3)?;
for (key, var_type) in &self.members {
match var_type {
IceType::Optional(type_name, tag) => {
writer.write(&format!("{} => {{\n", tag), 4)?;
writer.write(&format!("{} = Some({}::from_bytes(&bytes[read as usize..bytes.len()], &mut read)?);\n", &escape(&snakecase::to_snake_case(key)), type_name.rust_type()), 5)?;
writer.generate_close_block(4)?;
}
_ => { }
};
}
writer.write("_ => {\n", 4)?;
writer.write("return Err(Box::new(ProtocolError {}));\n", 5)?;
writer.generate_close_block(4)?;
writer.generate_close_block(3)?;
writer.write("flag_byte = bytes[read as usize..bytes.len()].first().unwrap();\n", 3)?;
writer.generate_close_block(2)?;
}
writer.write("let obj = Self{\n", 2)?;
for (key, _) in &self.members {
writer.write(&format!("{}: {},\n", &escape(&snakecase::to_snake_case(key)), &escape(&snakecase::to_snake_case(key))), 3)?;
}
writer.write("};\n", 2)?;
writer.write("*read_bytes = *read_bytes + read;\n", 2)?;
writer.write("Ok(obj)\n", 2)?;
writer.generate_close_block(1)?;
writer.generate_close_block(0)?;
writer.blank_line()
}
}