Line data Source code
1 : /*
2 : * Copyright (c) 2024 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 : #include <app/data-model-provider/ActionReturnStatus.h>
18 : #include <lib/core/CHIPConfig.h>
19 : #include <lib/core/CHIPError.h>
20 : #include <lib/support/CodeUtils.h>
21 : #include <protocols/interaction_model/StatusCode.h>
22 :
23 : #include <lib/support/StringBuilder.h>
24 :
25 : namespace chip {
26 : namespace app {
27 : namespace DataModel {
28 :
29 : using Protocols::InteractionModel::ClusterStatusCode;
30 : using Protocols::InteractionModel::Status;
31 :
32 : namespace {
33 :
34 19 : bool StatusIsTheSameAsError(const ClusterStatusCode & status, const CHIP_ERROR & err)
35 : {
36 19 : auto cluster_code = status.GetClusterSpecificCode();
37 19 : if (!cluster_code.HasValue())
38 : {
39 : // there exist Status::Success, however that may not be encoded
40 : // as a CHIP_ERROR_IM_GLOBAL_STATUS_VALUE as it is just as well a CHIP_NO_ERROR.
41 : // handle that separately
42 14 : if ((status.GetStatus() == Status::Success) && (err == CHIP_NO_ERROR))
43 : {
44 2 : return true;
45 : }
46 :
47 12 : return err == CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status.GetStatus());
48 : }
49 :
50 5 : if (status.GetStatus() != Status::Failure)
51 : {
52 3 : return false;
53 : }
54 :
55 2 : return err == CHIP_ERROR_IM_CLUSTER_STATUS_VALUE(cluster_code.Value());
56 : }
57 :
58 : } // namespace
59 :
60 184 : bool ActionReturnStatus::operator==(const ActionReturnStatus & other) const
61 : {
62 184 : if (mReturnStatus == other.mReturnStatus)
63 : {
64 150 : return true;
65 : }
66 :
67 34 : const ClusterStatusCode * thisStatus = std::get_if<ClusterStatusCode>(&mReturnStatus);
68 34 : const ClusterStatusCode * otherStatus = std::get_if<ClusterStatusCode>(&other.mReturnStatus);
69 :
70 34 : const CHIP_ERROR * thisErr = std::get_if<CHIP_ERROR>(&mReturnStatus);
71 34 : const CHIP_ERROR * otherErr = std::get_if<CHIP_ERROR>(&other.mReturnStatus);
72 :
73 34 : if (thisStatus && otherErr)
74 : {
75 9 : return StatusIsTheSameAsError(*thisStatus, *otherErr);
76 : }
77 :
78 25 : if (otherStatus && thisErr)
79 : {
80 10 : return StatusIsTheSameAsError(*otherStatus, *thisErr);
81 : }
82 :
83 15 : return false;
84 : }
85 :
86 399 : CHIP_ERROR ActionReturnStatus::GetUnderlyingError() const
87 : {
88 :
89 399 : if (const CHIP_ERROR * err = std::get_if<CHIP_ERROR>(&mReturnStatus))
90 : {
91 396 : return *err;
92 : }
93 :
94 3 : if (const ClusterStatusCode * status = std::get_if<ClusterStatusCode>(&mReturnStatus))
95 : {
96 3 : if (status->IsSuccess())
97 : {
98 1 : return CHIP_NO_ERROR;
99 : }
100 :
101 2 : chip::Optional<ClusterStatus> code = status->GetClusterSpecificCode();
102 :
103 3 : return code.HasValue() ? CHIP_ERROR_IM_CLUSTER_STATUS_VALUE(code.Value())
104 3 : : CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status->GetStatus());
105 : }
106 :
107 0 : chipDie();
108 : }
109 :
110 2488 : ClusterStatusCode ActionReturnStatus::GetStatusCode() const
111 : {
112 2488 : if (const ClusterStatusCode * status = std::get_if<ClusterStatusCode>(&mReturnStatus))
113 : {
114 12 : return *status;
115 : }
116 :
117 2476 : if (const CHIP_ERROR * err = std::get_if<CHIP_ERROR>(&mReturnStatus))
118 : {
119 2476 : return ClusterStatusCode(*err);
120 : }
121 :
122 : // all std::variant cases exhausted
123 0 : chipDie();
124 : }
125 :
126 13855 : bool ActionReturnStatus::IsSuccess() const
127 : {
128 13855 : if (const CHIP_ERROR * err = std::get_if<CHIP_ERROR>(&mReturnStatus))
129 : {
130 11360 : return (*err == CHIP_NO_ERROR);
131 : }
132 :
133 2495 : if (const ClusterStatusCode * status = std::get_if<ClusterStatusCode>(&mReturnStatus))
134 : {
135 2495 : return status->IsSuccess();
136 : }
137 :
138 : // all std::variant cases exhausted
139 0 : chipDie();
140 : }
141 :
142 790 : bool ActionReturnStatus::IsOutOfSpaceEncodingResponse() const
143 : {
144 790 : if (const CHIP_ERROR * err = std::get_if<CHIP_ERROR>(&mReturnStatus))
145 : {
146 790 : return (*err == CHIP_ERROR_NO_MEMORY) || (*err == CHIP_ERROR_BUFFER_TOO_SMALL);
147 : }
148 :
149 0 : return false;
150 : }
151 :
152 190 : const char * ActionReturnStatus::c_str(ActionReturnStatus::StringStorage & storage) const
153 : {
154 190 : if (const CHIP_ERROR * err = std::get_if<CHIP_ERROR>(&mReturnStatus))
155 : {
156 : #if CHIP_CONFIG_ERROR_FORMAT_AS_STRING
157 148 : return err->Format(); // any length
158 : #else
159 : storage.formatBuffer.Reset().AddFormat("%" CHIP_ERROR_FORMAT, err->Format());
160 : return storage.formatBuffer.c_str();
161 : #endif
162 : }
163 :
164 42 : if (const ClusterStatusCode * status = std::get_if<ClusterStatusCode>(&mReturnStatus))
165 : {
166 42 : storage.formatBuffer.Reset();
167 :
168 : #if CHIP_CONFIG_IM_STATUS_CODE_VERBOSE_FORMAT
169 42 : storage.formatBuffer.AddFormat("%s(%d)", Protocols::InteractionModel::StatusName(status->GetStatus()),
170 42 : static_cast<int>(status->GetStatus()));
171 : #else
172 : if (status->IsSuccess())
173 : {
174 : storage.formatBuffer.Add("Success");
175 : }
176 : else
177 : {
178 : storage.formatBuffer.AddFormat("Status<%d>", static_cast<int>(status->GetStatus()));
179 : }
180 : #endif
181 :
182 42 : chip::Optional<ClusterStatus> clusterCode = status->GetClusterSpecificCode();
183 42 : if (clusterCode.HasValue())
184 : {
185 16 : storage.formatBuffer.AddFormat(", Code %d", static_cast<int>(clusterCode.Value()));
186 : }
187 42 : return storage.formatBuffer.c_str();
188 : }
189 :
190 : // all std::variant cases exhausted
191 0 : chipDie();
192 : }
193 :
194 : } // namespace DataModel
195 : } // namespace app
196 : } // namespace chip
|