Loading tools/pdl/src/generator.rs +149 −194 Original line number Diff line number Diff line // The `format-push-string` lint was briefly enabled present in Rust // 1.62. It is now moved the disabled "restriction" category instead. // See https://github.com/rust-lang/rust-clippy/issues/9077 for the // problems with this lint. // // Remove this when we use Rust 1.63 or later. #![allow(clippy::format_push_string)] use crate::ast; use quote::{format_ident, quote}; use std::collections::HashMap; use std::fmt::Write; use std::path::Path; use syn::parse_quote; Loading @@ -19,12 +26,9 @@ macro_rules! quote_block { fn generate_preamble(path: &Path) -> String { let mut code = String::new(); let filename = path.file_name().unwrap().to_str().expect("non UTF-8 filename"); let _ = write!(code, "// @generated rust packets from {filename}\n\n"); code.push_str(&format!("// @generated rust packets from {filename}\n\n")); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { use bytes::{BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; Loading @@ -32,21 +36,13 @@ fn generate_preamble(path: &Path) -> String { use std::fmt; use std::sync::Arc; use thiserror::Error; } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { type Result<T> = std::result::Result<T, Error>; } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug, Error)] pub enum Error { #[error("Packet parsing failed")] Loading @@ -60,29 +56,20 @@ fn generate_preamble(path: &Path) -> String { #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")] InvalidEnumValueError { obj: String, field: String, value: u64, type_: String }, } } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug, Error)] #[error("{0}")] pub struct TryFromError(&'static str); } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { pub trait Packet { fn to_bytes(self) -> Bytes; fn to_vec(self) -> Vec<u8>; } } ); }); code } Loading Loading @@ -247,10 +234,7 @@ fn generate_packet_decl( let child_name = format_ident!("{id}Child"); if has_children { let child_data_idents = child_idents.iter().map(|ident| format_ident!("{ident}Data")); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug)] enum #data_child_ident { #(#child_idents(Arc<#child_data_idents>),)* Loading @@ -272,8 +256,7 @@ fn generate_packet_decl( #(#child_idents(#child_decl_packet_name),)* None, } } ); }); } let data_name = format_ident!("{id}Data"); Loading @@ -283,17 +266,13 @@ fn generate_packet_decl( } }); let plain_fields = fields.iter().map(|field| generate_field(field, parse_quote!())); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug)] struct #data_name { #(#plain_fields,)* #child_field } } ); }); let parent = parent_id.as_ref().map(|parent_id| match packets.get(parent_id.as_str()) { Some(ast::Decl::Packet { id, .. }) => { Loading @@ -307,30 +286,22 @@ fn generate_packet_decl( }); let packet_name = format_ident!("{id}Packet"); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug, Clone)] pub struct #packet_name { #parent #ident: Arc<#data_name>, } } ); }); let builder_name = format_ident!("{id}Builder"); let pub_fields = fields.iter().map(|field| generate_field(field, parse_quote!(pub))); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug)] pub struct #builder_name { #(#pub_fields,)* } } ); }); // TODO(mgeisler): use the `Buf` trait instead of tracking // the offset manually. Loading Loading @@ -361,10 +332,7 @@ fn generate_packet_decl( }) }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl #data_name { fn conforms(bytes: &[u8]) -> bool { // TODO(mgeisler): return Boolean expression directly. Loading Loading @@ -394,13 +362,9 @@ fn generate_packet_decl( ret } } } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl Packet for #packet_name { fn to_bytes(self) -> Bytes { let mut buffer = BytesMut::new(); Loading @@ -422,8 +386,7 @@ fn generate_packet_decl( packet.to_vec() } } } ); }); let specialize = has_children.then(|| { quote! { Loading @@ -438,10 +401,7 @@ fn generate_packet_decl( } }); let field_getters = fields.iter().map(|field| generate_field_getter(&ident, field)); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl #packet_name { pub fn parse(bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(#data_name::parse(bytes)?)).unwrap()) Loading @@ -456,18 +416,14 @@ fn generate_packet_decl( #(#field_getters)* } } ); }); let child = has_children.then(|| { quote! { child: #data_child_ident::None, } }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl #builder_name { pub fn build(self) -> #packet_name { let #ident = Arc::new(#data_name { Loading @@ -477,8 +433,7 @@ fn generate_packet_decl( #packet_name::new(#ident).unwrap() } } } ); }); code } Loading Loading
tools/pdl/src/generator.rs +149 −194 Original line number Diff line number Diff line // The `format-push-string` lint was briefly enabled present in Rust // 1.62. It is now moved the disabled "restriction" category instead. // See https://github.com/rust-lang/rust-clippy/issues/9077 for the // problems with this lint. // // Remove this when we use Rust 1.63 or later. #![allow(clippy::format_push_string)] use crate::ast; use quote::{format_ident, quote}; use std::collections::HashMap; use std::fmt::Write; use std::path::Path; use syn::parse_quote; Loading @@ -19,12 +26,9 @@ macro_rules! quote_block { fn generate_preamble(path: &Path) -> String { let mut code = String::new(); let filename = path.file_name().unwrap().to_str().expect("non UTF-8 filename"); let _ = write!(code, "// @generated rust packets from {filename}\n\n"); code.push_str(&format!("// @generated rust packets from {filename}\n\n")); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { use bytes::{BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; Loading @@ -32,21 +36,13 @@ fn generate_preamble(path: &Path) -> String { use std::fmt; use std::sync::Arc; use thiserror::Error; } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { type Result<T> = std::result::Result<T, Error>; } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug, Error)] pub enum Error { #[error("Packet parsing failed")] Loading @@ -60,29 +56,20 @@ fn generate_preamble(path: &Path) -> String { #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")] InvalidEnumValueError { obj: String, field: String, value: u64, type_: String }, } } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug, Error)] #[error("{0}")] pub struct TryFromError(&'static str); } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { pub trait Packet { fn to_bytes(self) -> Bytes; fn to_vec(self) -> Vec<u8>; } } ); }); code } Loading Loading @@ -247,10 +234,7 @@ fn generate_packet_decl( let child_name = format_ident!("{id}Child"); if has_children { let child_data_idents = child_idents.iter().map(|ident| format_ident!("{ident}Data")); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug)] enum #data_child_ident { #(#child_idents(Arc<#child_data_idents>),)* Loading @@ -272,8 +256,7 @@ fn generate_packet_decl( #(#child_idents(#child_decl_packet_name),)* None, } } ); }); } let data_name = format_ident!("{id}Data"); Loading @@ -283,17 +266,13 @@ fn generate_packet_decl( } }); let plain_fields = fields.iter().map(|field| generate_field(field, parse_quote!())); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug)] struct #data_name { #(#plain_fields,)* #child_field } } ); }); let parent = parent_id.as_ref().map(|parent_id| match packets.get(parent_id.as_str()) { Some(ast::Decl::Packet { id, .. }) => { Loading @@ -307,30 +286,22 @@ fn generate_packet_decl( }); let packet_name = format_ident!("{id}Packet"); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug, Clone)] pub struct #packet_name { #parent #ident: Arc<#data_name>, } } ); }); let builder_name = format_ident!("{id}Builder"); let pub_fields = fields.iter().map(|field| generate_field(field, parse_quote!(pub))); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { #[derive(Debug)] pub struct #builder_name { #(#pub_fields,)* } } ); }); // TODO(mgeisler): use the `Buf` trait instead of tracking // the offset manually. Loading Loading @@ -361,10 +332,7 @@ fn generate_packet_decl( }) }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl #data_name { fn conforms(bytes: &[u8]) -> bool { // TODO(mgeisler): return Boolean expression directly. Loading Loading @@ -394,13 +362,9 @@ fn generate_packet_decl( ret } } } ); }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl Packet for #packet_name { fn to_bytes(self) -> Bytes { let mut buffer = BytesMut::new(); Loading @@ -422,8 +386,7 @@ fn generate_packet_decl( packet.to_vec() } } } ); }); let specialize = has_children.then(|| { quote! { Loading @@ -438,10 +401,7 @@ fn generate_packet_decl( } }); let field_getters = fields.iter().map(|field| generate_field_getter(&ident, field)); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl #packet_name { pub fn parse(bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(#data_name::parse(bytes)?)).unwrap()) Loading @@ -456,18 +416,14 @@ fn generate_packet_decl( #(#field_getters)* } } ); }); let child = has_children.then(|| { quote! { child: #data_child_ident::None, } }); let _ = write!( code, "{}", "e_block! { code.push_str("e_block! { impl #builder_name { pub fn build(self) -> #packet_name { let #ident = Arc::new(#data_name { Loading @@ -477,8 +433,7 @@ fn generate_packet_decl( #packet_name::new(#ident).unwrap() } } } ); }); code } Loading