From 23c12ed2349bbcc43fb39bcf7b775f1b84f48c9d Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Wed, 14 Jun 2023 18:39:16 +0200 Subject: [PATCH] [matter_idl] Add min_value/max_value/min_length supports when parsing the xml files --- .../matter_idl/matter_idl_types.py | 5 +++ .../matter_idl/test_xml_parser.py | 25 +++++++++++--- .../matter_idl/zapxml/handlers/parsing.py | 34 +++++++++++++++++-- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/scripts/py_matter_idl/matter_idl/matter_idl_types.py b/scripts/py_matter_idl/matter_idl/matter_idl_types.py index 9e3b4beb53ed79..eb86e3ec4b99fc 100644 --- a/scripts/py_matter_idl/matter_idl/matter_idl_types.py +++ b/scripts/py_matter_idl/matter_idl/matter_idl_types.py @@ -99,8 +99,13 @@ class DataType: name: str # Applies for strings (char or binary) + min_length: Optional[int] = None max_length: Optional[int] = None + # Applies for numbers + min_value: Optional[int] = None + max_value: Optional[int] = None + @dataclass class Field: diff --git a/scripts/py_matter_idl/matter_idl/test_xml_parser.py b/scripts/py_matter_idl/matter_idl/test_xml_parser.py index 7828c4219694fd..d8c7bb0a6c5dc1 100755 --- a/scripts/py_matter_idl/matter_idl/test_xml_parser.py +++ b/scripts/py_matter_idl/matter_idl/test_xml_parser.py @@ -59,6 +59,9 @@ def testCluster(self): 0x1234 Test + SomeCharStringAttribute + SomeIntAttribute @@ -93,7 +96,17 @@ def testCluster(self): description="Test", attributes=[ Attribute(definition=Field( - data_type=DataType(name='INT32U'), + data_type=DataType( + name='CHAR_STRING', min_length=2, max_length=10), + code=10, + name='SomeCharStringAttribute', + qualities=FieldQuality.NULLABLE), + qualities=AttributeQuality.READABLE, + readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE), + + Attribute(definition=Field( + data_type=DataType( + name='INT32U', min_value=0, max_value=2), code=11, name='SomeIntAttribute', qualities=FieldQuality.NULLABLE), @@ -101,7 +114,8 @@ def testCluster(self): readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE), Attribute(definition=Field( - data_type=DataType(name='INT8U'), + data_type=DataType( + name='INT8U', min_value=0, max_value=10), code=22, name='AttributeWithAccess', qualities=FieldQuality.OPTIONAL), qualities=AttributeQuality.READABLE | AttributeQuality.WRITABLE, @@ -214,7 +228,10 @@ def testFabricScopedAndSensitive(self): name='Field3', qualities=FieldQuality.FABRIC_SENSITIVE), Field(data_type=DataType(name='int32u', - max_length=None), + min_length=None, + max_length=None, + min_value=None, + max_value=None), code=10, name='Field10')], qualities=StructQuality.FABRIC_SCOPED)], @@ -369,7 +386,7 @@ def testSkipsNotProcessedFields(self): Attribute( definition=Field( data_type=DataType( - name='Type'), + name='Type', min_value=0, max_value=9), code=0, name='Type', ), diff --git a/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py b/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py index 09243a627fea5e..cfa3bd59cd3315 100644 --- a/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py +++ b/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py @@ -14,14 +14,35 @@ from matter_idl.matter_idl_types import AccessPrivilege, Attribute, AttributeQuality, DataType, Field, FieldQuality +SIGNED_INTEGER_TYPES = { + 'int8s': 1, + 'int16s': 2, + 'int24s': 4, + 'int32s': 4, + 'int40s': 8, + 'int48s': 8, + 'int56s': 8, + 'int64s': 8, + 'temperature': 2, +} -def ParseInt(value: str) -> int: + +def IsSignedType(data_type: DataType) -> bool: + return data_type and data_type.name.lower() in SIGNED_INTEGER_TYPES.keys() + + +def ParseInt(value: str, data_type: DataType = None) -> int: """Convert a string that is a known integer into an actual number. Supports decimal or hex values prefixed with '0x' """ if value.startswith('0x'): - return int(value[2:], 16) + value = int(value[2:], 16) + if IsSignedType(data_type): + bits = SIGNED_INTEGER_TYPES[data_type.name.lower()] * 8 + if value & (1 << (bits - 1)): + value -= 1 << bits + return value else: return int(value) @@ -60,9 +81,18 @@ def AttrsToAttribute(attrs) -> Attribute: else: data_type = DataType(name=attrs['type']) + if 'minLength' in attrs: + data_type.min_length = ParseInt(attrs['minLength']) + if 'length' in attrs: data_type.max_length = ParseInt(attrs['length']) + if 'min' in attrs: + data_type.min_value = ParseInt(attrs['min'], data_type) + + if 'max' in attrs: + data_type.max_value = ParseInt(attrs['max'], data_type) + field = Field( data_type=data_type, code=ParseInt(attrs['code']),