From af2e1ef31749984dc7c054850f5dfb17666d021b Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 20 Jan 2022 22:29:25 -0500 Subject: [PATCH] Add support for datatype sizes and unit tests --- scripts/idl/matter_grammar.lark | 6 ++-- scripts/idl/matter_idl_parser.py | 9 ++++++ scripts/idl/matter_idl_types.py | 12 ++++++-- scripts/idl/test_matter_idl_parser.py | 41 ++++++++++++++++++++------- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/scripts/idl/matter_grammar.lark b/scripts/idl/matter_grammar.lark index 335a853b0ce8a4..b7c388bcb9c061 100644 --- a/scripts/idl/matter_grammar.lark +++ b/scripts/idl/matter_grammar.lark @@ -1,5 +1,5 @@ struct: "struct"i id "{" struct_field* "}" -enum: "enum"i id ":" type "{" enum_entry* "}" +enum: "enum"i id ":" data_type "{" enum_entry* "}" event: event_priority "event"i id "=" number "{" struct_field* "}" @@ -34,9 +34,11 @@ struct_field: member_attribute* field member_attribute: "optional"i -> optional | "nullable"i -> nullable -field: type id list_marker? "=" number ";" +field: data_type id list_marker? "=" number ";" list_marker: "[" "]" +data_type: type ("<" number ">")? + id: ID type: ID diff --git a/scripts/idl/matter_idl_parser.py b/scripts/idl/matter_idl_parser.py index 1ade381f5b2dc7..29b71d0caa62fb 100755 --- a/scripts/idl/matter_idl_parser.py +++ b/scripts/idl/matter_idl_parser.py @@ -46,6 +46,15 @@ def type(self, tokens): raise Error("Unexpected argument counts") return tokens[0].value + def data_type(self, tokens): + if len(tokens) == 1: + return DataType(name=tokens[0]) + # Just a string for data type + elif len(tokens) == 2: + return DataType(name=tokens[0], max_length=tokens[1]) + else: + raise Error("Unexpected size for data type") + @v_args(inline=True) def enum_entry(self, id, number): return EnumEntry(name=id, code=number) diff --git a/scripts/idl/matter_idl_types.py b/scripts/idl/matter_idl_types.py index 7ebc5b7cadb25e..587a45232068ba 100644 --- a/scripts/idl/matter_idl_types.py +++ b/scripts/idl/matter_idl_types.py @@ -1,7 +1,7 @@ import enum from dataclasses import dataclass, field -from typing import List, Set +from typing import List, Set, Union class FieldAttribute(enum.Enum): @@ -36,6 +36,14 @@ class EndpointContentType(enum.Enum): CLIENT_BINDING = enum.auto() +@dataclass +class DataType: + name: str + + # Applies for strings (char or binary) + max_length: Union[int, None] = None + + @dataclass class Field: data_type: str @@ -67,7 +75,7 @@ def is_global(self): class Struct: name: str fields: List[Field] - tag: StructTag = None + tag: Union[StructTag, None] = None @dataclass diff --git a/scripts/idl/test_matter_idl_parser.py b/scripts/idl/test_matter_idl_parser.py index 19c6d676364750..6acabea02956fd 100755 --- a/scripts/idl/test_matter_idl_parser.py +++ b/scripts/idl/test_matter_idl_parser.py @@ -56,7 +56,7 @@ def test_global_enum(self): """) expected = Idl(enums=[ - Enum(name='GlobalEnum', base_type='ENUM8', + Enum(name='GlobalEnum', base_type=DataType(name='ENUM8'), entries=[ EnumEntry(name="kValue1", code=1), EnumEntry(name="kOther", code=0x12), @@ -77,10 +77,10 @@ def test_global_struct(self): Struct(name='Something', fields=[ Field( - data_type="CHAR_STRING", code=1, name="astring", ), - Field(data_type="CLUSTER_ID", code=2, name="idlist", is_list=True, attributes=set( + data_type=DataType(name="CHAR_STRING"), code=1, name="astring", ), + Field(data_type=DataType(name="CLUSTER_ID"), code=2, name="idlist", is_list=True, attributes=set( [FieldAttribute.OPTIONAL])), - Field(data_type="int", code=0x123, name="valueThatIsNullable", attributes=set( + Field(data_type=DataType(name="int"), code=0x123, name="valueThatIsNullable", attributes=set( [FieldAttribute.NULLABLE])), ])] ) @@ -102,13 +102,34 @@ def test_cluster_attribute(self): code=0x321, attributes=[ Attribute(tags=set([AttributeTag.READABLE]), definition=Field( - data_type="int8u", code=1, name="roAttr")), + data_type=DataType(name="int8u"), code=1, name="roAttr")), Attribute(tags=set([AttributeTag.READABLE, AttributeTag.WRITABLE]), definition=Field( - data_type="int32u", code=123, name="rwAttr", is_list=True)), + data_type=DataType(name="int32u"), code=123, name="rwAttr", is_list=True)), Attribute(tags=set([AttributeTag.GLOBAL, AttributeTag.READABLE, AttributeTag.WRITABLE]), definition=Field( - data_type="int32u", code=124, name="grwAttr", is_list=True)), + data_type=DataType(name="int32u"), code=124, name="grwAttr", is_list=True)), Attribute(tags=set([AttributeTag.GLOBAL, AttributeTag.READABLE]), definition=Field( - data_type="int32u", code=125, name="groAttr", is_list=True)), + data_type=DataType(name="int32u"), code=125, name="groAttr", is_list=True)), + ] + )]) + self.assertEqual(actual, expected) + + def test_sized_attribute(self): + actual = parseText(""" + server cluster MyCluster = 1 { + attribute char_string<11> attr1 = 1; + attribute octet_string<33> attr2[] = 2; + } + """) + + expected = Idl(clusters=[ + Cluster(side=ClusterSide.SERVER, + name="MyCluster", + code=1, + attributes=[ + Attribute(tags=set([AttributeTag.READABLE, AttributeTag.WRITABLE]), definition=Field( + data_type=DataType(name="char_string", max_length=11), code=1, name="attr1")), + Attribute(tags=set([AttributeTag.READABLE, AttributeTag.WRITABLE]), definition=Field( + data_type=DataType(name="octet_string", max_length=33), code=2, name="attr2", is_list=True)), ] )]) self.assertEqual(actual, expected) @@ -158,7 +179,7 @@ def test_cluster_enum(self): name="WithEnums", code=0xab, enums=[ - Enum(name="TestEnum", base_type="ENUM16", + Enum(name="TestEnum", base_type=DataType(name="ENUM16"), entries=[ EnumEntry(name="A", code=0x123), EnumEntry(name="B", code=0x234), @@ -182,7 +203,7 @@ def test_cluster_events(self): code=0x123, events=[ Event(priority=EventPriority.CRITICAL, name="StartUp", code=0, fields=[ - Field(data_type="INT32U", + Field(data_type=DataType(name="INT32U"), code=0, name="softwareVersion"), ]), Event(priority=EventPriority.INFO,