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 : #pragma once
18 :
19 : #include <lib/core/CHIPError.h>
20 : #include <lib/support/StringBuilder.h>
21 : #include <protocols/interaction_model/StatusCode.h>
22 :
23 : #include <variant>
24 :
25 : namespace chip {
26 : namespace app {
27 : namespace DataModel {
28 :
29 : /// An ActionReturnStatus encodes the result of a read/write/invoke.
30 : ///
31 : /// Generally such actions result in a StatusIB in the interaction model,
32 : /// which is a code (InteractionModel::Status) and may have an associated
33 : /// cluster-specific code.
34 : ///
35 : /// However some actions specifically may return additional information for
36 : /// chunking, hence the existence of this class:
37 : ///
38 : /// - encapsulates a ClusterStatusCode for an actual action result
39 : /// - encapsulates a underlying CHIP_ERROR for reporting purposes
40 : /// - has a way to check for "chunking needed" status.
41 : ///
42 : /// The class is directly constructible from statuses (non-exlicit) to make
43 : /// returning of values easy.
44 : class ActionReturnStatus
45 : {
46 : public:
47 : // Provides additional statuses used for specific functionalities not necessarily covered
48 : // by the existing CHIP_ERROR or InteractionModel::Status
49 : enum class FixedStatus
50 : {
51 : kWriteSuccessNoOp,
52 : };
53 : /// Provides storage for the c_str() call for the action status.
54 : struct StringStorage
55 : {
56 : // Generally size should be sufficient.
57 : // The longest status code from StatusCodeList is NO_UPSTREAM_SUBSCRIPTION(197)
58 : // so we need space for one of:
59 : // "NO_UPSTREAM_SUBSCRIPTION(197)\0" = 30 // explicit verbose status code
60 : // "FAILURE(1), Code 255\0") // cluster failure, verbose
61 : // "SUCCESS(0), Code 255\0") // cluster success, verbose
62 : // "Status<197>, Code 255\0") // Cluster failure, non-verbose
63 : //
64 : // CHIP_ERROR has its own (global/static!) storage
65 : chip::StringBuilder<32> formatBuffer;
66 : };
67 :
68 15439 : ActionReturnStatus(CHIP_ERROR error) : mReturnStatus(error) {}
69 5294 : ActionReturnStatus(Protocols::InteractionModel::Status status) :
70 5294 : mReturnStatus(Protocols::InteractionModel::ClusterStatusCode(status))
71 5294 : {}
72 33 : ActionReturnStatus(Protocols::InteractionModel::ClusterStatusCode status) : mReturnStatus(status) {}
73 : ActionReturnStatus(FixedStatus status) : mReturnStatus(status) {}
74 :
75 : /// Constructs a status code. Either returns the underlying code directly
76 : /// or converts the underlying CHIP_ERROR into a cluster status code.
77 : Protocols::InteractionModel::ClusterStatusCode GetStatusCode() const;
78 :
79 : /// Gets the underlying CHIP_ERROR if it exists, otherwise it will
80 : /// return a CHIP_ERROR corresponding to the underlying return status.
81 : ///
82 : /// Success statusess will result in CHIP_NO_ERROR (i.e. cluster specitic success codes are lost)
83 : CHIP_ERROR GetUnderlyingError() const;
84 :
85 : /// If this is a CHIP_NO_ERROR or a Status::Success
86 : bool IsSuccess() const;
87 :
88 : /// Considers if the underlying error is an error or not (CHIP_NO_ERROR is the only non-erro)
89 : /// or if the underlying statuscode is not an error (success and cluster specific successes
90 : /// are not an error).
91 4937 : bool IsError() const { return !IsSuccess(); }
92 :
93 : /// Checks if the underlying error is an out of space condition (i.e. something that
94 : /// chunking can handle by sending partial list data).
95 : ///
96 : /// Generally this is when the return is based on CHIP_ERROR_NO_MEMORY or CHIP_ERROR_BUFFER_TOO_SMALL
97 : bool IsOutOfSpaceEncodingResponse() const;
98 :
99 : /// Check if the operation was successful but shouldn't trigger any specific operation
100 : /// (e.g. overwriting an attribute with the same value).
101 : bool IsNoOpSuccess() const;
102 :
103 : // NOTE: operator== will treat a CHIP_GLOBAL_IM_ERROR and a raw cluster status as equal if the statuses match,
104 : // even though a CHIP_ERROR has some formatting info like file/line
105 : bool operator==(const ActionReturnStatus & other) const;
106 25 : bool operator!=(const ActionReturnStatus & other) const { return !(*this == other); }
107 :
108 : /// Get the formatted string of this status.
109 : ///
110 : /// May use `storage` for storying the actual underlying character string.
111 : const char * c_str(StringStorage & storage) const;
112 :
113 : private:
114 : std::variant<CHIP_ERROR, Protocols::InteractionModel::ClusterStatusCode, ActionReturnStatus::FixedStatus> mReturnStatus;
115 : };
116 :
117 : } // namespace DataModel
118 : } // namespace app
119 : } // namespace chip
|