xref: /aosp_15_r20/external/webrtc/api/rtc_error.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #ifndef API_RTC_ERROR_H_
12*d9f75844SAndroid Build Coastguard Worker #define API_RTC_ERROR_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_UNIT_TEST
15*d9f75844SAndroid Build Coastguard Worker #include <ostream>
16*d9f75844SAndroid Build Coastguard Worker #endif  // WEBRTC_UNIT_TEST
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker #include <utility>  // For std::move.
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
23*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/rtc_export.h"
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
26*d9f75844SAndroid Build Coastguard Worker 
27*d9f75844SAndroid Build Coastguard Worker // Enumeration to represent distinct classes of errors that an application
28*d9f75844SAndroid Build Coastguard Worker // may wish to act upon differently. These roughly map to DOMExceptions or
29*d9f75844SAndroid Build Coastguard Worker // RTCError "errorDetailEnum" values in the web API, as described in the
30*d9f75844SAndroid Build Coastguard Worker // comments below.
31*d9f75844SAndroid Build Coastguard Worker enum class RTCErrorType {
32*d9f75844SAndroid Build Coastguard Worker   // No error.
33*d9f75844SAndroid Build Coastguard Worker   NONE,
34*d9f75844SAndroid Build Coastguard Worker 
35*d9f75844SAndroid Build Coastguard Worker   // An operation is valid, but currently unsupported.
36*d9f75844SAndroid Build Coastguard Worker   // Maps to OperationError DOMException.
37*d9f75844SAndroid Build Coastguard Worker   UNSUPPORTED_OPERATION,
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker   // A supplied parameter is valid, but currently unsupported.
40*d9f75844SAndroid Build Coastguard Worker   // Maps to OperationError DOMException.
41*d9f75844SAndroid Build Coastguard Worker   UNSUPPORTED_PARAMETER,
42*d9f75844SAndroid Build Coastguard Worker 
43*d9f75844SAndroid Build Coastguard Worker   // General error indicating that a supplied parameter is invalid.
44*d9f75844SAndroid Build Coastguard Worker   // Maps to InvalidAccessError or TypeError DOMException depending on context.
45*d9f75844SAndroid Build Coastguard Worker   INVALID_PARAMETER,
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker   // Slightly more specific than INVALID_PARAMETER; a parameter's value was
48*d9f75844SAndroid Build Coastguard Worker   // outside the allowed range.
49*d9f75844SAndroid Build Coastguard Worker   // Maps to RangeError DOMException.
50*d9f75844SAndroid Build Coastguard Worker   INVALID_RANGE,
51*d9f75844SAndroid Build Coastguard Worker 
52*d9f75844SAndroid Build Coastguard Worker   // Slightly more specific than INVALID_PARAMETER; an error occurred while
53*d9f75844SAndroid Build Coastguard Worker   // parsing string input.
54*d9f75844SAndroid Build Coastguard Worker   // Maps to SyntaxError DOMException.
55*d9f75844SAndroid Build Coastguard Worker   SYNTAX_ERROR,
56*d9f75844SAndroid Build Coastguard Worker 
57*d9f75844SAndroid Build Coastguard Worker   // The object does not support this operation in its current state.
58*d9f75844SAndroid Build Coastguard Worker   // Maps to InvalidStateError DOMException.
59*d9f75844SAndroid Build Coastguard Worker   INVALID_STATE,
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker   // An attempt was made to modify the object in an invalid way.
62*d9f75844SAndroid Build Coastguard Worker   // Maps to InvalidModificationError DOMException.
63*d9f75844SAndroid Build Coastguard Worker   INVALID_MODIFICATION,
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker   // An error occurred within an underlying network protocol.
66*d9f75844SAndroid Build Coastguard Worker   // Maps to NetworkError DOMException.
67*d9f75844SAndroid Build Coastguard Worker   NETWORK_ERROR,
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker   // Some resource has been exhausted; file handles, hardware resources, ports,
70*d9f75844SAndroid Build Coastguard Worker   // etc.
71*d9f75844SAndroid Build Coastguard Worker   // Maps to OperationError DOMException.
72*d9f75844SAndroid Build Coastguard Worker   RESOURCE_EXHAUSTED,
73*d9f75844SAndroid Build Coastguard Worker 
74*d9f75844SAndroid Build Coastguard Worker   // The operation failed due to an internal error.
75*d9f75844SAndroid Build Coastguard Worker   // Maps to OperationError DOMException.
76*d9f75844SAndroid Build Coastguard Worker   INTERNAL_ERROR,
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker   // An error occured that has additional data.
79*d9f75844SAndroid Build Coastguard Worker   // The additional data is specified in
80*d9f75844SAndroid Build Coastguard Worker   // https://w3c.github.io/webrtc-pc/#rtcerror-interface
81*d9f75844SAndroid Build Coastguard Worker   // Maps to RTCError DOMException.
82*d9f75844SAndroid Build Coastguard Worker   OPERATION_ERROR_WITH_DATA,
83*d9f75844SAndroid Build Coastguard Worker };
84*d9f75844SAndroid Build Coastguard Worker 
85*d9f75844SAndroid Build Coastguard Worker // Detail information, showing what further information should be present.
86*d9f75844SAndroid Build Coastguard Worker // https://w3c.github.io/webrtc-pc/#rtcerrordetailtype-enum
87*d9f75844SAndroid Build Coastguard Worker enum class RTCErrorDetailType {
88*d9f75844SAndroid Build Coastguard Worker   NONE,
89*d9f75844SAndroid Build Coastguard Worker   DATA_CHANNEL_FAILURE,
90*d9f75844SAndroid Build Coastguard Worker   DTLS_FAILURE,
91*d9f75844SAndroid Build Coastguard Worker   FINGERPRINT_FAILURE,
92*d9f75844SAndroid Build Coastguard Worker   SCTP_FAILURE,
93*d9f75844SAndroid Build Coastguard Worker   SDP_SYNTAX_ERROR,
94*d9f75844SAndroid Build Coastguard Worker   HARDWARE_ENCODER_NOT_AVAILABLE,
95*d9f75844SAndroid Build Coastguard Worker   HARDWARE_ENCODER_ERROR,
96*d9f75844SAndroid Build Coastguard Worker };
97*d9f75844SAndroid Build Coastguard Worker 
98*d9f75844SAndroid Build Coastguard Worker // Roughly corresponds to RTCError in the web api. Holds an error type, a
99*d9f75844SAndroid Build Coastguard Worker // message, and possibly additional information specific to that error.
100*d9f75844SAndroid Build Coastguard Worker //
101*d9f75844SAndroid Build Coastguard Worker // Doesn't contain anything beyond a type and message now, but will in the
102*d9f75844SAndroid Build Coastguard Worker // future as more errors are implemented.
103*d9f75844SAndroid Build Coastguard Worker class RTC_EXPORT RTCError {
104*d9f75844SAndroid Build Coastguard Worker  public:
105*d9f75844SAndroid Build Coastguard Worker   // Constructors.
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker   // Creates a "no error" error.
RTCError()108*d9f75844SAndroid Build Coastguard Worker   RTCError() {}
RTCError(RTCErrorType type)109*d9f75844SAndroid Build Coastguard Worker   explicit RTCError(RTCErrorType type) : type_(type) {}
110*d9f75844SAndroid Build Coastguard Worker 
RTCError(RTCErrorType type,std::string message)111*d9f75844SAndroid Build Coastguard Worker   RTCError(RTCErrorType type, std::string message)
112*d9f75844SAndroid Build Coastguard Worker       : type_(type), message_(std::move(message)) {}
113*d9f75844SAndroid Build Coastguard Worker 
114*d9f75844SAndroid Build Coastguard Worker   // In many use cases, it is better to use move than copy,
115*d9f75844SAndroid Build Coastguard Worker   // but copy and assignment are provided for those cases that need it.
116*d9f75844SAndroid Build Coastguard Worker   // Note that this has extra overhead because it copies strings.
117*d9f75844SAndroid Build Coastguard Worker   RTCError(const RTCError& other) = default;
118*d9f75844SAndroid Build Coastguard Worker   RTCError(RTCError&&) = default;
119*d9f75844SAndroid Build Coastguard Worker   RTCError& operator=(const RTCError& other) = default;
120*d9f75844SAndroid Build Coastguard Worker   RTCError& operator=(RTCError&&) = default;
121*d9f75844SAndroid Build Coastguard Worker 
122*d9f75844SAndroid Build Coastguard Worker   // Identical to default constructed error.
123*d9f75844SAndroid Build Coastguard Worker   //
124*d9f75844SAndroid Build Coastguard Worker   // Preferred over the default constructor for code readability.
125*d9f75844SAndroid Build Coastguard Worker   static RTCError OK();
126*d9f75844SAndroid Build Coastguard Worker 
127*d9f75844SAndroid Build Coastguard Worker   // Error type.
type()128*d9f75844SAndroid Build Coastguard Worker   RTCErrorType type() const { return type_; }
set_type(RTCErrorType type)129*d9f75844SAndroid Build Coastguard Worker   void set_type(RTCErrorType type) { type_ = type; }
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker   // Human-readable message describing the error. Shouldn't be used for
132*d9f75844SAndroid Build Coastguard Worker   // anything but logging/diagnostics, since messages are not guaranteed to be
133*d9f75844SAndroid Build Coastguard Worker   // stable.
134*d9f75844SAndroid Build Coastguard Worker   const char* message() const;
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker   void set_message(std::string message);
137*d9f75844SAndroid Build Coastguard Worker 
error_detail()138*d9f75844SAndroid Build Coastguard Worker   RTCErrorDetailType error_detail() const { return error_detail_; }
set_error_detail(RTCErrorDetailType detail)139*d9f75844SAndroid Build Coastguard Worker   void set_error_detail(RTCErrorDetailType detail) { error_detail_ = detail; }
sctp_cause_code()140*d9f75844SAndroid Build Coastguard Worker   absl::optional<uint16_t> sctp_cause_code() const { return sctp_cause_code_; }
set_sctp_cause_code(uint16_t cause_code)141*d9f75844SAndroid Build Coastguard Worker   void set_sctp_cause_code(uint16_t cause_code) {
142*d9f75844SAndroid Build Coastguard Worker     sctp_cause_code_ = cause_code;
143*d9f75844SAndroid Build Coastguard Worker   }
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker   // Convenience method for situations where you only care whether or not an
146*d9f75844SAndroid Build Coastguard Worker   // error occurred.
ok()147*d9f75844SAndroid Build Coastguard Worker   bool ok() const { return type_ == RTCErrorType::NONE; }
148*d9f75844SAndroid Build Coastguard Worker 
149*d9f75844SAndroid Build Coastguard Worker  private:
150*d9f75844SAndroid Build Coastguard Worker   RTCErrorType type_ = RTCErrorType::NONE;
151*d9f75844SAndroid Build Coastguard Worker   std::string message_;
152*d9f75844SAndroid Build Coastguard Worker   RTCErrorDetailType error_detail_ = RTCErrorDetailType::NONE;
153*d9f75844SAndroid Build Coastguard Worker   absl::optional<uint16_t> sctp_cause_code_;
154*d9f75844SAndroid Build Coastguard Worker };
155*d9f75844SAndroid Build Coastguard Worker 
156*d9f75844SAndroid Build Coastguard Worker // Outputs the error as a friendly string. Update this method when adding a new
157*d9f75844SAndroid Build Coastguard Worker // error type.
158*d9f75844SAndroid Build Coastguard Worker //
159*d9f75844SAndroid Build Coastguard Worker // Only intended to be used for logging/diagnostics. The returned char* points
160*d9f75844SAndroid Build Coastguard Worker // to literal string that lives for the whole duration of the program.
161*d9f75844SAndroid Build Coastguard Worker RTC_EXPORT const char* ToString(RTCErrorType error);
162*d9f75844SAndroid Build Coastguard Worker RTC_EXPORT const char* ToString(RTCErrorDetailType error);
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_UNIT_TEST
165*d9f75844SAndroid Build Coastguard Worker inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
166*d9f75844SAndroid Build Coastguard Worker     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
167*d9f75844SAndroid Build Coastguard Worker     RTCErrorType error) {
168*d9f75844SAndroid Build Coastguard Worker   return stream << ToString(error);
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker 
171*d9f75844SAndroid Build Coastguard Worker inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
172*d9f75844SAndroid Build Coastguard Worker     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
173*d9f75844SAndroid Build Coastguard Worker     RTCErrorDetailType error) {
174*d9f75844SAndroid Build Coastguard Worker   return stream << ToString(error);
175*d9f75844SAndroid Build Coastguard Worker }
176*d9f75844SAndroid Build Coastguard Worker #endif  // WEBRTC_UNIT_TEST
177*d9f75844SAndroid Build Coastguard Worker 
178*d9f75844SAndroid Build Coastguard Worker // Helper macro that can be used by implementations to create an error with a
179*d9f75844SAndroid Build Coastguard Worker // message and log it. `message` should be a string literal or movable
180*d9f75844SAndroid Build Coastguard Worker // std::string.
181*d9f75844SAndroid Build Coastguard Worker #define LOG_AND_RETURN_ERROR_EX(type, message, severity)                     \
182*d9f75844SAndroid Build Coastguard Worker   {                                                                          \
183*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(type != RTCErrorType::NONE);                                  \
184*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(severity) << message << " (" << ::webrtc::ToString(type) << ")"; \
185*d9f75844SAndroid Build Coastguard Worker     return ::webrtc::RTCError(type, message);                                \
186*d9f75844SAndroid Build Coastguard Worker   }
187*d9f75844SAndroid Build Coastguard Worker 
188*d9f75844SAndroid Build Coastguard Worker #define LOG_AND_RETURN_ERROR(type, message) \
189*d9f75844SAndroid Build Coastguard Worker   LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR)
190*d9f75844SAndroid Build Coastguard Worker 
191*d9f75844SAndroid Build Coastguard Worker // RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr
192*d9f75844SAndroid Build Coastguard Worker // models the concept of an object that is either a usable value, or an error
193*d9f75844SAndroid Build Coastguard Worker // Status explaining why such a value is not present. To this end RTCErrorOr<T>
194*d9f75844SAndroid Build Coastguard Worker // does not allow its RTCErrorType value to be RTCErrorType::NONE. This is
195*d9f75844SAndroid Build Coastguard Worker // enforced by a debug check in most cases.
196*d9f75844SAndroid Build Coastguard Worker //
197*d9f75844SAndroid Build Coastguard Worker // The primary use-case for RTCErrorOr<T> is as the return value of a function
198*d9f75844SAndroid Build Coastguard Worker // which may fail. For example, CreateRtpSender will fail if the parameters
199*d9f75844SAndroid Build Coastguard Worker // could not be successfully applied at the media engine level, but if
200*d9f75844SAndroid Build Coastguard Worker // successful will return a unique_ptr to an RtpSender.
201*d9f75844SAndroid Build Coastguard Worker //
202*d9f75844SAndroid Build Coastguard Worker // Example client usage for a RTCErrorOr<std::unique_ptr<T>>:
203*d9f75844SAndroid Build Coastguard Worker //
204*d9f75844SAndroid Build Coastguard Worker //  RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
205*d9f75844SAndroid Build Coastguard Worker //  if (result.ok()) {
206*d9f75844SAndroid Build Coastguard Worker //    std::unique_ptr<Foo> foo = result.ConsumeValue();
207*d9f75844SAndroid Build Coastguard Worker //    foo->DoSomethingCool();
208*d9f75844SAndroid Build Coastguard Worker //  } else {
209*d9f75844SAndroid Build Coastguard Worker //    RTC_LOG(LS_ERROR) << result.error();
210*d9f75844SAndroid Build Coastguard Worker //  }
211*d9f75844SAndroid Build Coastguard Worker //
212*d9f75844SAndroid Build Coastguard Worker // Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>:
213*d9f75844SAndroid Build Coastguard Worker //
214*d9f75844SAndroid Build Coastguard Worker //  RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) {
215*d9f75844SAndroid Build Coastguard Worker //    if (arg <= 0) {
216*d9f75844SAndroid Build Coastguard Worker //      return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive");
217*d9f75844SAndroid Build Coastguard Worker //    } else {
218*d9f75844SAndroid Build Coastguard Worker //      return std::unique_ptr<Foo>(new Foo(arg));
219*d9f75844SAndroid Build Coastguard Worker //    }
220*d9f75844SAndroid Build Coastguard Worker //  }
221*d9f75844SAndroid Build Coastguard Worker //
222*d9f75844SAndroid Build Coastguard Worker template <typename T>
223*d9f75844SAndroid Build Coastguard Worker class RTCErrorOr {
224*d9f75844SAndroid Build Coastguard Worker   // Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit
225*d9f75844SAndroid Build Coastguard Worker   // conversion from Foo to Bar exists.
226*d9f75844SAndroid Build Coastguard Worker   template <typename U>
227*d9f75844SAndroid Build Coastguard Worker   friend class RTCErrorOr;
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker  public:
230*d9f75844SAndroid Build Coastguard Worker   typedef T element_type;
231*d9f75844SAndroid Build Coastguard Worker 
232*d9f75844SAndroid Build Coastguard Worker   // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This
233*d9f75844SAndroid Build Coastguard Worker   // is marked 'explicit' to try to catch cases like 'return {};', where people
234*d9f75844SAndroid Build Coastguard Worker   // think RTCErrorOr<std::vector<int>> will be initialized with an empty
235*d9f75844SAndroid Build Coastguard Worker   // vector, instead of a RTCErrorType::INTERNAL_ERROR error.
RTCErrorOr()236*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {}
237*d9f75844SAndroid Build Coastguard Worker 
238*d9f75844SAndroid Build Coastguard Worker   // Constructs a new RTCErrorOr with the given non-ok error. After calling
239*d9f75844SAndroid Build Coastguard Worker   // this constructor, calls to value() will DCHECK-fail.
240*d9f75844SAndroid Build Coastguard Worker   //
241*d9f75844SAndroid Build Coastguard Worker   // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return
242*d9f75844SAndroid Build Coastguard Worker   // value, so it is convenient and sensible to be able to do 'return
243*d9f75844SAndroid Build Coastguard Worker   // RTCError(...)' when the return type is RTCErrorOr<T>.
244*d9f75844SAndroid Build Coastguard Worker   //
245*d9f75844SAndroid Build Coastguard Worker   // REQUIRES: !error.ok(). This requirement is DCHECKed.
RTCErrorOr(RTCError && error)246*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr(RTCError&& error) : error_(std::move(error)) {  // NOLINT
247*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!error_.ok());
248*d9f75844SAndroid Build Coastguard Worker   }
249*d9f75844SAndroid Build Coastguard Worker 
250*d9f75844SAndroid Build Coastguard Worker   // Constructs a new RTCErrorOr with the given value. After calling this
251*d9f75844SAndroid Build Coastguard Worker   // constructor, calls to value() will succeed, and calls to error() will
252*d9f75844SAndroid Build Coastguard Worker   // return a default-constructed RTCError.
253*d9f75844SAndroid Build Coastguard Worker   //
254*d9f75844SAndroid Build Coastguard Worker   // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type
255*d9f75844SAndroid Build Coastguard Worker   // so it is convenient and sensible to be able to do 'return T()'
256*d9f75844SAndroid Build Coastguard Worker   // when the return type is RTCErrorOr<T>.
RTCErrorOr(const T & value)257*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr(const T& value) : value_(value) {}        // NOLINT
RTCErrorOr(T && value)258*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr(T&& value) : value_(std::move(value)) {}  // NOLINT
259*d9f75844SAndroid Build Coastguard Worker 
260*d9f75844SAndroid Build Coastguard Worker   // Delete the copy constructor and assignment operator; there aren't any use
261*d9f75844SAndroid Build Coastguard Worker   // cases where you should need to copy an RTCErrorOr, as opposed to moving
262*d9f75844SAndroid Build Coastguard Worker   // it. Can revisit this decision if use cases arise in the future.
263*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr(const RTCErrorOr& other) = delete;
264*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr& operator=(const RTCErrorOr& other) = delete;
265*d9f75844SAndroid Build Coastguard Worker 
266*d9f75844SAndroid Build Coastguard Worker   // Move constructor and move-assignment operator.
267*d9f75844SAndroid Build Coastguard Worker   //
268*d9f75844SAndroid Build Coastguard Worker   // Visual Studio doesn't support "= default" with move constructors or
269*d9f75844SAndroid Build Coastguard Worker   // assignment operators (even though they compile, they segfault), so define
270*d9f75844SAndroid Build Coastguard Worker   // them explicitly.
RTCErrorOr(RTCErrorOr && other)271*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr(RTCErrorOr&& other)
272*d9f75844SAndroid Build Coastguard Worker       : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
273*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr& operator=(RTCErrorOr&& other) {
274*d9f75844SAndroid Build Coastguard Worker     error_ = std::move(other.error_);
275*d9f75844SAndroid Build Coastguard Worker     value_ = std::move(other.value_);
276*d9f75844SAndroid Build Coastguard Worker     return *this;
277*d9f75844SAndroid Build Coastguard Worker   }
278*d9f75844SAndroid Build Coastguard Worker 
279*d9f75844SAndroid Build Coastguard Worker   // Conversion constructor and assignment operator; T must be copy or move
280*d9f75844SAndroid Build Coastguard Worker   // constructible from U.
281*d9f75844SAndroid Build Coastguard Worker   template <typename U>
RTCErrorOr(RTCErrorOr<U> other)282*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr(RTCErrorOr<U> other)  // NOLINT
283*d9f75844SAndroid Build Coastguard Worker       : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
284*d9f75844SAndroid Build Coastguard Worker   template <typename U>
285*d9f75844SAndroid Build Coastguard Worker   RTCErrorOr& operator=(RTCErrorOr<U> other) {
286*d9f75844SAndroid Build Coastguard Worker     error_ = std::move(other.error_);
287*d9f75844SAndroid Build Coastguard Worker     value_ = std::move(other.value_);
288*d9f75844SAndroid Build Coastguard Worker     return *this;
289*d9f75844SAndroid Build Coastguard Worker   }
290*d9f75844SAndroid Build Coastguard Worker 
291*d9f75844SAndroid Build Coastguard Worker   // Returns a reference to our error. If this contains a T, then returns
292*d9f75844SAndroid Build Coastguard Worker   // default-constructed RTCError.
error()293*d9f75844SAndroid Build Coastguard Worker   const RTCError& error() const { return error_; }
294*d9f75844SAndroid Build Coastguard Worker 
295*d9f75844SAndroid Build Coastguard Worker   // Moves the error. Can be useful if, say "CreateFoo" returns an
296*d9f75844SAndroid Build Coastguard Worker   // RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an
297*d9f75844SAndroid Build Coastguard Worker   // RTCErrorOr<Bar>, and wants to forward the error up the stack.
MoveError()298*d9f75844SAndroid Build Coastguard Worker   RTCError MoveError() { return std::move(error_); }
299*d9f75844SAndroid Build Coastguard Worker 
300*d9f75844SAndroid Build Coastguard Worker   // Returns this->error().ok()
ok()301*d9f75844SAndroid Build Coastguard Worker   bool ok() const { return error_.ok(); }
302*d9f75844SAndroid Build Coastguard Worker 
303*d9f75844SAndroid Build Coastguard Worker   // Returns a reference to our current value, or DCHECK-fails if !this->ok().
304*d9f75844SAndroid Build Coastguard Worker   //
305*d9f75844SAndroid Build Coastguard Worker   // Can be convenient for the implementation; for example, a method may want
306*d9f75844SAndroid Build Coastguard Worker   // to access the value in some way before returning it to the next method on
307*d9f75844SAndroid Build Coastguard Worker   // the stack.
value()308*d9f75844SAndroid Build Coastguard Worker   const T& value() const {
309*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(ok());
310*d9f75844SAndroid Build Coastguard Worker     return value_;
311*d9f75844SAndroid Build Coastguard Worker   }
value()312*d9f75844SAndroid Build Coastguard Worker   T& value() {
313*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(ok());
314*d9f75844SAndroid Build Coastguard Worker     return value_;
315*d9f75844SAndroid Build Coastguard Worker   }
316*d9f75844SAndroid Build Coastguard Worker 
317*d9f75844SAndroid Build Coastguard Worker   // Moves our current value out of this object and returns it, or DCHECK-fails
318*d9f75844SAndroid Build Coastguard Worker   // if !this->ok().
MoveValue()319*d9f75844SAndroid Build Coastguard Worker   T MoveValue() {
320*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(ok());
321*d9f75844SAndroid Build Coastguard Worker     return std::move(value_);
322*d9f75844SAndroid Build Coastguard Worker   }
323*d9f75844SAndroid Build Coastguard Worker 
324*d9f75844SAndroid Build Coastguard Worker  private:
325*d9f75844SAndroid Build Coastguard Worker   RTCError error_;
326*d9f75844SAndroid Build Coastguard Worker   T value_;
327*d9f75844SAndroid Build Coastguard Worker };
328*d9f75844SAndroid Build Coastguard Worker 
329*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
330*d9f75844SAndroid Build Coastguard Worker 
331*d9f75844SAndroid Build Coastguard Worker #endif  // API_RTC_ERROR_H_
332