Skip to content

Commit 2535840

Browse files
vivien-applepull[bot]
authored andcommitted
[matter_idl] Add min_value/max_value/min_length supports when parsing the xml files (#27314)
1 parent 8cd2941 commit 2535840

File tree

4 files changed

+72
-8
lines changed

4 files changed

+72
-8
lines changed

scripts/py_matter_idl/matter_idl/generators/types.py

+26
Original file line numberDiff line numberDiff line change
@@ -412,3 +412,29 @@ def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[Basic
412412
"Data type %s is NOT known, but treating it as a generic IDL type." % data_type)
413413

414414
return result
415+
416+
417+
def IsSignedDataType(data_type: DataType) -> bool:
418+
"""
419+
Returns if the data type is a signed type.
420+
Returns if the data type is a signed data type of False if the data type can not be found.
421+
"""
422+
lowercase_name = data_type.name.lower()
423+
sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None)
424+
if sized_type is None:
425+
return False
426+
427+
return sized_type.is_signed
428+
429+
430+
def GetDataTypeSizeInBits(data_type: DataType) -> int:
431+
"""
432+
Returns the size in bits for a given data type or None if the data type can not be found.
433+
"""
434+
435+
lowercase_name = data_type.name.lower()
436+
sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None)
437+
if sized_type is None:
438+
return None
439+
440+
return sized_type.power_of_two_bits

scripts/py_matter_idl/matter_idl/matter_idl_types.py

+5
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,13 @@ class DataType:
9999
name: str
100100

101101
# Applies for strings (char or binary)
102+
min_length: Optional[int] = None
102103
max_length: Optional[int] = None
103104

105+
# Applies for numbers
106+
min_value: Optional[int] = None
107+
max_value: Optional[int] = None
108+
104109

105110
@dataclass
106111
class Field:

scripts/py_matter_idl/matter_idl/test_xml_parser.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def testCluster(self):
5959
<code>0x1234</code>
6060
<description>Test</description>
6161
62+
<attribute side="server" code="10" type="CHAR_STRING" minLength="2" length="10" isNullable="true" \
63+
reportable="true" writable="false">SomeCharStringAttribute</attribute>
64+
6265
<attribute side="server" code="11" type="INT32U" min="0" max="2" isNullable="true" \
6366
reportable="true" writable="false">SomeIntAttribute</attribute>
6467
@@ -93,15 +96,26 @@ def testCluster(self):
9396
description="Test",
9497
attributes=[
9598
Attribute(definition=Field(
96-
data_type=DataType(name='INT32U'),
99+
data_type=DataType(
100+
name='CHAR_STRING', min_length=2, max_length=10),
101+
code=10,
102+
name='SomeCharStringAttribute',
103+
qualities=FieldQuality.NULLABLE),
104+
qualities=AttributeQuality.READABLE,
105+
readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE),
106+
107+
Attribute(definition=Field(
108+
data_type=DataType(
109+
name='INT32U', min_value=0, max_value=2),
97110
code=11,
98111
name='SomeIntAttribute',
99112
qualities=FieldQuality.NULLABLE),
100113
qualities=AttributeQuality.READABLE,
101114
readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE),
102115

103116
Attribute(definition=Field(
104-
data_type=DataType(name='INT8U'),
117+
data_type=DataType(
118+
name='INT8U', min_value=0, max_value=10),
105119
code=22, name='AttributeWithAccess',
106120
qualities=FieldQuality.OPTIONAL),
107121
qualities=AttributeQuality.READABLE | AttributeQuality.WRITABLE,
@@ -214,7 +228,10 @@ def testFabricScopedAndSensitive(self):
214228
name='Field3',
215229
qualities=FieldQuality.FABRIC_SENSITIVE),
216230
Field(data_type=DataType(name='int32u',
217-
max_length=None),
231+
min_length=None,
232+
max_length=None,
233+
min_value=None,
234+
max_value=None),
218235
code=10,
219236
name='Field10')],
220237
qualities=StructQuality.FABRIC_SCOPED)],
@@ -369,7 +386,7 @@ def testSkipsNotProcessedFields(self):
369386
Attribute(
370387
definition=Field(
371388
data_type=DataType(
372-
name='Type'),
389+
name='Type', min_value=0, max_value=9),
373390
code=0,
374391
name='Type',
375392
),

scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,23 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from matter_idl.generators.types import GetDataTypeSizeInBits, IsSignedDataType
1516
from matter_idl.matter_idl_types import AccessPrivilege, Attribute, AttributeQuality, DataType, Field, FieldQuality
1617

1718

18-
def ParseInt(value: str) -> int:
19-
"""Convert a string that is a known integer into an actual number.
19+
def ParseInt(value: str, data_type: DataType = None) -> int:
20+
"""
21+
Convert a string that is a known integer into an actual number.
2022
21-
Supports decimal or hex values prefixed with '0x'
23+
Supports decimal or hex values prefixed with '0x'
2224
"""
2325
if value.startswith('0x'):
24-
return int(value[2:], 16)
26+
value = int(value[2:], 16)
27+
if data_type and IsSignedDataType(data_type):
28+
bits = GetDataTypeSizeInBits(data_type)
29+
if value & (1 << (bits - 1)):
30+
value -= 1 << bits
31+
return value
2532
else:
2633
return int(value)
2734

@@ -60,9 +67,18 @@ def AttrsToAttribute(attrs) -> Attribute:
6067
else:
6168
data_type = DataType(name=attrs['type'])
6269

70+
if 'minLength' in attrs:
71+
data_type.min_length = ParseInt(attrs['minLength'])
72+
6373
if 'length' in attrs:
6474
data_type.max_length = ParseInt(attrs['length'])
6575

76+
if 'min' in attrs:
77+
data_type.min_value = ParseInt(attrs['min'], data_type)
78+
79+
if 'max' in attrs:
80+
data_type.max_value = ParseInt(attrs['max'], data_type)
81+
6682
field = Field(
6783
data_type=data_type,
6884
code=ParseInt(attrs['code']),

0 commit comments

Comments
 (0)