pdl: Add support for reserved fields

Test: atest pdl_tests pdl_rust_generator_tests_{le,be}
Change-Id: Ie09c2fa09694f940e8584d56df3beb5019f91cf3
diff --git a/tools/pdl/Android.bp b/tools/pdl/Android.bp
index 8aff2f2..b31a322 100644
--- a/tools/pdl/Android.bp
+++ b/tools/pdl/Android.bp
@@ -70,6 +70,8 @@
         "tests/generated/packet_decl_mask_scalar_value_little_endian.rs",
         "tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs",
         "tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs",
+        "tests/generated/packet_decl_reserved_field_big_endian.rs",
+        "tests/generated/packet_decl_reserved_field_little_endian.rs",
         "tests/generated/packet_decl_simple_scalars_big_endian.rs",
         "tests/generated/packet_decl_simple_scalars_little_endian.rs",
         "tests/generated/preamble.rs",
diff --git a/tools/pdl/src/backends/rust.rs b/tools/pdl/src/backends/rust.rs
index 9b99ba3..9ed3746 100644
--- a/tools/pdl/src/backends/rust.rs
+++ b/tools/pdl/src/backends/rust.rs
@@ -71,10 +71,10 @@
     let id_data = format_ident!("{id}Data");
     let id_builder = format_ident!("{id}Builder");
 
+    let fields_with_ids = fields.iter().filter(|f| f.id().is_some()).collect::<Vec<_>>();
     let field_names =
-        fields.iter().map(|f| format_ident!("{}", f.id().unwrap())).collect::<Vec<_>>();
-    let field_types = fields.iter().map(types::rust_type).collect::<Vec<_>>();
-
+        fields_with_ids.iter().map(|f| format_ident!("{}", f.id().unwrap())).collect::<Vec<_>>();
+    let field_types = fields_with_ids.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>();
     let getter_names = field_names.iter().map(|id| format_ident!("get_{id}"));
 
     let packet_size =
@@ -410,4 +410,13 @@
           }
         "
     );
+
+    test_pdl!(
+        packet_decl_reserved_field,
+        "
+          packet Foo {
+            _reserved_: 40,
+          }
+        "
+    );
 }
diff --git a/tools/pdl/src/backends/rust/declarations.rs b/tools/pdl/src/backends/rust/declarations.rs
index c24721f..8120c51 100644
--- a/tools/pdl/src/backends/rust/declarations.rs
+++ b/tools/pdl/src/backends/rust/declarations.rs
@@ -27,6 +27,10 @@
                     #id: #field_type,
                 }
             }
+            ast::Field::Reserved { .. } => {
+                // Nothing to do here.
+                quote! {}
+            }
             _ => todo!(),
         });
     }
diff --git a/tools/pdl/src/backends/rust/parser.rs b/tools/pdl/src/backends/rust/parser.rs
index dbdb392..f9091c0 100644
--- a/tools/pdl/src/backends/rust/parser.rs
+++ b/tools/pdl/src/backends/rust/parser.rs
@@ -130,6 +130,10 @@
                         let #id = #type_id::#from_u(#v).unwrap();
                     }
                 }
+                ast::Field::Reserved { .. } => {
+                    // Nothing to do here.
+                    quote! {}
+                }
                 _ => todo!(),
             });
         }
diff --git a/tools/pdl/src/backends/rust/serializer.rs b/tools/pdl/src/backends/rust/serializer.rs
index d348765..5fd5fb1 100644
--- a/tools/pdl/src/backends/rust/serializer.rs
+++ b/tools/pdl/src/backends/rust/serializer.rs
@@ -77,6 +77,9 @@
                     shift: self.shift,
                 });
             }
+            ast::Field::Reserved { .. } => {
+                // Nothing to do here.
+            }
             _ => todo!(),
         }
 
