Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cf5f94b authored by Martin Geisler's avatar Martin Geisler Committed by Cherrypicker Worker
Browse files

pdl: Add support for struct fields

The canonical tests now pass for packets using struct fields: we
support all combinations of scalars and enums in the structs.

The missing field types are padding, custom, and, checksum fields. For
arrays, we still lack support for size modifiers.

Bug: 230475725
Tag: #feature
Test: atest pdl_tests pdl_rust_generator_tests_{le,be}
(cherry picked from https://android-review.googlesource.com/q/commit:d23ff8ada360e3f57d02913f593642da5a07d0f6)
Merged-In: I92024364796b4c366cbf7460d146136b3763fe7e
Change-Id: I92024364796b4c366cbf7460d146136b3763fe7e
parent 34cdcc25
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -195,7 +195,8 @@ fn generate_packet_decl(
    let all_field_names =
        all_fields.iter().map(|f| format_ident!("{}", f.id().unwrap())).collect::<Vec<_>>();
    let all_field_types = all_fields.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>();
    let all_field_borrows = all_fields.iter().map(|f| types::rust_borrow(f)).collect::<Vec<_>>();
    let all_field_borrows =
        all_fields.iter().map(|f| types::rust_borrow(f, scope)).collect::<Vec<_>>();
    let all_field_getter_names = all_field_names.iter().map(|id| format_ident!("get_{id}"));
    let all_field_self_field = all_fields.iter().map(|f| {
        for (parent, parent_id) in parents.iter().zip(parent_lower_ids.iter()) {
+40 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ impl<'a> FieldParser<'a> {
                *size,
                field.declaration(self.scope),
            ),
            ast::FieldDesc::Typedef { id, type_id } => self.add_typedef_field(id, type_id),
            ast::FieldDesc::Payload { size_modifier, .. } => {
                self.add_payload_field(size_modifier.as_deref())
            }
@@ -404,6 +405,45 @@ impl<'a> FieldParser<'a> {
        }
    }

    /// Parse typedef fields.
    ///
    /// This is only for non-enum fields: enums are parsed via
    /// add_bit_field.
    fn add_typedef_field(&mut self, id: &str, type_id: &str) {
        assert_eq!(self.shift, 0, "Typedef field does not start on an octet boundary");

        let decl = self.scope.typedef[type_id];
        if let ast::DeclDesc::Struct { parent_id: Some(_), .. } = &decl.desc {
            panic!("Derived struct used in typedef field");
        }

        let span = self.span;
        let id = format_ident!("{id}");
        let type_id = format_ident!("{type_id}");

        match decl.width(self.scope, true) {
            None => self.code.push(quote! {
                let #id = #type_id::parse_inner(&mut #span)?;
            }),
            Some(width) => {
                assert_eq!(width % 8, 0, "Typedef field type size is not a multiple of 8");
                let width = syn::Index::from(width / 8);
                self.code.push(if let ast::DeclDesc::Checksum { .. } = &decl.desc {
                    // TODO: handle checksum fields.
                    quote! {
                        #span.get_mut().advance(#width);
                    }
                } else {
                    quote! {
                        let (head, tail) = #span.get().split_at(#width);
                        #span.replace(tail);
                        let #id = #type_id::parse(head)?;
                    }
                });
            }
        }
    }

    /// Parse body and payload fields.
    fn add_payload_field(&mut self, size_modifier: Option<&str>) {
        let span = self.span;
+17 −0
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ impl<'a> FieldSerializer<'a> {
            ast::FieldDesc::Array { id, width, .. } => {
                self.add_array_field(id, *width, field.declaration(self.scope))
            }
            ast::FieldDesc::Typedef { id, type_id } => {
                self.add_typedef_field(id, type_id);
            }
            ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. } => {
                self.add_payload_field()
            }
@@ -269,6 +272,20 @@ impl<'a> FieldSerializer<'a> {
        });
    }

    fn add_typedef_field(&mut self, id: &str, type_id: &str) {
        assert_eq!(self.shift, 0, "Typedef field does not start on an octet boundary");
        let decl = self.scope.typedef[type_id];
        if let ast::DeclDesc::Struct { parent_id: Some(_), .. } = &decl.desc {
            panic!("Derived struct used in typedef field");
        }

        let id = format_ident!("{id}");
        let span = format_ident!("{}", self.span);
        self.code.push(quote! {
            self.#id.write_to(#span);
        });
    }

    fn add_payload_field(&mut self) {
        if self.shift != 0 && self.endianness == ast::EndiannessValue::BigEndian {
            panic!("Payload field does not start on an octet boundary");
+8 −4
Original line number Diff line number Diff line
//! Utility functions for dealing with Rust integer types.

use crate::ast;
use crate::parser::ast as parser_ast;
use crate::{ast, lint};
use quote::{format_ident, quote};

/// A Rust integer type such as `u8`.
@@ -67,10 +67,14 @@ pub fn rust_type(field: &parser_ast::Field) -> proc_macro2::TokenStream {
    }
}

pub fn rust_borrow(field: &parser_ast::Field) -> proc_macro2::TokenStream {
pub fn rust_borrow(field: &parser_ast::Field, scope: &lint::Scope<'_>) -> proc_macro2::TokenStream {
    match &field.desc {
        // TODO: not all typedef fields are copy-types.
        ast::FieldDesc::Scalar { .. } | ast::FieldDesc::Typedef { .. } => quote!(),
        ast::FieldDesc::Scalar { .. } => quote!(),
        ast::FieldDesc::Typedef { type_id, .. } => match &scope.typedef[type_id].desc {
            ast::DeclDesc::Enum { .. } => quote!(),
            ast::DeclDesc::Struct { .. } => quote!(&),
            desc => unreachable!("unexpected declaration: {desc:?}"),
        },
        ast::FieldDesc::Array { .. } => quote!(&),
        _ => todo!(),
    }
+42 −0
Original line number Diff line number Diff line
@@ -174,8 +174,50 @@ fn main() {
            "Packet_Reserved_Field",
            "Packet_Scalar_Field",
            "Packet_Size_Field",
            "Packet_Struct_Field",
            "ScalarChild_A",
            "ScalarChild_B",
            "Struct_Count_Field",
            "Struct_Array_Field_ByteElement_ConstantSize",
            "Struct_Array_Field_ByteElement_UnknownSize",
            "Struct_Array_Field_ByteElement_UnknownSize",
            "Struct_Array_Field_ByteElement_VariableCount",
            "Struct_Array_Field_ByteElement_VariableCount",
            "Struct_Array_Field_ByteElement_VariableSize",
            "Struct_Array_Field_ByteElement_VariableSize",
            "Struct_Array_Field_EnumElement_ConstantSize",
            "Struct_Array_Field_EnumElement_UnknownSize",
            "Struct_Array_Field_EnumElement_UnknownSize",
            "Struct_Array_Field_EnumElement_VariableCount",
            "Struct_Array_Field_EnumElement_VariableCount",
            "Struct_Array_Field_EnumElement_VariableSize",
            "Struct_Array_Field_EnumElement_VariableSize",
            "Struct_Array_Field_ScalarElement_ConstantSize",
            "Struct_Array_Field_ScalarElement_UnknownSize",
            "Struct_Array_Field_ScalarElement_UnknownSize",
            "Struct_Array_Field_ScalarElement_VariableCount",
            "Struct_Array_Field_ScalarElement_VariableCount",
            "Struct_Array_Field_ScalarElement_VariableSize",
            "Struct_Array_Field_ScalarElement_VariableSize",
            "Struct_Array_Field_SizedElement_ConstantSize",
            "Struct_Array_Field_SizedElement_UnknownSize",
            "Struct_Array_Field_SizedElement_UnknownSize",
            "Struct_Array_Field_SizedElement_VariableCount",
            "Struct_Array_Field_SizedElement_VariableCount",
            "Struct_Array_Field_SizedElement_VariableSize",
            "Struct_Array_Field_SizedElement_VariableSize",
            "Struct_Array_Field_UnsizedElement_ConstantSize",
            "Struct_Array_Field_UnsizedElement_UnknownSize",
            "Struct_Array_Field_UnsizedElement_UnknownSize",
            "Struct_Array_Field_UnsizedElement_VariableCount",
            "Struct_Array_Field_UnsizedElement_VariableCount",
            "Struct_Array_Field_UnsizedElement_VariableSize",
            "Struct_Array_Field_UnsizedElement_VariableSize",
            "Struct_Enum_Field",
            "Struct_FixedEnum_Field",
            "Struct_FixedScalar_Field",
            "Struct_Size_Field",
            "Struct_Struct_Field",
        ],
        &module_name,
    );
Loading