Index: webrtc/api/rtcerror.h |
diff --git a/webrtc/api/rtcerror.h b/webrtc/api/rtcerror.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..22714451b5f3239a58dfadc98e00b4d4f59f3b47 |
--- /dev/null |
+++ b/webrtc/api/rtcerror.h |
@@ -0,0 +1,291 @@ |
+/* |
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#ifndef WEBRTC_API_RTCERROR_H_ |
+#define WEBRTC_API_RTCERROR_H_ |
+ |
+#include <ostream> |
+#include <string> |
+#include <utility> // For std::move. |
+ |
+#include "webrtc/base/checks.h" |
+#include "webrtc/base/logging.h" |
+ |
+namespace webrtc { |
+ |
+// Enumeration to represent distinct classes of errors that an application |
+// may wish to act upon differently. These roughly map to DOMExceptions or |
+// RTCError "errorDetailEnum" values in the web API, as described in the |
+// comments below. |
+enum class RTCErrorType { |
+ // No error. |
+ NONE, |
+ |
+ // An operation is valid, but currently unsupported. |
+ // Maps to OperationError DOMException. |
+ UNSUPPORTED_OPERATION, |
+ |
+ // A supplied parameter is valid, but currently unsupported. |
+ // Maps to OperationError DOMException. |
+ UNSUPPORTED_PARAMETER, |
+ |
+ // General error indicating that a supplied parameter is invalid. |
+ // Maps to InvalidAccessError or TypeError DOMException depending on context. |
+ INVALID_PARAMETER, |
+ |
+ // Slightly more specific than INVALID_PARAMETER; a parameter's value was |
+ // outside the allowed range. |
+ // Maps to RangeError DOMException. |
+ INVALID_RANGE, |
+ |
+ // Slightly more specific than INVALID_PARAMETER; an error occurred while |
+ // parsing string input. |
+ // Maps to SyntaxError DOMException. |
+ SYNTAX_ERROR, |
+ |
+ // The object does not support this operation in its current state. |
+ // Maps to InvalidStateError DOMException. |
+ INVALID_STATE, |
+ |
+ // An attempt was made to modify the object in an invalid way. |
+ // Maps to InvalidModificationError DOMException. |
+ INVALID_MODIFICATION, |
+ |
+ // An error occurred within an underlying network protocol. |
+ // Maps to NetworkError DOMException. |
+ NETWORK_ERROR, |
+ |
+ // Some resource has been exhausted; file handles, hardware resources, ports, |
+ // etc. |
+ // Maps to OperationError DOMException. |
+ RESOURCE_EXHAUSTED, |
+ |
+ // The operation failed due to an internal error. |
+ // Maps to OperationError DOMException. |
+ INTERNAL_ERROR, |
+}; |
+ |
+// Roughly corresponds to RTCError in the web api. Holds an error type, a |
+// message, and possibly additional information specific to that error. |
+// |
+// Doesn't contain anything beyond a type and message now, but will in the |
+// future as more errors are implemented. |
+class RTCError { |
+ public: |
+ // Constructors. |
+ |
+ // Creates a "no error" error. |
+ RTCError() {} |
+ explicit RTCError(RTCErrorType type) : type_(type) {} |
+ // For performance, prefer using the constructor that takes a const char* if |
+ // the message is a static string. |
+ RTCError(RTCErrorType type, const char* message) |
+ : type_(type), static_message_(message), have_string_message_(false) {} |
+ RTCError(RTCErrorType type, std::string&& message) |
+ : type_(type), string_message_(message), have_string_message_(true) {} |
+ |
+ // Delete the copy constructor and assignment operator; there aren't any use |
+ // cases where you should need to copy an RTCError, as opposed to moving it. |
+ // Can revisit this decision if use cases arise in the future. |
+ RTCError(const RTCError& other) = delete; |
+ RTCError& operator=(const RTCError& other) = delete; |
+ |
+ // Move constructor and move-assignment operator. |
+ RTCError(RTCError&& other); |
+ RTCError& operator=(RTCError&& other); |
+ |
+ ~RTCError(); |
+ |
+ // Identical to default constructed error. |
+ // |
+ // Preferred over the default constructor for code readability. |
+ static RTCError OK(); |
+ |
+ // Error type. |
+ RTCErrorType type() const { return type_; } |
+ void set_type(RTCErrorType type) { type_ = type; } |
+ |
+ // Human-readable message describing the error. Shouldn't be used for |
+ // anything but logging/diagnostics, since messages are not guaranteed to be |
+ // stable. |
+ const char* message() const; |
+ // For performance, prefer using the method that takes a const char* if the |
+ // message is a static string. |
+ void set_message(const char* message); |
+ void set_message(std::string&& message); |
+ |
+ // Convenience method for situations where you only care whether or not an |
+ // error occurred. |
+ bool ok() const { return type_ == RTCErrorType::NONE; } |
+ |
+ private: |
+ RTCErrorType type_ = RTCErrorType::NONE; |
+ // For performance, we use static strings wherever possible. But in some |
+ // cases the error string may need to be constructed, in which case an |
+ // std::string is used. |
+ union { |
+ const char* static_message_ = ""; |
+ std::string string_message_; |
+ }; |
+ // Whether or not |static_message_| or |string_message_| is being used in the |
+ // above union. |
+ bool have_string_message_ = false; |
+}; |
+ |
+// Outputs the error as a friendly string. Update this method when adding a new |
+// error type. |
+// |
+// Only intended to be used for logging/disagnostics. |
+std::ostream& operator<<(std::ostream& stream, RTCErrorType error); |
+ |
+// Helper macro that can be used by implementations to create an error with a |
+// message and log it. |message| should be a string literal or movable |
+// std::string. |
+#define LOG_AND_RETURN_ERROR_EX(type, message, severity) \ |
+ { \ |
+ RTC_DCHECK(type != RTCErrorType::NONE); \ |
+ LOG(severity) << message << " (" << type << ")"; \ |
+ return webrtc::RTCError(type, message); \ |
+ } |
+ |
+#define LOG_AND_RETURN_ERROR(type, message) \ |
+ LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR) |
+ |
+// RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr |
+// models the concept of an object that is either a usable value, or an error |
+// Status explaining why such a value is not present. To this end RTCErrorOr<T> |
+// does not allow its RTCErrorType value to be RTCErrorType::NONE. This is |
+// enforced by a debug check in most cases. |
+// |
+// The primary use-case for RTCErrorOr<T> is as the return value of a function |
+// which may fail. For example, CreateRtpSender will fail if the parameters |
+// could not be successfully applied at the media engine level, but if |
+// successful will return a unique_ptr to an RtpSender. |
+// |
+// Example client usage for a RTCErrorOr<std::unique_ptr<T>>: |
+// |
+// RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); |
+// if (result.ok()) { |
+// std::unique_ptr<Foo> foo = result.ConsumeValue(); |
+// foo->DoSomethingCool(); |
+// } else { |
+// LOG(LS_ERROR) << result.error(); |
+// } |
+// |
+// Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>: |
+// |
+// RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) { |
+// if (arg <= 0) { |
+// return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive"); |
+// } else { |
+// return std::unique_ptr<Foo>(new Foo(arg)); |
+// } |
+// } |
+// |
+template <typename T> |
+class RTCErrorOr { |
+ // Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit |
+ // conversion from Foo to Bar exists. |
+ template <typename U> |
+ friend class RTCErrorOr; |
+ |
+ public: |
+ typedef T element_type; |
+ |
+ // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This |
+ // is marked 'explicit' to try to catch cases like 'return {};', where people |
+ // think RTCErrorOr<std::vector<int>> will be initialized with an empty |
+ // vector, instead of a RTCErrorType::INTERNAL_ERROR error. |
+ explicit RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {} |
+ |
+ // Constructs a new RTCErrorOr with the given non-ok error. After calling |
+ // this constructor, calls to value() will DCHECK-fail. |
+ // |
+ // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return |
+ // value, so it is convenient and sensible to be able to do 'return |
+ // RTCError(...)' when the return type is RTCErrorOr<T>. |
+ // |
+ // REQUIRES: !error.ok(). This requirement is DCHECKed. |
+ RTCErrorOr(RTCError&& error) : error_(std::move(error)) { |
+ RTC_DCHECK(!error.ok()); |
+ } |
+ |
+ // Constructs a new RTCErrorOr with the given value. After calling this |
+ // constructor, calls to value() will succeed, and calls to error() will |
+ // return a default-constructed RTCError. |
+ // |
+ // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type |
+ // so it is convenient and sensible to be able to do 'return T()' |
+ // when the return type is RTCErrorOr<T>. |
+ RTCErrorOr(T value) : value_(std::move(value)) {} |
+ |
+ // Delete the copy constructor and assignment operator; there aren't any use |
+ // cases where you should need to copy an RTCErrorOr, as opposed to moving |
+ // it. Can revisit this decision if use cases arise in the future. |
+ RTCErrorOr(const RTCErrorOr& other) = delete; |
+ RTCErrorOr& operator=(const RTCErrorOr& other) = delete; |
+ |
+ // Move constructor and move-assignment operator. |
+ RTCErrorOr(RTCErrorOr&& other) = default; |
+ RTCErrorOr& operator=(RTCErrorOr&& other) = default; |
+ |
+ // Conversion constructor and assignment operator; T must be copy or move |
+ // constructible from U. |
+ template <typename U> |
+ RTCErrorOr(RTCErrorOr<U> other) |
+ : error_(std::move(other.error_)), value_(std::move(other.value_)) {} |
+ template <typename U> |
+ RTCErrorOr& operator=(RTCErrorOr<U> other) { |
+ error_ = std::move(other.error_); |
+ value_ = std::move(other.value_); |
+ return *this; |
+ } |
+ |
+ // Returns a reference to our error. If this contains a T, then returns |
+ // default-constructed RTCError. |
+ const RTCError& error() const { return error_; } |
+ |
+ // Moves the error. Can be useful if, say "CreateFoo" returns an |
+ // RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an |
+ // RTCErrorOr<Bar>, and wants to forward the error up the stack. |
+ RTCError MoveError() { return std::move(error_); } |
+ |
+ // Returns this->error().ok() |
+ bool ok() const { return error_.ok(); } |
+ |
+ // Returns a reference to our current value, or DCHECK-fails if !this->ok(). |
+ // |
+ // Can be convenient for the implementation; for example, a method may want |
+ // to access the value in some way before returning it to the next method on |
+ // the stack. |
+ const T& value() const { |
+ RTC_DCHECK(ok()); |
+ return value_; |
+ } |
+ T& value() { |
+ RTC_DCHECK(ok()); |
+ return value_; |
+ } |
+ |
+ // Moves our current value out of this object and returns it, or DCHECK-fails |
+ // if !this->ok(). |
+ T MoveValue() { |
+ RTC_DCHECK(ok()); |
+ return std::move(value_); |
+ } |
+ |
+ private: |
+ RTCError error_; |
+ T value_; |
+}; |
+ |
+} // namespace webrtc |
+ |
+#endif // WEBRTC_API_RTCERROR_H_ |