@@ -110,7 +113,13 @@
             .collect::<Vec<_>>();
 
         match values.as_slice() {
-            [] => todo!(),
+            [] => {
+                let span = format_ident!("{}", self.span);
+                let count = syn::Index::from(self.shift / 8);
+                self.code.push(quote! {
+                    #span.put_bytes(0, #count);
+                });
+            }
             [value] => {
                 let put = types::put_uint(self.endianness, value, self.shift, self.span);
                 self.code.push(quote! {
diff --git a/tools/pdl/tests/generated/packet_decl_reserved_field_big_endian.rs b/tools/pdl/tests/generated/packet_decl_reserved_field_big_endian.rs
new file mode 100644
index 0000000..f8fd123
--- /dev/null
+++ b/tools/pdl/tests/generated/packet_decl_reserved_field_big_endian.rs
@@ -0,0 +1,108 @@
+// @generated rust packets from test
+
+#![allow(warnings, missing_docs)]
+
+use bytes::{Buf, BufMut, Bytes, BytesMut};
+use num_derive::{FromPrimitive, ToPrimitive};
+use num_traits::{FromPrimitive, ToPrimitive};
+use std::convert::{TryFrom, TryInto};
+use std::fmt;
+use std::sync::Arc;
+use thiserror::Error;
+
+type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Debug, Error)]
+pub enum Error {
+    #[error("Packet parsing failed")]
+    InvalidPacketError,
+    #[error("{field} was {value:x}, which is not known")]
+    ConstraintOutOfBounds { field: String, value: u64 },
+    #[error("when parsing {obj} needed length of {wanted} but got {got}")]
+    InvalidLengthError { obj: String, wanted: usize, got: usize },
+    #[error("Due to size restrictions a struct could not be parsed.")]
+    ImpossibleStructError,
+    #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
+    InvalidEnumValueError { obj: String, field: String, value: u64, type_: String },
+}
+
+#[derive(Debug, Error)]
+#[error("{0}")]
+pub struct TryFromError(&'static str);
+
+pub trait Packet {
+    fn to_bytes(self) -> Bytes;
+    fn to_vec(self) -> Vec<u8>;
+}
+
+#[derive(Debug)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+struct FooData {}
+#[derive(Debug, Clone)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct Foo {
+    #[cfg_attr(feature = "serde", serde(flatten))]
+    foo: Arc<FooData>,
+}
+#[derive(Debug)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct FooBuilder {}
+impl FooData {
+    fn conforms(bytes: &[u8]) -> bool {
+        bytes.len() >= 5
+    }
+    fn parse(mut bytes: &[u8]) -> Result<Self> {
+        if bytes.remaining() < 5 {
+            return Err(Error::InvalidLengthError {
+                obj: "Foo".to_string(),
+                wanted: 5,
+                got: bytes.remaining(),
+            });
+        }
+        Ok(Self {})
+    }
+    fn write_to(&self, buffer: &mut BytesMut) {
+        buffer.put_bytes(0, 5);
+    }
+    fn get_total_size(&self) -> usize {
+        self.get_size()
+    }
+    fn get_size(&self) -> usize {
+        5
+    }
+}
+impl Packet for Foo {
+    fn to_bytes(self) -> Bytes {
+        let mut buffer = BytesMut::with_capacity(self.foo.get_total_size());
+        self.foo.write_to(&mut buffer);
+        buffer.freeze()
+    }
+    fn to_vec(self) -> Vec<u8> {
+        self.to_bytes().to_vec()
+    }
+}
+impl From<Foo> for Bytes {
+    fn from(packet: Foo) -> Self {
+        packet.to_bytes()
+    }
+}
+impl From<Foo> for Vec<u8> {
+    fn from(packet: Foo) -> Self {
+        packet.to_vec()
+    }
+}
+impl Foo {
+    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> {
+        let foo = root;
+        Ok(Self { foo })
+    }
+}
+impl FooBuilder {
+    pub fn build(self) -> Foo {
+        let foo = Arc::new(FooData {});
+        Foo::new(foo).unwrap()
+    }
+}
diff --git a/tools/pdl/tests/generated/packet_decl_reserved_field_little_endian.rs b/tools/pdl/tests/generated/packet_decl_reserved_field_little_endian.rs
new file mode 100644
index 0000000..f8fd123
--- /dev/null
+++ b/tools/pdl/tests/generated/packet_decl_reserved_field_little_endian.rs
@@ -0,0 +1,108 @@
+// @generated rust packets from test
+
+#![allow(warnings, missing_docs)]
+
+use bytes::{Buf, BufMut, Bytes, BytesMut};
+use num_derive::{FromPrimitive, ToPrimitive};
+use num_traits::{FromPrimitive, ToPrimitive};
+use std::convert::{TryFrom, TryInto};
+use std::fmt;
+use std::sync::Arc;
+use thiserror::Error;
+
+type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Debug, Error)]
+pub enum Error {
+    #[error("Packet parsing failed")]
+    InvalidPacketError,
+    #[error("{field} was {value:x}, which is not known")]
+    ConstraintOutOfBounds { field: String, value: u64 },
+    #[error("when parsing {obj} needed length of {wanted} but got {got}")]
+    InvalidLengthError { obj: String, wanted: usize, got: usize },
+    #[error("Due to size restrictions a struct could not be parsed.")]
+    ImpossibleStructError,
+    #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
+    InvalidEnumValueError { obj: String, field: String, value: u64, type_: String },
+}
+
+#[derive(Debug, Error)]
+#[error("{0}")]
+pub struct TryFromError(&'static str);
+
+pub trait Packet {
+    fn to_bytes(self) -> Bytes;
+    fn to_vec(self) -> Vec<u8>;
+}
+
+#[derive(Debug)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+struct FooData {}
+#[derive(Debug, Clone)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct Foo {
+    #[cfg_attr(feature = "serde", serde(flatten))]
+    foo: Arc<FooData>,
+}
+#[derive(Debug)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+pub struct FooBuilder {}
+impl FooData {
+    fn conforms(bytes: &[u8]) -> bool {
+        bytes.len() >= 5
+    }
+    fn parse(mut bytes: &[u8]) -> Result<Self> {
+        if bytes.remaining() < 5 {
+            return Err(Error::InvalidLengthError {
+                obj: "Foo".to_string(),
+                wanted: 5,
+                got: bytes.remaining(),
+            });
+        }
+        Ok(Self {})
+    }
+    fn write_to(&self, buffer: &mut BytesMut) {
+        buffer.put_bytes(0, 5);
+    }
+    fn get_total_size(&self) -> usize {
+        self.get_size()
+    }
+    fn get_size(&self) -> usize {
+        5
+    }
+}
+impl Packet for Foo {
+    fn to_bytes(self) -> Bytes {
+        let mut buffer = BytesMut::with_capacity(self.foo.get_total_size());
+        self.foo.write_to(&mut buffer);
+        buffer.freeze()
+    }
+    fn to_vec(self) -> Vec<u8> {
+        self.to_bytes().to_vec()
+    }
+}
+impl From<Foo> for Bytes {
+    fn from(packet: Foo) -> Self {
+        packet.to_bytes()
+    }
+}
+impl From<Foo> for Vec<u8> {
+    fn from(packet: Foo) -> Self {
+        packet.to_vec()
+    }
+}
+impl Foo {
+    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> {
+        let foo = root;
+        Ok(Self { foo })
+    }
+}
+impl FooBuilder {
+    pub fn build(self) -> Foo {
+        let foo = Arc::new(FooData {});
+        Foo::new(foo).unwrap()
+    }
+}