Index: webrtc/api/rtcerror.h |
diff --git a/webrtc/api/rtcerror.h b/webrtc/api/rtcerror.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..97cd0ed0501f10528fb0d86681ed13f5f0d2a17f |
--- /dev/null |
+++ b/webrtc/api/rtcerror.h |
@@ -0,0 +1,280 @@ |
+/* |
+ * 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. |
kwiberg-webrtc
2017/02/14 09:51:49
If this sort of thing is a consideration, you may
tommi
2017/02/14 09:55:56
this is a consideration because there's no need to
kwiberg-webrtc
2017/02/14 11:37:25
Then I'd suggest having *only* the const char* and
tommi
2017/02/14 11:58:58
That sounds good to me. I may have mentioned it a
Taylor Brandstetter
2017/02/15 02:22:23
Done.
|
+ RTCError(RTCErrorType type, const char* message) |
+ : type_(type), message_(message), static_message_(true) {} |
+ RTCError(RTCErrorType type, const std::string& message) |
+ : type_(type), message_(message), static_message_(false) {} |
+ ~RTCError(); |
+ |
+ // Identical to default constructed error. |
+ // |
+ // Preferred over the default constructor for code readability, and reducing |
+ // unnecessary copies. |
+ static const 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(const 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 MessageUnion { |
+ MessageUnion() = default; |
+ MessageUnion(const char* message) : static_(message) {} |
+ MessageUnion(const std::string& message) : str_(new std::string(message)) {} |
+ const char* static_ = ""; |
+ std::string* str_; |
+ } message_; |
+ // Whether or not static_ or str_ is being used in the above union. |
+ bool static_message_ = true; |
+}; |
+ |
+// 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 methods that can be used by implementations to create an error with a |
+// message and log it. |
+webrtc::RTCError CreateAndLogError(webrtc::RTCErrorType type, |
+ const char* message, |
+ rtc::LoggingSeverity severity); |
+webrtc::RTCError CreateAndLogError(webrtc::RTCErrorType type, |
+ const std::string& message, |
+ rtc::LoggingSeverity severity); |
+// Logs at error level. |
+webrtc::RTCError CreateAndLogError(webrtc::RTCErrorType type, |
+ const char* message); |
+webrtc::RTCError CreateAndLogError(webrtc::RTCErrorType type, |
+ const std::string& message); |
+ |
+// 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::NONE 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::NONE error. |
+ explicit RTCErrorOr() = default; |
+ |
+ // 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(const RTCError& error) : error_(error) { RTC_DCHECK(!error.ok()); } |
+ 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_; } |
+ |
+ // 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_ |