Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <app-common/zap-generated/cluster-enums-check.h>
22 : #include <app/ConcreteAttributePath.h>
23 : #include <app/data-model/Nullable.h>
24 : #include <lib/core/CHIPError.h>
25 : #include <lib/core/CHIPSafeCasts.h>
26 : #include <lib/core/Optional.h>
27 : #include <lib/core/TLV.h>
28 : #include <lib/support/attribute-storage-null-handling.h>
29 : #include <protocols/interaction_model/Constants.h>
30 :
31 : namespace chip {
32 : namespace app {
33 : namespace Clusters {
34 1 : static auto __attribute__((unused)) EnsureKnownEnumValue(chip::VendorId val)
35 : {
36 1 : return val;
37 : }
38 : } // namespace Clusters
39 :
40 : namespace DataModel {
41 :
42 : //
43 : // Decode
44 : //
45 : template <typename X, typename std::enable_if_t<std::is_integral<X>::value, int> = 0>
46 3461 : CHIP_ERROR Decode(TLV::TLVReader & reader, X & x)
47 : {
48 3461 : return reader.Get(x);
49 : }
50 :
51 : template <typename X, typename std::enable_if_t<std::is_floating_point<X>::value, int> = 0>
52 77 : CHIP_ERROR Decode(TLV::TLVReader & reader, X & x)
53 : {
54 77 : return reader.Get(x);
55 : }
56 :
57 : template <typename X, typename std::enable_if_t<std::is_enum<X>::value, int> = 0>
58 83 : CHIP_ERROR Decode(TLV::TLVReader & reader, X & x)
59 : {
60 83 : ReturnErrorOnFailure(reader.Get(x));
61 83 : x = Clusters::EnsureKnownEnumValue(x);
62 83 : return CHIP_NO_ERROR;
63 : }
64 :
65 : template <typename X>
66 18 : CHIP_ERROR Decode(TLV::TLVReader & reader, BitFlags<X> & x)
67 : {
68 18 : return reader.Get(x);
69 : }
70 :
71 : //
72 : // @brief
73 : //
74 : // Decodes an octet string that is expected at the positioned reader.
75 : //
76 : // The passed in ByteSpan is ignored and updated to point directly into
77 : // the buffer backing the reader.
78 : //
79 7260 : inline CHIP_ERROR Decode(TLV::TLVReader & reader, ByteSpan & x)
80 : {
81 7260 : VerifyOrReturnError(reader.GetType() == TLV::kTLVType_ByteString, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
82 7247 : return reader.Get(x);
83 : }
84 :
85 : //
86 : // @brief
87 : //
88 : // Decodes a UTF-8 string that is expected at the positioned reader.
89 : //
90 : // The passed in char Span is ignored and updated to point directly into
91 : // the buffer backing the reader.
92 : //
93 26 : inline CHIP_ERROR Decode(TLV::TLVReader & reader, Span<const char> & x)
94 : {
95 26 : return reader.Get(x);
96 : }
97 :
98 : /*
99 : * @brief
100 : *
101 : * This specific variant that decodes cluster objects (like structs, commands, events) from TLV
102 : * depends on the presence of a Decode method on X. The signature of that method
103 : * is as follows:
104 : *
105 : * CHIP_ERROR <Object>::Decode(TLVReader &reader);
106 : *
107 : */
108 : template <typename X,
109 : typename std::enable_if_t<
110 : std::is_class<X>::value &&
111 : std::is_same<decltype(std::declval<X>().Decode(std::declval<TLV::TLVReader &>())), CHIP_ERROR>::value,
112 : X> * = nullptr>
113 5527 : CHIP_ERROR Decode(TLV::TLVReader & reader, X & x)
114 : {
115 5527 : return x.Decode(reader);
116 : }
117 :
118 : /*
119 : * @brief
120 : *
121 : * This specific variant decodes from TLV a cluster object that contains all attributes encapsulated within a single, monolithic
122 : * cluster object.
123 : *
124 : * Each attribute in the cluster is decoded based on the provided ConcreteAttributePath. The TLVReader is to be positioned right on
125 : * the data value for the specified attribute.
126 : *
127 : * This API depends on the presence of a Decode method on the object. The signature of that method
128 : * is as follows:
129 : *
130 : * CHIP_ERROR <Object>::Decode(TLVReader &reader, ConcreteAttributePath &path);
131 : *
132 : */
133 : template <
134 : typename X,
135 : typename std::enable_if_t<std::is_class<X>::value &&
136 : std::is_same<decltype(std::declval<X>().Decode(std::declval<TLV::TLVReader &>(),
137 : std::declval<const ConcreteAttributePath &>())),
138 : CHIP_ERROR>::value,
139 : X> * = nullptr>
140 12 : CHIP_ERROR Decode(TLV::TLVReader & reader, const ConcreteAttributePath & path, X & x)
141 : {
142 12 : return x.Decode(reader, path);
143 : }
144 :
145 : /*
146 : * @brief
147 : *
148 : * Decodes an optional value (struct field, command field, event field).
149 : */
150 : template <typename X>
151 : CHIP_ERROR Decode(TLV::TLVReader & reader, Optional<X> & x)
152 : {
153 : // If we are calling this, it means we found the right tag, so just decode
154 : // the item.
155 : return Decode(reader, x.Emplace());
156 : }
157 :
158 : /*
159 : * @brief
160 : *
161 : * Decodes a nullable value.
162 : */
163 : template <typename X>
164 1180 : CHIP_ERROR Decode(TLV::TLVReader & reader, Nullable<X> & x)
165 : {
166 1180 : if (reader.GetType() == TLV::kTLVType_Null)
167 : {
168 199 : x.SetNull();
169 199 : return CHIP_NO_ERROR;
170 : }
171 :
172 : // We have a value; decode it.
173 981 : ReturnErrorOnFailure(Decode(reader, x.SetNonNull()));
174 981 : if (!x.ExistingValueInEncodableRange())
175 : {
176 0 : return CHIP_IM_GLOBAL_STATUS(ConstraintError);
177 : }
178 981 : return CHIP_NO_ERROR;
179 : }
180 :
181 : } // namespace DataModel
182 : } // namespace app
183 : } // namespace chip
|