1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #ifndef PLATFORM_BASE_ERROR_H_ 6*3f982cf4SFabien Sanglard #define PLATFORM_BASE_ERROR_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <cassert> 9*3f982cf4SFabien Sanglard #include <ostream> 10*3f982cf4SFabien Sanglard #include <string> 11*3f982cf4SFabien Sanglard #include <utility> 12*3f982cf4SFabien Sanglard 13*3f982cf4SFabien Sanglard #include "platform/base/macros.h" 14*3f982cf4SFabien Sanglard 15*3f982cf4SFabien Sanglard namespace openscreen { 16*3f982cf4SFabien Sanglard 17*3f982cf4SFabien Sanglard // Represents an error returned by an OSP library operation. An error has a 18*3f982cf4SFabien Sanglard // code and an optional message. 19*3f982cf4SFabien Sanglard class Error { 20*3f982cf4SFabien Sanglard public: 21*3f982cf4SFabien Sanglard // TODO(crbug.com/openscreen/65): Group/rename OSP-specific errors 22*3f982cf4SFabien Sanglard enum class Code : int8_t { 23*3f982cf4SFabien Sanglard // No error occurred. 24*3f982cf4SFabien Sanglard kNone = 0, 25*3f982cf4SFabien Sanglard 26*3f982cf4SFabien Sanglard // A transient condition prevented the operation from proceeding (e.g., 27*3f982cf4SFabien Sanglard // cannot send on a non-blocking socket without blocking). This indicates 28*3f982cf4SFabien Sanglard // the caller should try again later. 29*3f982cf4SFabien Sanglard kAgain = -1, 30*3f982cf4SFabien Sanglard 31*3f982cf4SFabien Sanglard // CBOR errors. 32*3f982cf4SFabien Sanglard kCborParsing = 1, 33*3f982cf4SFabien Sanglard kCborEncoding, 34*3f982cf4SFabien Sanglard kCborIncompleteMessage, 35*3f982cf4SFabien Sanglard kCborInvalidResponseId, 36*3f982cf4SFabien Sanglard kCborInvalidMessage, 37*3f982cf4SFabien Sanglard 38*3f982cf4SFabien Sanglard // Presentation start errors. 39*3f982cf4SFabien Sanglard kNoAvailableReceivers, 40*3f982cf4SFabien Sanglard kRequestCancelled, 41*3f982cf4SFabien Sanglard kNoPresentationFound, 42*3f982cf4SFabien Sanglard kPreviousStartInProgress, 43*3f982cf4SFabien Sanglard kUnknownStartError, 44*3f982cf4SFabien Sanglard kUnknownRequestId, 45*3f982cf4SFabien Sanglard 46*3f982cf4SFabien Sanglard kAddressInUse, 47*3f982cf4SFabien Sanglard kDomainNameTooLong, 48*3f982cf4SFabien Sanglard kDomainNameLabelTooLong, 49*3f982cf4SFabien Sanglard 50*3f982cf4SFabien Sanglard kIOFailure, 51*3f982cf4SFabien Sanglard kInitializationFailure, 52*3f982cf4SFabien Sanglard kInvalidIPV4Address, 53*3f982cf4SFabien Sanglard kInvalidIPV6Address, 54*3f982cf4SFabien Sanglard kConnectionFailed, 55*3f982cf4SFabien Sanglard 56*3f982cf4SFabien Sanglard kSocketOptionSettingFailure, 57*3f982cf4SFabien Sanglard kSocketAcceptFailure, 58*3f982cf4SFabien Sanglard kSocketBindFailure, 59*3f982cf4SFabien Sanglard kSocketClosedFailure, 60*3f982cf4SFabien Sanglard kSocketConnectFailure, 61*3f982cf4SFabien Sanglard kSocketInvalidState, 62*3f982cf4SFabien Sanglard kSocketListenFailure, 63*3f982cf4SFabien Sanglard kSocketReadFailure, 64*3f982cf4SFabien Sanglard kSocketSendFailure, 65*3f982cf4SFabien Sanglard 66*3f982cf4SFabien Sanglard // MDNS errors. 67*3f982cf4SFabien Sanglard kMdnsRegisterFailure, 68*3f982cf4SFabien Sanglard kMdnsReadFailure, 69*3f982cf4SFabien Sanglard kMdnsNonConformingFailure, 70*3f982cf4SFabien Sanglard 71*3f982cf4SFabien Sanglard kParseError, 72*3f982cf4SFabien Sanglard kUnknownMessageType, 73*3f982cf4SFabien Sanglard 74*3f982cf4SFabien Sanglard kNoActiveConnection, 75*3f982cf4SFabien Sanglard kAlreadyClosed, 76*3f982cf4SFabien Sanglard kInvalidConnectionState, 77*3f982cf4SFabien Sanglard kNoStartedPresentation, 78*3f982cf4SFabien Sanglard kPresentationAlreadyStarted, 79*3f982cf4SFabien Sanglard 80*3f982cf4SFabien Sanglard kJsonParseError, 81*3f982cf4SFabien Sanglard kJsonWriteError, 82*3f982cf4SFabien Sanglard 83*3f982cf4SFabien Sanglard // OpenSSL errors. 84*3f982cf4SFabien Sanglard 85*3f982cf4SFabien Sanglard // Was unable to generate an RSA key. 86*3f982cf4SFabien Sanglard kRSAKeyGenerationFailure, 87*3f982cf4SFabien Sanglard kRSAKeyParseError, 88*3f982cf4SFabien Sanglard 89*3f982cf4SFabien Sanglard // Was unable to initialize an EVP_PKEY type. 90*3f982cf4SFabien Sanglard kEVPInitializationError, 91*3f982cf4SFabien Sanglard 92*3f982cf4SFabien Sanglard // Was unable to generate a certificate. 93*3f982cf4SFabien Sanglard kCertificateCreationError, 94*3f982cf4SFabien Sanglard 95*3f982cf4SFabien Sanglard // Certificate failed validation. 96*3f982cf4SFabien Sanglard kCertificateValidationError, 97*3f982cf4SFabien Sanglard 98*3f982cf4SFabien Sanglard // Failed to produce a hashing digest. 99*3f982cf4SFabien Sanglard kSha256HashFailure, 100*3f982cf4SFabien Sanglard 101*3f982cf4SFabien Sanglard // A non-recoverable SSL library error has occurred. 102*3f982cf4SFabien Sanglard kFatalSSLError, 103*3f982cf4SFabien Sanglard kFileLoadFailure, 104*3f982cf4SFabien Sanglard 105*3f982cf4SFabien Sanglard // Cast certificate errors. 106*3f982cf4SFabien Sanglard 107*3f982cf4SFabien Sanglard // Certificates were not provided for verification. 108*3f982cf4SFabien Sanglard kErrCertsMissing, 109*3f982cf4SFabien Sanglard 110*3f982cf4SFabien Sanglard // The certificates provided could not be parsed. 111*3f982cf4SFabien Sanglard kErrCertsParse, 112*3f982cf4SFabien Sanglard 113*3f982cf4SFabien Sanglard // Key usage is missing or is not set to Digital Signature. 114*3f982cf4SFabien Sanglard // This error could also be thrown if the CN is missing. 115*3f982cf4SFabien Sanglard kErrCertsRestrictions, 116*3f982cf4SFabien Sanglard 117*3f982cf4SFabien Sanglard // The current date is before the notBefore date or after the notAfter date. 118*3f982cf4SFabien Sanglard kErrCertsDateInvalid, 119*3f982cf4SFabien Sanglard 120*3f982cf4SFabien Sanglard // The certificate failed to chain to a trusted root. 121*3f982cf4SFabien Sanglard kErrCertsVerifyGeneric, 122*3f982cf4SFabien Sanglard 123*3f982cf4SFabien Sanglard // The certificate was not found in the trust store. 124*3f982cf4SFabien Sanglard kErrCertsVerifyUntrustedCert, 125*3f982cf4SFabien Sanglard 126*3f982cf4SFabien Sanglard // The CRL is missing or failed to verify. 127*3f982cf4SFabien Sanglard kErrCrlInvalid, 128*3f982cf4SFabien Sanglard 129*3f982cf4SFabien Sanglard // One of the certificates in the chain is revoked. 130*3f982cf4SFabien Sanglard kErrCertsRevoked, 131*3f982cf4SFabien Sanglard 132*3f982cf4SFabien Sanglard // The pathlen constraint of the root certificate was exceeded. 133*3f982cf4SFabien Sanglard kErrCertsPathlen, 134*3f982cf4SFabien Sanglard 135*3f982cf4SFabien Sanglard // Cast authentication errors. 136*3f982cf4SFabien Sanglard kCastV2PeerCertEmpty, 137*3f982cf4SFabien Sanglard kCastV2WrongPayloadType, 138*3f982cf4SFabien Sanglard kCastV2NoPayload, 139*3f982cf4SFabien Sanglard kCastV2PayloadParsingFailed, 140*3f982cf4SFabien Sanglard kCastV2MessageError, 141*3f982cf4SFabien Sanglard kCastV2NoResponse, 142*3f982cf4SFabien Sanglard kCastV2FingerprintNotFound, 143*3f982cf4SFabien Sanglard kCastV2CertNotSignedByTrustedCa, 144*3f982cf4SFabien Sanglard kCastV2CannotExtractPublicKey, 145*3f982cf4SFabien Sanglard kCastV2SignedBlobsMismatch, 146*3f982cf4SFabien Sanglard kCastV2TlsCertValidityPeriodTooLong, 147*3f982cf4SFabien Sanglard kCastV2TlsCertValidStartDateInFuture, 148*3f982cf4SFabien Sanglard kCastV2TlsCertExpired, 149*3f982cf4SFabien Sanglard kCastV2SenderNonceMismatch, 150*3f982cf4SFabien Sanglard kCastV2DigestUnsupported, 151*3f982cf4SFabien Sanglard kCastV2SignatureEmpty, 152*3f982cf4SFabien Sanglard 153*3f982cf4SFabien Sanglard // Cast channel errors. 154*3f982cf4SFabien Sanglard kCastV2ChannelNotOpen, 155*3f982cf4SFabien Sanglard kCastV2AuthenticationError, 156*3f982cf4SFabien Sanglard kCastV2ConnectError, 157*3f982cf4SFabien Sanglard kCastV2CastSocketError, 158*3f982cf4SFabien Sanglard kCastV2TransportError, 159*3f982cf4SFabien Sanglard kCastV2InvalidMessage, 160*3f982cf4SFabien Sanglard kCastV2InvalidChannelId, 161*3f982cf4SFabien Sanglard kCastV2ConnectTimeout, 162*3f982cf4SFabien Sanglard kCastV2PingTimeout, 163*3f982cf4SFabien Sanglard kCastV2ChannelPolicyMismatch, 164*3f982cf4SFabien Sanglard 165*3f982cf4SFabien Sanglard kCreateSignatureFailed, 166*3f982cf4SFabien Sanglard 167*3f982cf4SFabien Sanglard // Discovery errors. 168*3f982cf4SFabien Sanglard kUpdateReceivedRecordFailure, 169*3f982cf4SFabien Sanglard kRecordPublicationError, 170*3f982cf4SFabien Sanglard kProcessReceivedRecordFailure, 171*3f982cf4SFabien Sanglard 172*3f982cf4SFabien Sanglard // Generic errors. 173*3f982cf4SFabien Sanglard kUnknownError, 174*3f982cf4SFabien Sanglard kNotImplemented, 175*3f982cf4SFabien Sanglard kInsufficientBuffer, 176*3f982cf4SFabien Sanglard kParameterInvalid, 177*3f982cf4SFabien Sanglard kParameterOutOfRange, 178*3f982cf4SFabien Sanglard kParameterNullPointer, 179*3f982cf4SFabien Sanglard kIndexOutOfBounds, 180*3f982cf4SFabien Sanglard kItemAlreadyExists, 181*3f982cf4SFabien Sanglard kItemNotFound, 182*3f982cf4SFabien Sanglard kOperationInvalid, 183*3f982cf4SFabien Sanglard kOperationInProgress, 184*3f982cf4SFabien Sanglard kOperationCancelled, 185*3f982cf4SFabien Sanglard 186*3f982cf4SFabien Sanglard // Cast streaming errors 187*3f982cf4SFabien Sanglard kTypeError, 188*3f982cf4SFabien Sanglard kUnknownCodec, 189*3f982cf4SFabien Sanglard kInvalidCodecParameter, 190*3f982cf4SFabien Sanglard kSocketFailure, 191*3f982cf4SFabien Sanglard kUnencryptedOffer, 192*3f982cf4SFabien Sanglard kRemotingNotSupported, 193*3f982cf4SFabien Sanglard 194*3f982cf4SFabien Sanglard // A negotiation failure means that the current negotiation must be 195*3f982cf4SFabien Sanglard // restarted by the sender. 196*3f982cf4SFabien Sanglard kNegotiationFailure, 197*3f982cf4SFabien Sanglard }; 198*3f982cf4SFabien Sanglard 199*3f982cf4SFabien Sanglard Error(); 200*3f982cf4SFabien Sanglard Error(const Error& error); 201*3f982cf4SFabien Sanglard Error(Error&& error) noexcept; 202*3f982cf4SFabien Sanglard 203*3f982cf4SFabien Sanglard Error(Code code); // NOLINT 204*3f982cf4SFabien Sanglard Error(Code code, const std::string& message); 205*3f982cf4SFabien Sanglard Error(Code code, std::string&& message); 206*3f982cf4SFabien Sanglard ~Error(); 207*3f982cf4SFabien Sanglard 208*3f982cf4SFabien Sanglard Error& operator=(const Error& other); 209*3f982cf4SFabien Sanglard Error& operator=(Error&& other); 210*3f982cf4SFabien Sanglard bool operator==(const Error& other) const; 211*3f982cf4SFabien Sanglard bool operator!=(const Error& other) const; 212*3f982cf4SFabien Sanglard 213*3f982cf4SFabien Sanglard // Special case comparison with codes. Without this case, comparisons will 214*3f982cf4SFabien Sanglard // not work as expected, e.g. 215*3f982cf4SFabien Sanglard // const Error foo(Error::Code::kItemNotFound, "Didn't find an item"); 216*3f982cf4SFabien Sanglard // foo == Error::Code::kItemNotFound is actually false. 217*3f982cf4SFabien Sanglard bool operator==(Code code) const; 218*3f982cf4SFabien Sanglard bool operator!=(Code code) const; ok()219*3f982cf4SFabien Sanglard bool ok() const { return code_ == Code::kNone; } 220*3f982cf4SFabien Sanglard code()221*3f982cf4SFabien Sanglard Code code() const { return code_; } message()222*3f982cf4SFabien Sanglard const std::string& message() const { return message_; } message()223*3f982cf4SFabien Sanglard std::string& message() { return message_; } 224*3f982cf4SFabien Sanglard 225*3f982cf4SFabien Sanglard static const Error& None(); 226*3f982cf4SFabien Sanglard 227*3f982cf4SFabien Sanglard std::string ToString() const; 228*3f982cf4SFabien Sanglard 229*3f982cf4SFabien Sanglard private: 230*3f982cf4SFabien Sanglard Code code_ = Code::kNone; 231*3f982cf4SFabien Sanglard std::string message_; 232*3f982cf4SFabien Sanglard }; 233*3f982cf4SFabien Sanglard 234*3f982cf4SFabien Sanglard std::ostream& operator<<(std::ostream& os, const Error::Code& code); 235*3f982cf4SFabien Sanglard 236*3f982cf4SFabien Sanglard std::ostream& operator<<(std::ostream& out, const Error& error); 237*3f982cf4SFabien Sanglard 238*3f982cf4SFabien Sanglard // A convenience function to return a single value from a function that can 239*3f982cf4SFabien Sanglard // return a value or an error. For normal results, construct with a ValueType* 240*3f982cf4SFabien Sanglard // (ErrorOr takes ownership) and the Error will be kNone with an empty message. 241*3f982cf4SFabien Sanglard // For Error results, construct with an error code and value. 242*3f982cf4SFabien Sanglard // 243*3f982cf4SFabien Sanglard // Example: 244*3f982cf4SFabien Sanglard // 245*3f982cf4SFabien Sanglard // ErrorOr<Bar> Foo::DoSomething() { 246*3f982cf4SFabien Sanglard // if (success) { 247*3f982cf4SFabien Sanglard // return Bar(); 248*3f982cf4SFabien Sanglard // } else { 249*3f982cf4SFabien Sanglard // return Error(kBadThingHappened, "No can do"); 250*3f982cf4SFabien Sanglard // } 251*3f982cf4SFabien Sanglard // } 252*3f982cf4SFabien Sanglard // 253*3f982cf4SFabien Sanglard // TODO(mfoltz): Add support for type conversions. 254*3f982cf4SFabien Sanglard template <typename ValueType> 255*3f982cf4SFabien Sanglard class ErrorOr { 256*3f982cf4SFabien Sanglard public: None()257*3f982cf4SFabien Sanglard static ErrorOr<ValueType> None() { 258*3f982cf4SFabien Sanglard static ErrorOr<ValueType> error(Error::Code::kNone); 259*3f982cf4SFabien Sanglard return error; 260*3f982cf4SFabien Sanglard } 261*3f982cf4SFabien Sanglard ErrorOr(const ValueType & value)262*3f982cf4SFabien Sanglard ErrorOr(const ValueType& value) : value_(value), is_value_(true) {} // NOLINT ErrorOr(ValueType && value)263*3f982cf4SFabien Sanglard ErrorOr(ValueType&& value) noexcept // NOLINT 264*3f982cf4SFabien Sanglard : value_(std::move(value)), is_value_(true) {} 265*3f982cf4SFabien Sanglard ErrorOr(const Error & error)266*3f982cf4SFabien Sanglard ErrorOr(const Error& error) : error_(error), is_value_(false) { // NOLINT 267*3f982cf4SFabien Sanglard assert(error_.code() != Error::Code::kNone); 268*3f982cf4SFabien Sanglard } ErrorOr(Error && error)269*3f982cf4SFabien Sanglard ErrorOr(Error&& error) noexcept // NOLINT 270*3f982cf4SFabien Sanglard : error_(std::move(error)), is_value_(false) { 271*3f982cf4SFabien Sanglard assert(error_.code() != Error::Code::kNone); 272*3f982cf4SFabien Sanglard } ErrorOr(Error::Code code)273*3f982cf4SFabien Sanglard ErrorOr(Error::Code code) : error_(code), is_value_(false) { // NOLINT 274*3f982cf4SFabien Sanglard assert(error_.code() != Error::Code::kNone); 275*3f982cf4SFabien Sanglard } ErrorOr(Error::Code code,std::string message)276*3f982cf4SFabien Sanglard ErrorOr(Error::Code code, std::string message) 277*3f982cf4SFabien Sanglard : error_(code, std::move(message)), is_value_(false) { 278*3f982cf4SFabien Sanglard assert(error_.code() != Error::Code::kNone); 279*3f982cf4SFabien Sanglard } 280*3f982cf4SFabien Sanglard 281*3f982cf4SFabien Sanglard ErrorOr(const ErrorOr& other) = delete; ErrorOr(ErrorOr && other)282*3f982cf4SFabien Sanglard ErrorOr(ErrorOr&& other) noexcept : is_value_(other.is_value_) { 283*3f982cf4SFabien Sanglard // NB: Both |value_| and |error_| are uninitialized memory at this point! 284*3f982cf4SFabien Sanglard // Unlike the other constructors, the compiler will not auto-generate 285*3f982cf4SFabien Sanglard // constructor calls for either union member because neither appeared in 286*3f982cf4SFabien Sanglard // this constructor's initializer list. 287*3f982cf4SFabien Sanglard if (other.is_value_) { 288*3f982cf4SFabien Sanglard new (&value_) ValueType(std::move(other.value_)); 289*3f982cf4SFabien Sanglard } else { 290*3f982cf4SFabien Sanglard new (&error_) Error(std::move(other.error_)); 291*3f982cf4SFabien Sanglard } 292*3f982cf4SFabien Sanglard } 293*3f982cf4SFabien Sanglard 294*3f982cf4SFabien Sanglard ErrorOr& operator=(const ErrorOr& other) = delete; 295*3f982cf4SFabien Sanglard ErrorOr& operator=(ErrorOr&& other) noexcept { 296*3f982cf4SFabien Sanglard this->~ErrorOr<ValueType>(); 297*3f982cf4SFabien Sanglard new (this) ErrorOr<ValueType>(std::move(other)); 298*3f982cf4SFabien Sanglard return *this; 299*3f982cf4SFabien Sanglard } 300*3f982cf4SFabien Sanglard ~ErrorOr()301*3f982cf4SFabien Sanglard ~ErrorOr() { 302*3f982cf4SFabien Sanglard // NB: |value_| or |error_| must be explicitly destroyed since the compiler 303*3f982cf4SFabien Sanglard // will not auto-generate the destructor calls for union members. 304*3f982cf4SFabien Sanglard if (is_value_) { 305*3f982cf4SFabien Sanglard value_.~ValueType(); 306*3f982cf4SFabien Sanglard } else { 307*3f982cf4SFabien Sanglard error_.~Error(); 308*3f982cf4SFabien Sanglard } 309*3f982cf4SFabien Sanglard } 310*3f982cf4SFabien Sanglard is_error()311*3f982cf4SFabien Sanglard bool is_error() const { return !is_value_; } is_value()312*3f982cf4SFabien Sanglard bool is_value() const { return is_value_; } 313*3f982cf4SFabien Sanglard 314*3f982cf4SFabien Sanglard // Unlike Error, we CAN provide an operator bool here, since it is 315*3f982cf4SFabien Sanglard // more obvious to callers that ErrorOr<Foo> will be true if it's Foo. 316*3f982cf4SFabien Sanglard operator bool() const { return is_value_; } 317*3f982cf4SFabien Sanglard error()318*3f982cf4SFabien Sanglard const Error& error() const { 319*3f982cf4SFabien Sanglard assert(!is_value_); 320*3f982cf4SFabien Sanglard return error_; 321*3f982cf4SFabien Sanglard } error()322*3f982cf4SFabien Sanglard Error& error() { 323*3f982cf4SFabien Sanglard assert(!is_value_); 324*3f982cf4SFabien Sanglard return error_; 325*3f982cf4SFabien Sanglard } 326*3f982cf4SFabien Sanglard value()327*3f982cf4SFabien Sanglard const ValueType& value() const { 328*3f982cf4SFabien Sanglard assert(is_value_); 329*3f982cf4SFabien Sanglard return value_; 330*3f982cf4SFabien Sanglard } value()331*3f982cf4SFabien Sanglard ValueType& value() { 332*3f982cf4SFabien Sanglard assert(is_value_); 333*3f982cf4SFabien Sanglard return value_; 334*3f982cf4SFabien Sanglard } 335*3f982cf4SFabien Sanglard 336*3f982cf4SFabien Sanglard // Move only value or fallback value(ValueType && fallback)337*3f982cf4SFabien Sanglard ValueType&& value(ValueType&& fallback) { 338*3f982cf4SFabien Sanglard if (is_value()) { 339*3f982cf4SFabien Sanglard return std::move(value()); 340*3f982cf4SFabien Sanglard } 341*3f982cf4SFabien Sanglard return std::forward<ValueType>(fallback); 342*3f982cf4SFabien Sanglard } 343*3f982cf4SFabien Sanglard 344*3f982cf4SFabien Sanglard // Copy only value or fallback value(ValueType fallback)345*3f982cf4SFabien Sanglard ValueType value(ValueType fallback) const { 346*3f982cf4SFabien Sanglard if (is_value()) { 347*3f982cf4SFabien Sanglard return value(); 348*3f982cf4SFabien Sanglard } 349*3f982cf4SFabien Sanglard return std::move(fallback); 350*3f982cf4SFabien Sanglard } 351*3f982cf4SFabien Sanglard 352*3f982cf4SFabien Sanglard private: 353*3f982cf4SFabien Sanglard // Only one of these is an active member, determined by |is_value_|. Since 354*3f982cf4SFabien Sanglard // they are union'ed, they must be explicitly constructed and destroyed. 355*3f982cf4SFabien Sanglard union { 356*3f982cf4SFabien Sanglard ValueType value_; 357*3f982cf4SFabien Sanglard Error error_; 358*3f982cf4SFabien Sanglard }; 359*3f982cf4SFabien Sanglard 360*3f982cf4SFabien Sanglard // If true, |value_| is initialized and active. Otherwise, |error_| is 361*3f982cf4SFabien Sanglard // initialized and active. 362*3f982cf4SFabien Sanglard const bool is_value_; 363*3f982cf4SFabien Sanglard }; 364*3f982cf4SFabien Sanglard 365*3f982cf4SFabien Sanglard // Define comparison operators using SFINAE. 366*3f982cf4SFabien Sanglard template <typename ValueType> 367*3f982cf4SFabien Sanglard bool operator<(const ErrorOr<ValueType>& lhs, const ErrorOr<ValueType>& rhs) { 368*3f982cf4SFabien Sanglard // Handle the cases where one side is an error. 369*3f982cf4SFabien Sanglard if (lhs.is_error() != rhs.is_error()) { 370*3f982cf4SFabien Sanglard return lhs.is_error(); 371*3f982cf4SFabien Sanglard } 372*3f982cf4SFabien Sanglard 373*3f982cf4SFabien Sanglard // Handle the case where both sides are errors. 374*3f982cf4SFabien Sanglard if (lhs.is_error()) { 375*3f982cf4SFabien Sanglard return static_cast<int8_t>(lhs.error().code()) < 376*3f982cf4SFabien Sanglard static_cast<int8_t>(rhs.error().code()); 377*3f982cf4SFabien Sanglard } 378*3f982cf4SFabien Sanglard 379*3f982cf4SFabien Sanglard // Handle the case where both are values. 380*3f982cf4SFabien Sanglard return lhs.value() < rhs.value(); 381*3f982cf4SFabien Sanglard } 382*3f982cf4SFabien Sanglard 383*3f982cf4SFabien Sanglard template <typename ValueType> 384*3f982cf4SFabien Sanglard bool operator>(const ErrorOr<ValueType>& lhs, const ErrorOr<ValueType>& rhs) { 385*3f982cf4SFabien Sanglard return rhs < lhs; 386*3f982cf4SFabien Sanglard } 387*3f982cf4SFabien Sanglard 388*3f982cf4SFabien Sanglard template <typename ValueType> 389*3f982cf4SFabien Sanglard bool operator<=(const ErrorOr<ValueType>& lhs, const ErrorOr<ValueType>& rhs) { 390*3f982cf4SFabien Sanglard return !(lhs > rhs); 391*3f982cf4SFabien Sanglard } 392*3f982cf4SFabien Sanglard 393*3f982cf4SFabien Sanglard template <typename ValueType> 394*3f982cf4SFabien Sanglard bool operator>=(const ErrorOr<ValueType>& lhs, const ErrorOr<ValueType>& rhs) { 395*3f982cf4SFabien Sanglard return !(rhs < lhs); 396*3f982cf4SFabien Sanglard } 397*3f982cf4SFabien Sanglard 398*3f982cf4SFabien Sanglard template <typename ValueType> 399*3f982cf4SFabien Sanglard bool operator==(const ErrorOr<ValueType>& lhs, const ErrorOr<ValueType>& rhs) { 400*3f982cf4SFabien Sanglard // Handle the cases where one side is an error. 401*3f982cf4SFabien Sanglard if (lhs.is_error() != rhs.is_error()) { 402*3f982cf4SFabien Sanglard return false; 403*3f982cf4SFabien Sanglard } 404*3f982cf4SFabien Sanglard 405*3f982cf4SFabien Sanglard // Handle the case where both sides are errors. 406*3f982cf4SFabien Sanglard if (lhs.is_error()) { 407*3f982cf4SFabien Sanglard return lhs.error() == rhs.error(); 408*3f982cf4SFabien Sanglard } 409*3f982cf4SFabien Sanglard 410*3f982cf4SFabien Sanglard // Handle the case where both are values. 411*3f982cf4SFabien Sanglard return lhs.value() == rhs.value(); 412*3f982cf4SFabien Sanglard } 413*3f982cf4SFabien Sanglard 414*3f982cf4SFabien Sanglard template <typename ValueType> 415*3f982cf4SFabien Sanglard bool operator!=(const ErrorOr<ValueType>& lhs, const ErrorOr<ValueType>& rhs) { 416*3f982cf4SFabien Sanglard return !(lhs == rhs); 417*3f982cf4SFabien Sanglard } 418*3f982cf4SFabien Sanglard 419*3f982cf4SFabien Sanglard } // namespace openscreen 420*3f982cf4SFabien Sanglard 421*3f982cf4SFabien Sanglard #endif // PLATFORM_BASE_ERROR_H_ 422