diff --git a/tools/pdl/src/backends/rust.rs b/tools/pdl/src/backends/rust.rs index 35ec1dcff3eb84f6892d7b43ed0349781841c2be..7af876dcb8159463acc569718d7a49f8cafc2422 100644 --- a/tools/pdl/src/backends/rust.rs +++ b/tools/pdl/src/backends/rust.rs @@ -32,16 +32,6 @@ macro_rules! quote_block { } } -/// Find byte indices covering `offset..offset+width` bits. -pub fn get_field_range(offset: usize, width: usize) -> std::ops::Range<usize> { - let start = offset / 8; - let mut end = (offset + width) / 8; - if (offset + width) % 8 != 0 { - end += 1; - } - start..end -} - /// Generate a bit-mask which masks out `n` least significant bits. pub fn mask_bits(n: usize) -> syn::LitInt { syn::parse_str::<syn::LitInt>(&format!("{:#x}", (1u64 << n) - 1)).unwrap() @@ -152,12 +142,10 @@ fn generate_packet_decl( }); let mut field_parsers = Vec::new(); let mut field_writers = Vec::new(); - let mut offset = 0; for fields in chunks { let chunk = Chunk::new(fields); - field_parsers.push(chunk.generate_read(id, file.endianness.value, offset)); - field_writers.push(chunk.generate_write(file.endianness.value, offset)); - offset += chunk.get_width(); + field_parsers.push(chunk.generate_read(id, file.endianness.value)); + field_writers.push(chunk.generate_write(file.endianness.value)); } let field_names = fields.iter().map(Field::get_ident).collect::<Vec<_>>(); @@ -180,7 +168,7 @@ fn generate_packet_decl( #conforms } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(mut bytes: &[u8]) -> Result<Self> { #(#field_parsers)* Ok(Self { #(#field_names),* }) } @@ -202,8 +190,7 @@ fn generate_packet_decl( code.push_str("e_block! { impl Packet for #packet_name { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.#ident.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.#ident.get_total_size()); self.#ident.write_to(&mut buffer); buffer.freeze() } @@ -238,7 +225,7 @@ fn generate_packet_decl( let field_getters = fields.iter().map(|field| field.generate_getter(&ident)); code.push_str("e_block! { impl #packet_name { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(#data_name::parse(bytes)?)).unwrap()) } @@ -382,26 +369,4 @@ mod tests { } "#, ); - - #[test] - fn test_get_field_range() { - // Zero widths will give you an empty slice iff the offset is - // byte aligned. In both cases, the slice covers the empty - // width. In practice, PDL doesn't allow zero-width fields. - assert_eq!(get_field_range(/*offset=*/ 0, /*width=*/ 0), (0..0)); - assert_eq!(get_field_range(/*offset=*/ 5, /*width=*/ 0), (0..1)); - assert_eq!(get_field_range(/*offset=*/ 8, /*width=*/ 0), (1..1)); - assert_eq!(get_field_range(/*offset=*/ 9, /*width=*/ 0), (1..2)); - - // Non-zero widths work as expected. - assert_eq!(get_field_range(/*offset=*/ 0, /*width=*/ 1), (0..1)); - assert_eq!(get_field_range(/*offset=*/ 0, /*width=*/ 5), (0..1)); - assert_eq!(get_field_range(/*offset=*/ 0, /*width=*/ 8), (0..1)); - assert_eq!(get_field_range(/*offset=*/ 0, /*width=*/ 20), (0..3)); - - assert_eq!(get_field_range(/*offset=*/ 5, /*width=*/ 1), (0..1)); - assert_eq!(get_field_range(/*offset=*/ 5, /*width=*/ 3), (0..1)); - assert_eq!(get_field_range(/*offset=*/ 5, /*width=*/ 4), (0..2)); - assert_eq!(get_field_range(/*offset=*/ 5, /*width=*/ 20), (0..4)); - } } diff --git a/tools/pdl/src/backends/rust/chunk.rs b/tools/pdl/src/backends/rust/chunk.rs index bc46990c35ac4cc1ecd94f4256e62f599737afe7..e8a202d722905e656b3c4300c6f7715b62417ffa 100644 --- a/tools/pdl/src/backends/rust/chunk.rs +++ b/tools/pdl/src/backends/rust/chunk.rs @@ -1,9 +1,72 @@ use crate::ast; use crate::backends::rust::field::Field; -use crate::backends::rust::get_field_range; use crate::backends::rust::types::Integer; use quote::{format_ident, quote}; +fn endianness_suffix(width: usize, endianness_value: ast::EndiannessValue) -> &'static str { + if width > 8 && endianness_value == ast::EndiannessValue::LittleEndian { + "_le" + } else { + "" + } +} + +/// Parse an unsigned integer from `buffer`. +/// +/// The generated code requires that `buffer` is a mutable +/// `bytes::Buf` value. +fn get_uint( + endianness: ast::EndiannessValue, + buffer: proc_macro2::Ident, + width: usize, +) -> proc_macro2::TokenStream { + let suffix = endianness_suffix(width, endianness); + let rust_integer_widths = [8, 16, 32, 64]; + if rust_integer_widths.contains(&width) { + // We can use Buf::get_uNN. + let get_u = format_ident!("get_u{}{}", width, suffix); + quote! { + #buffer.#get_u() + } + } else { + // We fall back to Buf::get_uint. + let get_uint = format_ident!("get_uint{}", suffix); + let value_type = Integer::new(width); + let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8); + quote! { + #buffer.#get_uint(#value_nbytes) as #value_type + } + } +} + +/// Write an unsigned integer `value` to `buffer`. +/// +/// The generated code requires that `buffer` is a mutable +/// `bytes::BufMut` value. +fn put_uint( + endianness: ast::EndiannessValue, + buffer: proc_macro2::Ident, + value: proc_macro2::TokenStream, + width: usize, +) -> proc_macro2::TokenStream { + let suffix = endianness_suffix(width, endianness); + let rust_integer_widths = [8, 16, 32, 64]; + if rust_integer_widths.contains(&width) { + // We can use BufMut::put_uNN. + let put_u = format_ident!("put_u{}{}", width, suffix); + quote! { + #buffer.#put_u(#value) + } + } else { + // We fall back to BufMut::put_uint. + let put_uint = format_ident!("put_uint{}", suffix); + let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8); + quote! { + #buffer.#put_uint(#value as u64, #value_nbytes) + } + } +} + /// A chunk of field. /// /// While fields can have arbitrary widths, a chunk is always an @@ -35,19 +98,14 @@ impl Chunk<'_> { } /// Generate length checks for this chunk. - pub fn generate_length_check( - &self, - packet_name: &str, - offset: usize, - ) -> proc_macro2::TokenStream { - let range = get_field_range(offset, self.get_width()); - let wanted_length = syn::Index::from(range.end); + pub fn generate_length_check(&self, packet_name: &str) -> proc_macro2::TokenStream { + let wanted_length = proc_macro2::Literal::usize_unsuffixed(self.get_width() / 8); quote! { - if bytes.len() < #wanted_length { + if bytes.remaining() < #wanted_length { return Err(Error::InvalidLengthError { obj: #packet_name.to_string(), wanted: #wanted_length, - got: bytes.len(), + got: bytes.remaining(), }); } } @@ -58,46 +116,18 @@ impl Chunk<'_> { &self, packet_name: &str, endianness_value: ast::EndiannessValue, - offset: usize, ) -> proc_macro2::TokenStream { - assert!(offset % 8 == 0, "Chunks must be byte-aligned, got offset: {offset}"); - let getter = match endianness_value { - ast::EndiannessValue::BigEndian => format_ident!("from_be_bytes"), - ast::EndiannessValue::LittleEndian => format_ident!("from_le_bytes"), - }; - let chunk_name = self.get_name(); let chunk_width = self.get_width(); - let chunk_type = Integer::new(chunk_width); assert!(chunk_width % 8 == 0, "Chunks must have a byte size, got width: {chunk_width}"); - let range = get_field_range(offset, chunk_width); - let indices = range.map(syn::Index::from).collect::<Vec<_>>(); - let length_check = self.generate_length_check(packet_name, offset); - - // When the chunk_type.width is larger than chunk_width (e.g. - // chunk_width is 24 but chunk_type.width is 32), then we need - // zero padding. - let zero_padding_len = (chunk_type.width - chunk_width) / 8; - // We need the padding on the MSB side of the payload, so for - // big-endian, we need to padding on the left, for little-endian - // we need it on the right. - let (zero_padding_before, zero_padding_after) = match endianness_value { - ast::EndiannessValue::BigEndian => { - (vec![syn::Index::from(0); zero_padding_len], vec![]) - } - ast::EndiannessValue::LittleEndian => { - (vec![], vec![syn::Index::from(0); zero_padding_len]) - } - }; - + let length_check = self.generate_length_check(packet_name); + let read = get_uint(endianness_value, format_ident!("bytes"), chunk_width); let read_adjustments = self.generate_read_adjustments(); quote! { #length_check - let #chunk_name = #chunk_type::#getter([ - #(#zero_padding_before,)* #(bytes[#indices]),* #(, #zero_padding_after)* - ]); + let #chunk_name = #read; #read_adjustments } } @@ -127,26 +157,18 @@ impl Chunk<'_> { pub fn generate_write( &self, endianness_value: ast::EndiannessValue, - offset: usize, ) -> proc_macro2::TokenStream { - let writer = match endianness_value { - ast::EndiannessValue::BigEndian => format_ident!("to_be_bytes"), - ast::EndiannessValue::LittleEndian => format_ident!("to_le_bytes"), - }; - let chunk_width = self.get_width(); let chunk_name = self.get_name(); assert!(chunk_width % 8 == 0, "Chunks must have a byte size, got width: {chunk_width}"); - let range = get_field_range(offset, chunk_width); - let start = syn::Index::from(range.start); - let end = syn::Index::from(range.end); // TODO(mgeisler): let slice = (chunk_type_width > chunk_width).then( ... ) - let chunk_byte_width = syn::Index::from(chunk_width / 8); let write_adjustments = self.generate_write_adjustments(); + let write = + put_uint(endianness_value, format_ident!("buffer"), quote!(#chunk_name), chunk_width); quote! { #write_adjustments - buffer[#start..#end].copy_from_slice(&#chunk_name.#writer()[0..#chunk_byte_width]); + #write; } } @@ -187,7 +209,7 @@ mod tests { fn test_generate_read_8bit() { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 8 })]; let chunk = Chunk::new(&fields); - let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian, 80); + let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian); let code = quote! { fn main() { #chunk_read } }; assert_snapshot_eq( "tests/generated/generate_chunk_read_8bit.rs", @@ -199,7 +221,7 @@ mod tests { fn test_generate_read_16bit_le() { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 16 })]; let chunk = Chunk::new(&fields); - let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::LittleEndian, 80); + let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::LittleEndian); let code = quote! { fn main() { #chunk_read } }; assert_snapshot_eq( "tests/generated/generate_chunk_read_16bit_le.rs", @@ -211,7 +233,7 @@ mod tests { fn test_generate_read_16bit_be() { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 16 })]; let chunk = Chunk::new(&fields); - let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian, 80); + let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian); let code = quote! { fn main() { #chunk_read } }; assert_snapshot_eq( "tests/generated/generate_chunk_read_16bit_be.rs", @@ -223,7 +245,7 @@ mod tests { fn test_generate_read_24bit_le() { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 24 })]; let chunk = Chunk::new(&fields); - let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::LittleEndian, 80); + let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::LittleEndian); let code = quote! { fn main() { #chunk_read } }; assert_snapshot_eq( "tests/generated/generate_chunk_read_24bit_le.rs", @@ -235,7 +257,7 @@ mod tests { fn test_generate_read_24bit_be() { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 24 })]; let chunk = Chunk::new(&fields); - let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian, 80); + let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian); let code = quote! { fn main() { #chunk_read } }; assert_snapshot_eq( "tests/generated/generate_chunk_read_24bit_be.rs", @@ -250,7 +272,7 @@ mod tests { Field::Scalar(ScalarField { id: String::from("b"), width: 24 }), ]; let chunk = Chunk::new(&fields); - let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian, 80); + let chunk_read = chunk.generate_read("Foo", ast::EndiannessValue::BigEndian); let code = quote! { fn main() { #chunk_read } }; assert_snapshot_eq( "tests/generated/generate_chunk_read_multiple_fields.rs", @@ -301,10 +323,10 @@ mod tests { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 8 })]; let chunk = Chunk::new(&fields); assert_expr_eq( - chunk.generate_write(ast::EndiannessValue::BigEndian, 80), + chunk.generate_write(ast::EndiannessValue::BigEndian), quote! { let a = self.a; - buffer[10..11].copy_from_slice(&a.to_be_bytes()[0..1]); + buffer.put_u8(a); }, ); } @@ -314,10 +336,10 @@ mod tests { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 16 })]; let chunk = Chunk::new(&fields); assert_expr_eq( - chunk.generate_write(ast::EndiannessValue::BigEndian, 80), + chunk.generate_write(ast::EndiannessValue::BigEndian), quote! { let a = self.a; - buffer[10..12].copy_from_slice(&a.to_be_bytes()[0..2]); + buffer.put_u16(a); }, ); } @@ -327,10 +349,10 @@ mod tests { let fields = [Field::Scalar(ScalarField { id: String::from("a"), width: 24 })]; let chunk = Chunk::new(&fields); assert_expr_eq( - chunk.generate_write(ast::EndiannessValue::BigEndian, 80), + chunk.generate_write(ast::EndiannessValue::BigEndian), quote! { let a = self.a; - buffer[10..13].copy_from_slice(&a.to_be_bytes()[0..3]); + buffer.put_uint(a as u64, 3); }, ); } @@ -343,12 +365,12 @@ mod tests { ]; let chunk = Chunk::new(&fields); assert_expr_eq( - chunk.generate_write(ast::EndiannessValue::BigEndian, 80), + chunk.generate_write(ast::EndiannessValue::BigEndian), quote! { let chunk = 0; let chunk = chunk | (self.a as u64); let chunk = chunk | (((self.b as u64) & 0xffffff) << 16); - buffer[10..15].copy_from_slice(&chunk.to_be_bytes()[0..5]); + buffer.put_uint(chunk as u64, 5); }, ); } diff --git a/tools/pdl/src/backends/rust/preamble.rs b/tools/pdl/src/backends/rust/preamble.rs index 682651204e1a08d0f4365af0ba47978e3c401984..d31eede237e0a7be03a9c57adfa81b6c0ea76bb4 100644 --- a/tools/pdl/src/backends/rust/preamble.rs +++ b/tools/pdl/src/backends/rust/preamble.rs @@ -12,7 +12,7 @@ pub fn generate(path: &Path) -> String { code.push_str("#![allow(warnings, missing_docs)]\n\n"); code.push_str("e_block! { - use bytes::{BufMut, Bytes, BytesMut}; + use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; diff --git a/tools/pdl/tests/generated/generate_chunk_read_16bit_be.rs b/tools/pdl/tests/generated/generate_chunk_read_16bit_be.rs index 596f001cde3e70eea7fb6b0606c74c734376700f..2c07d1d1f01f64db99dbd311cc77c1335e1073de 100644 --- a/tools/pdl/tests/generated/generate_chunk_read_16bit_be.rs +++ b/tools/pdl/tests/generated/generate_chunk_read_16bit_be.rs @@ -1,10 +1,10 @@ fn main() { - if bytes.len() < 12 { + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 12, - got: bytes.len(), + wanted: 2, + got: bytes.remaining(), }); } - let a = u16::from_be_bytes([bytes[10], bytes[11]]); + let a = bytes.get_u16(); } diff --git a/tools/pdl/tests/generated/generate_chunk_read_16bit_le.rs b/tools/pdl/tests/generated/generate_chunk_read_16bit_le.rs index 3b645a2a40ed93cce76a502ebe0c6e0d7b89ec19..15dd4948fcfdb95689a38cfa7118c0d2659b1c2b 100644 --- a/tools/pdl/tests/generated/generate_chunk_read_16bit_le.rs +++ b/tools/pdl/tests/generated/generate_chunk_read_16bit_le.rs @@ -1,10 +1,10 @@ fn main() { - if bytes.len() < 12 { + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 12, - got: bytes.len(), + wanted: 2, + got: bytes.remaining(), }); } - let a = u16::from_le_bytes([bytes[10], bytes[11]]); + let a = bytes.get_u16_le(); } diff --git a/tools/pdl/tests/generated/generate_chunk_read_24bit_be.rs b/tools/pdl/tests/generated/generate_chunk_read_24bit_be.rs index 991619c369a73ca0a5fb06f5c4a427da29c4cae0..03dc6428e9579b2ec4d3c2234743f2e51e04940c 100644 --- a/tools/pdl/tests/generated/generate_chunk_read_24bit_be.rs +++ b/tools/pdl/tests/generated/generate_chunk_read_24bit_be.rs @@ -1,10 +1,10 @@ fn main() { - if bytes.len() < 13 { + if bytes.remaining() < 3 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 13, - got: bytes.len(), + wanted: 3, + got: bytes.remaining(), }); } - let a = u32::from_be_bytes([0, bytes[10], bytes[11], bytes[12]]); + let a = bytes.get_uint(3) as u32; } diff --git a/tools/pdl/tests/generated/generate_chunk_read_24bit_le.rs b/tools/pdl/tests/generated/generate_chunk_read_24bit_le.rs index f4e8aa665e745db87a8285be3ee11485a263c998..6930b5129f6e2fdd0516ca11ca780291ad5ce61e 100644 --- a/tools/pdl/tests/generated/generate_chunk_read_24bit_le.rs +++ b/tools/pdl/tests/generated/generate_chunk_read_24bit_le.rs @@ -1,10 +1,10 @@ fn main() { - if bytes.len() < 13 { + if bytes.remaining() < 3 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 13, - got: bytes.len(), + wanted: 3, + got: bytes.remaining(), }); } - let a = u32::from_le_bytes([bytes[10], bytes[11], bytes[12], 0]); + let a = bytes.get_uint_le(3) as u32; } diff --git a/tools/pdl/tests/generated/generate_chunk_read_8bit.rs b/tools/pdl/tests/generated/generate_chunk_read_8bit.rs index f6495b8e09fc6cce1e8d7c7b6555a8cdf534f38c..c8b6c13cb07b4cf5309e45b4bc07dd38e06f6d76 100644 --- a/tools/pdl/tests/generated/generate_chunk_read_8bit.rs +++ b/tools/pdl/tests/generated/generate_chunk_read_8bit.rs @@ -1,10 +1,10 @@ fn main() { - if bytes.len() < 11 { + if bytes.remaining() < 1 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 11, - got: bytes.len(), + wanted: 1, + got: bytes.remaining(), }); } - let a = u8::from_be_bytes([bytes[10]]); + let a = bytes.get_u8(); } diff --git a/tools/pdl/tests/generated/generate_chunk_read_multiple_fields.rs b/tools/pdl/tests/generated/generate_chunk_read_multiple_fields.rs index a37453859f279c443a9458a67044da32590a98f9..8eab84474fc1642c398efc0e468670d18f9717af 100644 --- a/tools/pdl/tests/generated/generate_chunk_read_multiple_fields.rs +++ b/tools/pdl/tests/generated/generate_chunk_read_multiple_fields.rs @@ -1,13 +1,12 @@ fn main() { - if bytes.len() < 15 { + if bytes.remaining() < 5 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 15, - got: bytes.len(), + wanted: 5, + got: bytes.remaining(), }); } - let chunk = - u64::from_be_bytes([0, 0, 0, bytes[10], bytes[11], bytes[12], bytes[13], bytes[14]]); + let chunk = bytes.get_uint(5) as u64; let a = chunk as u16; let b = ((chunk >> 16) & 0xffffff) as u32; } diff --git a/tools/pdl/tests/generated/packet_decl_complex_big_endian.rs b/tools/pdl/tests/generated/packet_decl_complex_big_endian.rs index b8684269eb1a3ea5ec4e87d0e6fe61a28cc46349..195fe833165eb4805ba561860f65668bbeb58b13 100644 --- a/tools/pdl/tests/generated/packet_decl_complex_big_endian.rs +++ b/tools/pdl/tests/generated/packet_decl_complex_big_endian.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; @@ -64,34 +64,34 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { - if bytes.len() < 2 { + fn parse(mut bytes: &[u8]) -> Result<Self> { + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), wanted: 2, - got: bytes.len(), + got: bytes.remaining(), }); } - let chunk = u16::from_be_bytes([bytes[0], bytes[1]]); + let chunk = bytes.get_u16(); let a = (chunk & 0x7) as u8; let b = (chunk >> 3) as u8; let c = ((chunk >> 11) & 0x1f) as u8; - if bytes.len() < 5 { + if bytes.remaining() < 3 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 5, - got: bytes.len(), + wanted: 3, + got: bytes.remaining(), }); } - let d = u32::from_be_bytes([0, bytes[2], bytes[3], bytes[4]]); - if bytes.len() < 7 { + let d = bytes.get_uint(3) as u32; + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 7, - got: bytes.len(), + wanted: 2, + got: bytes.remaining(), }); } - let chunk = u16::from_be_bytes([bytes[5], bytes[6]]); + let chunk = bytes.get_u16(); let e = (chunk & 0xfff); let f = ((chunk >> 12) & 0xf) as u8; Ok(Self { a, b, c, d, e, f }) @@ -101,13 +101,13 @@ impl FooData { let chunk = chunk | ((self.a as u16) & 0x7); let chunk = chunk | ((self.b as u16) << 3); let chunk = chunk | (((self.c as u16) & 0x1f) << 11); - buffer[0..2].copy_from_slice(&chunk.to_be_bytes()[0..2]); + buffer.put_u16(chunk); let d = self.d; - buffer[2..5].copy_from_slice(&d.to_be_bytes()[0..3]); + buffer.put_uint(d as u64, 3); let chunk = 0; let chunk = chunk | (self.e & 0xfff); let chunk = chunk | (((self.f as u16) & 0xf) << 12); - buffer[5..7].copy_from_slice(&chunk.to_be_bytes()[0..2]); + buffer.put_u16(chunk); } fn get_total_size(&self) -> usize { self.get_size() @@ -119,8 +119,7 @@ impl FooData { impl Packet for FooPacket { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.foo.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.foo.get_total_size()); self.foo.write_to(&mut buffer); buffer.freeze() } @@ -140,7 +139,7 @@ impl From<FooPacket> for Vec<u8> { } impl FooPacket { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(FooData::parse(bytes)?)).unwrap()) } fn new(root: Arc<FooData>) -> std::result::Result<Self, &'static str> { diff --git a/tools/pdl/tests/generated/packet_decl_complex_little_endian.rs b/tools/pdl/tests/generated/packet_decl_complex_little_endian.rs index bdc72299ef10f7b4357b3e29be9c45bf7a6be144..c81bf004c87737102f1bf907f4bad1a6ee75123d 100644 --- a/tools/pdl/tests/generated/packet_decl_complex_little_endian.rs +++ b/tools/pdl/tests/generated/packet_decl_complex_little_endian.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; @@ -64,34 +64,34 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { - if bytes.len() < 2 { + fn parse(mut bytes: &[u8]) -> Result<Self> { + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), wanted: 2, - got: bytes.len(), + got: bytes.remaining(), }); } - let chunk = u16::from_le_bytes([bytes[0], bytes[1]]); + let chunk = bytes.get_u16_le(); let a = (chunk & 0x7) as u8; let b = (chunk >> 3) as u8; let c = ((chunk >> 11) & 0x1f) as u8; - if bytes.len() < 5 { + if bytes.remaining() < 3 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 5, - got: bytes.len(), + wanted: 3, + got: bytes.remaining(), }); } - let d = u32::from_le_bytes([bytes[2], bytes[3], bytes[4], 0]); - if bytes.len() < 7 { + let d = bytes.get_uint_le(3) as u32; + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 7, - got: bytes.len(), + wanted: 2, + got: bytes.remaining(), }); } - let chunk = u16::from_le_bytes([bytes[5], bytes[6]]); + let chunk = bytes.get_u16_le(); let e = (chunk & 0xfff); let f = ((chunk >> 12) & 0xf) as u8; Ok(Self { a, b, c, d, e, f }) @@ -101,13 +101,13 @@ impl FooData { let chunk = chunk | ((self.a as u16) & 0x7); let chunk = chunk | ((self.b as u16) << 3); let chunk = chunk | (((self.c as u16) & 0x1f) << 11); - buffer[0..2].copy_from_slice(&chunk.to_le_bytes()[0..2]); + buffer.put_u16_le(chunk); let d = self.d; - buffer[2..5].copy_from_slice(&d.to_le_bytes()[0..3]); + buffer.put_uint_le(d as u64, 3); let chunk = 0; let chunk = chunk | (self.e & 0xfff); let chunk = chunk | (((self.f as u16) & 0xf) << 12); - buffer[5..7].copy_from_slice(&chunk.to_le_bytes()[0..2]); + buffer.put_u16_le(chunk); } fn get_total_size(&self) -> usize { self.get_size() @@ -119,8 +119,7 @@ impl FooData { impl Packet for FooPacket { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.foo.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.foo.get_total_size()); self.foo.write_to(&mut buffer); buffer.freeze() } @@ -140,7 +139,7 @@ impl From<FooPacket> for Vec<u8> { } impl FooPacket { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(FooData::parse(bytes)?)).unwrap()) } fn new(root: Arc<FooData>) -> std::result::Result<Self, &'static str> { diff --git a/tools/pdl/tests/generated/packet_decl_empty_big_endian.rs b/tools/pdl/tests/generated/packet_decl_empty_big_endian.rs index e82edd44c72decc63682c5498677aa282ab86317..e76e7fd9938958bf869e5114b9dc548def665d1f 100644 --- a/tools/pdl/tests/generated/packet_decl_empty_big_endian.rs +++ b/tools/pdl/tests/generated/packet_decl_empty_big_endian.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; @@ -50,7 +50,7 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self {}) } fn write_to(&self, buffer: &mut BytesMut) {} @@ -64,8 +64,7 @@ impl FooData { impl Packet for FooPacket { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.foo.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.foo.get_total_size()); self.foo.write_to(&mut buffer); buffer.freeze() } @@ -85,7 +84,7 @@ impl From<FooPacket> for Vec<u8> { } impl FooPacket { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(FooData::parse(bytes)?)).unwrap()) } fn new(root: Arc<FooData>) -> std::result::Result<Self, &'static str> { diff --git a/tools/pdl/tests/generated/packet_decl_empty_little_endian.rs b/tools/pdl/tests/generated/packet_decl_empty_little_endian.rs index e82edd44c72decc63682c5498677aa282ab86317..e76e7fd9938958bf869e5114b9dc548def665d1f 100644 --- a/tools/pdl/tests/generated/packet_decl_empty_little_endian.rs +++ b/tools/pdl/tests/generated/packet_decl_empty_little_endian.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; @@ -50,7 +50,7 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self {}) } fn write_to(&self, buffer: &mut BytesMut) {} @@ -64,8 +64,7 @@ impl FooData { impl Packet for FooPacket { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.foo.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.foo.get_total_size()); self.foo.write_to(&mut buffer); buffer.freeze() } @@ -85,7 +84,7 @@ impl From<FooPacket> for Vec<u8> { } impl FooPacket { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(FooData::parse(bytes)?)).unwrap()) } fn new(root: Arc<FooData>) -> std::result::Result<Self, &'static str> { diff --git a/tools/pdl/tests/generated/packet_decl_simple_big_endian.rs b/tools/pdl/tests/generated/packet_decl_simple_big_endian.rs index 821e0dfc20f3edb5f38f5daabab0e3489f853690..bdf253e1b5dd5f0f686a8d4d749b0b9c8f6973a3 100644 --- a/tools/pdl/tests/generated/packet_decl_simple_big_endian.rs +++ b/tools/pdl/tests/generated/packet_decl_simple_big_endian.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; @@ -58,40 +58,40 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 6 } - fn parse(bytes: &[u8]) -> Result<Self> { - if bytes.len() < 1 { + fn parse(mut bytes: &[u8]) -> Result<Self> { + if bytes.remaining() < 1 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), wanted: 1, - got: bytes.len(), + got: bytes.remaining(), }); } - let x = u8::from_be_bytes([bytes[0]]); - if bytes.len() < 3 { + let x = bytes.get_u8(); + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 3, - got: bytes.len(), + wanted: 2, + got: bytes.remaining(), }); } - let y = u16::from_be_bytes([bytes[1], bytes[2]]); - if bytes.len() < 6 { + let y = bytes.get_u16(); + if bytes.remaining() < 3 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 6, - got: bytes.len(), + wanted: 3, + got: bytes.remaining(), }); } - let z = u32::from_be_bytes([0, bytes[3], bytes[4], bytes[5]]); + let z = bytes.get_uint(3) as u32; Ok(Self { x, y, z }) } fn write_to(&self, buffer: &mut BytesMut) { let x = self.x; - buffer[0..1].copy_from_slice(&x.to_be_bytes()[0..1]); + buffer.put_u8(x); let y = self.y; - buffer[1..3].copy_from_slice(&y.to_be_bytes()[0..2]); + buffer.put_u16(y); let z = self.z; - buffer[3..6].copy_from_slice(&z.to_be_bytes()[0..3]); + buffer.put_uint(z as u64, 3); } fn get_total_size(&self) -> usize { self.get_size() @@ -103,8 +103,7 @@ impl FooData { impl Packet for FooPacket { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.foo.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.foo.get_total_size()); self.foo.write_to(&mut buffer); buffer.freeze() } @@ -124,7 +123,7 @@ impl From<FooPacket> for Vec<u8> { } impl FooPacket { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(FooData::parse(bytes)?)).unwrap()) } fn new(root: Arc<FooData>) -> std::result::Result<Self, &'static str> { diff --git a/tools/pdl/tests/generated/packet_decl_simple_little_endian.rs b/tools/pdl/tests/generated/packet_decl_simple_little_endian.rs index 23295f0c9238210a28fd1e7b3f46b5b1da57dc70..fb205555413e5d4ee548a8cca2fb5b45de8d96d7 100644 --- a/tools/pdl/tests/generated/packet_decl_simple_little_endian.rs +++ b/tools/pdl/tests/generated/packet_decl_simple_little_endian.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto}; @@ -58,40 +58,40 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 6 } - fn parse(bytes: &[u8]) -> Result<Self> { - if bytes.len() < 1 { + fn parse(mut bytes: &[u8]) -> Result<Self> { + if bytes.remaining() < 1 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), wanted: 1, - got: bytes.len(), + got: bytes.remaining(), }); } - let x = u8::from_le_bytes([bytes[0]]); - if bytes.len() < 3 { + let x = bytes.get_u8(); + if bytes.remaining() < 2 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 3, - got: bytes.len(), + wanted: 2, + got: bytes.remaining(), }); } - let y = u16::from_le_bytes([bytes[1], bytes[2]]); - if bytes.len() < 6 { + let y = bytes.get_u16_le(); + if bytes.remaining() < 3 { return Err(Error::InvalidLengthError { obj: "Foo".to_string(), - wanted: 6, - got: bytes.len(), + wanted: 3, + got: bytes.remaining(), }); } - let z = u32::from_le_bytes([bytes[3], bytes[4], bytes[5], 0]); + let z = bytes.get_uint_le(3) as u32; Ok(Self { x, y, z }) } fn write_to(&self, buffer: &mut BytesMut) { let x = self.x; - buffer[0..1].copy_from_slice(&x.to_le_bytes()[0..1]); + buffer.put_u8(x); let y = self.y; - buffer[1..3].copy_from_slice(&y.to_le_bytes()[0..2]); + buffer.put_u16_le(y); let z = self.z; - buffer[3..6].copy_from_slice(&z.to_le_bytes()[0..3]); + buffer.put_uint_le(z as u64, 3); } fn get_total_size(&self) -> usize { self.get_size() @@ -103,8 +103,7 @@ impl FooData { impl Packet for FooPacket { fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::new(); - buffer.resize(self.foo.get_total_size(), 0); + let mut buffer = BytesMut::with_capacity(self.foo.get_total_size()); self.foo.write_to(&mut buffer); buffer.freeze() } @@ -124,7 +123,7 @@ impl From<FooPacket> for Vec<u8> { } impl FooPacket { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(mut bytes: &[u8]) -> Result<Self> { Ok(Self::new(Arc::new(FooData::parse(bytes)?)).unwrap()) } fn new(root: Arc<FooData>) -> std::result::Result<Self, &'static str> { diff --git a/tools/pdl/tests/generated/preamble.rs b/tools/pdl/tests/generated/preamble.rs index a78ae55c502a25e647f6d367029015a2655c5c83..b59429241cd90b874e25590e46aa57dd978ce1f9 100644 --- a/tools/pdl/tests/generated/preamble.rs +++ b/tools/pdl/tests/generated/preamble.rs @@ -2,7 +2,7 @@ #![allow(warnings, missing_docs)] -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive}; use std::convert::{TryFrom, TryInto};