diff options
author | Henri Chataing <henrichataing@google.com> | 2023-11-14 03:08:14 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-11-14 03:08:14 +0000 |
commit | ade635fe114c2291bd7a9ca8112d8eae98790f3a (patch) | |
tree | 40b5fb74851bbe10e4eedcb94a663faf615c15bb | |
parent | 9bec3b0f5326e077d31cae56a6d73521e05a482b (diff) | |
parent | f70cf5b56b0ae7e2ca177589b0b35458e2f9233d (diff) | |
download | pdl-compiler-ade635fe114c2291bd7a9ca8112d8eae98790f3a.tar.gz |
Upgrade pdl-compiler to 0.2.3 am: 9c933187bc am: f70cf5b56b
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pdl-compiler/+/2828637
Change-Id: I208237369e77ab2df73d42e2142e40eb57503b5b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | Android.bp | 8 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | cargo2android_toplevel.bp | 3 | ||||
-rw-r--r-- | patches/0001-Add-scripts-Android.bp.patch | 4 | ||||
-rw-r--r-- | src/backends/intermediate.rs | 23 | ||||
-rw-r--r-- | src/backends/rust.rs | 10 | ||||
-rw-r--r-- | src/backends/rust/parser.rs | 41 | ||||
-rw-r--r-- | src/backends/rust/serializer.rs | 14 | ||||
-rw-r--r-- | src/backends/rust_no_allocation/mod.rs | 8 | ||||
-rw-r--r-- | src/bin/generate-canonical-tests.rs | 1 | ||||
-rw-r--r-- | src/lib.rs | 62 | ||||
-rw-r--r-- | tests/generated/payload_with_size_modifier_big_endian.rs | 187 | ||||
-rw-r--r-- | tests/generated/payload_with_size_modifier_little_endian.rs | 187 | ||||
-rwxr-xr-x | tests/run_rust_generator_tests.sh | 2 |
16 files changed, 506 insertions, 56 deletions
@@ -7,7 +7,7 @@ rust_binary_host { name: "generate_canonical_tests", crate_name: "generate_canonical_tests", cargo_env_compat: true, - cargo_pkg_version: "0.2.2", + cargo_pkg_version: "0.2.3", srcs: ["src/bin/generate-canonical-tests.rs"], edition: "2021", features: [ @@ -35,7 +35,7 @@ rust_library_host { name: "libpdl_compiler", crate_name: "pdl_compiler", cargo_env_compat: true, - cargo_pkg_version: "0.2.2", + cargo_pkg_version: "0.2.3", srcs: ["src/lib.rs"], edition: "2021", features: [ @@ -62,7 +62,7 @@ rust_binary_host { name: "pdlc", crate_name: "pdlc", cargo_env_compat: true, - cargo_pkg_version: "0.2.2", + cargo_pkg_version: "0.2.3", srcs: ["src/main.rs"], edition: "2021", features: [ @@ -296,7 +296,6 @@ genrule { " --exclude-declaration PartialChild5_B" + " --exclude-declaration PartialChild12_A" + " --exclude-declaration PartialChild12_B" + - " --exclude-declaration Packet_Payload_Field_SizeModifier" + " --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier" + @@ -321,7 +320,6 @@ genrule { " --exclude-declaration Struct_Checksum_Field_FromStart" + " --exclude-declaration Struct_Checksum_Field_FromEnd_" + " --exclude-declaration Struct_Checksum_Field_FromEnd" + - " --exclude-declaration Packet_Payload_Field_SizeModifier" + " --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier" + @@ -12,7 +12,7 @@ [package] edition = "2021" name = "pdl-compiler" -version = "0.2.2" +version = "0.2.3" authors = [ "Henri Chataing <henrichataing@google.com>", "David de Jesus Duarte <licorne@google.com>", diff --git a/Cargo.toml.orig b/Cargo.toml.orig index a50b93f..4d86b22 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "pdl-compiler" -version = "0.2.2" +version = "0.2.3" edition = "2021" description = "Parser and serializer generator for protocol binary packets" repository = "https://github.com/google/pdl/" @@ -11,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/pdl-compiler/pdl-compiler-0.1.6.crate" + value: "https://static.crates.io/crates/pdl-compiler/pdl-compiler-0.2.3.crate" } - version: "0.1.6" + version: "0.2.3" license_type: NOTICE last_upgrade_date { year: 2023 - month: 8 - day: 12 + month: 11 + day: 13 } } diff --git a/cargo2android_toplevel.bp b/cargo2android_toplevel.bp index 123dff1..76aee62 100644 --- a/cargo2android_toplevel.bp +++ b/cargo2android_toplevel.bp @@ -7,6 +7,7 @@ genrule_defaults { "//system/nfc:__subpackages__", "//external/uwb/src", "//packages/modules/Bluetooth:__subpackages__", + "//tools/netsim:__subpackages__", ], } @@ -207,7 +208,6 @@ genrule { " --exclude-declaration PartialChild5_B" + " --exclude-declaration PartialChild12_A" + " --exclude-declaration PartialChild12_B" + - " --exclude-declaration Packet_Payload_Field_SizeModifier" + " --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier" + @@ -232,7 +232,6 @@ genrule { " --exclude-declaration Struct_Checksum_Field_FromStart" + " --exclude-declaration Struct_Checksum_Field_FromEnd_" + " --exclude-declaration Struct_Checksum_Field_FromEnd" + - " --exclude-declaration Packet_Payload_Field_SizeModifier" + " --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier" + diff --git a/patches/0001-Add-scripts-Android.bp.patch b/patches/0001-Add-scripts-Android.bp.patch index b5f4f1f..30817f9 100644 --- a/patches/0001-Add-scripts-Android.bp.patch +++ b/patches/0001-Add-scripts-Android.bp.patch @@ -14,7 +14,7 @@ new file mode 100644 index 0000000..bb0932c --- /dev/null +++ b/scripts/Android.bp -@@ -0,0 +1,43 @@ +@@ -0,0 +1,58 @@ +// Python generator. +python_binary_host { + name: "pdl_python_generator", @@ -73,6 +73,6 @@ index 0000000..bb0932c + host_supported: true, + vendor_available: true, +} --- +-- 2.41.0.487.g6d72f3e995-goog diff --git a/src/backends/intermediate.rs b/src/backends/intermediate.rs index 9c3c231..4c92ae0 100644 --- a/src/backends/intermediate.rs +++ b/src/backends/intermediate.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::collections::{hash_map::Entry, HashMap}; +use std::collections::{btree_map::Entry, BTreeMap, HashMap}; use crate::ast; use crate::parser; @@ -23,8 +23,8 @@ pub struct Schema<'a> { } pub struct PacketOrStruct<'a> { - pub computed_offsets: HashMap<ComputedOffsetId<'a>, ComputedOffset<'a>>, - pub computed_values: HashMap<ComputedValueId<'a>, ComputedValue<'a>>, + pub computed_offsets: BTreeMap<ComputedOffsetId<'a>, ComputedOffset<'a>>, + pub computed_values: BTreeMap<ComputedValueId<'a>, ComputedValue<'a>>, /// whether the parse of this packet needs to know its length, /// or if the packet can determine its own length pub length: PacketOrStructLength, @@ -41,7 +41,7 @@ pub struct Enum<'a> { pub width: usize, } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub enum ComputedValueId<'a> { // needed for array fields + varlength structs - note that this is in OCTETS, not BITS // this always works since array entries are either structs (which are byte-aligned) or integer-octet-width scalars @@ -54,7 +54,7 @@ pub enum ComputedValueId<'a> { Custom(u16), } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub enum ComputedOffsetId<'a> { // these quantities are known by the runtime HeaderStart, @@ -69,6 +69,7 @@ pub enum ComputedOffsetId<'a> { TrailerStart, } +#[derive(PartialEq, Eq, Debug, PartialOrd, Ord)] pub enum ComputedValue<'a> { Constant(usize), CountStructsUpToSize { @@ -90,7 +91,7 @@ pub enum ComputedValue<'a> { }, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum ComputedOffset<'a> { ConstantPlusOffsetInBits(ComputedOffsetId<'a>, i64), SumWithOctets(ComputedOffsetId<'a>, ComputedValueId<'a>), @@ -127,8 +128,8 @@ fn process_enum<'a>(schema: &mut Schema<'a>, id: &'a str, tags: &'a [ast::Tag], schema.packets_and_structs.insert( id, PacketOrStruct { - computed_offsets: HashMap::new(), - computed_values: HashMap::new(), + computed_offsets: BTreeMap::new(), + computed_values: BTreeMap::new(), length: PacketOrStructLength::Static(width), }, ); @@ -148,8 +149,8 @@ fn compute_getters<'a>( ) -> PacketOrStruct<'a> { let mut prev_pos_id = None; let mut curr_pos_id = ComputedOffsetId::HeaderStart; - let mut computed_values = HashMap::new(); - let mut computed_offsets = HashMap::new(); + let mut computed_values = BTreeMap::new(); + let mut computed_offsets = BTreeMap::new(); let mut cnt = 0; @@ -518,7 +519,7 @@ fn compute_getters<'a>( } fn compute_length_to_goal( - computed_offsets: &HashMap<ComputedOffsetId, ComputedOffset>, + computed_offsets: &BTreeMap<ComputedOffsetId, ComputedOffset>, start: ComputedOffsetId, goal: ComputedOffsetId, ) -> Option<i64> { diff --git a/src/backends/rust.rs b/src/backends/rust.rs index 5a6c921..6609482 100644 --- a/src/backends/rust.rs +++ b/src/backends/rust.rs @@ -1582,6 +1582,16 @@ mod tests { " ); + test_pdl!( + payload_with_size_modifier, + " + packet Test { + _size_(_payload_): 8, + _payload_ : [+1], + } + " + ); + // TODO(mgeisler): enable this test when we have an approach to // struct fields with parents. // diff --git a/src/backends/rust/parser.rs b/src/backends/rust/parser.rs index 8eaee06..8e76592 100644 --- a/src/backends/rust/parser.rs +++ b/src/backends/rust/parser.rs @@ -570,28 +570,8 @@ impl<'a> FieldParser<'a> { let payload_size_field = self.decl.payload_size(); let offset_from_end = self.payload_field_offset_from_end(); - if size_modifier.is_some() { - todo!( - "Unsupported size modifier for {packet}: {size_modifier:?}", - packet = self.packet_name - ); - } - if self.shift != 0 { - if payload_size_field.is_some() { - panic!("Unexpected payload size for non byte aligned payload"); - } - - //let rounded_size = self.shift / 8 + if self.shift % 8 == 0 { 0 } else { 1 }; - //let padding_bits = 8 * rounded_size - self.shift; - //let reserved_field = - // ast::Field::Reserved { loc: ast::SourceRange::default(), width: padding_bits }; - //TODO: self.add_bit_field(&reserved_field); -- - // reserved_field does not live long enough. - - // TODO: consume span of rounded size - } else { - // TODO: consume span + todo!("Unexpected non byte aligned payload"); } if let Some(ast::FieldDesc::Size { field_id, .. }) = &payload_size_field.map(|f| &f.desc) { @@ -599,6 +579,25 @@ impl<'a> FieldParser<'a> { // payload and update the span in case fields are placed // after the payload. let size_field = size_field_ident(field_id); + if let Some(size_modifier) = size_modifier { + let size_modifier = proc_macro2::Literal::usize_unsuffixed( + size_modifier.parse::<usize>().expect("failed to parse the size modifier"), + ); + let packet_name = &self.packet_name; + // Push code to check that the size is greater than the size + // modifier. Required to safely substract the modifier from the + // size. + self.code.push(quote! { + if #size_field < #size_modifier { + return Err(Error::InvalidLengthError { + obj: #packet_name.to_string(), + wanted: #size_modifier, + got: #size_field, + }); + } + let #size_field = #size_field - #size_modifier; + }); + } self.check_size(self.span, "e!(#size_field )); self.code.push(quote! { let payload = &#span.get()[..#size_field]; diff --git a/src/backends/rust/serializer.rs b/src/backends/rust/serializer.rs index 64bc567..b83f7c8 100644 --- a/src/backends/rust/serializer.rs +++ b/src/backends/rust/serializer.rs @@ -66,7 +66,7 @@ impl<'a> FieldSerializer<'a> { self.add_typedef_field(id, type_id); } ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. } => { - self.add_payload_field() + self.add_payload_field(); } // Padding field handled in serialization of associated array field. ast::FieldDesc::Padding { .. } => (), @@ -225,6 +225,18 @@ impl<'a> FieldSerializer<'a> { let field_size_name = format_ident!("{field_id}_size"); let array_size = match (&value_field.desc, value_field_decl.map(|decl| &decl.desc)) { + (ast::FieldDesc::Payload { size_modifier: Some(size_modifier) }, _) => { + let size_modifier = proc_macro2::Literal::usize_unsuffixed( + size_modifier + .parse::<usize>() + .expect("failed to parse the size modifier"), + ); + if let ast::DeclDesc::Packet { .. } = &decl.desc { + quote! { (self.child.get_total_size() + #size_modifier) } + } else { + quote! { (self.payload.len() + #size_modifier) } + } + } (ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. }, _) => { if let ast::DeclDesc::Packet { .. } = &decl.desc { quote! { self.child.get_total_size() } diff --git a/src/backends/rust_no_allocation/mod.rs b/src/backends/rust_no_allocation/mod.rs index 858526f..c98bc12 100644 --- a/src/backends/rust_no_allocation/mod.rs +++ b/src/backends/rust_no_allocation/mod.rs @@ -73,12 +73,8 @@ pub fn generate(file: &parser::ast::File, schema: &Schema) -> Result<String, Str .map(|decl| generate_decl(decl, schema, &children)) .collect::<Result<TokenStream, _>>()?; - out.push_str( - "e! { - #declarations - } - .to_string(), - ); + let syntax_tree = syn::parse2(declarations).expect("Could not parse code"); + out.push_str(&prettyplease::unparse(&syntax_tree)); Ok(out) } diff --git a/src/bin/generate-canonical-tests.rs b/src/bin/generate-canonical-tests.rs index d044edf..1e18490 100644 --- a/src/bin/generate-canonical-tests.rs +++ b/src/bin/generate-canonical-tests.rs @@ -188,6 +188,7 @@ fn main() { "Packet_Payload_Field_UnknownSize", "Packet_Payload_Field_UnknownSize_Terminal", "Packet_Payload_Field_VariableSize", + "Packet_Payload_Field_SizeModifier", "Packet_Reserved_Field", "Packet_Scalar_Field", "Packet_Size_Field", @@ -20,3 +20,65 @@ pub mod backends; pub mod parser; #[cfg(test)] pub mod test_utils; + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn rust_no_allocation_output_is_deterministic() { + // The generated code should be deterministic, to avoid unnecessary rebuilds during + // incremental builds. + let src = r#" +little_endian_packets + +enum Enum1 : 8 { + ENUM_VARIANT_ONE = 0x01, + ENUM_VARIANT_TWO = 0x02, +} + +packet Packet1 { + opcode : Enum1, + _payload_, +} + +struct Struct1 { + handle : 16, +} + +struct Struct2 { + _payload_ +} + +struct Struct3 { + handle : Struct1, + value : Struct2, +} + +packet Packet2 : Packet1(opcode = ENUM_VARIANT_ONE) { + handle : Struct1, + value : Struct2, +} +"# + .to_owned(); + + let mut sources1 = ast::SourceDatabase::new(); + let mut sources2 = ast::SourceDatabase::new(); + let mut sources3 = ast::SourceDatabase::new(); + + let file1 = parser::parse_inline(&mut sources1, "foo", src.clone()).unwrap(); + let file2 = parser::parse_inline(&mut sources2, "foo", src.clone()).unwrap(); + let file3 = parser::parse_inline(&mut sources3, "foo", src).unwrap(); + + let schema1 = backends::intermediate::generate(&file1).unwrap(); + let schema2 = backends::intermediate::generate(&file2).unwrap(); + let schema3 = backends::intermediate::generate(&file3).unwrap(); + + let result1 = backends::rust_no_allocation::generate(&file1, &schema1).unwrap(); + let result2 = backends::rust_no_allocation::generate(&file2, &schema2).unwrap(); + let result3 = backends::rust_no_allocation::generate(&file3, &schema3).unwrap(); + + assert_eq!(result1, result2); + assert_eq!(result2, result3); + } +} diff --git a/tests/generated/payload_with_size_modifier_big_endian.rs b/tests/generated/payload_with_size_modifier_big_endian.rs new file mode 100644 index 0000000..beec02b --- /dev/null +++ b/tests/generated/payload_with_size_modifier_big_endian.rs @@ -0,0 +1,187 @@ +#![rustfmt::skip] +/// @generated rust packets from test. +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use std::convert::{TryFrom, TryInto}; +use std::cell::Cell; +use std::fmt; +use pdl_runtime::{Error, Packet}; +type Result<T> = std::result::Result<T, Error>; +/// Private prevents users from creating arbitrary scalar values +/// in situations where the value needs to be validated. +/// Users can freely deref the value, but only the backend +/// may create it. +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct Private<T>(T); +impl<T> std::ops::Deref for Private<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TestDataChild { + Payload(Bytes), + None, +} +impl TestDataChild { + fn get_total_size(&self) -> usize { + match self { + TestDataChild::Payload(bytes) => bytes.len(), + TestDataChild::None => 0, + } + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TestChild { + Payload(Bytes), + None, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TestData { + child: TestDataChild, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Test { + #[cfg_attr(feature = "serde", serde(flatten))] + test: TestData, +} +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TestBuilder { + pub payload: Option<Bytes>, +} +impl TestData { + fn conforms(bytes: &[u8]) -> bool { + bytes.len() >= 1 + } + fn parse(bytes: &[u8]) -> Result<Self> { + let mut cell = Cell::new(bytes); + let packet = Self::parse_inner(&mut cell)?; + Ok(packet) + } + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> { + if bytes.get().remaining() < 1 { + return Err(Error::InvalidLengthError { + obj: "Test".to_string(), + wanted: 1, + got: bytes.get().remaining(), + }); + } + let payload_size = bytes.get_mut().get_u8() as usize; + if payload_size < 1 { + return Err(Error::InvalidLengthError { + obj: "Test".to_string(), + wanted: 1, + got: payload_size, + }); + } + let payload_size = payload_size - 1; + if bytes.get().remaining() < payload_size { + return Err(Error::InvalidLengthError { + obj: "Test".to_string(), + wanted: payload_size, + got: bytes.get().remaining(), + }); + } + let payload = &bytes.get()[..payload_size]; + bytes.get_mut().advance(payload_size); + let child = match () { + _ if !payload.is_empty() => { + TestDataChild::Payload(Bytes::copy_from_slice(payload)) + } + _ => TestDataChild::None, + }; + Ok(Self { child }) + } + fn write_to(&self, buffer: &mut BytesMut) { + if (self.child.get_total_size() + 1) > 0xff { + panic!( + "Invalid length for {}::{}: {} > {}", "Test", "_payload_", (self.child + .get_total_size() + 1), 0xff + ); + } + buffer.put_u8((self.child.get_total_size() + 1) as u8); + match &self.child { + TestDataChild::Payload(payload) => buffer.put_slice(payload), + TestDataChild::None => {} + } + } + fn get_total_size(&self) -> usize { + self.get_size() + } + fn get_size(&self) -> usize { + 1 + self.child.get_total_size() + } +} +impl Packet for Test { + fn to_bytes(self) -> Bytes { + let mut buffer = BytesMut::with_capacity(self.test.get_size()); + self.test.write_to(&mut buffer); + buffer.freeze() + } + fn to_vec(self) -> Vec<u8> { + self.to_bytes().to_vec() + } +} +impl From<Test> for Bytes { + fn from(packet: Test) -> Self { + packet.to_bytes() + } +} +impl From<Test> for Vec<u8> { + fn from(packet: Test) -> Self { + packet.to_vec() + } +} +impl Test { + pub fn parse(bytes: &[u8]) -> Result<Self> { + let mut cell = Cell::new(bytes); + let packet = Self::parse_inner(&mut cell)?; + Ok(packet) + } + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> { + let data = TestData::parse_inner(&mut bytes)?; + Self::new(data) + } + pub fn specialize(&self) -> TestChild { + match &self.test.child { + TestDataChild::Payload(payload) => TestChild::Payload(payload.clone()), + TestDataChild::None => TestChild::None, + } + } + fn new(test: TestData) -> Result<Self> { + Ok(Self { test }) + } + pub fn get_payload(&self) -> &[u8] { + match &self.test.child { + TestDataChild::Payload(bytes) => &bytes, + TestDataChild::None => &[], + } + } + fn write_to(&self, buffer: &mut BytesMut) { + self.test.write_to(buffer) + } + pub fn get_size(&self) -> usize { + self.test.get_size() + } +} +impl TestBuilder { + pub fn build(self) -> Test { + let test = TestData { + child: match self.payload { + None => TestDataChild::None, + Some(bytes) => TestDataChild::Payload(bytes), + }, + }; + Test::new(test).unwrap() + } +} +impl From<TestBuilder> for Test { + fn from(builder: TestBuilder) -> Test { + builder.build().into() + } +} diff --git a/tests/generated/payload_with_size_modifier_little_endian.rs b/tests/generated/payload_with_size_modifier_little_endian.rs new file mode 100644 index 0000000..beec02b --- /dev/null +++ b/tests/generated/payload_with_size_modifier_little_endian.rs @@ -0,0 +1,187 @@ +#![rustfmt::skip] +/// @generated rust packets from test. +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use std::convert::{TryFrom, TryInto}; +use std::cell::Cell; +use std::fmt; +use pdl_runtime::{Error, Packet}; +type Result<T> = std::result::Result<T, Error>; +/// Private prevents users from creating arbitrary scalar values +/// in situations where the value needs to be validated. +/// Users can freely deref the value, but only the backend +/// may create it. +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct Private<T>(T); +impl<T> std::ops::Deref for Private<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TestDataChild { + Payload(Bytes), + None, +} +impl TestDataChild { + fn get_total_size(&self) -> usize { + match self { + TestDataChild::Payload(bytes) => bytes.len(), + TestDataChild::None => 0, + } + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TestChild { + Payload(Bytes), + None, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TestData { + child: TestDataChild, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Test { + #[cfg_attr(feature = "serde", serde(flatten))] + test: TestData, +} +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TestBuilder { + pub payload: Option<Bytes>, +} +impl TestData { + fn conforms(bytes: &[u8]) -> bool { + bytes.len() >= 1 + } + fn parse(bytes: &[u8]) -> Result<Self> { + let mut cell = Cell::new(bytes); + let packet = Self::parse_inner(&mut cell)?; + Ok(packet) + } + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> { + if bytes.get().remaining() < 1 { + return Err(Error::InvalidLengthError { + obj: "Test".to_string(), + wanted: 1, + got: bytes.get().remaining(), + }); + } + let payload_size = bytes.get_mut().get_u8() as usize; + if payload_size < 1 { + return Err(Error::InvalidLengthError { + obj: "Test".to_string(), + wanted: 1, + got: payload_size, + }); + } + let payload_size = payload_size - 1; + if bytes.get().remaining() < payload_size { + return Err(Error::InvalidLengthError { + obj: "Test".to_string(), + wanted: payload_size, + got: bytes.get().remaining(), + }); + } + let payload = &bytes.get()[..payload_size]; + bytes.get_mut().advance(payload_size); + let child = match () { + _ if !payload.is_empty() => { + TestDataChild::Payload(Bytes::copy_from_slice(payload)) + } + _ => TestDataChild::None, + }; + Ok(Self { child }) + } + fn write_to(&self, buffer: &mut BytesMut) { + if (self.child.get_total_size() + 1) > 0xff { + panic!( + "Invalid length for {}::{}: {} > {}", "Test", "_payload_", (self.child + .get_total_size() + 1), 0xff + ); + } + buffer.put_u8((self.child.get_total_size() + 1) as u8); + match &self.child { + TestDataChild::Payload(payload) => buffer.put_slice(payload), + TestDataChild::None => {} + } + } + fn get_total_size(&self) -> usize { + self.get_size() + } + fn get_size(&self) -> usize { + 1 + self.child.get_total_size() + } +} +impl Packet for Test { + fn to_bytes(self) -> Bytes { + let mut buffer = BytesMut::with_capacity(self.test.get_size()); + self.test.write_to(&mut buffer); + buffer.freeze() + } + fn to_vec(self) -> Vec<u8> { + self.to_bytes().to_vec() + } +} +impl From<Test> for Bytes { + fn from(packet: Test) -> Self { + packet.to_bytes() + } +} +impl From<Test> for Vec<u8> { + fn from(packet: Test) -> Self { + packet.to_vec() + } +} +impl Test { + pub fn parse(bytes: &[u8]) -> Result<Self> { + let mut cell = Cell::new(bytes); + let packet = Self::parse_inner(&mut cell)?; + Ok(packet) + } + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> { + let data = TestData::parse_inner(&mut bytes)?; + Self::new(data) + } + pub fn specialize(&self) -> TestChild { + match &self.test.child { + TestDataChild::Payload(payload) => TestChild::Payload(payload.clone()), + TestDataChild::None => TestChild::None, + } + } + fn new(test: TestData) -> Result<Self> { + Ok(Self { test }) + } + pub fn get_payload(&self) -> &[u8] { + match &self.test.child { + TestDataChild::Payload(bytes) => &bytes, + TestDataChild::None => &[], + } + } + fn write_to(&self, buffer: &mut BytesMut) { + self.test.write_to(buffer) + } + pub fn get_size(&self) -> usize { + self.test.get_size() + } +} +impl TestBuilder { + pub fn build(self) -> Test { + let test = TestData { + child: match self.payload { + None => TestDataChild::None, + Some(bytes) => TestDataChild::Payload(bytes), + }, + }; + Test::new(test).unwrap() + } +} +impl From<TestBuilder> for Test { + fn from(builder: TestBuilder) -> Test { + builder.build().into() + } +} diff --git a/tests/run_rust_generator_tests.sh b/tests/run_rust_generator_tests.sh index 5e8ecf1..92e6f05 100755 --- a/tests/run_rust_generator_tests.sh +++ b/tests/run_rust_generator_tests.sh @@ -34,7 +34,6 @@ cargo run --bin pdlc -- \ --exclude-declaration PartialChild5_B \ --exclude-declaration PartialChild12_A \ --exclude-declaration PartialChild12_B \ - --exclude-declaration Packet_Payload_Field_SizeModifier \ --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_ \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier \ @@ -53,7 +52,6 @@ cargo run --bin pdlc -- \ --exclude-declaration Struct_Checksum_Field_FromStart \ --exclude-declaration Struct_Checksum_Field_FromEnd_ \ --exclude-declaration Struct_Checksum_Field_FromEnd \ - --exclude-declaration Packet_Payload_Field_SizeModifier \ --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_ \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier \ |