Adding RTCErrorOr class to be used by ORTC APIs.

This utility class can be used to represent either an error or a
successful return value. Follows the pattern of StatusOr in the protobuf
library.

This will be used by ORTC factory methods; for instance, CreateRtpSender
will either return an RtpSender or an error if the parameters are
invalid or some other failure occurs.

This CL also moves RTCError classes to a separate file, and adds tests
that were missing before.

BUG=webrtc:7013

Review-Url: https://codereview.webrtc.org/2692723002
Cr-Commit-Position: refs/heads/master@{#16659}
diff --git a/webrtc/api/rtcerror.h b/webrtc/api/rtcerror.h
new file mode 100644
index 0000000..2271445
--- /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_