| // Copyright 2025 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| //! Verifies that the MojomParse attribute is correctly derived. |
| //! |
| //! FOR_RELEASE: Rewrite the below comment to be clearer. |
| //! |
| //! Testing strategy: The existing tests for mojom bindings are end-to-end, |
| //! relying on mojom files to specify their inputs and outputs. However, we |
| //! want to unit-test the parser and deparser alone. Since they take ASTs as |
| //! input, we first validate that the bindings generate the correct ASTs, and |
| //! then we can use the bindings to generate various parser/deparser tests. |
| //! |
| //! The types in this file correspond to those defined in |
| //! //mojo/public/rust/test_mojom/parser_unittests.mojom |
| |
| chromium::import! { |
| "//mojo/public/rust/mojom_value_parser:mojom_value_parser_core"; |
| "//mojo/public/rust/mojom_value_parser:parser_unittests_rust"; |
| } |
| |
| use rust_gtest_interop::prelude::*; |
| |
| use mojom_value_parser_core::*; |
| use ordered_float::OrderedFloat; |
| use parser_unittests_rust::parser_unittests::*; |
| use std::collections::HashMap; |
| use std::sync::LazyLock; |
| |
| use crate::helpers::*; |
| |
| /// Represents a type defined in a Mojom file. |
| /// |
| /// Conceptually, it has three parts, corresponding to the three AST types: |
| /// 1. The type itself, as written in the Mojom file. |
| /// 2. The packed representation of the type. |
| /// 3. A constructor for creating values of that type. |
| /// |
| /// Unfortunately, the arguments to the constructor will vary based on the |
| /// MojomType it represents, so we can't write down a single type for the third |
| /// field. Instead, we must manually write a corresponding constructor for |
| /// every TestType, and track them by name. |
| struct TestType { |
| base_type: MojomType, |
| /// Human-readable type name for debugging output |
| type_name: &'static str, |
| /// Contents of a PackedStructuredType::Struct |
| packed_type: MojomWireType, |
| // Imagine there's a third `constructor` entry here. |
| } |
| |
| fn wrap_struct_fields_type(fields: Vec<(String, MojomType)>) -> MojomType { |
| let (field_names, fields) = fields.into_iter().unzip(); |
| MojomType::Struct { fields, field_names } |
| } |
| |
| fn wrap_struct_fields_value(fields: Vec<(String, MojomValue)>) -> MojomValue { |
| let (field_names, fields) = fields.into_iter().unzip(); |
| MojomValue::Struct(field_names, fields) |
| } |
| |
| fn wrap_packed_struct_fields( |
| fields: Vec<(String, StructuredBodyElementOwned)>, |
| num_elements_in_value: usize, |
| ) -> MojomWireType { |
| let (packed_field_names, packed_field_types) = fields.into_iter().unzip(); |
| MojomWireType::Pointer { |
| nested_data_type: PackedStructuredType::Struct { |
| packed_field_names, |
| packed_field_types, |
| num_elements_in_value, |
| }, |
| is_nullable: false, |
| } |
| } |
| |
| // Helper macros since otherwise the lines get too long |
| // and it's harder to read the test cases |
| macro_rules! bare_leaf { |
| ($leaf_ty:expr) => { |
| MojomWireType::Leaf { leaf_type: $leaf_ty, is_nullable: false } |
| }; |
| ($leaf_ty:expr, $nullable:expr) => { |
| MojomWireType::Leaf { leaf_type: $leaf_ty, is_nullable: $nullable } |
| }; |
| } |
| |
| macro_rules! struct_leaf { |
| ($ord:expr, $leaf_ty:expr) => { |
| StructuredBodyElement::SingleValue( |
| $ord, |
| MojomWireType::Leaf { leaf_type: $leaf_ty, is_nullable: false }, |
| ) |
| }; |
| ($ord:expr, $leaf_ty:expr, $nullable:expr) => { |
| StructuredBodyElement::SingleValue( |
| $ord, |
| MojomWireType::Leaf { leaf_type: $leaf_ty, is_nullable: $nullable }, |
| ) |
| }; |
| } |
| |
| impl TestType { |
| /// Return the packed version of this type as a struct field with the given |
| /// ordinal |
| fn as_struct_field(&self, ordinal: Ordinal) -> StructuredBodyElementOwned { |
| StructuredBodyElement::SingleValue(ordinal, self.packed_type.clone()) |
| } |
| |
| /// Return the packed version of this type as a union field |
| fn as_union_field(&self) -> MojomWireType { |
| match self.packed_type.clone() { |
| // Nested unions are represented as pointers |
| MojomWireType::Union { variants, is_nullable } => MojomWireType::Pointer { |
| nested_data_type: PackedStructuredType::Union { variants }, |
| is_nullable, |
| }, |
| // Everything else is represented as itself. |
| _ => self.packed_type.clone(), |
| } |
| } |
| |
| // These are separate functions mostly to avoid cluttering all the existing |
| // calls to as_struct_field with an extra, unused parameter |
| fn as_nullable_struct_field(&self, ordinal: Ordinal) -> StructuredBodyElementOwned { |
| StructuredBodyElement::SingleValue(ordinal, self.packed_type.clone().make_nullable()) |
| } |
| |
| fn as_nullable_union_field(&self) -> MojomWireType { |
| self.as_union_field().make_nullable() |
| } |
| |
| /// Given the rust type T corresponding to this TestType, validate that: |
| /// (1) T's associated MojomType and MojomWireType match ours, and |
| /// (2) The input value of type T can be converted to and from the input |
| /// MojomValue |
| fn validate_mojomparse<T: MojomParse + std::fmt::Debug + Clone + PartialEq>( |
| &self, |
| rust_val: T, |
| mojom_val: MojomValue, |
| ) { |
| // FOR RELEASE: These assertion macros seem to print a massive (and utterly |
| // useless) stack trace. See if we can turn that off. |
| expect_eq!( |
| T::mojom_type(), |
| self.base_type, |
| "Type {} had the wrong associated MojomType!", |
| self.type_name |
| ); |
| |
| expect_eq!( |
| *T::wire_type(), |
| self.packed_type, |
| "Type {} failed to pack correctly!", |
| self.type_name |
| ); |
| |
| // Test conversion to/from MojomValues |
| expect_eq!(&mojom_val, &rust_val.clone().into()); |
| expect_eq!(rust_val, mojom_val.try_into().unwrap()); |
| } |
| |
| /// Similar to `validate_mojomparse`, but for types which contain handles. |
| /// Since no two different handle values will ever be equal, it uses a |
| /// special comparison operator that ignores handles. |
| fn validate_mojomparse_handles<T: MojomParse + std::fmt::Debug + PartialEq>( |
| &self, |
| rust_val: T, |
| get_mojom_val: impl Fn() -> MojomValue, |
| ) { |
| expect_eq!( |
| T::mojom_type(), |
| self.base_type, |
| "Type {} had the wrong associated MojomType!", |
| self.type_name |
| ); |
| |
| expect_eq!( |
| *T::wire_type(), |
| self.packed_type, |
| "Type {} failed to pack correctly!", |
| self.type_name |
| ); |
| |
| expect_true!(equivalent_value(&get_mojom_val(), &rust_val.into())); |
| // Unfortunately, we don't have `equivalent_value` for rust types. |
| // We could write a bunch of them if we _really_ wanted to, but for now |
| // we satisfy ourselves by checking round-trip conversions. |
| expect_true!(equivalent_value( |
| &get_mojom_val(), |
| // The function we really want to test here is T::try_from |
| &T::try_from(get_mojom_val()).unwrap().into() |
| )); |
| } |
| } |
| |
| // We'll be creating all our test types at global scope, so we can reference |
| // them from various testing functions. |
| |
| // Mojom Definition: |
| // struct Empty {}; |
| static EMPTY_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "Empty", |
| base_type: wrap_struct_fields_type(vec![]), |
| packed_type: wrap_packed_struct_fields(vec![], 0), |
| }); |
| |
| fn empty_mojom() -> MojomValue { |
| wrap_struct_fields_value(vec![]) |
| } |
| |
| // Mojom Definition: |
| // struct FourInts { |
| // int8 a; |
| // int16 b; |
| // int32 c; |
| // int64 d; |
| // }; |
| static FOUR_INTS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "FourInts", |
| base_type: wrap_struct_fields_type(vec![ |
| ("a".to_string(), MojomType::Int8), |
| ("b".to_string(), MojomType::Int16), |
| ("c".to_string(), MojomType::Int32), |
| ("d".to_string(), MojomType::Int64), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("a".to_string(), struct_leaf!(0, PackedLeafType::Int8)), |
| ("b".to_string(), struct_leaf!(1, PackedLeafType::Int16)), |
| ("c".to_string(), struct_leaf!(2, PackedLeafType::Int32)), |
| ("d".to_string(), struct_leaf!(3, PackedLeafType::Int64)), |
| ], |
| 4, |
| ), |
| }); |
| |
| fn four_ints_mojom(a: i8, b: i16, c: i32, d: i64) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("a".to_string(), MojomValue::Int8(a)), |
| ("b".to_string(), MojomValue::Int16(b)), |
| ("c".to_string(), MojomValue::Int32(c)), |
| ("d".to_string(), MojomValue::Int64(d)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // struct FourIntsReversed { |
| // int64 d; |
| // int32 c; |
| // int16 b; |
| // int8 a; |
| // }; |
| static FOUR_INTS_REVERSED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "FourIntsReversed", |
| base_type: wrap_struct_fields_type(vec![ |
| ("d".to_string(), MojomType::Int64), |
| ("c".to_string(), MojomType::Int32), |
| ("b".to_string(), MojomType::Int16), |
| ("a".to_string(), MojomType::Int8), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("d".to_string(), struct_leaf!(0, PackedLeafType::Int64)), |
| ("c".to_string(), struct_leaf!(1, PackedLeafType::Int32)), |
| ("b".to_string(), struct_leaf!(2, PackedLeafType::Int16)), |
| ("a".to_string(), struct_leaf!(3, PackedLeafType::Int8)), |
| ], |
| 4, |
| ), |
| }); |
| |
| fn four_ints_reversed_mojom(a: i8, b: i16, c: i32, d: i64) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("d".to_string(), MojomValue::Int64(d)), |
| ("c".to_string(), MojomValue::Int32(c)), |
| ("b".to_string(), MojomValue::Int16(b)), |
| ("a".to_string(), MojomValue::Int8(a)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // struct FourIntsIntermixed { |
| // int8 a; |
| // int32 b; |
| // int16 c; |
| // int8 d; |
| // }; |
| static FOUR_INTS_INTERMIXED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "FourIntsIntermixed", |
| base_type: wrap_struct_fields_type(vec![ |
| ("a".to_string(), MojomType::Int8), |
| ("b".to_string(), MojomType::Int32), |
| ("c".to_string(), MojomType::Int16), |
| ("d".to_string(), MojomType::Int8), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("a".to_string(), struct_leaf!(0, PackedLeafType::Int8)), |
| ("d".to_string(), struct_leaf!(3, PackedLeafType::Int8)), |
| ("c".to_string(), struct_leaf!(2, PackedLeafType::Int16)), |
| ("b".to_string(), struct_leaf!(1, PackedLeafType::Int32)), |
| ], |
| 4, |
| ), |
| }); |
| |
| fn four_ints_intermixed_mojom(a: i8, b: i32, c: i16, d: i8) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("a".to_string(), MojomValue::Int8(a)), |
| ("b".to_string(), MojomValue::Int32(b)), |
| ("c".to_string(), MojomValue::Int16(c)), |
| ("d".to_string(), MojomValue::Int8(d)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // struct OnceNested { |
| // FourInts f1; |
| // uint32 a; |
| // int8 b; |
| // FourIntsReversed f2; |
| // FourIntsIntermixed f3; |
| // uint16 c; |
| // }; |
| static ONCE_NESTED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "OnceNested", |
| base_type: wrap_struct_fields_type(vec![ |
| ("f1".to_string(), FOUR_INTS_TY.base_type.clone()), |
| ("a".to_string(), MojomType::UInt32), |
| ("b".to_string(), MojomType::Int8), |
| ("f2".to_string(), FOUR_INTS_REVERSED_TY.base_type.clone()), |
| ("f3".to_string(), FOUR_INTS_INTERMIXED_TY.base_type.clone()), |
| ("c".to_string(), MojomType::UInt16), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("f1".to_string(), FOUR_INTS_TY.as_struct_field(0)), |
| ("a".to_string(), struct_leaf!(1, PackedLeafType::UInt32)), |
| ("b".to_string(), struct_leaf!(2, PackedLeafType::Int8)), |
| ("c".to_string(), struct_leaf!(5, PackedLeafType::UInt16)), |
| ("f2".to_string(), FOUR_INTS_REVERSED_TY.as_struct_field(3)), |
| ("f3".to_string(), FOUR_INTS_INTERMIXED_TY.as_struct_field(4)), |
| ], |
| 6, |
| ), |
| }); |
| |
| fn once_nested_mojom( |
| f1: MojomValue, |
| a: u32, |
| b: i8, |
| f2: MojomValue, |
| f3: MojomValue, |
| c: u16, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("f1".to_string(), f1), |
| ("a".to_string(), MojomValue::UInt32(a)), |
| ("b".to_string(), MojomValue::Int8(b)), |
| ("f2".to_string(), f2), |
| ("f3".to_string(), f3), |
| ("c".to_string(), MojomValue::UInt16(c)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // struct TwiceNested { |
| // OnceNested o; |
| // int16 a; |
| // FourInts f; |
| // }; |
| static TWICE_NESTED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "TwiceNested", |
| base_type: wrap_struct_fields_type(vec![ |
| ("o".to_string(), ONCE_NESTED_TY.base_type.clone()), |
| ("a".to_string(), MojomType::Int16), |
| ("f".to_string(), FOUR_INTS_TY.base_type.clone()), |
| ("b".to_string(), MojomType::Int32), |
| ("c".to_string(), MojomType::Int32), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("o".to_string(), ONCE_NESTED_TY.as_struct_field(0)), |
| ("a".to_string(), struct_leaf!(1, PackedLeafType::Int16)), |
| ("b".to_string(), struct_leaf!(3, PackedLeafType::Int32)), |
| ("f".to_string(), FOUR_INTS_TY.as_struct_field(2)), |
| ("c".to_string(), struct_leaf!(4, PackedLeafType::Int32)), |
| ], |
| 5, |
| ), |
| }); |
| |
| fn twice_nested_mojom(o: MojomValue, a: i16, f: MojomValue, b: i32, c: i32) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("o".to_string(), o), |
| ("a".to_string(), MojomValue::Int16(a)), |
| ("f".to_string(), f), |
| ("b".to_string(), MojomValue::Int32(b)), |
| ("c".to_string(), MojomValue::Int32(c)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // struct TenBoolsAndAByte { |
| // bool b0; ... bool b4; |
| // uint8 n1; |
| // bool b5; ... bool b9; |
| // }; |
| static TEN_BOOLS_AND_A_BYTE_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "TenBoolsAndAByte", |
| base_type: wrap_struct_fields_type(vec![ |
| ("b0".to_string(), MojomType::Bool), |
| ("b1".to_string(), MojomType::Bool), |
| ("b2".to_string(), MojomType::Bool), |
| ("b3".to_string(), MojomType::Bool), |
| ("b4".to_string(), MojomType::Bool), |
| ("n1".to_string(), MojomType::UInt8), |
| ("b5".to_string(), MojomType::Bool), |
| ("b6".to_string(), MojomType::Bool), |
| ("b7".to_string(), MojomType::Bool), |
| ("b8".to_string(), MojomType::Bool), |
| ("b9".to_string(), MojomType::Bool), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ( |
| "b0".to_string(), |
| StructuredBodyElement::Bitfield([ |
| Some((0, false)), |
| Some((1, false)), |
| Some((2, false)), |
| Some((3, false)), |
| Some((4, false)), |
| Some((6, false)), |
| Some((7, false)), |
| Some((8, false)), |
| ]), |
| ), |
| ("n1".to_string(), struct_leaf!(5, PackedLeafType::UInt8)), |
| ( |
| "b8".to_string(), |
| StructuredBodyElement::Bitfield([ |
| Some((9, false)), |
| Some((10, false)), |
| None, |
| None, |
| None, |
| None, |
| None, |
| None, |
| ]), |
| ), |
| ], |
| 11, |
| ), |
| }); |
| |
| #[allow(clippy::too_many_arguments)] |
| fn ten_bools_and_a_byte_mojom( |
| b0: bool, |
| b1: bool, |
| b2: bool, |
| b3: bool, |
| b4: bool, |
| n1: u8, |
| b5: bool, |
| b6: bool, |
| b7: bool, |
| b8: bool, |
| b9: bool, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("b0".to_string(), MojomValue::Bool(b0)), |
| ("b1".to_string(), MojomValue::Bool(b1)), |
| ("b2".to_string(), MojomValue::Bool(b2)), |
| ("b3".to_string(), MojomValue::Bool(b3)), |
| ("b4".to_string(), MojomValue::Bool(b4)), |
| ("n1".to_string(), MojomValue::UInt8(n1)), |
| ("b5".to_string(), MojomValue::Bool(b5)), |
| ("b6".to_string(), MojomValue::Bool(b6)), |
| ("b7".to_string(), MojomValue::Bool(b7)), |
| ("b8".to_string(), MojomValue::Bool(b8)), |
| ("b9".to_string(), MojomValue::Bool(b9)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // struct TenBoolsAndTwoBytes { |
| // bool b0; ... bool b4; |
| // uint16 n1; |
| // bool b5; ... bool b9; |
| // }; |
| static TEN_BOOLS_AND_TWO_BYTES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "TenBoolsAndTwoBytes", |
| base_type: wrap_struct_fields_type(vec![ |
| ("b0".to_string(), MojomType::Bool), |
| ("b1".to_string(), MojomType::Bool), |
| ("b2".to_string(), MojomType::Bool), |
| ("b3".to_string(), MojomType::Bool), |
| ("b4".to_string(), MojomType::Bool), |
| ("n1".to_string(), MojomType::UInt16), |
| ("b5".to_string(), MojomType::Bool), |
| ("b6".to_string(), MojomType::Bool), |
| ("b7".to_string(), MojomType::Bool), |
| ("b8".to_string(), MojomType::Bool), |
| ("b9".to_string(), MojomType::Bool), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ( |
| "b0".to_string(), |
| StructuredBodyElement::Bitfield([ |
| Some((0, false)), |
| Some((1, false)), |
| Some((2, false)), |
| Some((3, false)), |
| Some((4, false)), |
| Some((6, false)), |
| Some((7, false)), |
| Some((8, false)), |
| ]), |
| ), |
| ( |
| "b8".to_string(), |
| StructuredBodyElement::Bitfield([ |
| Some((9, false)), |
| Some((10, false)), |
| None, |
| None, |
| None, |
| None, |
| None, |
| None, |
| ]), |
| ), |
| ("n1".to_string(), struct_leaf!(5, PackedLeafType::UInt16)), |
| ], |
| 11, |
| ), |
| }); |
| |
| #[allow(clippy::too_many_arguments)] |
| fn ten_bools_and_two_bytes_mojom( |
| b0: bool, |
| b1: bool, |
| b2: bool, |
| b3: bool, |
| b4: bool, |
| n1: u16, |
| b5: bool, |
| b6: bool, |
| b7: bool, |
| b8: bool, |
| b9: bool, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("b0".to_string(), MojomValue::Bool(b0)), |
| ("b1".to_string(), MojomValue::Bool(b1)), |
| ("b2".to_string(), MojomValue::Bool(b2)), |
| ("b3".to_string(), MojomValue::Bool(b3)), |
| ("b4".to_string(), MojomValue::Bool(b4)), |
| ("n1".to_string(), MojomValue::UInt16(n1)), |
| ("b5".to_string(), MojomValue::Bool(b5)), |
| ("b6".to_string(), MojomValue::Bool(b6)), |
| ("b7".to_string(), MojomValue::Bool(b7)), |
| ("b8".to_string(), MojomValue::Bool(b8)), |
| ("b9".to_string(), MojomValue::Bool(b9)), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestMojomParseDerive)] |
| /// Tests that the MojomParse trait is correctly |
| /// derived for each of the types in the mojom file. |
| fn test_mojomparse() { |
| FOUR_INTS_TY.validate_mojomparse( |
| FourInts { a: 10, b: -20, c: 400, d: -8000 }, |
| four_ints_mojom(10, -20, 400, -8000), |
| ); |
| |
| EMPTY_TY.validate_mojomparse(Empty {}, empty_mojom()); |
| |
| FOUR_INTS_REVERSED_TY.validate_mojomparse( |
| FourIntsReversed { a: 10, b: -20, c: 400, d: -8000 }, |
| four_ints_reversed_mojom(10, -20, 400, -8000), |
| ); |
| |
| FOUR_INTS_INTERMIXED_TY.validate_mojomparse( |
| FourIntsIntermixed { a: 10, b: 400, c: -20, d: -5 }, |
| four_ints_intermixed_mojom(10, 400, -20, -5), |
| ); |
| |
| let once_nested_val = OnceNested { |
| f1: FourInts { a: 1, b: 2, c: 3, d: 4 }, |
| a: 13, |
| b: 14, |
| f2: FourIntsReversed { a: 5, b: 6, c: 7, d: 8 }, |
| f3: FourIntsIntermixed { a: 9, b: 10, c: 11, d: 12 }, |
| c: 15, |
| }; |
| let once_nested_mojom_val = || { |
| once_nested_mojom( |
| four_ints_mojom(1, 2, 3, 4), |
| 13, |
| 14, |
| four_ints_reversed_mojom(5, 6, 7, 8), |
| four_ints_intermixed_mojom(9, 10, 11, 12), |
| 15, |
| ) |
| }; |
| ONCE_NESTED_TY.validate_mojomparse(once_nested_val.clone(), once_nested_mojom_val()); |
| |
| TWICE_NESTED_TY.validate_mojomparse( |
| TwiceNested { |
| o: once_nested_val, |
| a: 16, |
| f: FourInts { a: 17, b: 18, c: 19, d: 20 }, |
| b: 21, |
| c: 22, |
| }, |
| twice_nested_mojom(once_nested_mojom_val(), 16, four_ints_mojom(17, 18, 19, 20), 21, 22), |
| ); |
| |
| TEN_BOOLS_AND_A_BYTE_TY.validate_mojomparse( |
| TenBoolsAndAByte { |
| b0: true, |
| b1: false, |
| b2: true, |
| b3: false, |
| b4: true, |
| n1: 200, |
| b5: false, |
| b6: true, |
| b7: false, |
| b8: true, |
| b9: false, |
| }, |
| ten_bools_and_a_byte_mojom( |
| true, false, true, false, true, 200, false, true, false, true, false, |
| ), |
| ); |
| TEN_BOOLS_AND_TWO_BYTES_TY.validate_mojomparse( |
| TenBoolsAndTwoBytes { |
| b0: true, |
| b1: false, |
| b2: true, |
| b3: false, |
| b4: true, |
| n1: 50000, |
| b5: false, |
| b6: true, |
| b7: false, |
| b8: true, |
| b9: false, |
| }, |
| ten_bools_and_two_bytes_mojom( |
| true, false, true, false, true, 50000, false, true, false, true, false, |
| ), |
| ); |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestBadConversion)] |
| /// Test that we can't convert between incompatible types |
| fn test_bad_conversion() { |
| let empty = empty_mojom(); |
| |
| let four_ints = four_ints_mojom(10, -20, 400, -8000); |
| |
| let four_ints_reversed = four_ints_reversed_mojom(10, -20, 400, -8000); |
| |
| let four_ints_intermixed = four_ints_intermixed_mojom(10, 400, -20, -5); |
| |
| let once_nested = || { |
| once_nested_mojom( |
| four_ints_mojom(1, 2, 3, 4), |
| 13, |
| 14, |
| four_ints_reversed_mojom(5, 6, 7, 8), |
| four_ints_intermixed_mojom(9, 10, 11, 12), |
| 15, |
| ) |
| }; |
| |
| let twice_nested = |
| twice_nested_mojom(once_nested(), 16, four_ints_mojom(17, 18, 19, 20), 21, 22); |
| |
| let ten_bools_byte = || { |
| ten_bools_and_a_byte_mojom( |
| true, false, true, false, true, 200, false, true, false, true, false, |
| ) |
| }; |
| let ten_bools_bytes = ten_bools_and_two_bytes_mojom( |
| true, false, true, false, true, 50000, false, true, false, true, false, |
| ); |
| |
| // There are far too many bad paths to test them all, so this is just an |
| // arbitrary scattershot approach so we have _some_ coverage. |
| // TODO(crbug.com/456214728) Replace with matchers from the googletest crate |
| // if we switch to it. |
| expect_true!(FourInts::try_from(four_ints_reversed).is_err()); |
| expect_true!(FourInts::try_from(once_nested()).is_err()); |
| expect_true!(FourInts::try_from(empty).is_err()); |
| |
| expect_true!(TenBoolsAndAByte::try_from(ten_bools_bytes).is_err()); |
| expect_true!(TenBoolsAndAByte::try_from(four_ints_intermixed).is_err()); |
| |
| expect_true!(OnceNested::try_from(twice_nested).is_err()); |
| expect_true!(OnceNested::try_from(ten_bools_byte()).is_err()); |
| |
| expect_true!(Empty::try_from(ten_bools_byte()).is_err()); |
| expect_true!(Empty::try_from(four_ints).is_err()); |
| } |
| |
| // Mojom Definition: |
| // struct SomeEnums { |
| // TestEnum e1; |
| // uint16 n1; |
| // TestEnum2 e2; |
| // } |
| const TEST_ENUM_PRED: Predicate<i32> = |
| Predicate::new::<TestEnum>(&(TestEnum::is_valid as fn(i32) -> bool)); |
| const TEST_ENUM2_PRED: Predicate<i32> = |
| Predicate::new::<TestEnum2>(&(TestEnum2::is_valid as fn(i32) -> bool)); |
| |
| static SOME_ENUMS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "SomeEnums", |
| base_type: wrap_struct_fields_type(vec![ |
| ("e1".to_string(), MojomType::Enum { is_valid: TEST_ENUM_PRED }), |
| ("n1".to_string(), MojomType::UInt64), |
| ("e2".to_string(), MojomType::Enum { is_valid: TEST_ENUM2_PRED }), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("e1".to_string(), struct_leaf!(0, PackedLeafType::Enum { is_valid: TEST_ENUM_PRED })), |
| ("e2".to_string(), struct_leaf!(2, PackedLeafType::Enum { is_valid: TEST_ENUM2_PRED })), |
| ("n1".to_string(), struct_leaf!(1, PackedLeafType::UInt64)), |
| ], |
| 3, |
| ), |
| }); |
| |
| fn some_enums_mojom(e1: i32, n1: u64, e2: i32) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("e1".to_string(), MojomValue::Enum(e1)), |
| ("n1".to_string(), MojomValue::UInt64(n1)), |
| ("e2".to_string(), MojomValue::Enum(e2)), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestEnums)] |
| fn test_enums() { |
| SOME_ENUMS_TY.validate_mojomparse( |
| SomeEnums { e1: TestEnum::Four, n1: 42, e2: TestEnum2::Eleven }, |
| some_enums_mojom(4, 42, 11), |
| ); |
| SOME_ENUMS_TY.validate_mojomparse( |
| SomeEnums { e1: TestEnum::Zero, n1: 0, e2: TestEnum2::Twelve }, |
| some_enums_mojom(0, 0, 12), |
| ); |
| SOME_ENUMS_TY.validate_mojomparse( |
| SomeEnums { e1: TestEnum::Three, n1: 3, e2: TestEnum2::Four }, |
| some_enums_mojom(3, 3, 4), |
| ); |
| SOME_ENUMS_TY.validate_mojomparse( |
| SomeEnums { e1: TestEnum::Seven, n1: 7, e2: TestEnum2::FourtyTwo }, |
| some_enums_mojom(7, 7, 42), |
| ); |
| |
| expect_true!(TestEnum::try_from(8).is_err()); |
| expect_true!(TestEnum::try_from(11).is_err()); |
| expect_true!(TestEnum2::try_from(0).is_err()); |
| expect_true!(TestEnum2::try_from(99).is_err()); |
| |
| expect_true!(TestEnumWithNegativeDiscriminants::is_valid(-1)); |
| expect_true!(TestEnumWithNegativeDiscriminants::is_valid(0)); |
| expect_true!(TestEnumWithNegativeDiscriminants::is_valid(1)); |
| expect_true!(!TestEnumWithNegativeDiscriminants::is_valid(2)); |
| expect_true!(!TestEnumWithNegativeDiscriminants::is_valid(-2)); |
| |
| expect_eq!( |
| TestEnumWithNegativeDiscriminants::try_from(-1).unwrap(), |
| TestEnumWithNegativeDiscriminants::NegVal |
| ); |
| expect_eq!( |
| TestEnumWithNegativeDiscriminants::try_from(0).unwrap(), |
| TestEnumWithNegativeDiscriminants::ZeroVal |
| ); |
| expect_eq!( |
| TestEnumWithNegativeDiscriminants::try_from(1).unwrap(), |
| TestEnumWithNegativeDiscriminants::PosVal |
| ); |
| } |
| |
| // Mojom Definition: |
| // union BaseUnion { |
| // int8 n1; |
| // uint64 u1; |
| // TestEnum e1; |
| // bool b1; |
| // bool b2; |
| // Empty em1; |
| // FourInts f1; |
| // } |
| static BASE_UNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "BaseUnion", |
| base_type: MojomType::Union { |
| variants: [ |
| (0, MojomType::Int8), |
| (1, MojomType::UInt64), |
| (2, MojomType::Enum { is_valid: TEST_ENUM_PRED }), |
| (3, MojomType::Bool), |
| (4, MojomType::Bool), |
| (5, EMPTY_TY.base_type.clone()), |
| (6, FOUR_INTS_TY.base_type.clone()), |
| (7, MojomType::Float32), |
| ] |
| .into(), |
| }, |
| packed_type: MojomWireType::Union { |
| variants: [ |
| (0, bare_leaf!(PackedLeafType::Int8)), |
| (1, bare_leaf!(PackedLeafType::UInt64)), |
| (2, bare_leaf!(PackedLeafType::Enum { is_valid: TEST_ENUM_PRED })), |
| (3, bare_leaf!(PackedLeafType::Bool)), |
| (4, bare_leaf!(PackedLeafType::Bool)), |
| (5, EMPTY_TY.as_union_field()), |
| (6, FOUR_INTS_TY.as_union_field()), |
| (7, bare_leaf!(PackedLeafType::Float32)), |
| ] |
| .into(), |
| is_nullable: false, |
| }, |
| }); |
| |
| fn base_union_mojom_n1(n1: i8) -> MojomValue { |
| MojomValue::Union(0, Box::new(MojomValue::Int8(n1))) |
| } |
| |
| fn base_union_mojom_u1(u1: u64) -> MojomValue { |
| MojomValue::Union(1, Box::new(MojomValue::UInt64(u1))) |
| } |
| |
| fn base_union_mojom_e1(e1: i32) -> MojomValue { |
| MojomValue::Union(2, Box::new(MojomValue::Enum(e1))) |
| } |
| |
| fn base_union_mojom_b1(b1: bool) -> MojomValue { |
| MojomValue::Union(3, Box::new(MojomValue::Bool(b1))) |
| } |
| |
| fn base_union_mojom_b2(b2: bool) -> MojomValue { |
| MojomValue::Union(4, Box::new(MojomValue::Bool(b2))) |
| } |
| |
| fn base_union_mojom_em1(em1: MojomValue) -> MojomValue { |
| MojomValue::Union(5, Box::new(em1)) |
| } |
| |
| fn base_union_mojom_f1(f1: MojomValue) -> MojomValue { |
| MojomValue::Union(6, Box::new(f1)) |
| } |
| |
| fn base_union_mojom_fl(fl: f32) -> MojomValue { |
| MojomValue::Union(7, Box::new(MojomValue::Float32(fl.into()))) |
| } |
| |
| // Mojom Definition: |
| // union NestedUnion { |
| // int32 n; |
| // BaseUnion u; |
| // } |
| static NESTED_UNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "NestedUnion", |
| base_type: MojomType::Union { |
| variants: [(0, MojomType::Int32), (1, BASE_UNION_TY.base_type.clone())].into(), |
| }, |
| packed_type: MojomWireType::Union { |
| variants: [(0, bare_leaf!(PackedLeafType::Int32)), (1, BASE_UNION_TY.as_union_field())] |
| .into(), |
| is_nullable: false, |
| }, |
| }); |
| |
| fn nested_union_mojom_n(n: i32) -> MojomValue { |
| MojomValue::Union(0, Box::new(MojomValue::Int32(n))) |
| } |
| |
| fn nested_union_mojom_u(u: MojomValue) -> MojomValue { |
| MojomValue::Union(1, Box::new(u)) |
| } |
| |
| // Mojom Definition: |
| // struct WithNestedUnion { |
| // int64 n1; |
| // NestedUnion u; |
| // int32 n2; |
| // } |
| static WITH_NESTED_UNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "WithNestedUnion", |
| base_type: wrap_struct_fields_type(vec![ |
| ("n1".to_string(), MojomType::Int64), |
| ("u".to_string(), NESTED_UNION_TY.base_type.clone()), |
| ("n2".to_string(), MojomType::Int32), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("n1".to_string(), struct_leaf!(0, PackedLeafType::Int64)), |
| ("u".to_string(), NESTED_UNION_TY.as_struct_field(1)), |
| ("n2".to_string(), struct_leaf!(2, PackedLeafType::Int32)), |
| ], |
| 3, |
| ), |
| }); |
| |
| fn with_nested_union_mojom(n1: i64, u: MojomValue, n2: i32) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("n1".to_string(), MojomValue::Int64(n1)), |
| ("u".to_string(), u), |
| ("n2".to_string(), MojomValue::Int32(n2)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // union NestederUnion { |
| // bool b; |
| // int8 n; |
| // NestedUnion u; |
| // WithNestedUnion w; |
| // }; |
| static NESTEDER_UNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "NestederUnion", |
| base_type: MojomType::Union { |
| variants: [ |
| (0, MojomType::Bool), |
| (1, MojomType::Int8), |
| (2, NESTED_UNION_TY.base_type.clone()), |
| (3, WITH_NESTED_UNION_TY.base_type.clone()), |
| ] |
| .into(), |
| }, |
| packed_type: MojomWireType::Union { |
| variants: [ |
| (0, bare_leaf!(PackedLeafType::Bool)), |
| (1, bare_leaf!(PackedLeafType::Int8)), |
| (2, NESTED_UNION_TY.as_union_field()), |
| (3, WITH_NESTED_UNION_TY.as_union_field()), |
| ] |
| .into(), |
| is_nullable: false, |
| }, |
| }); |
| |
| fn nesteder_union_mojom_b(b: bool) -> MojomValue { |
| MojomValue::Union(0, Box::new(MojomValue::Bool(b))) |
| } |
| |
| fn nesteder_union_mojom_n(n: i8) -> MojomValue { |
| MojomValue::Union(1, Box::new(MojomValue::Int8(n))) |
| } |
| |
| fn nesteder_union_mojom_u(u: MojomValue) -> MojomValue { |
| MojomValue::Union(2, Box::new(u)) |
| } |
| |
| fn nesteder_union_mojom_w(w: MojomValue) -> MojomValue { |
| MojomValue::Union(3, Box::new(w)) |
| } |
| |
| // Mojom Definition: |
| // struct WithManyUnions { |
| // NestedUnion u1; |
| // int8 i1; |
| // NestederUnion u2; |
| // double d1; |
| // BaseUnion u3; |
| // NestederUnion u4; |
| // int32 i2; |
| // int32 i3; |
| // }; |
| static WITH_MANY_UNIONS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "WithManyUnions", |
| base_type: wrap_struct_fields_type(vec![ |
| ("u1".to_string(), NESTED_UNION_TY.base_type.clone()), |
| ("i1".to_string(), MojomType::Int8), |
| ("u2".to_string(), NESTEDER_UNION_TY.base_type.clone()), |
| ("d1".to_string(), MojomType::Float64), |
| ("u3".to_string(), BASE_UNION_TY.base_type.clone()), |
| ("u4".to_string(), NESTEDER_UNION_TY.base_type.clone()), |
| ("i2".to_string(), MojomType::Int32), |
| ("i3".to_string(), MojomType::Int32), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("u1".to_string(), NESTED_UNION_TY.as_struct_field(0)), |
| ("i1".to_string(), struct_leaf!(1, PackedLeafType::Int8)), |
| ("i2".to_string(), struct_leaf!(6, PackedLeafType::Int32)), |
| ("u2".to_string(), NESTEDER_UNION_TY.as_struct_field(2)), |
| ("d1".to_string(), struct_leaf!(3, PackedLeafType::Float64)), |
| ("u3".to_string(), BASE_UNION_TY.as_struct_field(4)), |
| ("u4".to_string(), NESTEDER_UNION_TY.as_struct_field(5)), |
| ("i3".to_string(), struct_leaf!(7, PackedLeafType::Int32)), |
| ], |
| 8, |
| ), |
| }); |
| |
| #[allow(clippy::too_many_arguments)] |
| fn with_many_unions_mojom( |
| u1: MojomValue, |
| i1: i8, |
| u2: MojomValue, |
| d1: f64, |
| u3: MojomValue, |
| u4: MojomValue, |
| i2: i32, |
| i3: i32, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("u1".to_string(), u1), |
| ("i1".to_string(), MojomValue::Int8(i1)), |
| ("u2".to_string(), u2), |
| ("d1".to_string(), MojomValue::Float64(d1.into())), |
| ("u3".to_string(), u3), |
| ("u4".to_string(), u4), |
| ("i2".to_string(), MojomValue::Int32(i2)), |
| ("i3".to_string(), MojomValue::Int32(i3)), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestUnions)] |
| fn test_unions() { |
| BASE_UNION_TY.validate_mojomparse(BaseUnion::n1(10), base_union_mojom_n1(10)); |
| BASE_UNION_TY.validate_mojomparse(BaseUnion::u1(987654321), base_union_mojom_u1(987654321)); |
| BASE_UNION_TY.validate_mojomparse(BaseUnion::e1(TestEnum::Three), base_union_mojom_e1(3)); |
| BASE_UNION_TY.validate_mojomparse(BaseUnion::b1(false), base_union_mojom_b1(false)); |
| BASE_UNION_TY.validate_mojomparse(BaseUnion::b2(true), base_union_mojom_b2(true)); |
| BASE_UNION_TY |
| .validate_mojomparse(BaseUnion::em1(Empty {}), base_union_mojom_em1(empty_mojom())); |
| BASE_UNION_TY.validate_mojomparse( |
| BaseUnion::f1(FourInts { a: 5, b: 6, c: 7, d: 8 }), |
| base_union_mojom_f1(four_ints_mojom(5, 6, 7, 8)), |
| ); |
| BASE_UNION_TY.validate_mojomparse(BaseUnion::fl(3.14), base_union_mojom_fl(3.14)); |
| |
| expect_true!(BaseUnion::try_from(MojomValue::Union(99, Box::new(MojomValue::Int8(0)))).is_err()); |
| expect_true!( |
| BaseUnion::try_from(MojomValue::Union(0, Box::new(MojomValue::UInt64(0)))).is_err() |
| ); |
| |
| NESTED_UNION_TY.validate_mojomparse(NestedUnion::n(60), nested_union_mojom_n(60)); |
| NESTED_UNION_TY.validate_mojomparse( |
| NestedUnion::u(BaseUnion::n1(70)), |
| nested_union_mojom_u(base_union_mojom_n1(70)), |
| ); |
| |
| WITH_NESTED_UNION_TY.validate_mojomparse( |
| WithNestedUnion { n1: 800, u: NestedUnion::n(90), n2: 1000 }, |
| with_nested_union_mojom(800, nested_union_mojom_n(90), 1000), |
| ); |
| |
| NESTEDER_UNION_TY.validate_mojomparse(NestederUnion::b(false), nesteder_union_mojom_b(false)); |
| NESTEDER_UNION_TY.validate_mojomparse(NestederUnion::n(-1), nesteder_union_mojom_n(-1)); |
| NESTEDER_UNION_TY.validate_mojomparse( |
| NestederUnion::u(NestedUnion::n(123)), |
| nesteder_union_mojom_u(nested_union_mojom_n(123)), |
| ); |
| NESTEDER_UNION_TY.validate_mojomparse( |
| NestederUnion::w(WithNestedUnion { n1: 1000, u: NestedUnion::n(-50), n2: 200 }), |
| nesteder_union_mojom_w(with_nested_union_mojom(1000, nested_union_mojom_n(-50), 200)), |
| ); |
| |
| WITH_MANY_UNIONS_TY.validate_mojomparse( |
| WithManyUnions { |
| u1: NestedUnion::n(50), |
| i1: 11, |
| u2: NestederUnion::b(false), |
| d1: 3.14159, |
| u3: BaseUnion::n1(55), |
| u4: NestederUnion::n(12), |
| i2: 33, |
| i3: 44, |
| }, |
| with_many_unions_mojom( |
| nested_union_mojom_n(50), |
| 11, |
| nesteder_union_mojom_b(false), |
| 3.14159, |
| base_union_mojom_n1(55), |
| nesteder_union_mojom_n(12), |
| 33, |
| 44, |
| ), |
| ) |
| } |
| |
| macro_rules! array { |
| ($element_type:expr, $num_elements:expr) => { |
| MojomType::Array { element_type: Box::new($element_type), num_elements: $num_elements } |
| }; |
| } |
| |
| macro_rules! packed_array { |
| ($element_type:expr, $num_elements:expr) => { |
| MojomWireType::Pointer { |
| nested_data_type: PackedStructuredType::Array { |
| element_type: std::sync::Arc::new($element_type), |
| array_type: if let Some(n) = $num_elements { |
| PackedArrayType::SizedArray(n) |
| } else { |
| PackedArrayType::UnsizedArray |
| }, |
| }, |
| is_nullable: false, |
| } |
| }; |
| } |
| |
| // Mojom Definition: |
| // array<int16> |
| static ARRAY_INT16_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<int16>", |
| base_type: array!(MojomType::Int16, None), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Int16), None), |
| }); |
| |
| fn array_int16_mojom(elts: Vec<i16>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::Int16).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<uint64, 3> |
| static ARRAY_UINT64_SIZED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<uint64, 3>", |
| base_type: array!(MojomType::UInt64, Some(3)), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::UInt64), Some(3)), |
| }); |
| |
| fn array_uint64_sized_mojom(elts: [u64; 3]) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::UInt64).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<bool> |
| static ARRAY_BOOL_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<bool>", |
| base_type: array!(MojomType::Bool, None), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Bool), None), |
| }); |
| |
| fn array_bool_mojom(elts: Vec<bool>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::Bool).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<bool, 13> |
| static ARRAY_BOOL_SIZED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<bool, 13>", |
| base_type: array!(MojomType::Bool, Some(13)), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Bool), Some(13)), |
| }); |
| |
| fn array_bool_sized_mojom(elts: [bool; 13]) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::Bool).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<TestEnum> |
| static ARRAY_ENUM_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<TestEnum>", |
| base_type: array!(MojomType::Enum { is_valid: TEST_ENUM_PRED }, None), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Enum { is_valid: TEST_ENUM_PRED }), None), |
| }); |
| |
| fn array_enum_mojom(elts: Vec<TestEnum>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(|e| MojomValue::Enum(e.into())).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<BaseUnion> |
| static ARRAY_UNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<BaseUnion>", |
| base_type: array!(BASE_UNION_TY.base_type.clone(), None), |
| packed_type: packed_array!(BASE_UNION_TY.packed_type.clone(), None), |
| }); |
| |
| fn array_union_mojom(elts: Vec<BaseUnion>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::from).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<NestedUnion> |
| static ARRAY_UNION_NESTED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<NestedUnion>", |
| base_type: array!(NESTED_UNION_TY.base_type.clone(), None), |
| packed_type: packed_array!(NESTED_UNION_TY.packed_type.clone(), None), |
| }); |
| |
| fn array_union_nested_mojom(elts: Vec<NestedUnion>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::from).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<FourInts> |
| static ARRAY_FOURINTS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<FourInts>", |
| base_type: array!(FOUR_INTS_TY.base_type.clone(), None), |
| packed_type: packed_array!(FOUR_INTS_TY.packed_type.clone(), None), |
| }); |
| |
| fn array_fourints_mojom(elts: Vec<FourInts>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(MojomValue::from).collect()) |
| } |
| |
| // Mojom Definition: |
| // array<array<uint8>> |
| static ARRAY_NESTED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<array<uint8>>", |
| base_type: array!(array!(MojomType::UInt8, None), None), |
| packed_type: packed_array!(packed_array!(bare_leaf!(PackedLeafType::UInt8), None), None), |
| }); |
| |
| fn array_nested_mojom(elts: Vec<Vec<u8>>) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter() |
| .map(|inner_vec| { |
| MojomValue::Array(inner_vec.into_iter().map(MojomValue::UInt8).collect()) |
| }) |
| .collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // array<array<uint8, 2>, 3> |
| static ARRAY_NESTED_SIZED_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<array<uint8, 2>, 3>", |
| base_type: array!(array!(MojomType::UInt8, Some(2)), Some(3)), |
| packed_type: packed_array!(packed_array!(bare_leaf!(PackedLeafType::UInt8), Some(2)), Some(3)), |
| }); |
| |
| fn array_nested_sized_mojom(elts: [[u8; 2]; 3]) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter() |
| .map(|inner_arr| { |
| MojomValue::Array(inner_arr.into_iter().map(MojomValue::UInt8).collect()) |
| }) |
| .collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // array<float> |
| static ARRAY_FLOAT_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<float>", |
| base_type: array!(MojomType::Float32, None), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Float32), None), |
| }); |
| |
| fn array_float_mojom(elts: Vec<f32>) -> MojomValue { |
| MojomValue::Array(elts.into_iter().map(|e| MojomValue::Float32(e.into())).collect()) |
| } |
| |
| // Mojom Definition: |
| // struct Arrays { |
| // array<int16> ints; |
| // array<uint64, 3> ints_sized; |
| // array<bool> bools; |
| // array<bool, 13> bool_sized; |
| // array<float> floats; |
| // array<TestEnum> enums; |
| // array<BaseUnion> unions; |
| // array<NestedUnion> unions_nested; |
| // array<FourInts> fourints; |
| // array<array<uint8>> nested; |
| // array<array<uint8, 2>, 3> nested_sized; |
| // }; |
| static ARRAYS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "Arrays", |
| base_type: wrap_struct_fields_type(vec![ |
| ("ints".to_string(), ARRAY_INT16_TY.base_type.clone()), |
| ("ints_sized".to_string(), ARRAY_UINT64_SIZED_TY.base_type.clone()), |
| ("bools".to_string(), ARRAY_BOOL_TY.base_type.clone()), |
| ("bool_sized".to_string(), ARRAY_BOOL_SIZED_TY.base_type.clone()), |
| ("floats".to_string(), ARRAY_FLOAT_TY.base_type.clone()), |
| ("enums".to_string(), ARRAY_ENUM_TY.base_type.clone()), |
| ("unions".to_string(), ARRAY_UNION_TY.base_type.clone()), |
| ("unions_nested".to_string(), ARRAY_UNION_NESTED_TY.base_type.clone()), |
| ("fourints".to_string(), ARRAY_FOURINTS_TY.base_type.clone()), |
| ("nested".to_string(), ARRAY_NESTED_TY.base_type.clone()), |
| ("nested_sized".to_string(), ARRAY_NESTED_SIZED_TY.base_type.clone()), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ( |
| "ints".to_string(), |
| StructuredBodyElement::SingleValue(0, ARRAY_INT16_TY.packed_type.clone()), |
| ), |
| ( |
| "ints_sized".to_string(), |
| StructuredBodyElement::SingleValue(1, ARRAY_UINT64_SIZED_TY.packed_type.clone()), |
| ), |
| ( |
| "bools".to_string(), |
| StructuredBodyElement::SingleValue(2, ARRAY_BOOL_TY.packed_type.clone()), |
| ), |
| ( |
| "bool_sized".to_string(), |
| StructuredBodyElement::SingleValue(3, ARRAY_BOOL_SIZED_TY.packed_type.clone()), |
| ), |
| ( |
| "floats".to_string(), |
| StructuredBodyElement::SingleValue(4, ARRAY_FLOAT_TY.packed_type.clone()), |
| ), |
| ( |
| "enums".to_string(), |
| StructuredBodyElement::SingleValue(5, ARRAY_ENUM_TY.packed_type.clone()), |
| ), |
| ( |
| "unions".to_string(), |
| StructuredBodyElement::SingleValue(6, ARRAY_UNION_TY.packed_type.clone()), |
| ), |
| ( |
| "unions_nested".to_string(), |
| StructuredBodyElement::SingleValue(7, ARRAY_UNION_NESTED_TY.packed_type.clone()), |
| ), |
| ( |
| "fourints".to_string(), |
| StructuredBodyElement::SingleValue(8, ARRAY_FOURINTS_TY.packed_type.clone()), |
| ), |
| ( |
| "nested".to_string(), |
| StructuredBodyElement::SingleValue(9, ARRAY_NESTED_TY.packed_type.clone()), |
| ), |
| ( |
| "nested_sized".to_string(), |
| StructuredBodyElement::SingleValue(10, ARRAY_NESTED_SIZED_TY.packed_type.clone()), |
| ), |
| ], |
| 11, |
| ), |
| }); |
| |
| #[allow(clippy::too_many_arguments)] |
| fn arrays_mojom( |
| ints: Vec<i16>, |
| ints_sized: [u64; 3], |
| bools: Vec<bool>, |
| bool_sized: [bool; 13], |
| floats: Vec<f32>, |
| enums: Vec<TestEnum>, |
| unions: Vec<BaseUnion>, |
| unions_nested: Vec<NestedUnion>, |
| fourints: Vec<FourInts>, |
| nested: Vec<Vec<u8>>, |
| nested_sized: [[u8; 2]; 3], |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("ints".to_string(), array_int16_mojom(ints)), |
| ("ints_sized".to_string(), array_uint64_sized_mojom(ints_sized)), |
| ("bools".to_string(), array_bool_mojom(bools)), |
| ("bool_sized".to_string(), array_bool_sized_mojom(bool_sized)), |
| ("floats".to_string(), array_float_mojom(floats)), |
| ("enums".to_string(), array_enum_mojom(enums)), |
| ("unions".to_string(), array_union_mojom(unions)), |
| ("unions_nested".to_string(), array_union_nested_mojom(unions_nested)), |
| ("fourints".to_string(), array_fourints_mojom(fourints)), |
| ("nested".to_string(), array_nested_mojom(nested)), |
| ("nested_sized".to_string(), array_nested_sized_mojom(nested_sized)), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestArrays)] |
| fn test_arrays() { |
| ARRAY_INT16_TY |
| .validate_mojomparse::<Vec<i16>>(vec![1, -2, 3, -4], array_int16_mojom(vec![1, -2, 3, -4])); |
| ARRAY_UINT64_SIZED_TY |
| .validate_mojomparse::<[u64; 3]>([5, 6, 7], array_uint64_sized_mojom([5, 6, 7])); |
| ARRAY_BOOL_TY.validate_mojomparse::<Vec<bool>>( |
| vec![true, false, true, false, true, false, true, false, true], |
| array_bool_mojom(vec![true, false, true, false, true, false, true, false, true]), |
| ); |
| ARRAY_BOOL_SIZED_TY.validate_mojomparse::<[bool; 13]>( |
| [true, true, false, true, false, false, true, true, false, true, false, false, true], |
| array_bool_sized_mojom([ |
| true, true, false, true, false, false, true, true, false, true, false, false, true, |
| ]), |
| ); |
| ARRAY_FLOAT_TY.validate_mojomparse::<Vec<f32>>( |
| vec![1.0, -2.0, 3.14], |
| array_float_mojom(vec![1.0, -2.0, 3.14]), |
| ); |
| ARRAY_ENUM_TY.validate_mojomparse::<Vec<TestEnum>>( |
| vec![TestEnum::Zero, TestEnum::Seven, TestEnum::Four], |
| array_enum_mojom(vec![TestEnum::Zero, TestEnum::Seven, TestEnum::Four]), |
| ); |
| ARRAY_UNION_TY.validate_mojomparse::<Vec<BaseUnion>>( |
| vec![BaseUnion::n1(10), BaseUnion::u1(20), BaseUnion::e1(TestEnum::Three)], |
| array_union_mojom(vec![ |
| BaseUnion::n1(10), |
| BaseUnion::u1(20), |
| BaseUnion::e1(TestEnum::Three), |
| ]), |
| ); |
| ARRAY_UNION_NESTED_TY.validate_mojomparse::<Vec<NestedUnion>>( |
| vec![NestedUnion::n(30), NestedUnion::u(BaseUnion::n1(40))], |
| array_union_nested_mojom(vec![NestedUnion::n(30), NestedUnion::u(BaseUnion::n1(40))]), |
| ); |
| ARRAY_FOURINTS_TY.validate_mojomparse::<Vec<FourInts>>( |
| vec![FourInts { a: 1, b: 2, c: 3, d: 4 }, FourInts { a: 5, b: 6, c: 7, d: 8 }], |
| array_fourints_mojom(vec![ |
| FourInts { a: 1, b: 2, c: 3, d: 4 }, |
| FourInts { a: 5, b: 6, c: 7, d: 8 }, |
| ]), |
| ); |
| ARRAY_NESTED_TY.validate_mojomparse::<Vec<Vec<u8>>>( |
| vec![vec![1, 2], vec![3, 4, 5]], |
| array_nested_mojom(vec![vec![1, 2], vec![3, 4, 5]]), |
| ); |
| ARRAY_NESTED_SIZED_TY.validate_mojomparse::<[[u8; 2]; 3]>( |
| [[6, 7], [8, 9], [10, 11]], |
| array_nested_sized_mojom([[6, 7], [8, 9], [10, 11]]), |
| ); |
| |
| let array_val = array_int16_mojom(vec![]); |
| expect_true!(FourInts::try_from(array_val).is_err()); |
| |
| expect_true!(<Vec<i16>>::try_from(empty_mojom()).is_err()); |
| expect_true!(<[u64; 3]>::try_from(empty_mojom()).is_err()); |
| |
| ARRAYS_TY.validate_mojomparse( |
| Arrays { |
| ints: vec![101, -201, 301, -401], |
| ints_sized: [501, 601, 701], |
| bools: vec![false, true, false, true, false, true, false, true, false], |
| bool_sized: [ |
| false, false, true, false, true, true, false, false, true, false, true, true, false, |
| ], |
| floats: vec![1.1, 2.2, 3.3], |
| enums: vec![TestEnum::Four, TestEnum::Zero, TestEnum::Seven], |
| unions: vec![BaseUnion::n1(12), BaseUnion::u1(22), BaseUnion::e1(TestEnum::Four)], |
| unions_nested: vec![NestedUnion::n(32), NestedUnion::u(BaseUnion::n1(42))], |
| fourints: vec![ |
| FourInts { a: 12, b: 22, c: 32, d: 42 }, |
| FourInts { a: 52, b: 62, c: 72, d: 82 }, |
| ], |
| nested: vec![vec![11, 22], vec![33, 44, 55]], |
| nested_sized: [[16, 17], [18, 19], [20, 21]], |
| }, |
| arrays_mojom( |
| vec![101, -201, 301, -401], |
| [501, 601, 701], |
| vec![false, true, false, true, false, true, false, true, false], |
| [false, false, true, false, true, true, false, false, true, false, true, true, false], |
| vec![1.1, 2.2, 3.3], |
| vec![TestEnum::Four, TestEnum::Zero, TestEnum::Seven], |
| vec![BaseUnion::n1(12), BaseUnion::u1(22), BaseUnion::e1(TestEnum::Four)], |
| vec![NestedUnion::n(32), NestedUnion::u(BaseUnion::n1(42))], |
| vec![FourInts { a: 12, b: 22, c: 32, d: 42 }, FourInts { a: 52, b: 62, c: 72, d: 82 }], |
| vec![vec![11, 22], vec![33, 44, 55]], |
| [[16, 17], [18, 19], [20, 21]], |
| ), |
| ); |
| } |
| |
| macro_rules! map { |
| ($key_type:expr, $value_type:expr) => { |
| MojomType::Map { key_type: Box::new($key_type), value_type: Box::new($value_type) } |
| }; |
| } |
| |
| macro_rules! packed_map { |
| ($key_type:expr, $value_type:expr) => { |
| MojomWireType::Pointer { |
| nested_data_type: PackedStructuredType::Map { |
| key_type: std::sync::Arc::new($key_type), |
| value_type: std::sync::Arc::new($value_type), |
| }, |
| is_nullable: false, |
| } |
| }; |
| } |
| |
| // Mojom Definition: |
| // map<uint8, uint8> |
| static MAP_U8_U8_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<uint8, uint8>", |
| base_type: map!(MojomType::UInt8, MojomType::UInt8), |
| packed_type: packed_map!(bare_leaf!(PackedLeafType::UInt8), bare_leaf!(PackedLeafType::UInt8)), |
| }); |
| |
| fn map_u8_u8_mojom(elts: HashMap<u8, u8>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::UInt8(k), MojomValue::UInt8(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // map<bool, uint16> |
| static MAP_BOOL_U16_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<bool, uint16>", |
| base_type: map!(MojomType::Bool, MojomType::UInt16), |
| packed_type: packed_map!(bare_leaf!(PackedLeafType::Bool), bare_leaf!(PackedLeafType::UInt16)), |
| }); |
| |
| fn map_bool_u16_mojom(elts: HashMap<bool, u16>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::Bool(k), MojomValue::UInt16(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // map<TestEnum, int32> |
| static MAP_ENUM_I32_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<TestEnum, int32>", |
| base_type: map!(MojomType::Enum { is_valid: TEST_ENUM_PRED }, MojomType::Int32), |
| packed_type: packed_map!( |
| bare_leaf!(PackedLeafType::Enum { is_valid: TEST_ENUM_PRED }), |
| bare_leaf!(PackedLeafType::Int32) |
| ), |
| }); |
| |
| fn map_enum_i32_mojom(elts: HashMap<TestEnum, i32>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::Enum(k.into()), MojomValue::Int32(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // map<int8, FourInts> |
| static MAP_I8_FOURINTS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<int8, FourInts>", |
| base_type: map!(MojomType::Int8, FOUR_INTS_TY.base_type.clone()), |
| packed_type: packed_map!(bare_leaf!(PackedLeafType::Int8), FOUR_INTS_TY.packed_type.clone()), |
| }); |
| |
| fn map_i8_fourints_mojom(elts: HashMap<i8, FourInts>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::Int8(k), MojomValue::from(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // map<int8, NestedUnion> |
| static MAP_I8_NESTEDUNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<int8, NestedUnion>", |
| base_type: map!(MojomType::Int8, NESTED_UNION_TY.base_type.clone()), |
| packed_type: packed_map!(bare_leaf!(PackedLeafType::Int8), NESTED_UNION_TY.packed_type.clone()), |
| }); |
| |
| fn map_i8_nestedunion_mojom(elts: HashMap<i8, NestedUnion>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::Int8(k), MojomValue::from(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // map<int8, map<int16, uint32>> |
| static MAP_I8_MAP_I16_U32_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<int8, map<int16, uint32>>", |
| base_type: map!(MojomType::Int8, map!(MojomType::Int16, MojomType::UInt32)), |
| packed_type: packed_map!( |
| bare_leaf!(PackedLeafType::Int8), |
| packed_map!(bare_leaf!(PackedLeafType::Int16), bare_leaf!(PackedLeafType::UInt32)) |
| ), |
| }); |
| |
| fn map_i8_map_i16_u32_mojom(elts: HashMap<i8, HashMap<i16, u32>>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::Int8(k), MojomValue::from(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // map<float, int32> |
| static MAP_FLOAT_I32_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<float, int32>", |
| base_type: map!(MojomType::Float32, MojomType::Int32), |
| packed_type: packed_map!( |
| bare_leaf!(PackedLeafType::Float32), |
| bare_leaf!(PackedLeafType::Int32) |
| ), |
| }); |
| |
| fn map_float_i32_mojom(elts: HashMap<OrderedFloat<f32>, i32>) -> MojomValue { |
| MojomValue::Map( |
| elts.into_iter().map(|(k, v)| (MojomValue::Float32(k), MojomValue::Int32(v))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // struct Maps { |
| // map<uint8, uint8> eights; |
| // map<bool, uint16> bools; |
| // map<TestEnum, int32> enums; |
| // map<int8, FourInts> to_struct; |
| // map<int8, NestedUnion> to_union; |
| // map<int8, map<int16, uint32>> to_map; |
| // map<float, int32> float_map; |
| // } |
| static MAPS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "Maps", |
| base_type: wrap_struct_fields_type(vec![ |
| ("eights".to_string(), MAP_U8_U8_TY.base_type.clone()), |
| ("bools".to_string(), MAP_BOOL_U16_TY.base_type.clone()), |
| ("enums".to_string(), MAP_ENUM_I32_TY.base_type.clone()), |
| ("to_struct".to_string(), MAP_I8_FOURINTS_TY.base_type.clone()), |
| ("to_union".to_string(), MAP_I8_NESTEDUNION_TY.base_type.clone()), |
| ("to_map".to_string(), MAP_I8_MAP_I16_U32_TY.base_type.clone()), |
| ("float_map".to_string(), MAP_FLOAT_I32_TY.base_type.clone()), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("eights".to_string(), MAP_U8_U8_TY.as_struct_field(0)), |
| ("bools".to_string(), MAP_BOOL_U16_TY.as_struct_field(1)), |
| ("enums".to_string(), MAP_ENUM_I32_TY.as_struct_field(2)), |
| ("to_struct".to_string(), MAP_I8_FOURINTS_TY.as_struct_field(3)), |
| ("to_union".to_string(), MAP_I8_NESTEDUNION_TY.as_struct_field(4)), |
| ("to_map".to_string(), MAP_I8_MAP_I16_U32_TY.as_struct_field(5)), |
| ("float_map".to_string(), MAP_FLOAT_I32_TY.as_struct_field(6)), |
| ], |
| 7, |
| ), |
| }); |
| |
| fn maps_mojom( |
| eights: HashMap<u8, u8>, |
| bools: HashMap<bool, u16>, |
| enums: HashMap<TestEnum, i32>, |
| to_struct: HashMap<i8, FourInts>, |
| to_union: HashMap<i8, NestedUnion>, |
| to_map: HashMap<i8, HashMap<i16, u32>>, |
| float_map: HashMap<OrderedFloat<f32>, i32>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("eights".to_string(), map_u8_u8_mojom(eights)), |
| ("bools".to_string(), map_bool_u16_mojom(bools)), |
| ("enums".to_string(), map_enum_i32_mojom(enums)), |
| ("to_struct".to_string(), map_i8_fourints_mojom(to_struct)), |
| ("to_union".to_string(), map_i8_nestedunion_mojom(to_union)), |
| ("to_map".to_string(), map_i8_map_i16_u32_mojom(to_map)), |
| ("float_map".to_string(), map_float_i32_mojom(float_map)), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestMaps)] |
| fn test_maps() { |
| let eights_data = [(1, 2), (3, 4)]; |
| MAP_U8_U8_TY.validate_mojomparse::<HashMap<u8, u8>>( |
| eights_data.into(), |
| map_u8_u8_mojom(eights_data.into()), |
| ); |
| |
| let bools_data = [(true, 10), (false, 20)]; |
| MAP_BOOL_U16_TY.validate_mojomparse::<HashMap<bool, u16>>( |
| bools_data.into(), |
| map_bool_u16_mojom(bools_data.into()), |
| ); |
| |
| let enums_data = [(TestEnum::Zero, -1), (TestEnum::Seven, -2)]; |
| MAP_ENUM_I32_TY.validate_mojomparse::<HashMap<TestEnum, i32>>( |
| enums_data.clone().into(), |
| map_enum_i32_mojom(enums_data.clone().into()), |
| ); |
| |
| let to_struct_data = [(5, FourInts { a: 1, b: 2, c: 3, d: 4 })]; |
| MAP_I8_FOURINTS_TY.validate_mojomparse::<HashMap<i8, FourInts>>( |
| to_struct_data.clone().into(), |
| map_i8_fourints_mojom(to_struct_data.clone().into()), |
| ); |
| |
| let to_union_data = [(-8, NestedUnion::n(50)), (-9, NestedUnion::u(BaseUnion::n1(10)))]; |
| MAP_I8_NESTEDUNION_TY.validate_mojomparse::<HashMap<i8, NestedUnion>>( |
| to_union_data.clone().into(), |
| map_i8_nestedunion_mojom(to_union_data.clone().into()), |
| ); |
| |
| let to_map_data = |
| [(1, [(10, 100), (20, 200)].into()), (2, [(30, 300), (40, 400), (50, 500)].into())]; |
| MAP_I8_MAP_I16_U32_TY.validate_mojomparse::<HashMap<i8, HashMap<i16, u32>>>( |
| to_map_data.clone().into(), |
| map_i8_map_i16_u32_mojom(to_map_data.clone().into()), |
| ); |
| |
| let float_map_data = [(1.1.into(), 10), (2.2.into(), 20)]; |
| MAP_FLOAT_I32_TY.validate_mojomparse::<HashMap<OrderedFloat<f32>, i32>>( |
| float_map_data.into(), |
| map_float_i32_mojom(float_map_data.into()), |
| ); |
| |
| MAPS_TY.validate_mojomparse( |
| Maps { |
| eights: eights_data.into(), |
| bools: bools_data.into(), |
| enums: enums_data.clone().into(), |
| to_struct: to_struct_data.clone().into(), |
| to_union: to_union_data.clone().into(), |
| to_map: to_map_data.clone().into(), |
| float_map: float_map_data.into(), |
| }, |
| maps_mojom( |
| eights_data.into(), |
| bools_data.into(), |
| enums_data.into(), |
| to_struct_data.into(), |
| to_union_data.into(), |
| to_map_data.into(), |
| float_map_data.into(), |
| ), |
| ); |
| } |
| |
| // Mojom definition: string |
| static STRING_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "string", |
| base_type: MojomType::String, |
| packed_type: MojomWireType::Pointer { |
| nested_data_type: PackedStructuredType::Array { |
| element_type: std::sync::Arc::new(MojomWireType::Leaf { |
| leaf_type: PackedLeafType::UInt8, |
| is_nullable: false, |
| }), |
| array_type: PackedArrayType::String, |
| }, |
| is_nullable: false, |
| }, |
| }); |
| |
| // Mojom Definition: array<string> |
| static ARRAY_STRING_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<string>", |
| base_type: array!(MojomType::String, None), |
| packed_type: packed_array!(STRING_TY.packed_type.clone(), None), |
| }); |
| |
| // Mojom Definition: map<uint8, string> |
| static MAP_U8_STRING_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<uint8, string>", |
| base_type: map!(MojomType::UInt8, MojomType::String), |
| packed_type: packed_map!(bare_leaf!(PackedLeafType::UInt8), STRING_TY.packed_type.clone()), |
| }); |
| |
| // Mojom Definition: map<string, int16> |
| static MAP_STRING_I16_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "map<string, int16>", |
| base_type: map!(MojomType::String, MojomType::Int16), |
| packed_type: packed_map!(STRING_TY.packed_type.clone(), bare_leaf!(PackedLeafType::Int16)), |
| }); |
| |
| // Mojom Definition: |
| // struct Strings { |
| // string str; |
| // array<string> arr; |
| // map<uint8, string> to_str; |
| // map<string, int16> from_str; |
| // HoldsComplexTypes u; |
| // } |
| static STRINGS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "Strings", |
| base_type: wrap_struct_fields_type(vec![ |
| ("str".to_string(), STRING_TY.base_type.clone()), |
| ("arr".to_string(), ARRAY_STRING_TY.base_type.clone()), |
| ("to_str".to_string(), MAP_U8_STRING_TY.base_type.clone()), |
| ("from_str".to_string(), MAP_STRING_I16_TY.base_type.clone()), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("str".to_string(), STRING_TY.as_struct_field(0)), |
| ("arr".to_string(), ARRAY_STRING_TY.as_struct_field(1)), |
| ("to_str".to_string(), MAP_U8_STRING_TY.as_struct_field(2)), |
| ("from_str".to_string(), MAP_STRING_I16_TY.as_struct_field(3)), |
| ], |
| 4, |
| ), |
| }); |
| |
| fn mojomvalue_from_str(str: &str) -> MojomValue { |
| MojomValue::String(str.to_string()) |
| } |
| |
| fn strings_mojom( |
| str: &str, |
| arr: Vec<&str>, |
| to_str: HashMap<u8, &str>, |
| from_str: HashMap<&str, i16>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("str".to_string(), mojomvalue_from_str(str)), |
| ("arr".to_string(), MojomValue::Array(arr.into_iter().map(mojomvalue_from_str).collect())), |
| ( |
| "to_str".to_string(), |
| MojomValue::Map( |
| to_str |
| .into_iter() |
| .map(|(k, v)| (MojomValue::UInt8(k), mojomvalue_from_str(v))) |
| .collect(), |
| ), |
| ), |
| ( |
| "from_str".to_string(), |
| MojomValue::Map( |
| from_str |
| .into_iter() |
| .map(|(k, v)| (mojomvalue_from_str(k), MojomValue::Int16(v))) |
| .collect(), |
| ), |
| ), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestStrings)] |
| fn test_strings() { |
| STRINGS_TY.validate_mojomparse( |
| Strings { |
| str: "test".to_string(), |
| arr: vec!["a".to_string(), "b".to_string()], |
| to_str: [(1, "one".to_string()), (2, "two".to_string())].into(), |
| from_str: [("three".to_string(), 3), ("four".to_string(), 4)].into(), |
| }, |
| strings_mojom( |
| "test", |
| vec!["a", "b"], |
| [(1, "one"), (2, "two")].into(), |
| [("three", 3), ("four", 4)].into(), |
| ), |
| ); |
| |
| STRINGS_TY.validate_mojomparse( |
| Strings { |
| str: "".to_string(), |
| arr: vec![], |
| to_str: HashMap::new(), |
| from_str: HashMap::new(), |
| }, |
| strings_mojom("", vec![], HashMap::new(), HashMap::new()), |
| ); |
| } |
| |
| // Mojom Definition: |
| // union HoldsComplexTypes { |
| // string str; |
| // array<int8> arr; |
| // map<int8, int8> m; |
| // } |
| static HOLDS_COMPLEX_TYPES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "HoldsComplexTypes", |
| base_type: MojomType::Union { |
| variants: [ |
| (0, STRING_TY.base_type.clone()), |
| (1, ARRAY_INT16_TY.base_type.clone()), |
| (2, MAP_U8_U8_TY.base_type.clone()), |
| ] |
| .into(), |
| }, |
| packed_type: MojomWireType::Union { |
| variants: [ |
| (0, STRING_TY.as_union_field()), |
| (1, ARRAY_INT16_TY.as_union_field()), |
| (2, MAP_U8_U8_TY.as_union_field()), |
| ] |
| .into(), |
| is_nullable: false, |
| }, |
| }); |
| |
| fn holds_complex_types_mojom_str(str: &str) -> MojomValue { |
| MojomValue::Union(0, Box::new(MojomValue::String(str.to_string()))) |
| } |
| |
| fn holds_complex_types_mojom_arr(arr: Vec<i16>) -> MojomValue { |
| MojomValue::Union( |
| 1, |
| Box::new(MojomValue::Array(arr.into_iter().map(MojomValue::Int16).collect())), |
| ) |
| } |
| |
| fn holds_complex_types_mojom_m(map: HashMap<u8, u8>) -> MojomValue { |
| MojomValue::Union( |
| 2, |
| Box::new(MojomValue::Map( |
| map.into_iter().map(|(k, v)| (MojomValue::UInt8(k), MojomValue::UInt8(v))).collect(), |
| )), |
| ) |
| } |
| |
| static COMPLEX_UNION_HOLDER_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "ComplexUnionHolder", |
| base_type: wrap_struct_fields_type(vec![( |
| "u".to_string(), |
| HOLDS_COMPLEX_TYPES_TY.base_type.clone(), |
| )]), |
| packed_type: wrap_packed_struct_fields( |
| vec![("u".to_string(), HOLDS_COMPLEX_TYPES_TY.as_struct_field(0))], |
| 1, |
| ), |
| }); |
| |
| #[gtest(RustTestMojomParsingAttr, TestComplexUnion)] |
| fn test_complex_union() { |
| // Test both the union and the union inside a struct |
| HOLDS_COMPLEX_TYPES_TY.validate_mojomparse( |
| HoldsComplexTypes::str("hello".to_string()), |
| holds_complex_types_mojom_str("hello"), |
| ); |
| |
| COMPLEX_UNION_HOLDER_TY.validate_mojomparse( |
| ComplexUnionHolder { u: HoldsComplexTypes::str("eek".to_string()) }, |
| wrap_struct_fields_value(vec![("u".to_string(), holds_complex_types_mojom_str("eek"))]), |
| ); |
| |
| HOLDS_COMPLEX_TYPES_TY.validate_mojomparse( |
| HoldsComplexTypes::arr(vec![1, 2, 3]), |
| holds_complex_types_mojom_arr(vec![1, 2, 3]), |
| ); |
| |
| COMPLEX_UNION_HOLDER_TY.validate_mojomparse( |
| ComplexUnionHolder { u: HoldsComplexTypes::arr(vec![99, 222, 301, 282]) }, |
| wrap_struct_fields_value(vec![( |
| "u".to_string(), |
| holds_complex_types_mojom_arr(vec![99, 222, 301, 282]), |
| )]), |
| ); |
| |
| HOLDS_COMPLEX_TYPES_TY.validate_mojomparse( |
| HoldsComplexTypes::m([(1, 10), (2, 20)].into()), |
| holds_complex_types_mojom_m([(1, 10), (2, 20)].into()), |
| ); |
| |
| COMPLEX_UNION_HOLDER_TY.validate_mojomparse( |
| ComplexUnionHolder { u: HoldsComplexTypes::m([(19, 120), (29, 210)].into()) }, |
| wrap_struct_fields_value(vec![( |
| "u".to_string(), |
| holds_complex_types_mojom_m([(19, 120), (29, 210)].into()), |
| )]), |
| ); |
| } |
| |
| /// Wrap the type in `MojomType::Nullable` and a new box |
| macro_rules! nullable_ty { |
| ($inner_ty:expr) => { |
| MojomType::Nullable { inner_type: Box::new($inner_ty) } |
| }; |
| } |
| |
| /// Wrap the (optional) value in `MojomValue::Nullable` and a new box |
| macro_rules! nullable_val { |
| ($inner_val:expr) => { |
| MojomValue::Nullable($inner_val.map(Box::new)) |
| }; |
| } |
| |
| // Mojom Definition: |
| // struct NullableBasics { |
| // bool? b; |
| // uint16? u16; |
| // int8? i8; |
| // Empty? empty; |
| // TestEnum? e; |
| // FourInts? fourints; |
| // float? f1; |
| // double? f2; |
| // } |
| static NULLABLE_BASICS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "NullableBasics", |
| base_type: wrap_struct_fields_type(vec![ |
| ("b".to_string(), nullable_ty!(MojomType::Bool)), |
| ("n1".to_string(), nullable_ty!(MojomType::UInt16)), |
| ("n2".to_string(), nullable_ty!(MojomType::Int8)), |
| ("empty".to_string(), nullable_ty!(EMPTY_TY.base_type.clone())), |
| ("e".to_string(), nullable_ty!(MojomType::Enum { is_valid: TEST_ENUM_PRED })), |
| ("fourints".to_string(), nullable_ty!(FOUR_INTS_TY.base_type.clone())), |
| ("f1".to_string(), nullable_ty!(MojomType::Float32)), |
| ("f2".to_string(), nullable_ty!(MojomType::Float64)), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ( |
| "b_tag".to_string(), |
| StructuredBodyElement::Bitfield([ |
| Some((0, true)), |
| Some((0, false)), |
| Some((1, true)), |
| Some((2, true)), |
| Some((4, true)), |
| Some((6, true)), |
| Some((7, true)), |
| None, |
| ]), |
| ), |
| ("n2_val".to_string(), struct_leaf!(2, PackedLeafType::Int8, true)), |
| ("n1_val".to_string(), struct_leaf!(1, PackedLeafType::UInt16, true)), |
| ( |
| "e_val".to_string(), |
| struct_leaf!(4, PackedLeafType::Enum { is_valid: TEST_ENUM_PRED }, true), |
| ), |
| ("empty".to_string(), EMPTY_TY.as_nullable_struct_field(3)), |
| ("fourints".to_string(), FOUR_INTS_TY.as_nullable_struct_field(5)), |
| ("f1_val".to_string(), struct_leaf!(6, PackedLeafType::Float32, true)), |
| ("f2_val".to_string(), struct_leaf!(7, PackedLeafType::Float64, true)), |
| ], |
| 8, |
| ), |
| }); |
| |
| #[allow(clippy::too_many_arguments)] |
| fn nullable_basics_mojom( |
| b: Option<bool>, |
| n1: Option<u16>, |
| n2: Option<i8>, |
| empty: Option<MojomValue>, |
| e: Option<i32>, |
| fourints: Option<MojomValue>, |
| f1: Option<f32>, |
| f2: Option<f64>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("b".to_string(), nullable_val!(b.map(MojomValue::Bool))), |
| ("n1".to_string(), nullable_val!(n1.map(MojomValue::UInt16))), |
| ("n2".to_string(), nullable_val!(n2.map(MojomValue::Int8))), |
| ("empty".to_string(), nullable_val!(empty)), |
| ("e".to_string(), nullable_val!(e.map(MojomValue::Enum))), |
| ("fourints".to_string(), nullable_val!(fourints)), |
| ("f1".to_string(), nullable_val!(f1.map(|f| MojomValue::Float32(f.into())))), |
| ("f2".to_string(), nullable_val!(f2.map(|f| MojomValue::Float64(f.into())))), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // array<bool?> |
| static ARRAY_NULL_BOOL_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<bool?>", |
| base_type: array!(nullable_ty!(MojomType::Bool), None), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Bool, true), None), |
| }); |
| |
| fn array_null_bool_mojom(elts: Vec<Option<bool>>) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter().map(|elt| nullable_val!(elt.map(MojomValue::Bool))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // array<Empty?> |
| static ARRAY_NULL_EMPTY_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<Empty?>", |
| base_type: array!(nullable_ty!(EMPTY_TY.base_type.clone()), None), |
| packed_type: packed_array!(EMPTY_TY.packed_type.clone().make_nullable(), None), |
| }); |
| |
| fn array_null_empty_mojom(elts: Vec<Option<Empty>>) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter().map(|elt| nullable_val!(elt.map(MojomValue::from))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // array<TestEnum?> |
| static ARRAY_NULL_ENUM_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<TestEnum?>", |
| base_type: array!(nullable_ty!(MojomType::Enum { is_valid: TEST_ENUM_PRED }), None), |
| packed_type: packed_array!( |
| bare_leaf!(PackedLeafType::Enum { is_valid: TEST_ENUM_PRED }, true), |
| None |
| ), |
| }); |
| |
| fn array_null_enum_mojom(elts: Vec<Option<TestEnum>>) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter() |
| .map(|elt| nullable_val!(elt.map(|e| MojomValue::Enum(e.into())))) |
| .collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // array<BaseUnion?> |
| static ARRAY_NULL_UNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<BaseUnion?>", |
| base_type: array!(nullable_ty!(BASE_UNION_TY.base_type.clone()), None), |
| packed_type: packed_array!(BASE_UNION_TY.packed_type.clone().make_nullable(), None), |
| }); |
| |
| fn array_null_union_mojom(elts: Vec<Option<BaseUnion>>) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter().map(|elt| nullable_val!(elt.map(MojomValue::from))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // struct ArraysOfNullables { |
| // array<bool?> bools; |
| // array<Empty?> empties; |
| // array<TestEnum?> enums; |
| // array<BaseUnion?> unions; |
| // } |
| static ARRAYS_OF_NULLABLES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "ArraysOfNullables", |
| base_type: wrap_struct_fields_type(vec![ |
| ("bools".to_string(), ARRAY_NULL_BOOL_TY.base_type.clone()), |
| ("empties".to_string(), ARRAY_NULL_EMPTY_TY.base_type.clone()), |
| ("enums".to_string(), ARRAY_NULL_ENUM_TY.base_type.clone()), |
| ("unions".to_string(), ARRAY_NULL_UNION_TY.base_type.clone()), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("bools".to_string(), ARRAY_NULL_BOOL_TY.as_struct_field(0)), |
| ("empties".to_string(), ARRAY_NULL_EMPTY_TY.as_struct_field(1)), |
| ("enums".to_string(), ARRAY_NULL_ENUM_TY.as_struct_field(2)), |
| ("unions".to_string(), ARRAY_NULL_UNION_TY.as_struct_field(3)), |
| ], |
| 4, |
| ), |
| }); |
| |
| fn arrays_of_nullables_mojom( |
| bools: Vec<Option<bool>>, |
| empties: Vec<Option<Empty>>, |
| enums: Vec<Option<TestEnum>>, |
| unions: Vec<Option<BaseUnion>>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("bools".to_string(), array_null_bool_mojom(bools)), |
| ("empties".to_string(), array_null_empty_mojom(empties)), |
| ("enums".to_string(), array_null_enum_mojom(enums)), |
| ("unions".to_string(), array_null_union_mojom(unions)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // array<bool>? |
| static NULL_ARRAY_BOOL_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<bool>?", |
| base_type: nullable_ty!(array!(MojomType::Bool, None)), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Bool, false), None).make_nullable(), |
| }); |
| |
| fn null_array_bool_mojom(elts: Option<Vec<bool>>) -> MojomValue { |
| nullable_val!(elts.map(|e| MojomValue::Array(e.into_iter().map(MojomValue::Bool).collect()))) |
| } |
| |
| // Mojom Definition: |
| // array<bool?>? |
| static NULL_ARRAY_NULL_BOOL_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<bool?>?", |
| base_type: nullable_ty!(array!(nullable_ty!(MojomType::Bool), None)), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Bool, true), None).make_nullable(), |
| }); |
| |
| fn null_array_null_bool_mojom(elts: Option<Vec<Option<bool>>>) -> MojomValue { |
| nullable_val!(elts.map(array_null_bool_mojom)) |
| } |
| |
| // Mojom Definition: |
| // struct NullableArrays { |
| // array<bool>? null_arr; |
| // array<bool?>? double_null_arr; |
| // } |
| static NULLABLE_ARRAYS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "NullableArrays", |
| base_type: wrap_struct_fields_type(vec![ |
| ("null_arr".to_string(), NULL_ARRAY_BOOL_TY.base_type.clone()), |
| ("double_null_arr".to_string(), NULL_ARRAY_NULL_BOOL_TY.base_type.clone()), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("null_arr".to_string(), NULL_ARRAY_BOOL_TY.as_struct_field(0)), |
| ("double_null_arr".to_string(), NULL_ARRAY_NULL_BOOL_TY.as_struct_field(1)), |
| ], |
| 2, |
| ), |
| }); |
| |
| fn nullable_arrays_mojom( |
| null_arr: Option<Vec<bool>>, |
| double_null_arr: Option<Vec<Option<bool>>>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("null_arr".to_string(), null_array_bool_mojom(null_arr)), |
| ("double_null_arr".to_string(), null_array_null_bool_mojom(double_null_arr)), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // union UnionWithNullables { |
| // Empty? e; |
| // string? str; |
| // BaseUnion? u; |
| // } |
| static UNION_WITH_NULLABLES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "UnionWithNullables", |
| base_type: MojomType::Union { |
| variants: [ |
| (0, nullable_ty!(EMPTY_TY.base_type.clone())), |
| (1, nullable_ty!(MojomType::String)), |
| (2, nullable_ty!(BASE_UNION_TY.base_type.clone())), |
| ] |
| .into(), |
| }, |
| packed_type: MojomWireType::Union { |
| variants: [ |
| (0, EMPTY_TY.as_nullable_union_field()), |
| (1, STRING_TY.as_nullable_union_field()), |
| (2, BASE_UNION_TY.as_nullable_union_field()), |
| ] |
| .into(), |
| is_nullable: false, |
| }, |
| }); |
| |
| fn union_with_nullables_mojom_e(e: Option<Empty>) -> MojomValue { |
| MojomValue::Union(0, Box::new(nullable_val!(e.map(|_| empty_mojom())))) |
| } |
| |
| fn union_with_nullables_mojom_str(str: Option<&str>) -> MojomValue { |
| MojomValue::Union(1, Box::new(nullable_val!(str.map(|s| MojomValue::String(s.to_string()))))) |
| } |
| |
| fn union_with_nullables_mojom_u(u: Option<MojomValue>) -> MojomValue { |
| MojomValue::Union(2, Box::new(nullable_val!(u))) |
| } |
| |
| // Mojom Definition: |
| // struct NullableOthers { |
| // UnionWithNullables? u; |
| // map<uint8, uint8>? m; |
| // string? str; |
| // } |
| static NULLABLE_OTHERS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "NullableOthers", |
| base_type: wrap_struct_fields_type(vec![ |
| ("u".to_string(), nullable_ty!(UNION_WITH_NULLABLES_TY.base_type.clone())), |
| ("m".to_string(), nullable_ty!(MAP_U8_U8_TY.base_type.clone())), |
| ("str".to_string(), nullable_ty!(STRING_TY.base_type.clone())), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("u".to_string(), UNION_WITH_NULLABLES_TY.as_nullable_struct_field(0)), |
| ("m".to_string(), MAP_U8_U8_TY.as_nullable_struct_field(1)), |
| ("str".to_string(), STRING_TY.as_nullable_struct_field(2)), |
| ], |
| 3, |
| ), |
| }); |
| |
| fn nullable_others_mojom( |
| u: Option<MojomValue>, |
| m: Option<HashMap<u8, u8>>, |
| str: Option<&str>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("u".to_string(), nullable_val!(u)), |
| ("m".to_string(), nullable_val!(m.map(map_u8_u8_mojom))), |
| ("str".to_string(), nullable_val!(str.map(|s| MojomValue::String(s.to_string())))), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestNullables)] |
| fn test_nullables() { |
| NULLABLE_BASICS_TY.validate_mojomparse( |
| NullableBasics { |
| b: None, |
| n1: None, |
| n2: None, |
| empty: None, |
| e: None, |
| fourints: None, |
| f1: None, |
| f2: None, |
| }, |
| nullable_basics_mojom(None, None, None, None, None, None, None, None), |
| ); |
| NULLABLE_BASICS_TY.validate_mojomparse( |
| NullableBasics { |
| b: Some(true), |
| n1: Some(33), |
| n2: Some(12), |
| empty: Some(Empty {}), |
| e: Some(TestEnum::Four), |
| fourints: Some(FourInts { a: 1, b: 2, c: 3, d: 4 }), |
| f1: Some(3.14), |
| f2: Some(2.71828), |
| }, |
| nullable_basics_mojom( |
| Some(true), |
| Some(33), |
| Some(12), |
| Some(empty_mojom()), |
| Some(4), |
| Some(four_ints_mojom(1, 2, 3, 4)), |
| Some(3.14), |
| Some(2.71828), |
| ), |
| ); |
| |
| ARRAYS_OF_NULLABLES_TY.validate_mojomparse( |
| ArraysOfNullables { |
| bools: vec![Some(true), None, Some(false)], |
| empties: vec![None, Some(Empty {}), None, None, None], |
| enums: vec![Some(TestEnum::Seven), None, Some(TestEnum::Zero), Some(TestEnum::Seven)], |
| unions: vec![Some(BaseUnion::n1(5)), None, Some(BaseUnion::b1(true))], |
| }, |
| arrays_of_nullables_mojom( |
| vec![Some(true), None, Some(false)], |
| vec![None, Some(Empty {}), None, None, None], |
| vec![Some(TestEnum::Seven), None, Some(TestEnum::Zero), Some(TestEnum::Seven)], |
| vec![Some(BaseUnion::n1(5)), None, Some(BaseUnion::b1(true))], |
| ), |
| ); |
| |
| NULLABLE_ARRAYS_TY.validate_mojomparse( |
| NullableArrays { |
| null_arr: Some(vec![true, false, true]), |
| double_null_arr: Some(vec![Some(true), None, Some(false)]), |
| }, |
| nullable_arrays_mojom( |
| Some(vec![true, false, true]), |
| Some(vec![Some(true), None, Some(false)]), |
| ), |
| ); |
| NULLABLE_ARRAYS_TY.validate_mojomparse( |
| NullableArrays { null_arr: None, double_null_arr: None }, |
| nullable_arrays_mojom(None, None), |
| ); |
| |
| UNION_WITH_NULLABLES_TY |
| .validate_mojomparse(UnionWithNullables::e(None), union_with_nullables_mojom_e(None)); |
| UNION_WITH_NULLABLES_TY |
| .validate_mojomparse(UnionWithNullables::str(None), union_with_nullables_mojom_str(None)); |
| UNION_WITH_NULLABLES_TY |
| .validate_mojomparse(UnionWithNullables::u(None), union_with_nullables_mojom_u(None)); |
| |
| UNION_WITH_NULLABLES_TY.validate_mojomparse( |
| UnionWithNullables::e(Some(Empty {})), |
| union_with_nullables_mojom_e(Some(Empty {})), |
| ); |
| UNION_WITH_NULLABLES_TY.validate_mojomparse( |
| UnionWithNullables::str(Some("hello".to_string())), |
| union_with_nullables_mojom_str(Some("hello")), |
| ); |
| UNION_WITH_NULLABLES_TY.validate_mojomparse( |
| UnionWithNullables::u(Some(BaseUnion::n1(123))), |
| union_with_nullables_mojom_u(Some(base_union_mojom_n1(123))), |
| ); |
| UNION_WITH_NULLABLES_TY.validate_mojomparse( |
| UnionWithNullables::u(Some(BaseUnion::b1(true))), |
| union_with_nullables_mojom_u(Some(base_union_mojom_b1(true))), |
| ); |
| UNION_WITH_NULLABLES_TY.validate_mojomparse( |
| UnionWithNullables::u(Some(BaseUnion::f1(FourInts { a: 1, b: 2, c: 3, d: 4 }))), |
| union_with_nullables_mojom_u(Some(base_union_mojom_f1(four_ints_mojom(1, 2, 3, 4)))), |
| ); |
| |
| NULLABLE_OTHERS_TY.validate_mojomparse( |
| NullableOthers { u: None, m: None, str: None }, |
| nullable_others_mojom(None, None, None), |
| ); |
| NULLABLE_OTHERS_TY.validate_mojomparse( |
| NullableOthers { |
| u: Some(UnionWithNullables::u(Some(BaseUnion::n1(42)))), |
| m: Some([(1, 2), (3, 4)].into()), |
| str: Some("hello".to_string()), |
| }, |
| nullable_others_mojom( |
| Some(union_with_nullables_mojom_u(Some(base_union_mojom_n1(42)))), |
| Some([(1, 2), (3, 4)].into()), |
| Some("hello"), |
| ), |
| ); |
| } |
| |
| // Mojom Definition: |
| // struct Handles { |
| // handle h1; |
| // handle? h2; |
| // handle<message_pipe> h3; |
| // handle<message_pipe>? h4; |
| // } |
| static HANDLES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "Handles", |
| base_type: wrap_struct_fields_type(vec![ |
| ("h1".to_string(), MojomType::Handle), |
| ("h2".to_string(), nullable_ty!(MojomType::Handle)), |
| ("h3".to_string(), MojomType::Handle), |
| ("h4".to_string(), nullable_ty!(MojomType::Handle)), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("h1".to_string(), struct_leaf!(0, PackedLeafType::Handle, false)), |
| ("h2".to_string(), struct_leaf!(1, PackedLeafType::Handle, true)), |
| ("h3".to_string(), struct_leaf!(2, PackedLeafType::Handle, false)), |
| ("h4".to_string(), struct_leaf!(3, PackedLeafType::Handle, true)), |
| ], |
| 4, |
| ), |
| }); |
| |
| fn handles_mojom( |
| h1: UntypedHandle, |
| h2: Option<UntypedHandle>, |
| h3: UntypedHandle, |
| h4: Option<UntypedHandle>, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("h1".to_string(), MojomValue::Handle(h1)), |
| ("h2".to_string(), nullable_val!(h2.map(MojomValue::Handle))), |
| ("h3".to_string(), MojomValue::Handle(h3)), |
| ("h4".to_string(), nullable_val!(h4.map(MojomValue::Handle))), |
| ]) |
| } |
| |
| // Mojom Definition: |
| // union WithHandles { |
| // handle? h1; |
| // handle<message_pipe> h2; |
| // uint8 n; |
| // } |
| static WITH_HANDLES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "WithHandles", |
| base_type: MojomType::Union { |
| variants: [ |
| (0, nullable_ty!(MojomType::Handle)), |
| (1, MojomType::Handle), |
| (2, MojomType::UInt8), |
| ] |
| .into(), |
| }, |
| packed_type: MojomWireType::Union { |
| variants: [ |
| (0, bare_leaf!(PackedLeafType::Handle, true)), |
| (1, bare_leaf!(PackedLeafType::Handle)), |
| (2, bare_leaf!(PackedLeafType::UInt8)), |
| ] |
| .into(), |
| is_nullable: false, |
| }, |
| }); |
| |
| fn base_union_mojom_h1(h1: Option<UntypedHandle>) -> MojomValue { |
| MojomValue::Union(0, Box::new(nullable_val!(h1.map(MojomValue::Handle)))) |
| } |
| |
| fn base_union_mojom_h2(h2: UntypedHandle) -> MojomValue { |
| MojomValue::Union(1, Box::new(MojomValue::Handle(h2))) |
| } |
| |
| fn base_union_mojom_n(e1: u8) -> MojomValue { |
| MojomValue::Union(2, Box::new(MojomValue::UInt8(e1))) |
| } |
| |
| // Mojom Definition: |
| // array<handle?> |
| static ARRAY_NULL_HANDLE_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "array<handle?>", |
| base_type: array!(nullable_ty!(MojomType::Handle), None), |
| packed_type: packed_array!(bare_leaf!(PackedLeafType::Handle, true), None), |
| }); |
| |
| fn array_null_handle_mojom(elts: Vec<Option<UntypedHandle>>) -> MojomValue { |
| MojomValue::Array( |
| elts.into_iter().map(|elt| nullable_val!(elt.map(MojomValue::Handle))).collect(), |
| ) |
| } |
| |
| // Mojom Definition: |
| // struct NestedHandles { |
| // handle h1; |
| // array<handle?> arr; |
| // handle h2; |
| // WithHandles wh; |
| // handle h3; |
| // }; |
| static NESTED_HANDLES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { |
| type_name: "NestedHandles", |
| base_type: wrap_struct_fields_type(vec![ |
| ("h1".to_string(), MojomType::Handle), |
| ("arr".to_string(), ARRAY_NULL_HANDLE_TY.base_type.clone()), |
| ("h2".to_string(), MojomType::Handle), |
| ("wh".to_string(), WITH_HANDLES_TY.base_type.clone()), |
| ("h3".to_string(), MojomType::Handle), |
| ]), |
| packed_type: wrap_packed_struct_fields( |
| vec![ |
| ("h1".to_string(), struct_leaf!(0, PackedLeafType::Handle)), |
| ("h2".to_string(), struct_leaf!(2, PackedLeafType::Handle)), |
| ("arr".to_string(), ARRAY_NULL_HANDLE_TY.as_struct_field(1)), |
| ("wh".to_string(), WITH_HANDLES_TY.as_struct_field(3)), |
| ("h3".to_string(), struct_leaf!(4, PackedLeafType::Handle)), |
| ], |
| 5, |
| ), |
| }); |
| |
| fn nested_handles_mojom( |
| h1: UntypedHandle, |
| arr: Vec<Option<UntypedHandle>>, |
| h2: UntypedHandle, |
| wh: MojomValue, |
| h3: UntypedHandle, |
| ) -> MojomValue { |
| wrap_struct_fields_value(vec![ |
| ("h1".to_string(), MojomValue::Handle(h1)), |
| ("arr".to_string(), array_null_handle_mojom(arr)), |
| ("h2".to_string(), MojomValue::Handle(h2)), |
| ("wh".to_string(), wh), |
| ("h3".to_string(), MojomValue::Handle(h3)), |
| ]) |
| } |
| |
| #[gtest(RustTestMojomParsingAttr, TestHandles)] |
| fn test_handles() { |
| HANDLES_TY.validate_mojomparse_handles( |
| Handles { h1: dummy_handle(), h2: None, h3: dummy_handle().into(), h4: None }, |
| || handles_mojom(dummy_handle(), None, dummy_handle(), None), |
| ); |
| |
| HANDLES_TY.validate_mojomparse_handles( |
| Handles { |
| h1: dummy_handle(), |
| h2: Some(dummy_handle()), |
| h3: dummy_handle().into(), |
| h4: Some(dummy_handle().into()), |
| }, |
| || { |
| handles_mojom( |
| dummy_handle(), |
| Some(dummy_handle()), |
| dummy_handle(), |
| Some(dummy_handle()), |
| ) |
| }, |
| ); |
| |
| WITH_HANDLES_TY |
| .validate_mojomparse_handles(WithHandles::h1(None), || base_union_mojom_h1(None)); |
| WITH_HANDLES_TY.validate_mojomparse_handles(WithHandles::h1(Some(dummy_handle())), || { |
| base_union_mojom_h1(Some(dummy_handle())) |
| }); |
| WITH_HANDLES_TY.validate_mojomparse_handles(WithHandles::h2(dummy_handle().into()), || { |
| base_union_mojom_h2(dummy_handle()) |
| }); |
| WITH_HANDLES_TY.validate_mojomparse_handles(WithHandles::n(42), || base_union_mojom_n(42)); |
| |
| NESTED_HANDLES_TY.validate_mojomparse_handles( |
| NestedHandles { |
| h1: dummy_handle(), |
| arr: vec![Some(dummy_handle()), None, Some(dummy_handle())], |
| h2: dummy_handle(), |
| wh: WithHandles::h2(dummy_handle().into()), |
| h3: dummy_handle(), |
| }, |
| || { |
| nested_handles_mojom( |
| dummy_handle(), |
| vec![Some(dummy_handle()), None, Some(dummy_handle())], |
| dummy_handle(), |
| base_union_mojom_h2(dummy_handle()), |
| dummy_handle(), |
| ) |
| }, |
| ); |
| } |