Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[matter_idl] Add min_value/max_value/min_length supports when parsing… #27314

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions scripts/py_matter_idl/matter_idl/generators/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,3 +412,29 @@ def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[Basic
"Data type %s is NOT known, but treating it as a generic IDL type." % data_type)

return result


def IsSignedDataType(data_type: DataType) -> bool:
"""
Returns if the data type is a signed type.
Returns if the data type is a signed data type of False if the data type can not be found.
"""
lowercase_name = data_type.name.lower()
sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None)
if sized_type is None:
return False

return sized_type.is_signed


def GetDataTypeSizeInBits(data_type: DataType) -> int:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return type is incorrect here: returning none implies Optional[int]

"""
Returns the size in bits for a given data type or None if the data type can not be found.
"""

lowercase_name = data_type.name.lower()
sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None)
if sized_type is None:
return None

return sized_type.power_of_two_bits
5 changes: 5 additions & 0 deletions scripts/py_matter_idl/matter_idl/matter_idl_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
25 changes: 21 additions & 4 deletions scripts/py_matter_idl/matter_idl/test_xml_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ def testCluster(self):
<code>0x1234</code>
<description>Test</description>

<attribute side="server" code="10" type="CHAR_STRING" minLength="2" length="10" isNullable="true" \
reportable="true" writable="false">SomeCharStringAttribute</attribute>

<attribute side="server" code="11" type="INT32U" min="0" max="2" isNullable="true" \
reportable="true" writable="false">SomeIntAttribute</attribute>

Expand Down Expand Up @@ -93,15 +96,26 @@ 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),
qualities=AttributeQuality.READABLE,
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,
Expand Down Expand Up @@ -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)],
Expand Down Expand Up @@ -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',
),
Expand Down
24 changes: 20 additions & 4 deletions scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.

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


def ParseInt(value: str) -> int:
"""Convert a string that is a known integer into an actual number.
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'
Supports decimal or hex values prefixed with '0x'
"""
if value.startswith('0x'):
return int(value[2:], 16)
value = int(value[2:], 16)
if data_type and IsSignedDataType(data_type):
bits = GetDataTypeSizeInBits(data_type)
if value & (1 << (bits - 1)):
value -= 1 << bits
return value
else:
return int(value)

Expand Down Expand Up @@ -60,9 +67,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']),
Expand Down