@@ -2,6 +2,7 @@ use ::flat_ast::*;
22use std:: io:: { Result , Write } ;
33use :: heck:: * ;
44use std:: collections:: HashMap ;
5+ use flat_ast:: RestrictionContent :: { Enumeration , Length , MaxValue , MinValue } ;
56
67pub ( crate ) struct CodeSourceGenerator < ' a , W : Write + ' a > {
78 writer : & ' a mut :: writer:: Writer < W > ,
@@ -32,7 +33,9 @@ impl<'a, W: Write> CodeSourceGenerator<'a, W> {
3233 pub fn generate ( & mut self , packet : & Packet ) -> Result < ( ) > {
3334 let version = self . version . clone ( ) ;
3435 cg ! ( self , "/* Generated with IDL v{} */\n " , version) ;
35- cg ! ( self , r#"use bincode::{{Encode, Decode}};"# ) ;
36+ cg ! ( self , r#"use bincode::{{Encode, Decode, enc::Encoder, de::Decoder, error::DecodeError}};"# ) ;
37+ cg ! ( self , r#"use bincode::de::read::Reader;"# ) ;
38+ cg ! ( self , r#"use bincode::enc::write::Writer;"# ) ;
3639 cg ! ( self , r#"use crate::packet::PacketPayload;"# ) ;
3740
3841 let mut iserialize: HashMap < String , String > = HashMap :: new ( ) ;
@@ -70,7 +73,7 @@ impl<'a, W: Write> CodeSourceGenerator<'a, W> {
7073
7174 cg ! ( self ) ;
7275
73- cg ! ( self , r#"#[derive(Debug, Encode, Decode )]"# ) ;
76+ cg ! ( self , r#"#[derive(Debug)]"# ) ;
7477 cg ! ( self , "pub struct {} {{" , packet. class_name( ) . to_upper_camel_case( ) ) ;
7578 self . indent ( ) ;
7679 for content in packet. contents ( ) {
@@ -85,6 +88,62 @@ impl<'a, W: Write> CodeSourceGenerator<'a, W> {
8588
8689 cg ! ( self ) ;
8790 cg ! ( self , "impl PacketPayload for {} {{}}" , packet. class_name( ) . to_upper_camel_case( ) ) ;
91+ cg ! ( self ) ;
92+ cg ! ( self , "impl Encode for {} {{" , packet. class_name( ) . to_upper_camel_case( ) ) ;
93+ self . indent ( ) ;
94+ cg ! ( self , "fn encode<E: Encoder>(&self, encoder: &mut E) -> std::result::Result<(), bincode::error::EncodeError> {{" ) ;
95+ self . indent ( ) ;
96+ for content in packet. contents ( ) {
97+ use self :: PacketContent :: * ;
98+ match content {
99+ Element ( ref elem) => {
100+ let name = rename_if_reserved ( elem. name ( ) ) ;
101+ cg ! ( self , "self.{}.encode(encoder)?;" , name) ;
102+ } ,
103+ _ => { }
104+ } ;
105+ }
106+ cg ! ( self , "Ok(())" ) ;
107+ self . dedent ( ) ;
108+ cg ! ( self , "}}" ) ;
109+ self . dedent ( ) ;
110+ cg ! ( self , "}}" ) ;
111+
112+ cg ! ( self ) ;
113+ cg ! ( self , "impl Decode for {} {{" , packet. class_name( ) . to_upper_camel_case( ) ) ;
114+ self . indent ( ) ;
115+ cg ! ( self , "fn decode<D: Decoder>(decoder: &mut D) -> std::result::Result<Self, bincode::error::DecodeError> {{" ) ;
116+ self . indent ( ) ;
117+ for content in packet. contents ( ) {
118+ use self :: PacketContent :: * ;
119+ match content {
120+ Element ( ref elem) => {
121+ let name = rename_if_reserved ( elem. name ( ) ) ;
122+ let trimmed_type = elem. type_ ( ) . trim ( ) . to_string ( ) ;
123+ let rust_type = iserialize. get ( elem. type_ ( ) . trim ( ) ) . unwrap_or_else ( || {
124+ debug ! ( r#"Type "{}" not found, outputting anyway"# , elem. type_( ) ) ;
125+ & trimmed_type
126+ } ) ;
127+ cg ! ( self , "let {} = {}::decode(decoder)?;" , name, rust_type) ;
128+ } ,
129+ _ => { }
130+ } ;
131+ }
132+ cg ! ( self , "Ok({} {{" , packet. class_name( ) . to_upper_camel_case( ) ) ;
133+ for content in packet. contents ( ) {
134+ use self :: PacketContent :: * ;
135+ match content {
136+ Element ( ref elem) => {
137+ cg ! ( self , "{}," , rename_if_reserved( elem. name( ) ) ) ;
138+ } ,
139+ _ => { }
140+ } ;
141+ }
142+ cg ! ( self , "}})" ) ;
143+ self . dedent ( ) ;
144+ cg ! ( self , "}}" ) ;
145+ self . dedent ( ) ;
146+ cg ! ( self , "}}" ) ;
88147
89148
90149 Ok ( ( ) )
@@ -216,7 +275,7 @@ impl<'a, W: Write> CodeSourceGenerator<'a, W> {
216275 // };
217276 let name = rename_if_reserved ( elem. name ( ) ) ;
218277 // cg!(self, "{}: {}{}{},", elem.name(), type_, bits, default);
219- cg ! ( self , "{}: {}{}," , name, type_, bits) ;
278+ cg ! ( self , "pub(crate) {}: {}{}," , name, type_, bits) ;
220279 Ok ( ( ) )
221280 }
222281
@@ -235,8 +294,8 @@ impl<'a, W: Write> CodeSourceGenerator<'a, W> {
235294
236295 if is_enum {
237296 cg ! ( self , r#"#[repr({})]"# , rust_type) ;
238- cg ! ( self , r#"#[derive(Debug, Encode, Decode )]"# ) ;
239- cg ! ( self , "enum {} {{" , name. to_upper_camel_case( ) ) ;
297+ cg ! ( self , r#"#[derive(Debug, Clone )]"# ) ;
298+ cg ! ( self , "pub(crate) enum {} {{" , name. to_upper_camel_case( ) ) ;
240299 self . indent ( ) ;
241300 for content in restrict. contents ( ) {
242301 if let Enumeration ( en) = content {
@@ -245,14 +304,142 @@ impl<'a, W: Write> CodeSourceGenerator<'a, W> {
245304 }
246305 }
247306 } else {
248- cg ! ( self , r#"#[derive(Debug, Encode, Decode )]"# ) ;
249- cg ! ( self , "struct {} {{" , name. to_upper_camel_case( ) ) ;
307+ cg ! ( self , r#"#[derive(Debug)]"# ) ;
308+ cg ! ( self , "pub struct {} {{" , name. to_upper_camel_case( ) ) ;
250309 self . indent ( ) ;
251- cg ! ( self , "{}: {}," , name. to_string( ) . to_snake_case( ) , rust_type) ;
310+ cg ! ( self , "pub(crate) {}: {}," , name. to_string( ) . to_snake_case( ) , rust_type) ;
252311 }
253312
254313 self . dedent ( ) ;
255314 cg ! ( self , "}}" ) ;
315+
316+ cg ! ( self ) ;
317+ self . restrict_encode ( & restrict, name, iserialize) ?;
318+ cg ! ( self ) ;
319+ self . restrict_decode ( & restrict, name, iserialize) ?;
320+ Ok ( ( ) )
321+ }
322+
323+ fn restrict_encode ( & mut self , restrict : & Restriction , name : & str , iserialize : & HashMap < String , String > ) -> Result < ( ) > {
324+ let is_enum = restrict. contents ( ) . iter ( ) . find ( |content| match content {
325+ Enumeration ( _) => true ,
326+ _ => false
327+ } ) . is_some ( ) ;
328+ let trimmed_type = restrict. base ( ) . trim ( ) . to_string ( ) ;
329+ let rust_type = iserialize. get ( restrict. base ( ) . trim ( ) ) . unwrap_or_else ( || {
330+ debug ! ( r#"Type "{}" not found, outputting anyway"# , restrict. base( ) ) ;
331+ & trimmed_type
332+ } ) ;
333+
334+ cg ! ( self , "impl Encode for {} {{" , name. to_upper_camel_case( ) ) ;
335+ self . indent ( ) ;
336+ cg ! ( self , "fn encode<E: Encoder>(&self, encoder: &mut E) -> std::result::Result<(), bincode::error::EncodeError> {{" ) ;
337+ self . indent ( ) ;
338+ if is_enum {
339+ cg ! ( self , "encoder.writer().write(&[self.clone() as u8]).map_err(Into::into)" ) ;
340+ } else {
341+ let data = name. to_string ( ) . to_snake_case ( ) ;
342+ cg ! ( self , "let bytes = self.{}.as_bytes();" , data) ;
343+ for content in restrict. contents ( ) {
344+ match content {
345+ Length ( l) => {
346+ cg ! ( self , "let fixed_length = {};" , l) ;
347+ cg ! ( self , "if bytes.len() > fixed_length {{" ) ;
348+ self . indent ( ) ;
349+ cg ! ( self , "return Err(bincode::error::EncodeError::OtherString(format!(" ) ;
350+ cg ! ( self , "\" {} length exceeds fixed size: {{}} > {{}}\" , bytes.len(), fixed_length)));" , data) ;
351+ self . dedent ( ) ;
352+ cg ! ( self , "}}" ) ;
353+ cg ! ( self , "encoder.writer().write(bytes)?;" ) ;
354+ cg ! ( self , "encoder.writer().write(&vec![0; fixed_length - bytes.len()])?;" ) ;
355+ cg ! ( self , "Ok(())" ) ;
356+ } ,
357+ MinValue ( v) => {
358+
359+ } ,
360+ MaxValue ( v) => {
361+
362+ } ,
363+ _ => panic ! ( "enumeration in restrict when there shouldn't be one" )
364+ }
365+ }
366+ }
367+ self . dedent ( ) ;
368+ cg ! ( self , "}}" ) ;
369+ self . dedent ( ) ;
370+ cg ! ( self , "}}" ) ;
371+
372+ Ok ( ( ) )
373+ }
374+
375+ fn restrict_decode ( & mut self , restrict : & Restriction , name : & str , iserialize : & HashMap < String , String > ) -> Result < ( ) > {
376+ let is_enum = restrict. contents ( ) . iter ( ) . find ( |content| match content {
377+ Enumeration ( _) => true ,
378+ _ => false
379+ } ) . is_some ( ) ;
380+ let trimmed_type = restrict. base ( ) . trim ( ) . to_string ( ) ;
381+ let rust_type = iserialize. get ( restrict. base ( ) . trim ( ) ) . unwrap_or_else ( || {
382+ debug ! ( r#"Type "{}" not found, outputting anyway"# , restrict. base( ) ) ;
383+ & trimmed_type
384+ } ) ;
385+
386+ cg ! ( self , "impl Decode for {} {{" , name. to_upper_camel_case( ) ) ;
387+ self . indent ( ) ;
388+ cg ! ( self , "fn decode<D: Decoder>(decoder: &mut D) -> std::result::Result<Self, bincode::error::DecodeError> {{" ) ;
389+ self . indent ( ) ;
390+ if is_enum {
391+ cg ! ( self , "let value = {}::decode(decoder)?;" , rust_type) ;
392+ cg ! ( self , "match value {{" ) ;
393+ self . indent ( ) ;
394+ for content in restrict. contents ( ) {
395+ if let Enumeration ( en) = content {
396+ cg ! ( self , "{} => Ok({}::{})," , en. id( ) , name. to_upper_camel_case( ) , en. value( ) . to_upper_camel_case( ) ) ;
397+ }
398+ }
399+ cg ! ( self , "_ => Err(bincode::error::DecodeError::OtherString(format!(\" Invalid value for {}: {{}}\" , value)))," , name. to_upper_camel_case( ) ) ;
400+ self . dedent ( ) ;
401+ cg ! ( self , "}}" ) ;
402+ } else {
403+ let data = name. to_string ( ) . to_snake_case ( ) ;
404+ let mut fixed_length = 64 ;
405+ let mut minValueCheck = String :: new ( ) ;
406+ let mut maxValueCheck = String :: new ( ) ;
407+ for content in restrict. contents ( ) {
408+ match content {
409+ Length ( l) => {
410+ fixed_length = * l;
411+ } ,
412+ MinValue ( v) => {
413+ minValueCheck = format ! ( "if {} < {} {{Err(bincode::error::DecodeError::OtherString(format!(\" Invalid value for {}: {{}} < {{}}\" , {}, {})))}}" , data, v, data, data, v) . into ( ) ;
414+ } ,
415+ MaxValue ( v) => {
416+ maxValueCheck = format ! ( "if {} > {} {{Err(bincode::error::DecodeError::OtherString(format!(\" Invalid value for {}: {{}} > {{}}\" , {}, {})))}}" , data, v, data, data, v) . into ( ) ;
417+ } ,
418+ _ => panic ! ( "enumeration in restrict when there shouldn't be one" )
419+ }
420+ }
421+
422+ if rust_type == "String" {
423+ cg ! ( self , "let mut buffer = vec![0u8; {}];" , fixed_length) ;
424+ cg ! ( self , "decoder.reader().read(&mut buffer)?;" ) ;
425+ cg ! ( self , "let {} = {}::from_utf8(buffer)" , data, rust_type) ;
426+ cg ! ( self , ".map_err(|e| DecodeError::OtherString(format!(\" Invalid UTF-8: {{}}\" , e)))?" ) ;
427+ cg ! ( self , ".trim_end_matches('\\ 0')" ) ;
428+ cg ! ( self , ".to_string();" ) ;
429+ } else {
430+ cg ! ( self , "let {} = {}::decode(buffer)?;" , data, rust_type) ;
431+
432+ cg ! ( self , "{}" , minValueCheck) ;
433+
434+ cg ! ( self , "{}" , maxValueCheck) ;
435+ }
436+ cg ! ( self , "Ok({} {{ {} }})" , name. to_upper_camel_case( ) , data) ;
437+ }
438+ self . dedent ( ) ;
439+ cg ! ( self , "}}" ) ;
440+ self . dedent ( ) ;
441+ cg ! ( self , "}}" ) ;
442+
256443 Ok ( ( ) )
257444 }
258445}
@@ -273,4 +460,3 @@ fn rename_if_reserved(name: &str) -> String {
273460 name. to_string ( ) . to_snake_case ( )
274461 }
275462}
276-
0 commit comments