Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: webrtc/api/rtcerror.h

Issue 2692723002: Adding RTCErrorOr class to be used by ORTC APIs. (Closed)
Patch Set: Use const char* for error message. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/api/peerconnectioninterface.h ('k') | webrtc/api/rtcerror.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_
« no previous file with comments | « webrtc/api/peerconnectioninterface.h ('k') | webrtc/api/rtcerror.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698