Line data Source code
1 : /*
2 : * Copyright (c) 2025 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 : #pragma once
18 :
19 : #include <app/data-model-provider/MetadataTypes.h>
20 : #include <app/server-cluster/ServerClusterInterface.h>
21 : #include <data-model-providers/endpoint/EndpointProviderInterface.h>
22 : #include <lib/core/DataModelTypes.h>
23 : #include <lib/support/Span.h>
24 :
25 : #include <variant>
26 :
27 : namespace chip {
28 : namespace app {
29 :
30 : /**
31 : * @brief An implementation of EndpointProviderInterface that uses `chip::Span` to refer to its data.
32 : *
33 : * This provider is constructed using its `Builder` class. It stores `chip::Span` members that
34 : * point to externally managed arrays for its configuration (device types, server/client clusters,
35 : * semantic tags, etc.).
36 : *
37 : * @warning Lifetime of Span-Referenced Data:
38 : * `SpanEndpointProvider` does NOT take ownership of the data arrays referenced by its
39 : * internal `chip::Span` members. The caller who provides these Spans (usually via the
40 : * `Builder`) MUST ensure that the underlying data remains valid for the entire lifetime
41 : * of the `SpanEndpointProvider` instance.
42 : * - For `Span<T>` (e.g., `Span<const ClusterId>`, `Span<const DeviceTypeEntry>`), the
43 : * array of `T` elements must outlive the `SpanEndpointProvider`.
44 : * - For `Span<T*>` (e.g., `Span<ServerClusterInterface *>`), both the array of pointers
45 : * (`T*`) and the objects (`T`) pointed to by those pointers must outlive the
46 : * `SpanEndpointProvider`.
47 : * Failure to adhere to these lifetime requirements will lead to undefined behavior.
48 : */
49 : class SpanEndpointProvider : public EndpointProviderInterface
50 : {
51 : public:
52 : class Builder
53 : {
54 : public:
55 : explicit Builder(EndpointId id);
56 :
57 : Builder & SetComposition(DataModel::EndpointCompositionPattern composition);
58 : Builder & SetParentId(EndpointId parentId);
59 : Builder & SetServerClusters(Span<ServerClusterInterface *> serverClusters);
60 : Builder & SetClientClusters(Span<const ClusterId> clientClusters);
61 : Builder & SetSemanticTags(Span<const SemanticTag> semanticTags);
62 : Builder & SetDeviceTypes(Span<const DataModel::DeviceTypeEntry> deviceTypes);
63 :
64 : // Builds the SpanEndpointProvider.
65 : // Returns a std::variant containing either the successfully built SpanEndpointProvider
66 : // or a CHIP_ERROR if the build failed (e.g., due to invalid arguments).
67 : // Callers should check the variant's active alternative before use.
68 : std::variant<SpanEndpointProvider, CHIP_ERROR> build();
69 :
70 : private:
71 : EndpointId mEndpointId;
72 : DataModel::EndpointCompositionPattern mComposition = DataModel::EndpointCompositionPattern::kFullFamily;
73 : EndpointId mParentId = kInvalidEndpointId;
74 : Span<ServerClusterInterface *> mServerClusters;
75 : Span<const ClusterId> mClientClusters;
76 : Span<const SemanticTag> mSemanticTags;
77 : Span<const DataModel::DeviceTypeEntry> mDeviceTypes;
78 : };
79 :
80 466 : ~SpanEndpointProvider() override = default;
81 :
82 : // Delete copy and move constructors and assignment operators
83 : SpanEndpointProvider(const SpanEndpointProvider &) = delete;
84 : SpanEndpointProvider & operator=(const SpanEndpointProvider &) = delete;
85 233 : SpanEndpointProvider(SpanEndpointProvider &&) = default; // Allow move
86 : SpanEndpointProvider & operator=(SpanEndpointProvider &&) = default; // Allow move
87 :
88 33180 : const DataModel::EndpointEntry & GetEndpointEntry() const override { return mEndpointEntry; }
89 :
90 : // Iteration methods
91 : CHIP_ERROR SemanticTags(ReadOnlyBufferBuilder<SemanticTag> & out) const override;
92 : CHIP_ERROR DeviceTypes(ReadOnlyBufferBuilder<DataModel::DeviceTypeEntry> & out) const override;
93 : CHIP_ERROR ClientClusters(ReadOnlyBufferBuilder<ClusterId> & out) const override;
94 :
95 : // Getter for ServerClusterInterface, returns nullptr if the cluster is not found.
96 : ServerClusterInterface * GetServerCluster(ClusterId clusterId) const override;
97 : CHIP_ERROR ServerClusterInterfaces(ReadOnlyBufferBuilder<ServerClusterInterface *> & out) const override;
98 :
99 : private:
100 : // Private constructor for Builder
101 : SpanEndpointProvider(EndpointId id, DataModel::EndpointCompositionPattern composition, EndpointId parentId,
102 : Span<ServerClusterInterface *> serverClusters, Span<const ClusterId> clientClusters,
103 : Span<const SemanticTag> semanticTags, Span<const DataModel::DeviceTypeEntry> deviceTypes);
104 :
105 : // Iteration methods
106 : // GetEndpointEntry is already public
107 : DataModel::EndpointEntry mEndpointEntry;
108 : Span<const DataModel::DeviceTypeEntry> mDeviceTypes;
109 : Span<const SemanticTag> mSemanticTags;
110 : Span<const ClusterId> mClientClusters;
111 : Span<ServerClusterInterface *> mServerClusters;
112 : };
113 :
114 : } // namespace app
115 : } // namespace chip
|