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(&quote_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(&quote_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(&quote_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};