{{~ for mod in __mod.sub_mods ~}} pub mod {{mod.name}}; {{~end~}} {{~ if __mod.name != '' ~}} use super::*; {{~end~}} use luban_lib::*; {{~ for enum in __mod.enums ~}} {{~ if enum.comment != '' ~}} ///{{enum.comment | html.escape}} {{~end~}} {{~ if enum.is_flags ~}} bitflags::bitflags!{ #[derive(Debug, Hash, Eq, PartialEq)] pub struct {{enum.name}} : u32 { {{~ for item in enum.items ~}} {{~if item.comment_or_alias != '' ~}} ///{{item.comment_or_alias | html.escape}} {{~end~}} const {{item.name}} = {{item.int_value}}; {{~end~}} } } {{~else~}} #[derive(Debug, Hash, Eq, PartialEq, macros::EnumFromNum)] pub enum {{enum.name}} { {{~ for item in enum.items ~}} {{~if item.comment_or_alias != '' ~}} ///{{item.comment_or_alias | html.escape}} {{~end~}} {{item.name}} = {{item.value}}, {{~end~}} {{~if enum.items.empty?~}} None {{~end~}} } impl From for {{enum.name}} { fn from(value: i32) -> Self { match value { {{~ for item in enum.items ~}} {{item.value}} => {{enum.name}}::{{item.name}}, {{~end~}} _ => panic!("Invalid value for {{enum.name}}:{}", value), } } } {{~end~}} {{~end~}} {{~ for bean in __mod.beans hierarchy_fields = bean.hierarchy_export_fields ~}} #[derive(Debug)] {{~if bean.parent != ''~}} #[derive(macros::TryIntoBase)] {{~end~}} pub struct {{bean.name}} { {{~ for field in hierarchy_fields ~}} {{~if field.comment != '' ~}} /// {{escape_comment field.comment}} {{~end~}} pub {{field.name}}: {{declaring_type_name field.ctype}}, {{~end~}} } {{~if bean.is_abstract_type~}} impl {{bean.name}} { pub fn new(mut buf: &mut ByteBuf) -> Result, LubanError> { let type_id = buf.read_int(); match type_id { {{~for child in bean.hierarchy_not_abstract_children~}} {{full_name child}}::__ID__ => Ok(std::sync::Arc::new({{full_name child}}::new(buf)?)), {{~end~}} _ => Err(LubanError::Bean(format!("Invalid type for {{bean.name}}:{}", type_id))) } } } pub trait T{{bean.name}} { {{~ for field in hierarchy_fields ~}} fn {{getter_name field.name}}(&self) -> &{{declaring_type_name field.ctype}}; {{~end~}} } {{~for child in bean.hierarchy_not_abstract_children~}} impl {{base_trait_name bean}} for {{full_name child}} { {{~ for field in hierarchy_fields ~}} fn {{getter_name field.name}}(&self) -> &{{declaring_type_name field.ctype}} { &self.{{field.name}} } {{~end~}} } {{~end~}} impl<'a> GetBase<'a, &'a dyn {{base_trait_name bean}}> for AbstractBase { fn get_base(&'a self) -> Result<&'a dyn {{base_trait_name bean}}, LubanError> { {{~for child in bean.hierarchy_not_abstract_children~}} let base: Result<&{{full_name child}}, _> = self.try_into(); if let Ok(r) = base { return Ok(r); } {{~end~}} Err(LubanError::Polymorphic(format!("Invalid type for {{bean.name}}"))) } } {{~else~}} impl {{bean.name}}{ pub fn new(mut buf: &mut ByteBuf) -> Result<{{bean.name}}, LubanError> { {{~ for field in hierarchy_fields ~}} {{deserialize field.name 'buf' field.ctype}} {{~end~}} Ok({{bean.name}} { {{ for field in hierarchy_fields }}{{field.name}}, {{end}}}) } pub const __ID__: i32 = {{bean.id}}; } {{~end~}} {{~end~}} {{~ for table in __mod.tables key_type = declaring_type_name table.key_ttype if table.value_ttype.def_bean.is_abstract_type value_type = declaring_type_name table.value_ttype else value_type = "std::sync::Arc<"+declaring_type_name table.value_ttype+">" end name = table.name map_type = "std::collections::HashMap<"+key_type+", "+value_type+">" ~}} {{ func index_type_name ret (declaring_type_name $0.type) end func table_union_map_type_name ret 'std::collections::HashMap<(' + (array.each table.index_list @index_type_name | array.join ', ') + '), ' + value_type + '>' end func table_key_list varName = $0 indexList = table.index_list |array.each do; ret varName + '.' + (format_property_name __code_style $0.index_field.name); end; ret array.join indexList ', ' end func table_param_def_list paramList = table.index_list |array.each do; ret (declaring_type_name $0.type) + ' ' + $0.index_field.name; end ret array.join paramList ', ' end func table_param_name_list paramList = table.index_list |array.each do; ret $0.index_field.name; end ret array.join paramList ', ' end }} {{~ if table.comment != '' ~}} ///{{table.comment | html.escape}} {{~end~}} #[derive(Debug)] pub struct {{table.name}} { {{~if table.is_map_table ~}} pub data_list: Vec<{{value_type}}>, pub data_map: {{map_type}}, {{~else if table.is_list_table ~}} pub data_list: Vec<{{value_type}}>, {{~if table.is_union_index~}} pub data_map_union: {{table_union_map_type_name}}, {{~else if !table.index_list.empty?~}} {{~for idx in table.index_list~}} pub data_map_{{idx.index_field.name}}: std::collections::HashMap<{{declaring_type_name idx.type}}, {{value_type}}>, {{~end~}} {{~end~}} {{~else~}} pub data: {{declaring_type_name table.value_ttype}}, {{~end~}} } {{~if table.is_map_table ~}} impl {{name}} { pub fn new(mut buf: ByteBuf) -> Result, LubanError> { let mut data_map: {{map_type}} = Default::default(); let mut data_list: Vec<{{value_type}}> = vec![]; for x in (0..buf.read_size()).rev() { {{deserialize_row "row" "buf" table.value_ttype}} data_list.push(row.clone()); {{~ if table.value_ttype.def_bean.is_abstract_type ~}} let key = >::get_base(std::ops::Deref::deref(&row))?; data_map.insert(key.{{getter_name table.index_field.name}}().clone(), row.clone()); {{~else~}} data_map.insert(row.{{table.index_field.name}}.clone(), row.clone()); {{~end~}} } Ok(std::sync::Arc::new({{name}} { data_map, data_list })) } pub fn get(&self, key: &{{key_type}}) -> Option<{{value_type}}> { self.data_map.get(key).map(|x| x.clone()) } } impl std::ops::Index<{{key_type}}> for {{name}} { type Output = {{value_type}}; fn index(&self, index: {{key_type}}) -> &Self::Output { &self.data_map.get(&index).unwrap() } } {{~else if table.is_list_table ~}} impl {{name}} { pub fn new(mut buf: ByteBuf) -> Result, LubanError> { let mut data_list: Vec<{{value_type}}> = vec![]; for x in (0..buf.read_size()).rev() { {{deserialize_row "row" "buf" table.value_ttype}} data_list.push(row.clone()); } {{~if table.is_union_index~}} let mut data_map_union: {{table_union_map_type_name}} = Default::default(); for x in &data_list { data_map_union.insert(({{table_key_list "x"}}.clone()), x.clone()); } {{~else if !table.index_list.empty?~}} {{~for idx in table.index_list~}} let mut data_map_{{idx.index_field.name}}: std::collections::HashMap<{{declaring_type_name idx.index_field.ctype}}, {{value_type}}> = Default::default(); {{~end~}} for x in &data_list { {{~for idx in table.index_list~}} data_map_{{idx.index_field.name}}.insert(x.{{format_property_name __code_style idx.index_field.name}}.clone(), x.clone()); {{~end~}} } {{~end~}} Ok(std::sync::Arc::new({{table.name}} { data_list, {{~if table.is_union_index~}} data_map_union, {{~else if !table.index_list.empty?~}} {{~for idx in table.index_list~}} data_map_{{idx.index_field.name}}, {{~end~}} {{~end~}} })) } {{~if table.is_union_index~}} pub fn get(&self, key: &({{array.each table.index_list @index_type_name | array.join ', '}})) -> Option<{{value_type}}> { self.data_map_union.get(key).map(|x| x.clone()) } {{~else if !table.index_list.empty? ~}} {{~for idx in table.index_list index = format_property_name __code_style idx.index_field.name ~}} pub fn get_by_{{index}}(&self, key: &{{declaring_type_name idx.type}}) -> Option<{{value_type}}> { self.data_map_{{index}}.get(key).map(|x| x.clone()) } {{~end~}} {{~end~}} } {{~else~}} impl {{name}} { pub fn new(mut buf: ByteBuf) -> Result, LubanError> { let n = buf.read_size(); if n != 1 { return Err(LubanError::Table(format!("table mode=one, but size != 1"))); } {{deserialize 'data' 'buf' table.value_ttype}} Ok(std::sync::Arc::new({{name}} { data })) } } {{~end~}} {{~end~}}