From d8dbcb4fb20a2ab992360f6e130285e92efc5bb6 Mon Sep 17 00:00:00 2001 From: marcos <15697303+gmarcosb@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:53:20 -0700 Subject: [PATCH] Update zapt templates to handle typedef --- .../templates/commands.zapt | 29 ++---- .../templates/partials/decodable_value.zapt | 28 +++--- .../data_model_xml/handlers/handlers.py | 26 ++++- .../matter_idl/generators/idl/MatterIdl.jinja | 11 +++ .../matter_idl/generators/java/__init__.py | 21 ++-- .../matter_idl/generators/kotlin/__init__.py | 4 +- .../matter_idl/generators/type_definitions.py | 47 ++++++++- .../matter_idl/matter_grammar.lark | 5 +- .../matter_idl/matter_idl_parser.py | 28 +++++- .../matter_idl/matter_idl_types.py | 9 ++ .../matter_idl/test_matter_idl_parser.py | 16 ++- .../matter_idl/zapxml/handlers/handlers.py | 41 +++++++- scripts/tools/zap_regen_all.py | 2 + src/app/common/BUILD.gn | 6 ++ src/app/common/templates/templates.json | 9 ++ .../partials/cluster-typedefs-typedef.zapt | 2 + .../partials/idl/cluster_definition.zapt | 4 + .../partials/idl/global_types.zapt | 6 ++ .../templates/app/cluster-objects.zapt | 1 + .../templates/app/cluster-typedefs.zapt | 53 ++++++++++ .../zcl/data-model/chip/global-structs.xml | 1 + .../zcl/data-model/chip/global-typedefs.xml | 29 ++++++ .../zcl/data-model/chip/test-cluster.xml | 24 +++++ .../zcl/zcl-with-test-extensions.json | 11 ++- src/app/zap-templates/zcl/zcl.json | 11 ++- src/app/zap-templates/zcl/zcl.xsd | 13 ++- .../java/templates/partials/decode_value.zapt | 98 +++++++++---------- src/controller/java/templates/templates.json | 4 - .../templates/partials/typedef_def.zapt | 1 + .../templates/python-CHIPClusters-py.zapt | 6 +- .../templates/python-cluster-Objects-py.zapt | 16 ++- .../python/templates/templates.json | 4 + .../CHIP/templates/MTRBaseClusters.zapt | 11 +++ .../CHIP/templates/partials/decode_value.zapt | 52 +++++----- .../CHIP/templates/partials/encode_value.zapt | 32 +++--- .../CHIP/templates/partials/typedef_decl.zapt | 2 + .../Framework/CHIP/templates/templates.json | 4 + src/lib/core/BUILD.gn | 1 + 38 files changed, 509 insertions(+), 159 deletions(-) create mode 100644 src/app/zap-templates/partials/cluster-typedefs-typedef.zapt create mode 100644 src/app/zap-templates/templates/app/cluster-typedefs.zapt create mode 100644 src/app/zap-templates/zcl/data-model/chip/global-typedefs.xml create mode 100644 src/controller/python/templates/partials/typedef_def.zapt create mode 100644 src/darwin/Framework/CHIP/templates/partials/typedef_decl.zapt diff --git a/examples/darwin-framework-tool/templates/commands.zapt b/examples/darwin-framework-tool/templates/commands.zapt index 3b80f653c82a14..2b3206afbb6f5a 100644 --- a/examples/darwin-framework-tool/templates/commands.zapt +++ b/examples/darwin-framework-tool/templates/commands.zapt @@ -223,29 +223,14 @@ public: params.timedWriteTimeout = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil; {{#if_chip_complex}} - {{asObjectiveCType type parent.name}} value; - {{>decodable_value target="value" source="mValue" cluster=parent.name errorCode="return err;" depth=0}} + {{asObjectiveCType type parent.name}} value; + {{>decodable_value target="value" source="mValue" cluster=parent.name errorCode="return err;" depth=0}} + {{else if isNullable}} + {{asObjectiveCType type parent.name}} value; + {{>decodable_value target="value" source="mValue" cluster=parent.name isOptional=false isArray=false errorCode="return err;" depth=0}} {{else}} - {{#if isNullable}} - {{asObjectiveCType type parent.name}} value = nil; - if (!mValue.IsNull()) { - {{#if (isOctetString type)}} - value = [[NSData alloc] initWithBytes:mValue.Value().data() length:mValue.Value().size()]; - {{else if (isString type)}} - value = [[NSString alloc] initWithBytes:mValue.Value().data() length:mValue.Value().size() encoding:NSUTF8StringEncoding]; - {{else}} - value = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:mValue.Value()]; - {{/if}} - } - {{else}} - {{#if (isOctetString type)}} - {{asObjectiveCType type parent.name}} value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()]; - {{else if (isString type)}} - {{asObjectiveCType type parent.name}} value = [[NSString alloc] initWithBytes:mValue.data() length:mValue.size() encoding:NSUTF8StringEncoding]; - {{else}} - {{asObjectiveCType type parent.name}} value = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:mValue{{#if isNullable}}.Value(){{/if}}]; - {{/if}} - {{/if}} + {{asObjectiveCType type parent.name}} + {{>decodable_value target="value" source="mValue" cluster=parent.name isOptional=false isArray=false errorCode="return err;" depth=0}} {{/if_chip_complex}} [cluster write{{>attribute}}WithValue:value params:params completion:^(NSError * _Nullable error) { diff --git a/examples/darwin-framework-tool/templates/partials/decodable_value.zapt b/examples/darwin-framework-tool/templates/partials/decodable_value.zapt index 8d0442000a070c..1f81430200cb82 100644 --- a/examples/darwin-framework-tool/templates/partials/decodable_value.zapt +++ b/examples/darwin-framework-tool/templates/partials/decodable_value.zapt @@ -27,18 +27,24 @@ {{>decodable_value target=(concat ../target "." (asStructPropertyName label)) source=(concat ../source "." (asLowerCamelCase label)) cluster=../cluster depth=(incrementDepth ../depth) }} {{/zcl_struct_items_by_struct_and_cluster_name}} {{else}} - {{#if_is_strongly_typed_chip_enum type}} - {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:chip::to_underlying({{source}})]; + {{#if_is_typedef type}} + {{#zcl_typedef_by_typedef_and_cluster_name type cluster}} + {{>decodable_value target=../target source=../source errorCode=../errorCode cluster=../cluster depth=../depth }} + {{/zcl_typedef_by_typedef_and_cluster_name}} {{else}} - {{#if_is_strongly_typed_bitmap type}} - {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}.Raw()]; - {{else if (isOctetString type)}} - {{target}} = [NSData dataWithBytes:{{source}}.data() length:{{source}}.size()]; - {{else if (isCharString type)}} - {{target}} = [[NSString alloc] initWithBytes:{{source}}.data() length:{{source}}.size() encoding:NSUTF8StringEncoding]; + {{#if_is_strongly_typed_chip_enum type}} + {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:chip::to_underlying({{source}})]; {{else}} - {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}]; - {{/if_is_strongly_typed_bitmap}} - {{/if_is_strongly_typed_chip_enum}} + {{#if_is_strongly_typed_bitmap type}} + {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}.Raw()]; + {{else if (isOctetString type)}} + {{target}} = [NSData dataWithBytes:{{source}}.data() length:{{source}}.size()]; + {{else if (isCharString type)}} + {{target}} = [[NSString alloc] initWithBytes:{{source}}.data() length:{{source}}.size() encoding:NSUTF8StringEncoding]; + {{else}} + {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}]; + {{/if_is_strongly_typed_bitmap}} + {{/if_is_strongly_typed_chip_enum}} + {{/if_is_typedef}} {{/if_is_struct}} {{/if}} diff --git a/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/handlers.py b/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/handlers.py index 858ec6a19f6d87..07664912f792c5 100644 --- a/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/handlers.py +++ b/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/handlers.py @@ -18,7 +18,7 @@ from xml.sax.xmlreader import AttributesImpl from matter_idl.matter_idl_types import (ApiMaturity, Attribute, AttributeQuality, Bitmap, Cluster, Command, CommandQuality, - ConstantEntry, DataType, Enum, Field, FieldQuality, Idl, Struct, StructTag) + ConstantEntry, DataType, Enum, Field, FieldQuality, Idl, Struct, StructTag, Typedef) from .base import BaseHandler, HandledDepth from .context import Context @@ -178,6 +178,10 @@ def GetNextProcessor(self, name: str, attrs: AttributesImpl): self._field.data_type.name = NormalizeDataType(attrs["type"]) return BaseHandler(self.context, handled=HandledDepth.SINGLE_TAG) + elif name == "typedef": + LOGGER.warning( + f"Anonymous typedef not supported when handling field {self._field.name}") + return BaseHandler(self.context, handled=HandledDepth.ENTIRE_TREE) else: return BaseHandler(self.context) @@ -281,6 +285,24 @@ def GetNextProcessor(self, name: str, attrs: AttributesImpl): else: return BaseHandler(self.context) +class TypedefHandler(BaseHandler): + def __init__(self, context: Context, cluster: Cluster, attrs: AttributesImpl): + super().__init__(context, handled=HandledDepth.SINGLE_TAG) + self._cluster = cluster + + # TODO: base type is GUESSED here because xml does not contain it + self._typedef = Typedef(name=NormalizeName( + attrs["name"]), base_type="UNKNOWN") + + def EndProcessing(self): + self._cluster.typedefs.append(self._typedef) + + def GetNextProcessor(self, name: str, attrs: AttributesImpl): + if name == "section": + # Documentation data, skipped + return BaseHandler(self.context, handled=HandledDepth.ENTIRE_TREE) + else: + return BaseHandler(self.context) class EventsHandler(BaseHandler): def __init__(self, context: Context, cluster: Cluster): @@ -548,6 +570,8 @@ def GetNextProcessor(self, name: str, attrs: AttributesImpl): return BitmapHandler(self.context, self._cluster, attrs) elif name == "struct": return StructHandler(self.context, self._cluster, attrs) + elif name == "typedef": + return TypedefHandler(self.context, self._cluster, attrs) else: return BaseHandler(self.context) diff --git a/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja b/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja index 0e132e581b7712..160c882da92107 100644 --- a/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja +++ b/scripts/py_matter_idl/matter_idl/generators/idl/MatterIdl.jinja @@ -55,6 +55,10 @@ bitmap {{bitmap.name}} : {{ bitmap.base_type}} { {% endfor %} +{%- for typedef in idl.global_typedefs %} +typedef {{typedef.name}} : {{ typedef.base_type}}; +{% endfor %} + {%- for cluster in idl.clusters %} {% if cluster.description %}/** {{cluster.description}} */ {% endif %} @@ -83,6 +87,13 @@ bitmap {{bitmap.name}} : {{ bitmap.base_type}} { {% endfor %} + {%- for typedef in cluster.typedefs | selectattr("is_global")%} + /* GLOBAL: + typedef {{typedef.name}} : {{ typedef.base_type}}; + */ + + {% endfor %} + {%- for s in cluster.structs | selectattr("is_global") %} /* GLOBAL: {{render_struct(s) | indent(2)}} diff --git a/scripts/py_matter_idl/matter_idl/generators/java/__init__.py b/scripts/py_matter_idl/matter_idl/generators/java/__init__.py index d21107653dfb46..fd61e38bde2905 100644 --- a/scripts/py_matter_idl/matter_idl/generators/java/__init__.py +++ b/scripts/py_matter_idl/matter_idl/generators/java/__init__.py @@ -59,7 +59,7 @@ class GlobalType: def _UnderlyingType(field: Field, context: TypeLookupContext) -> Optional[str]: - actual = ParseDataType(field.data_type, context) + actual = ParseDataType(field.data_type, context, desugar_typedef = True) if isinstance(actual, (IdlEnumType, IdlBitmapType)): actual = actual.base_type @@ -132,7 +132,7 @@ def _CppType(field: Field, context: TypeLookupContext) -> str: if field.data_type.name.lower() in _KNOWN_DECODABLE_TYPES: return _KNOWN_DECODABLE_TYPES[field.data_type.name.lower()] - actual = ParseDataType(field.data_type, context) + actual = ParseDataType(field.data_type, context, desugar_typedef = True) if isinstance(actual, BasicString): if actual.is_binary: return 'chip::ByteSpan' @@ -278,7 +278,7 @@ def attributesWithSupportedCallback(attrs, context: TypeLookupContext): # Attributes will be generated for all types # except non-list structures if not attr.definition.is_list: - underlying = ParseDataType(attr.definition.data_type, context) + underlying = ParseDataType(attr.definition.data_type, context, desugar_typedef = True) if isinstance(underlying, IdlType): continue @@ -420,6 +420,10 @@ def is_bitmap(self): def is_untyped_bitmap(self): return self.context.is_untyped_bitmap_type(self.data_type.name) + @property + def is_typedef(self): + return self.context.is_typedef_type(self.data_type.name) + def clone(self): return EncodableValue(self.context, self.data_type, self.attrs) @@ -469,7 +473,7 @@ def jni_fundamental_type(self): @property def boxed_java_type(self): - t = ParseDataType(self.data_type, self.context) + t = ParseDataType(self.data_type, self.context, desugar_typedef = True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: @@ -506,7 +510,7 @@ def boxed_java_type(self): @property def java_tlv_type(self): - t = ParseDataType(self.data_type, self.context) + t = ParseDataType(self.data_type, self.context, desugar_typedef = True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: @@ -537,7 +541,8 @@ def java_tlv_type(self): @property def kotlin_type(self): - t = ParseDataType(self.data_type, self.context) + # TODO: Use inline value class where possible (types not defined in java) + t = ParseDataType(self.data_type, self.context, desugar_typedef = True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: @@ -583,7 +588,7 @@ def unboxed_java_signature(self): if self.is_optional or self.is_list: raise Exception("Not a basic type: %r" % self) - t = ParseDataType(self.data_type, self.context) + t = ParseDataType(self.data_type, self.context, desugar_typedef = True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: @@ -611,7 +616,7 @@ def boxed_java_signature(self): if self.is_list: return "Ljava/util/ArrayList;" - t = ParseDataType(self.data_type, self.context) + t = ParseDataType(self.data_type, self.context, desugar_typedef = True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: diff --git a/scripts/py_matter_idl/matter_idl/generators/kotlin/__init__.py b/scripts/py_matter_idl/matter_idl/generators/kotlin/__init__.py index 405f505a0980d3..c82f67d2e07496 100644 --- a/scripts/py_matter_idl/matter_idl/generators/kotlin/__init__.py +++ b/scripts/py_matter_idl/matter_idl/generators/kotlin/__init__.py @@ -420,7 +420,7 @@ def get_underlying_enum(self): @property def kotlin_type(self): - t = ParseDataType(self.data_type, self.context) + t = ParseDataType(self.data_type, self.context, desugar_typedef=True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: @@ -507,7 +507,7 @@ def boxed_java_signature(self): if self.is_list: return "Ljava/util/ArrayList;" - t = ParseDataType(self.data_type, self.context) + t = ParseDataType(self.data_type, self.context, desugar_typedef=True) if isinstance(t, FundamentalType): if t == FundamentalType.BOOL: diff --git a/scripts/py_matter_idl/matter_idl/generators/type_definitions.py b/scripts/py_matter_idl/matter_idl/generators/type_definitions.py index 4f9fa56779042b..44435eb4600391 100644 --- a/scripts/py_matter_idl/matter_idl/generators/type_definitions.py +++ b/scripts/py_matter_idl/matter_idl/generators/type_definitions.py @@ -161,6 +161,15 @@ def is_struct(self) -> bool: return self.item_type == IdlItemType.STRUCT +@dataclass +class IdlTypedefType: + """ + A typedef (concrete type that aliases another type) + """ + idl_name: str + base_type: Union[BasicInteger, BasicString, FundamentalType, IdlType, IdlEnumType, IdlBitmapType] + + # Data types, held by ZAP in chip-types.xml and generally by the spec. __CHIP_SIZED_TYPES__ = { "bitmap16": BasicInteger(idl_name="bitmap16", byte_count=2, is_signed=False), @@ -295,6 +304,13 @@ def find_bitmap(self, name) -> Optional[matter_idl_types.Bitmap]: return None + def find_typedef(self, name) -> Optional[matter_idl_types.Typedef]: + for s in self.all_typedefs: + if s.name == name: + return s + + return None + @property def all_enums(self): """ @@ -330,6 +346,18 @@ def all_structs(self): for e in self.cluster.structs: yield e + @property + def all_typedefs(self): + """ + All typedefs defined within this lookup context. + + typedefs are only defined at cluster level. If lookup context does not + include a typedef, the typedef list will be empty. + """ + if self.cluster: + for t in self.cluster.typedefs: + yield t + def is_enum_type(self, name: str): """ Determine if the given type name is an enumeration. @@ -347,6 +375,12 @@ def is_struct_type(self, name: str): """ return any(map(lambda s: s.name == name, self.all_structs)) + def is_typedef_type(self, name: str): + """ + Determine if the given type name is type that is known to be a typedef + """ + return any(map(lambda s: s.name == name, self.all_typedefs)) + def is_untyped_bitmap_type(self, name: str): """Determine if the given type is a untyped bitmap (just an interger size).""" return name.lower() in {"bitmap8", "bitmap16", "bitmap32", "bitmap64"} @@ -364,7 +398,7 @@ def is_bitmap_type(self, name: str): return any(map(lambda s: s.name == name, self.all_bitmaps)) -def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[BasicInteger, BasicString, FundamentalType, IdlType, IdlEnumType, IdlBitmapType]: +def ParseDataType(data_type: DataType, lookup: TypeLookupContext, desugar_typedef: bool = False) -> Union[BasicInteger, BasicString, FundamentalType, IdlType, IdlEnumType, IdlBitmapType, IdlTypedefType]: """ Given a AST data type and a lookup context, match it to a type that can be later be used for generation. @@ -404,9 +438,18 @@ def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[Basic b = lookup.find_bitmap(data_type.name) if b: - # Valid enum found. it MUST be based on a valid data type + # Valid bitmap found. it MUST be based on a valid data type return IdlBitmapType(idl_name=data_type.name, base_type=__CHIP_SIZED_TYPES__[b.base_type.lower()]) + t = lookup.find_typedef(data_type.name) + if t: + # Valid typedef found. it MUST be based on a valid data type + typedef_base_type = ParseDataType(DataType(name=t.base_type), lookup) + if desugar_typedef: + return typedef_base_type + else: + return IdlTypedefType(idl_name=data_type.name, base_type=typedef_base_type) + result = IdlType(idl_name=data_type.name, item_type=IdlItemType.UNKNOWN) if lookup.find_struct(data_type.name): result.item_type = IdlItemType.STRUCT diff --git a/scripts/py_matter_idl/matter_idl/matter_grammar.lark b/scripts/py_matter_idl/matter_idl/matter_grammar.lark index 4013c51bb52a59..befad5f8e97bdd 100644 --- a/scripts/py_matter_idl/matter_idl/matter_grammar.lark +++ b/scripts/py_matter_idl/matter_idl/matter_grammar.lark @@ -12,6 +12,7 @@ struct_qualities: struct_quality* enum: "enum"i id ":" type "{" constant_entry* "}" bitmap: "bitmap"i id ":" type "{" constant_entry* "}" +typedef: "typedef"i id ":" type ";" ?access_privilege: "view"i -> view_privilege | "operate"i -> operate_privilege @@ -68,7 +69,7 @@ cluster_revision: "revision"i positive_integer ";" // no direct meaning currently cluster: [maturity] ( "client" | "server" )? "cluster"i id "=" positive_integer "{" [cluster_revision] cluster_content* "}" -?cluster_content: [maturity] (enum|bitmap|event|attribute|struct|request_struct|response_struct|command) +?cluster_content: [maturity] (enum|bitmap|event|attribute|struct|request_struct|response_struct|command|typedef) endpoint: "endpoint"i positive_integer "{" endpoint_content* "}" ?endpoint_content: endpoint_cluster_binding | endpoint_server_cluster | endpoint_device_type @@ -116,7 +117,7 @@ POSITIVE_INTEGER: /\d+/ HEX_INTEGER: /0x[A-Fa-f0-9]+/ ID: /[a-zA-Z_][a-zA-Z0-9_]*/ -idl: (struct|enum|bitmap|cluster|endpoint)* +idl: (struct|enum|bitmap|cluster|endpoint|typedef)* %import common.ESCAPED_STRING %import common.WS diff --git a/scripts/py_matter_idl/matter_idl/matter_idl_parser.py b/scripts/py_matter_idl/matter_idl/matter_idl_parser.py index e071d008d1d726..20add72cf0bccd 100755 --- a/scripts/py_matter_idl/matter_idl/matter_idl_parser.py +++ b/scripts/py_matter_idl/matter_idl/matter_idl_parser.py @@ -23,7 +23,7 @@ AttributeStorage, Bitmap, Cluster, Command, CommandInstantiation, CommandQuality, ConstantEntry, DataType, DeviceType, Endpoint, Enum, Event, EventPriority, EventQuality, Field, FieldQuality, Idl, ParseMetaData, ServerClusterInstantiation, Struct, StructQuality, - StructTag) + StructTag, Typedef) def UnionOfAllFlags(flags_list): @@ -207,6 +207,10 @@ def enum(self, id, type, *entries): def bitmap(self, id, type, *entries): return Bitmap(name=id, base_type=type, entries=list(entries)) + @v_args(inline=True) + def typedef(self, id, type): + return Typedef(name=id, base_type=type) + def field(self, args): data_type, name = args[0], args[1] is_list = (len(args) == 4) @@ -496,6 +500,8 @@ def cluster(self, meta, api_maturity, name, code, revision, *content): result.structs.append(item) elif isinstance(item, Command): result.commands.append(item) + elif isinstance(item, Typedef): + result.typedefs.append(item) else: raise Exception("UNKNOWN cluster content item: %r" % item) @@ -508,6 +514,7 @@ def idl(self, items): global_bitmaps = [] global_enums = [] global_structs = [] + global_typedefs =[] for item in items: if isinstance(item, Cluster): @@ -520,10 +527,12 @@ def idl(self, items): global_bitmaps.append(dataclasses.replace(item, is_global=True)) elif isinstance(item, Struct): global_structs.append(dataclasses.replace(item, is_global=True)) + elif isinstance(item, Typedef): + global_typedefs.append(dataclasses.replace(item, is_global=True)) else: raise Exception("UNKNOWN idl content item: %r" % item) - return Idl(clusters=clusters, endpoints=endpoints, global_bitmaps=global_bitmaps, global_enums=global_enums, global_structs=global_structs) + return Idl(clusters=clusters, endpoints=endpoints, global_bitmaps=global_bitmaps, global_enums=global_enums, global_structs=global_structs, global_typedefs=global_typedefs) def prefix_doc_comment(self): print("TODO: prefix") @@ -563,15 +572,16 @@ def __init__(self, idl: Idl): self.bitmap_map = {b.name: b for b in idl.global_bitmaps} self.enum_map = {e.name: e for e in idl.global_enums} self.struct_map = {s.name: s for s in idl.global_structs} + self.typedef_map = {t.name: t for t in idl.global_typedefs} - self.global_types = set(self.bitmap_map.keys()).union(set(self.enum_map.keys())).union(set(self.struct_map.keys())) + self.global_types = set(self.bitmap_map.keys()).union(set(self.enum_map.keys())).union(set(self.struct_map.keys())).union(set(self.typedef_map.keys())) # Spec does not enforce unique naming in bitmap/enum/struct, however in practice # if we have both enum Foo and bitmap Foo for example, it would be impossible # to disambiguate `attribute Foo foo = 1` for the actual type we want. # # As a result, we do not try to namespace this and just error out - if len(self.global_types) != len(self.bitmap_map) + len(self.enum_map) + len(self.struct_map): + if len(self.global_types) != len(self.bitmap_map) + len(self.enum_map) + len(self.struct_map) + len(self.typedef_map): raise ValueError("Global type names are not unique.") def merge_global_types_into_cluster(self, cluster: Cluster) -> Cluster: @@ -604,6 +614,10 @@ def merge_global_types_into_cluster(self, cluster: Cluster) -> Cluster: global_types_added.add(type_name) changed = True cluster.structs.append(self.struct_map[type_name]) + elif type_name in self.typedef_map: + global_types_added.add(type_name) + changed = True + cluster.typedefs.append(self.typedef_map[type_name]) return cluster @@ -638,7 +652,11 @@ def __init__(self, skip_meta: bool, merge_globals: bool): ) def parse(self, file: str, file_name: Optional[str] = None): - idl = self.transformer.transform(self.parser.parse(file)) + idl = None + try: + idl = self.transformer.transform(self.parser.parse(file)) + except Exception as e: + raise Exception(f"Failed to parse: {file_name}") from e idl.parse_file_name = file_name # ZAP may generate the same definition of clusters several times. 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 d4a2195457ed60..4aee2ef3678441 100644 --- a/scripts/py_matter_idl/matter_idl/matter_idl_types.py +++ b/scripts/py_matter_idl/matter_idl/matter_idl_types.py @@ -206,6 +206,13 @@ class Bitmap: is_global: bool = False +@dataclass +class Typedef: + name: str + base_type: str + api_maturity: ApiMaturity = ApiMaturity.STABLE + is_global: bool = False + @dataclass class Command: name: str @@ -235,6 +242,7 @@ class Cluster: events: List[Event] = field(default_factory=list) attributes: List[Attribute] = field(default_factory=list) structs: List[Struct] = field(default_factory=list) + typedefs: List[Typedef] = field(default_factory=list) commands: List[Command] = field(default_factory=list) description: Optional[str] = None api_maturity: ApiMaturity = ApiMaturity.STABLE @@ -297,6 +305,7 @@ class Idl: global_bitmaps: List[Bitmap] = field(default_factory=list) global_enums: List[Enum] = field(default_factory=list) global_structs: List[Struct] = field(default_factory=list) + global_typedefs: List[Typedef] = field(default_factory=list) # IDL file name is available only if parsing provides a file name parse_file_name: Optional[str] = field(default=None) diff --git a/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py b/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py index ab79c279b0697f..405d9ad1e9bac1 100755 --- a/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py +++ b/scripts/py_matter_idl/matter_idl/test_matter_idl_parser.py @@ -34,7 +34,7 @@ from matter_idl.matter_idl_types import (AccessPrivilege, ApiMaturity, Attribute, AttributeInstantiation, AttributeQuality, AttributeStorage, Bitmap, Cluster, Command, CommandInstantiation, CommandQuality, ConstantEntry, DataType, DeviceType, Endpoint, Enum, Event, EventPriority, EventQuality, - Field, FieldQuality, Idl, ParseMetaData, ServerClusterInstantiation, Struct, StructTag) + Field, FieldQuality, Idl, ParseMetaData, ServerClusterInstantiation, Struct, StructTag, Typedef) class GeneratorContentStorage(GeneratorStorage): @@ -336,6 +336,20 @@ def test_cluster_enum(self): )]) self.assertIdlEqual(actual, expected) + def test_cluster_typedef(self): + actual = parseText(""" + client cluster WithTypedefs = 0xab { + typedef TestTypedef : int16u; + } + """) + expected = Idl(clusters=[ + Cluster(name="WithTypedefs", + code=0xab, + typedefs=[ + Typedef(name="TestTypedef", base_type="int16u")], + )]) + self.assertIdlEqual(actual, expected) + def test_event_field_api_maturity(self): actual = parseText(""" server cluster MaturityTest = 1 { diff --git a/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py b/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py index a303f263f10bc1..0b9700fd9ff2a2 100644 --- a/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py +++ b/scripts/py_matter_idl/matter_idl/zapxml/handlers/handlers.py @@ -16,7 +16,7 @@ from typing import Any, Optional from matter_idl.matter_idl_types import (Attribute, Bitmap, Cluster, Command, CommandQuality, ConstantEntry, DataType, Enum, Event, - EventPriority, EventQuality, Field, FieldQuality, Idl, Struct, StructQuality, StructTag) + EventPriority, EventQuality, Field, FieldQuality, Idl, Struct, StructQuality, StructTag, Typedef) from .base import BaseHandler, HandledDepth from .context import Context, IdlPostProcessor @@ -355,6 +355,43 @@ def FinalizeProcessing(self, idl: Idl): def EndProcessing(self): self.context.AddIdlPostProcessor(self) +class TypedefHandler(BaseHandler, IdlPostProcessor): + """ Handling /configurator/typedef elements.""" + + def __init__(self, context: Context, attrs): + super().__init__(context) + + # no cluster codes means global. Note that at the time + # of writing this, no global typedefs were defined in XMLs + self._cluster_codes = set() + self.typedef = Typedef(name=attrs['name'], + base_type=attrs['type']) + + def GetNextProcessor(self, name, attrs): + if name.lower() == 'cluster': + self._cluster_codes.add(ParseInt(attrs['code'])) + return BaseHandler(self.context, handled=HandledDepth.SINGLE_TAG) + else: + return BaseHandler(self.context) + + def FinalizeProcessing(self, idl: Idl): + if not self._cluster_codes: + idl.global_typedefs.append(self._typedef) + return + + found = set() + for c in idl.clusters: + if c.code in self._cluster_codes: + c.typedefs.append(self._typedef) + found.add(c.code) + + if found != self._cluster_codes: + LOGGER.error('Typedef %s could not find its clusters (codes: %r)' % + (self._typedef.name, self._cluster_codes - found)) + + def EndProcessing(self): + self.context.AddIdlPostProcessor(self) + class FeaturesHandler(BaseHandler): """Handles .../features @@ -704,5 +741,7 @@ def GetNextProcessor(self, name: str, attrs): return BaseHandler(self.context, handled=HandledDepth.ENTIRE_TREE) elif name.lower() == 'global': return GlobalHandler(self.context) + elif name.lower() == 'typedef': + return TypedefHandler(self.context, attrs) else: return BaseHandler(self.context) diff --git a/scripts/tools/zap_regen_all.py b/scripts/tools/zap_regen_all.py index 65fbab040ec58b..783a8a00535f55 100755 --- a/scripts/tools/zap_regen_all.py +++ b/scripts/tools/zap_regen_all.py @@ -312,6 +312,8 @@ def codeFormat(self): def generate(self) -> TargetRunStats: generate_start = time.time() + logging.info("Executing: %s" % self.command) + subprocess.check_call(self.command) self.codeFormat() diff --git a/src/app/common/BUILD.gn b/src/app/common/BUILD.gn index 36022674cc053a..d17fee37c251ee 100644 --- a/src/app/common/BUILD.gn +++ b/src/app/common/BUILD.gn @@ -68,3 +68,9 @@ source_set("enums") { public_configs = [ ":includes" ] } + +source_set("typedefs") { + sources = [ "${chip_root}/zzz_generated/app-common/app-common/zap-generated/cluster-typedefs.h" ] + + public_configs = [ ":includes" ] +} diff --git a/src/app/common/templates/templates.json b/src/app/common/templates/templates.json index 148ab5419f5b84..4fe98783763d35 100644 --- a/src/app/common/templates/templates.json +++ b/src/app/common/templates/templates.json @@ -25,6 +25,10 @@ "name": "cluster_enums_enum", "path": "../../zap-templates/partials/cluster-enums-enum.zapt" }, + { + "name": "cluster_typedefs_typedef", + "path": "../../zap-templates/partials/cluster-typedefs-typedef.zapt" + }, { "name": "cluster_enums_ensure_known_value", "path": "../../zap-templates/partials/cluster-enums-ensure-known-value.zapt" @@ -98,6 +102,11 @@ "path": "../../zap-templates/templates/app/cluster-enums-check.zapt", "name": "Enum and bitmap method check header for clusters", "output": "cluster-enums-check.h" + }, + { + "path": "../../zap-templates/templates/app/cluster-typedefs.zapt", + "name": "Typedef header for clusters", + "output": "cluster-typedefs.h" } ] } diff --git a/src/app/zap-templates/partials/cluster-typedefs-typedef.zapt b/src/app/zap-templates/partials/cluster-typedefs-typedef.zapt new file mode 100644 index 00000000000000..9bf5e237922c2b --- /dev/null +++ b/src/app/zap-templates/partials/cluster-typedefs-typedef.zapt @@ -0,0 +1,2 @@ +// Typedef for {{label}} +using {{asType label}} = {{zapTypeToEncodableClusterObjectType type}}; \ No newline at end of file diff --git a/src/app/zap-templates/partials/idl/cluster_definition.zapt b/src/app/zap-templates/partials/idl/cluster_definition.zapt index be431ae7d7cc2c..ba78e828d27fdb 100644 --- a/src/app/zap-templates/partials/idl/cluster_definition.zapt +++ b/src/app/zap-templates/partials/idl/cluster_definition.zapt @@ -22,6 +22,10 @@ cluster {{asUpperCamelCase name}} = {{!}} } {{/zcl_enums}} + {{#zcl_typedefs}} + typedef {{asUpperCamelCase name preserveAcronyms=true}} : {{type}}; + + {{/zcl_typedefs}} {{#zcl_bitmaps}} bitmap {{asUpperCamelCase name preserveAcronyms=true}} : bitmap{{multiply size 8}} { {{#zcl_bitmap_items}} diff --git a/src/app/zap-templates/partials/idl/global_types.zapt b/src/app/zap-templates/partials/idl/global_types.zapt index bd72b43b2b36b5..f793ea9cede903 100644 --- a/src/app/zap-templates/partials/idl/global_types.zapt +++ b/src/app/zap-templates/partials/idl/global_types.zapt @@ -8,6 +8,12 @@ enum {{asUpperCamelCase name preserveAcronyms=true}} : enum{{multiply size 8}} { {{/if}} {{/zcl_enums}} +{{#zcl_typedefs}} +{{#if has_no_clusters}} +typedef {{asUpperCamelCase name preserveAcronyms=true}} : {{type}}; + +{{/if}} +{{/zcl_typedefs}} {{#zcl_bitmaps}} {{#if has_no_clusters}} {{#if_is_atomic name}} diff --git a/src/app/zap-templates/templates/app/cluster-objects.zapt b/src/app/zap-templates/templates/app/cluster-objects.zapt index 00cd367f85bfcb..8ccc0f2e8c8fa9 100644 --- a/src/app/zap-templates/templates/app/cluster-objects.zapt +++ b/src/app/zap-templates/templates/app/cluster-objects.zapt @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/src/app/zap-templates/templates/app/cluster-typedefs.zapt b/src/app/zap-templates/templates/app/cluster-typedefs.zapt new file mode 100644 index 00000000000000..fc6e8c2a009113 --- /dev/null +++ b/src/app/zap-templates/templates/app/cluster-typedefs.zapt @@ -0,0 +1,53 @@ +{{> header}} + +#pragma once + +#include + + +namespace chip { +namespace app { +namespace Clusters { + +namespace detail { +// typedefs shared across multiple clusters. +{{#zcl_typedefs}} + +{{#if has_more_than_one_cluster}} + +{{> cluster_typedefs_typedef ns=""}} + +{{/if}} +{{/zcl_typedefs}} + +} // namespace detail + +namespace Globals { +// Global typedefs. +{{#zcl_typedefs}} + +{{#if has_no_clusters}} + +{{> cluster_typedefs_typedef ns=""}} + +{{/if}} +{{/zcl_typedefs}} +} // namespace Globals + +{{#zcl_clusters}} +namespace {{asUpperCamelCase name}} { +{{#zcl_typedefs}} + +{{#if has_more_than_one_cluster}} +using {{asUpperCamelCase name}} = Clusters::detail::{{asUpperCamelCase name}}; +{{else}} +{{> cluster_typedefs_typedef ns=(asUpperCamelCase ../name)}} + +{{/if}} +{{/zcl_typedefs}} +} // namespace {{asUpperCamelCase name}} + +{{/zcl_clusters}} +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/zap-templates/zcl/data-model/chip/global-structs.xml b/src/app/zap-templates/zcl/data-model/chip/global-structs.xml index 743fdf366b724b..00f34435c735cc 100644 --- a/src/app/zap-templates/zcl/data-model/chip/global-structs.xml +++ b/src/app/zap-templates/zcl/data-model/chip/global-structs.xml @@ -38,5 +38,6 @@ limitations under the License. + diff --git a/src/app/zap-templates/zcl/data-model/chip/global-typedefs.xml b/src/app/zap-templates/zcl/data-model/chip/global-typedefs.xml new file mode 100644 index 00000000000000..e9503344a22ada --- /dev/null +++ b/src/app/zap-templates/zcl/data-model/chip/global-typedefs.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml index 258c7cba5106df..c50a1fa3f5095c 100644 --- a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml @@ -59,8 +59,14 @@ limitations under the License. + + + + + + @@ -104,6 +110,10 @@ limitations under the License. + + + @@ -202,6 +212,8 @@ limitations under the License. global_enum global_struct + typedef_attr + global_typedef mei_int8u @@ -310,6 +324,7 @@ limitations under the License. + + + @@ -605,6 +622,12 @@ limitations under the License. + + + + + + @@ -657,6 +680,7 @@ limitations under the License. + diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 2c3a67aee3d069..b2e1ceb181b4c0 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -66,6 +66,7 @@ "global-bitmaps.xml", "global-enums.xml", "global-structs.xml", + "global-typedefs.xml", "groups-cluster.xml", "group-key-mgmt-cluster.xml", "icd-management-cluster.xml", @@ -692,7 +693,15 @@ }, "mandatoryDeviceTypes": "0x0016", "defaultReportingPolicy": "mandatory", - "ZCLDataTypes": ["ARRAY", "BITMAP", "ENUM", "NUMBER", "STRING", "STRUCT"], + "ZCLDataTypes": [ + "ARRAY", + "BITMAP", + "ENUM", + "NUMBER", + "STRING", + "STRUCT", + "TYPEDEF" + ], "fabricHandling": { "automaticallyCreateFields": true, "indexFieldId": 254, diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 52933915f01e6f..5e9e9167880472 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -60,6 +60,7 @@ "global-bitmaps.xml", "global-enums.xml", "global-structs.xml", + "global-typedefs.xml", "groups-cluster.xml", "group-key-mgmt-cluster.xml", "icd-management-cluster.xml", @@ -686,7 +687,15 @@ }, "mandatoryDeviceTypes": "0x0016", "defaultReportingPolicy": "mandatory", - "ZCLDataTypes": ["ARRAY", "BITMAP", "ENUM", "NUMBER", "STRING", "STRUCT"], + "ZCLDataTypes": [ + "ARRAY", + "BITMAP", + "ENUM", + "NUMBER", + "STRING", + "STRUCT", + "TYPEDEF" + ], "fabricHandling": { "automaticallyCreateFields": true, "indexFieldId": 254, diff --git a/src/app/zap-templates/zcl/zcl.xsd b/src/app/zap-templates/zcl/zcl.xsd index 1f78e6b9e076f0..75ca12447eec0b 100644 --- a/src/app/zap-templates/zcl/zcl.xsd +++ b/src/app/zap-templates/zcl/zcl.xsd @@ -147,6 +147,7 @@ This schema describes the format of the XML files, that describe the ZCL specifi + @@ -157,7 +158,7 @@ This schema describes the format of the XML files, that describe the ZCL specifi - + @@ -391,6 +392,16 @@ This schema describes the format of the XML files, that describe the ZCL specifi + + + + + + + + + + diff --git a/src/controller/java/templates/partials/decode_value.zapt b/src/controller/java/templates/partials/decode_value.zapt index 6401ef1c8b7f12..4f5885c7be487a 100644 --- a/src/controller/java/templates/partials/decode_value.zapt +++ b/src/controller/java/templates/partials/decode_value.zapt @@ -25,60 +25,58 @@ if ({{source}}.IsNull()) { {{>decode_value target=(concat "newElement_" depth) source=(concat "entry_" depth) cluster=cluster depth=(incrementDepth depth) isArray=false forceNotList=true omitDeclaration=false earlyReturn=earlyReturn}} chip::JniReferences::GetInstance().AddToList({{target}}, newElement_{{depth}}); } -{{else}} - {{#if_is_struct type}} - {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} - {{>decode_value target=(concat ../target "_" (asLowerCamelCase label)) source=(concat ../source "." (asLowerCamelCase label)) cluster=../cluster depth=(incrementDepth ../depth) omitDeclaration=false earlyReturn=../earlyReturn}} - {{/zcl_struct_items_by_struct_and_cluster_name}} +{{else if_is_typedef type}} + {{#zcl_typedef_by_typedef_and_cluster_name type cluster}} + {{>decode_value target=../target source=../source cluster=../cluster errorCode=../errorCode depth=../depth isNullable=../isNullable omitDeclaration=../omitDeclaration earlyReturn=../earlyReturn }} + {{/zcl_typedef_by_typedef_and_cluster_name}} +{{else if_is_struct type}} + {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} + {{>decode_value target=(concat ../target "_" (asLowerCamelCase label)) source=(concat ../source "." (asLowerCamelCase label)) cluster=../cluster depth=(incrementDepth ../depth) omitDeclaration=false earlyReturn=../earlyReturn}} + {{/zcl_struct_items_by_struct_and_cluster_name}} - { - jclass {{asLowerCamelCase type}}StructClass_{{depth}}; - err = chip::JniReferences::GetInstance().GetLocalClassRef(env, "chip/devicecontroller/ChipStructs${{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase type}}", {{asLowerCamelCase type}}StructClass_{{depth}}); - if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "Could not find class ChipStructs${{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase type}}"); - return {{earlyReturn}}; - } + { + jclass {{asLowerCamelCase type}}StructClass_{{depth}}; + err = chip::JniReferences::GetInstance().GetLocalClassRef(env, "chip/devicecontroller/ChipStructs${{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase type}}", {{asLowerCamelCase type}}StructClass_{{depth}}); + if (err != CHIP_NO_ERROR) { + ChipLogError(Zcl, "Could not find class ChipStructs${{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase type}}"); + return {{earlyReturn}}; + } - jmethodID {{asLowerCamelCase type}}StructCtor_{{depth}}; - err = chip::JniReferences::GetInstance().FindMethod( - env, {{asLowerCamelCase type}}StructClass_{{depth}}, "", - "({{#zcl_struct_items_by_struct_and_cluster_name type cluster}}{{asJniSignature type null (asUpperCamelCase ../cluster) true}}{{/zcl_struct_items_by_struct_and_cluster_name}})V", - &{{asLowerCamelCase type}}StructCtor_{{depth}}); - if (err != CHIP_NO_ERROR || {{asLowerCamelCase type}}StructCtor_{{depth}} == nullptr) { - ChipLogError(Zcl, "Could not find ChipStructs${{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase type}} constructor"); - return {{earlyReturn}}; - } + jmethodID {{asLowerCamelCase type}}StructCtor_{{depth}}; + err = chip::JniReferences::GetInstance().FindMethod( + env, {{asLowerCamelCase type}}StructClass_{{depth}}, "", + "({{#zcl_struct_items_by_struct_and_cluster_name type cluster}}{{asJniSignature type null (asUpperCamelCase ../cluster) true}}{{/zcl_struct_items_by_struct_and_cluster_name}})V", + &{{asLowerCamelCase type}}StructCtor_{{depth}}); + if (err != CHIP_NO_ERROR || {{asLowerCamelCase type}}StructCtor_{{depth}} == nullptr) { + ChipLogError(Zcl, "Could not find ChipStructs${{asUpperCamelCase cluster}}Cluster{{asUpperCamelCase type}} constructor"); + return {{earlyReturn}}; + } - {{target}} = env->NewObject({{asLowerCamelCase type}}StructClass_{{depth}}, {{asLowerCamelCase type}}StructCtor_{{depth}} - {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} - , {{../target}}_{{asLowerCamelCase label}} + {{target}} = env->NewObject({{asLowerCamelCase type}}StructClass_{{depth}}, {{asLowerCamelCase type}}StructCtor_{{depth}} + {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} + , {{../target}}_{{asLowerCamelCase label}} {{/zcl_struct_items_by_struct_and_cluster_name}} ); - } +} +{{else if_is_strongly_typed_chip_enum type}} + std::string {{target}}ClassName = "{{asJniClassName type null (asUpperCamelCase cluster)}}"; + std::string {{target}}CtorSignature = "({{asJniSignature type null (asUpperCamelCase cluster) false}})V"; + {{asJniBasicType type false}} jni{{target}} = static_cast<{{asJniBasicType type false}}>({{source}}); + chip::JniReferences::GetInstance().CreateBoxedObject<{{asJniBasicType type false}}>({{target}}ClassName.c_str(), {{target}}CtorSignature.c_str(), jni{{target}}, {{target}}); +{{else if (isOctetString type)}} + jbyteArray {{target}}ByteArray = env->NewByteArray(static_cast({{source}}.size())); + env->SetByteArrayRegion({{target}}ByteArray, 0, static_cast({{source}}.size()), reinterpret_cast({{source}}.data())); + {{target}} = {{target}}ByteArray; +{{else if (isCharString type)}} + LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF({{source}}, {{target}})); +{{else}} + std::string {{target}}ClassName = "{{asJniClassName type null (asUpperCamelCase cluster)}}"; + std::string {{target}}CtorSignature = "({{asJniSignature type null (asUpperCamelCase cluster) false}})V"; + {{#if_is_strongly_typed_bitmap type}} + {{asJniBasicType type false}} jni{{target}} = static_cast<{{asJniBasicType type false}}>({{source}}.Raw()); + chip::JniReferences::GetInstance().CreateBoxedObject<{{asJniBasicType type false}}>({{target}}ClassName.c_str(), {{target}}CtorSignature.c_str(), jni{{target}}, {{target}}); {{else}} - {{#if_is_strongly_typed_chip_enum type}} - std::string {{target}}ClassName = "{{asJniClassName type null (asUpperCamelCase cluster)}}"; - std::string {{target}}CtorSignature = "({{asJniSignature type null (asUpperCamelCase cluster) false}})V"; - {{asJniBasicType type false}} jni{{target}} = static_cast<{{asJniBasicType type false}}>({{source}}); - chip::JniReferences::GetInstance().CreateBoxedObject<{{asJniBasicType type false}}>({{target}}ClassName.c_str(), {{target}}CtorSignature.c_str(), jni{{target}}, {{target}}); - {{else}} - {{#if (isOctetString type)}} - jbyteArray {{target}}ByteArray = env->NewByteArray(static_cast({{source}}.size())); - env->SetByteArrayRegion({{target}}ByteArray, 0, static_cast({{source}}.size()), reinterpret_cast({{source}}.data())); - {{target}} = {{target}}ByteArray; - {{else if (isCharString type)}} - LogErrorOnFailure(chip::JniReferences::GetInstance().CharToStringUTF({{source}}, {{target}})); - {{else}} - std::string {{target}}ClassName = "{{asJniClassName type null (asUpperCamelCase cluster)}}"; - std::string {{target}}CtorSignature = "({{asJniSignature type null (asUpperCamelCase cluster) false}})V"; - {{#if_is_strongly_typed_bitmap type}} - {{asJniBasicType type false}} jni{{target}} = static_cast<{{asJniBasicType type false}}>({{source}}.Raw()); - chip::JniReferences::GetInstance().CreateBoxedObject<{{asJniBasicType type false}}>({{target}}ClassName.c_str(), {{target}}CtorSignature.c_str(), jni{{target}}, {{target}}); - {{else}} - {{asJniBasicType type false}} jni{{target}} = static_cast<{{asJniBasicType type false}}>({{source}}); - chip::JniReferences::GetInstance().CreateBoxedObject<{{asJniBasicType type false}}>({{target}}ClassName.c_str(), {{target}}CtorSignature.c_str(), jni{{target}}, {{target}}); - {{/if_is_strongly_typed_bitmap}} - {{/if}} - {{/if_is_strongly_typed_chip_enum}} - {{/if_is_struct}} + {{asJniBasicType type false}} jni{{target}} = static_cast<{{asJniBasicType type false}}>({{source}}); + chip::JniReferences::GetInstance().CreateBoxedObject<{{asJniBasicType type false}}>({{target}}ClassName.c_str(), {{target}}CtorSignature.c_str(), jni{{target}}, {{target}}); + {{/if_is_strongly_typed_bitmap}} {{/if}} \ No newline at end of file diff --git a/src/controller/java/templates/templates.json b/src/controller/java/templates/templates.json index 5ff5eb7ef0dad5..4a04bec24af685 100644 --- a/src/controller/java/templates/templates.json +++ b/src/controller/java/templates/templates.json @@ -24,10 +24,6 @@ "name": "cluster_header", "path": "../../../app/zap-templates/partials/cluster_header.zapt" }, - { - "name": "encode_value", - "path": "partials/encode_value.zapt" - }, { "name": "decode_value", "path": "partials/decode_value.zapt" diff --git a/src/controller/python/templates/partials/typedef_def.zapt b/src/controller/python/templates/partials/typedef_def.zapt new file mode 100644 index 00000000000000..1a8a953a77b392 --- /dev/null +++ b/src/controller/python/templates/partials/typedef_def.zapt @@ -0,0 +1 @@ + {{asType label}} = '{{zapTypeToPythonClusterObjectType type ns=../cluster}}' diff --git a/src/controller/python/templates/python-CHIPClusters-py.zapt b/src/controller/python/templates/python-CHIPClusters-py.zapt index 284cd650a0a772..b1e1be1db40b9e 100644 --- a/src/controller/python/templates/python-CHIPClusters-py.zapt +++ b/src/controller/python/templates/python-CHIPClusters-py.zapt @@ -26,9 +26,11 @@ class ChipClusters: {{#zcl_command_arguments}} {{#if_is_struct type}} "{{asLowerCamelCase label}}": "{{type}}", - {{else}} + {{else if_is_typedef type}} + "{{asLowerCamelCase label}}": "{{type}}", + {{else}} "{{asLowerCamelCase label}}": "{{#if (isCharString type)}}str{{else}}{{as_underlying_python_zcl_type type ../../id}}{{/if}}", - {{/if_is_struct}} + {{/if_is_struct}} {{/zcl_command_arguments}} }, }, diff --git a/src/controller/python/templates/python-cluster-Objects-py.zapt b/src/controller/python/templates/python-cluster-Objects-py.zapt index 381d266668082a..8689d7e21cf34d 100644 --- a/src/controller/python/templates/python-cluster-Objects-py.zapt +++ b/src/controller/python/templates/python-cluster-Objects-py.zapt @@ -2,7 +2,7 @@ {{> header}} ''' -# This file contains generated struct, enum, command definition. +# This file contains generated struct, enum, typedef, and command definition. # Users are not expected to import this file, instead, users can use import chip.clusters, # which will import all symbols from this file and can get a readable, pretty naming like # clusters.OnOff.commands.OnCommand @@ -55,6 +55,13 @@ class Globals: {{/if}} {{/zcl_structs}} + class Typedefs: +{{#zcl_typedefs}} +{{#if has_no_clusters}} +{{> typedef_def cluster="Globals"}} + +{{/if}} +{{/zcl_typedefs}} {{#zcl_clusters}} @@ -106,6 +113,13 @@ class {{asUpperCamelCase name}}(Cluster): {{> struct_def cluster=(asUpperCamelCase parent.name) }} {{/zcl_structs}} +{{#zcl_typedefs}} +{{#first}} + class Typedefs: +{{/first}} +{{> typedef_def cluster=(asUpperCamelCase parent.name) }} + +{{/zcl_typedefs}} {{#zcl_commands}} {{#first}} class Commands: diff --git a/src/controller/python/templates/templates.json b/src/controller/python/templates/templates.json index ebe67b0f384b22..8b0c0f4b368d2b 100644 --- a/src/controller/python/templates/templates.json +++ b/src/controller/python/templates/templates.json @@ -32,6 +32,10 @@ { "name": "struct_def", "path": "partials/struct_def.zapt" + }, + { + "name": "typedef_def", + "path": "partials/typedef_def.zapt" } ], "templates": [ diff --git a/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt b/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt index 6ca88e84dcad1a..e76a994cdad3bf 100644 --- a/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRBaseClusters.zapt @@ -114,6 +114,13 @@ subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptio {{/if}} {{/zcl_enums}} +{{#zcl_typedefs}} +{{#if has_no_clusters}} +{{> typedef_decl cluster="Globals" name=name typedefLabel=label}} + +{{/if}} +{{/zcl_typedefs}} + {{#zcl_clusters}} {{#zcl_enums}} {{> enum_decl cluster=../name name=name enumLabel=label}} @@ -167,6 +174,10 @@ typedef NS_OPTIONS({{asUnderlyingZclType name}}, {{objCEnumName clusterName bitm {{/zcl_bitmaps}} +{{#zcl_typedefs}} +{{> typedef_decl cluster=../name name=name typedefLabel=label}} + +{{/zcl_typedefs}} {{/zcl_clusters}} {{#zcl_clusters}} diff --git a/src/darwin/Framework/CHIP/templates/partials/decode_value.zapt b/src/darwin/Framework/CHIP/templates/partials/decode_value.zapt index 16a9acbc6d4048..ec2fcdd955ca43 100644 --- a/src/darwin/Framework/CHIP/templates/partials/decode_value.zapt +++ b/src/darwin/Framework/CHIP/templates/partials/decode_value.zapt @@ -26,32 +26,30 @@ } {{target}} = array_{{depth}}; } +{{else if_is_typedef type}} + {{#zcl_typedef_by_typedef_and_cluster_name type cluster}} + {{>decode_value target=../target cluster=../cluster source=../source errorCode=../errorCode depth=(incrementDepth ../depth) }} + {{/zcl_typedef_by_typedef_and_cluster_name}} +{{else if_is_struct type}} + {{target}} = [{{asObjectiveCClass type cluster forceNotList=true}} new]; + {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} + {{#if (isSupported (asUpperCamelCase ../cluster preserveAcronyms=true) struct=(asUpperCamelCase ../type preserveAcronyms=true) structField=(asStructPropertyName label))}} + {{>decode_value target=(concat ../target "." (asStructPropertyName label)) source=(concat ../source "." (asLowerCamelCase label)) cluster=../cluster errorCode=../errorCode depth=(incrementDepth ../depth) }} + {{/if}} + {{/zcl_struct_items_by_struct_and_cluster_name}} +{{else if_is_strongly_typed_chip_enum type}} + {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:chip::to_underlying({{source}})]; +{{else if_is_strongly_typed_bitmap type}} + {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}.Raw()]; +{{else if (isOctetString type)}} + {{target}} = AsData({{source}}); +{{else if (isCharString type)}} + {{target}} = AsString({{source}}); + if ({{target}} == nil) { + {{! Invalid UTF-8. Just make up an error for now. }} + CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + {{errorCode}} + } {{else}} - {{#if_is_struct type}} - {{target}} = [{{asObjectiveCClass type cluster forceNotList=true}} new]; - {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} - {{#if (isSupported (asUpperCamelCase ../cluster preserveAcronyms=true) struct=(asUpperCamelCase ../type preserveAcronyms=true) structField=(asStructPropertyName label))}} - {{>decode_value target=(concat ../target "." (asStructPropertyName label)) source=(concat ../source "." (asLowerCamelCase label)) cluster=../cluster errorCode=../errorCode depth=(incrementDepth ../depth) }} - {{/if}} - {{/zcl_struct_items_by_struct_and_cluster_name}} - {{else}} - {{#if_is_strongly_typed_chip_enum type}} - {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:chip::to_underlying({{source}})]; - {{else}} - {{#if_is_strongly_typed_bitmap type}} - {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}.Raw()]; - {{else if (isOctetString type)}} - {{target}} = AsData({{source}}); - {{else if (isCharString type)}} - {{target}} = AsString({{source}}); - if ({{target}} == nil) { - {{! Invalid UTF-8. Just make up an error for now. }} - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; - {{errorCode}} - } - {{else}} - {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}]; - {{/if_is_strongly_typed_bitmap}} - {{/if_is_strongly_typed_chip_enum}} - {{/if_is_struct}} + {{target}} = [NSNumber numberWith{{asObjectiveCNumberType "" type false}}:{{source}}]; {{/if}} diff --git a/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt b/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt index 16e2b3e1234417..700c5d98be10c5 100644 --- a/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt +++ b/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt @@ -44,22 +44,20 @@ {{target}} = AsByteSpan({{source}}); {{else if (isCharString type)}} {{target}} = AsCharSpan({{source}}); +{{else if_is_typedef type}} + {{#zcl_typedef_by_typedef_and_cluster_name type cluster}} + {{>encode_value target=../target source=../source cluster=../cluster errorCode=../errorCode depth=(incrementDepth ../depth) }} + {{/zcl_typedef_by_typedef_and_cluster_name}} +{{else if_is_struct type}} + {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} + {{#if (isSupported (asUpperCamelCase ../cluster preserveAcronyms=true) struct=(asUpperCamelCase ../type preserveAcronyms=true) structField=(asStructPropertyName label))}} + {{>encode_value target=(concat ../target "." (asLowerCamelCase label)) source=(concat ../source "." (asStructPropertyName label)) cluster=../cluster errorCode=../errorCode depth=(incrementDepth ../depth)}} + {{/if}} + {{/zcl_struct_items_by_struct_and_cluster_name}} +{{else if_is_strongly_typed_chip_enum type}} + {{target}} = static_cast>({{source}}.{{asObjectiveCNumberType source type true}}Value); +{{else if_is_strongly_typed_bitmap type}} + {{target}} = static_cast>({{source}}.{{asObjectiveCNumberType source type true}}Value); {{else}} - {{#if_is_struct type}} - {{#zcl_struct_items_by_struct_and_cluster_name type cluster}} - {{#if (isSupported (asUpperCamelCase ../cluster preserveAcronyms=true) struct=(asUpperCamelCase ../type preserveAcronyms=true) structField=(asStructPropertyName label))}} - {{>encode_value target=(concat ../target "." (asLowerCamelCase label)) source=(concat ../source "." (asStructPropertyName label)) cluster=../cluster errorCode=../errorCode depth=(incrementDepth ../depth)}} - {{/if}} - {{/zcl_struct_items_by_struct_and_cluster_name}} - {{else}} - {{#if_is_strongly_typed_chip_enum type}} - {{target}} = static_cast>({{source}}.{{asObjectiveCNumberType source type true}}Value); - {{else}} - {{#if_is_strongly_typed_bitmap type}} - {{target}} = static_cast>({{source}}.{{asObjectiveCNumberType source type true}}Value); - {{else}} - {{target}} = {{source}}.{{asObjectiveCNumberType source type true}}Value; - {{/if_is_strongly_typed_bitmap}} - {{/if_is_strongly_typed_chip_enum}} - {{/if_is_struct}} + {{target}} = {{source}}.{{asObjectiveCNumberType source type true}}Value; {{/if}} diff --git a/src/darwin/Framework/CHIP/templates/partials/typedef_decl.zapt b/src/darwin/Framework/CHIP/templates/partials/typedef_decl.zapt new file mode 100644 index 00000000000000..86deb02b28dbb6 --- /dev/null +++ b/src/darwin/Framework/CHIP/templates/partials/typedef_decl.zapt @@ -0,0 +1,2 @@ +{{! Arguments: cluster (might be "Globals", is not case-canonicalized), name, typedefLabel }} +typedef {{asObjectiveCType type cluster}} {{asUnderlyingZclType name}}; \ No newline at end of file diff --git a/src/darwin/Framework/CHIP/templates/templates.json b/src/darwin/Framework/CHIP/templates/templates.json index d7e4b2106bc98e..5fffbfd268ba23 100644 --- a/src/darwin/Framework/CHIP/templates/templates.json +++ b/src/darwin/Framework/CHIP/templates/templates.json @@ -56,6 +56,10 @@ "name": "enum_decl", "path": "partials/enum_decl.zapt" }, + { + "name": "typedef_decl", + "path": "partials/typedef_decl.zapt" + }, { "name": "renamed_struct_field_impl", "path": "partials/renamed_struct_field_impl.zapt" diff --git a/src/lib/core/BUILD.gn b/src/lib/core/BUILD.gn index 906b8a4988aee0..962c78ea73a411 100644 --- a/src/lib/core/BUILD.gn +++ b/src/lib/core/BUILD.gn @@ -190,6 +190,7 @@ static_library("core") { ":chip_config_header", ":error", "${chip_root}/src/app/common:enums", + "${chip_root}/src/app/common:typedefs", "${chip_root}/src/ble", "${chip_root}/src/inet", "${chip_root}/src/lib/support",