1*14675a02SAndroid Build Coastguard Worker /* 2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC 3*14675a02SAndroid Build Coastguard Worker * 4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*14675a02SAndroid Build Coastguard Worker * 8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*14675a02SAndroid Build Coastguard Worker * 10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*14675a02SAndroid Build Coastguard Worker * limitations under the License. 15*14675a02SAndroid Build Coastguard Worker */ 16*14675a02SAndroid Build Coastguard Worker 17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_RESULT_H_ 18*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_RESULT_H_ 19*14675a02SAndroid Build Coastguard Worker 20*14675a02SAndroid Build Coastguard Worker #include <optional> 21*14675a02SAndroid Build Coastguard Worker #include <type_traits> 22*14675a02SAndroid Build Coastguard Worker #include <variant> 23*14675a02SAndroid Build Coastguard Worker 24*14675a02SAndroid Build Coastguard Worker #include "fcp/base/error.h" 25*14675a02SAndroid Build Coastguard Worker #include "fcp/base/meta.h" 26*14675a02SAndroid Build Coastguard Worker #include "fcp/base/source_location.h" 27*14675a02SAndroid Build Coastguard Worker 28*14675a02SAndroid Build Coastguard Worker namespace fcp { 29*14675a02SAndroid Build Coastguard Worker namespace result_internal { 30*14675a02SAndroid Build Coastguard Worker 31*14675a02SAndroid Build Coastguard Worker template <typename R> 32*14675a02SAndroid Build Coastguard Worker struct ResultTraits; 33*14675a02SAndroid Build Coastguard Worker 34*14675a02SAndroid Build Coastguard Worker } // namespace result_internal 35*14675a02SAndroid Build Coastguard Worker 36*14675a02SAndroid Build Coastguard Worker // A Result is either a value (T) or an opaque Error. There are two main ways to 37*14675a02SAndroid Build Coastguard Worker // use one. 38*14675a02SAndroid Build Coastguard Worker // 39*14675a02SAndroid Build Coastguard Worker // Transform: Given a Result<T> r, and a callable f from T to Result<U>, 40*14675a02SAndroid Build Coastguard Worker // r.Then(f) returns Result<U>. Note that errors are passed through (without 41*14675a02SAndroid Build Coastguard Worker // calling f). 42*14675a02SAndroid Build Coastguard Worker // 43*14675a02SAndroid Build Coastguard Worker // Similarly, given a Result<T> r, and a callable f from T to U, r.Map(f) 44*14675a02SAndroid Build Coastguard Worker // returns Result<U>. The difference is that Then can introduce new errors (it 45*14675a02SAndroid Build Coastguard Worker // returns Result<U>) whereas Map only transforms values to other values. 46*14675a02SAndroid Build Coastguard Worker // 47*14675a02SAndroid Build Coastguard Worker // Result<int> some_int = ... 48*14675a02SAndroid Build Coastguard Worker // Result<bool> b = some_int.Then([](int i) -> Result<int> { 49*14675a02SAndroid Build Coastguard Worker // if (i < 0) { 50*14675a02SAndroid Build Coastguard Worker // return TraceError<...>(...); 51*14675a02SAndroid Build Coastguard Worker // } else { 52*14675a02SAndroid Build Coastguard Worker // return i; 53*14675a02SAndroid Build Coastguard Worker // } 54*14675a02SAndroid Build Coastguard Worker // }).Map([](int i) -> bool) { 55*14675a02SAndroid Build Coastguard Worker // return i % 2 == 0; 56*14675a02SAndroid Build Coastguard Worker // }); 57*14675a02SAndroid Build Coastguard Worker // 58*14675a02SAndroid Build Coastguard Worker // Propagate: The FCP_TRY macro unwraps results to their values. If a result 59*14675a02SAndroid Build Coastguard Worker // contains an error, it is returned (from the function where FCP_TRY appears). 60*14675a02SAndroid Build Coastguard Worker // 61*14675a02SAndroid Build Coastguard Worker // Result<int> GetInt(); 62*14675a02SAndroid Build Coastguard Worker // 63*14675a02SAndroid Build Coastguard Worker // Result<bool> F() { 64*14675a02SAndroid Build Coastguard Worker // int i = FCP_TRY(GetInt()); 65*14675a02SAndroid Build Coastguard Worker // if (i < 0) { 66*14675a02SAndroid Build Coastguard Worker // } 67*14675a02SAndroid Build Coastguard Worker // 68*14675a02SAndroid Build Coastguard Worker // return i % 2 == 0; 69*14675a02SAndroid Build Coastguard Worker // } 70*14675a02SAndroid Build Coastguard Worker // 71*14675a02SAndroid Build Coastguard Worker // Result<T> provides implicit conversions from T and Error. As above, in 72*14675a02SAndroid Build Coastguard Worker // functions returning Result<T>, it is useful and encourage to return a T or 73*14675a02SAndroid Build Coastguard Worker // Error directly. 74*14675a02SAndroid Build Coastguard Worker template <typename T> 75*14675a02SAndroid Build Coastguard Worker class ABSL_MUST_USE_RESULT Result { 76*14675a02SAndroid Build Coastguard Worker public: 77*14675a02SAndroid Build Coastguard Worker using ValueType = T; 78*14675a02SAndroid Build Coastguard Worker 79*14675a02SAndroid Build Coastguard Worker // These make Result<> usable as an argument to Match() (see match.h). 80*14675a02SAndroid Build Coastguard Worker using VariantType = std::variant<Error, T>; variant()81*14675a02SAndroid Build Coastguard Worker constexpr VariantType& variant() & { return val_; } variant()82*14675a02SAndroid Build Coastguard Worker constexpr VariantType const& variant() const& { return val_; } variant()83*14675a02SAndroid Build Coastguard Worker constexpr VariantType&& variant() && { return std::move(val_); } 84*14675a02SAndroid Build Coastguard Worker 85*14675a02SAndroid Build Coastguard Worker // Implicit conversion from T Result(T t)86*14675a02SAndroid Build Coastguard Worker constexpr Result(T t) : val_(std::move(t)) {} // NOLINT 87*14675a02SAndroid Build Coastguard Worker 88*14675a02SAndroid Build Coastguard Worker // Implicit conversion from Error Result(Error e)89*14675a02SAndroid Build Coastguard Worker Result(Error e) : val_(e) {} // NOLINT 90*14675a02SAndroid Build Coastguard Worker is_error()91*14675a02SAndroid Build Coastguard Worker constexpr bool is_error() const { 92*14675a02SAndroid Build Coastguard Worker return std::holds_alternative<Error>(val_); 93*14675a02SAndroid Build Coastguard Worker } 94*14675a02SAndroid Build Coastguard Worker 95*14675a02SAndroid Build Coastguard Worker // Returns a *reference* to the contained value. 96*14675a02SAndroid Build Coastguard Worker // Requires (CHECK): !is_error() GetValueOrDie()97*14675a02SAndroid Build Coastguard Worker constexpr T const& GetValueOrDie() const& { 98*14675a02SAndroid Build Coastguard Worker FCP_CHECK(std::holds_alternative<T>(val_)); 99*14675a02SAndroid Build Coastguard Worker return absl::get<T>(val_); 100*14675a02SAndroid Build Coastguard Worker } 101*14675a02SAndroid Build Coastguard Worker 102*14675a02SAndroid Build Coastguard Worker // Returns the contained value (by move). 103*14675a02SAndroid Build Coastguard Worker // This applies for results which are rvalues. 104*14675a02SAndroid Build Coastguard Worker // 105*14675a02SAndroid Build Coastguard Worker // Example: 106*14675a02SAndroid Build Coastguard Worker // Result<X> r = f(); 107*14675a02SAndroid Build Coastguard Worker // X v = std::move(r).GetValueOrDie(); 108*14675a02SAndroid Build Coastguard Worker // 109*14675a02SAndroid Build Coastguard Worker // Example: 110*14675a02SAndroid Build Coastguard Worker // X v = f().GetValueOrDie(); 111*14675a02SAndroid Build Coastguard Worker // 112*14675a02SAndroid Build Coastguard Worker // Requires (CHECK): !is_error() GetValueOrDie()113*14675a02SAndroid Build Coastguard Worker constexpr T GetValueOrDie() && { 114*14675a02SAndroid Build Coastguard Worker FCP_CHECK(std::holds_alternative<T>(val_)); 115*14675a02SAndroid Build Coastguard Worker return absl::get<T>(std::move(val_)); 116*14675a02SAndroid Build Coastguard Worker } 117*14675a02SAndroid Build Coastguard Worker 118*14675a02SAndroid Build Coastguard Worker // Returns the contained error. 119*14675a02SAndroid Build Coastguard Worker // Requires (CHECK): is_error() GetErrorOrDie()120*14675a02SAndroid Build Coastguard Worker Error GetErrorOrDie() const { 121*14675a02SAndroid Build Coastguard Worker FCP_CHECK(std::holds_alternative<Error>(val_)); 122*14675a02SAndroid Build Coastguard Worker return absl::get<Error>(val_); 123*14675a02SAndroid Build Coastguard Worker } 124*14675a02SAndroid Build Coastguard Worker 125*14675a02SAndroid Build Coastguard Worker // Transforms this Result into another (with value type U). 126*14675a02SAndroid Build Coastguard Worker // 127*14675a02SAndroid Build Coastguard Worker // If this Result holds an Error, it is passed through. 128*14675a02SAndroid Build Coastguard Worker // If this Result holds a value, then the callable 'fn' is applied to it. 129*14675a02SAndroid Build Coastguard Worker // The callable 'fn' is expected to return Result<U>. 130*14675a02SAndroid Build Coastguard Worker // 131*14675a02SAndroid Build Coastguard Worker // Example: 132*14675a02SAndroid Build Coastguard Worker // 133*14675a02SAndroid Build Coastguard Worker // Result<int> some_int = ... 134*14675a02SAndroid Build Coastguard Worker // Result<bool> b = some_int.Then([](int i) -> Result<bool> { 135*14675a02SAndroid Build Coastguard Worker // if (i < 0) { 136*14675a02SAndroid Build Coastguard Worker // return TraceError<...>(...); 137*14675a02SAndroid Build Coastguard Worker // } else { 138*14675a02SAndroid Build Coastguard Worker // return i % 2 == 0; 139*14675a02SAndroid Build Coastguard Worker // } 140*14675a02SAndroid Build Coastguard Worker // }); 141*14675a02SAndroid Build Coastguard Worker template <typename Fn> Then(Fn fn)142*14675a02SAndroid Build Coastguard Worker constexpr auto Then(Fn fn) const& { 143*14675a02SAndroid Build Coastguard Worker return ThenInternal<false>(*this, std::move(fn)); 144*14675a02SAndroid Build Coastguard Worker } 145*14675a02SAndroid Build Coastguard Worker 146*14675a02SAndroid Build Coastguard Worker template <typename Fn> Then(Fn fn)147*14675a02SAndroid Build Coastguard Worker constexpr auto Then(Fn fn) && { 148*14675a02SAndroid Build Coastguard Worker return ThenInternal<true>(std::move(*this), std::move(fn)); 149*14675a02SAndroid Build Coastguard Worker } 150*14675a02SAndroid Build Coastguard Worker 151*14675a02SAndroid Build Coastguard Worker // Maps values of type T to a values of type U. 152*14675a02SAndroid Build Coastguard Worker // 153*14675a02SAndroid Build Coastguard Worker // If this Result holds an Error, it is passed through. 154*14675a02SAndroid Build Coastguard Worker // If this Result holds a value, then the callable 'fn' is applied to it. 155*14675a02SAndroid Build Coastguard Worker // 156*14675a02SAndroid Build Coastguard Worker // Example: 157*14675a02SAndroid Build Coastguard Worker // 158*14675a02SAndroid Build Coastguard Worker // Result<int> some_int = ... 159*14675a02SAndroid Build Coastguard Worker // Result<bool> b = some_int.Map([](int i) { 160*14675a02SAndroid Build Coastguard Worker // return i % 2 == 0; 161*14675a02SAndroid Build Coastguard Worker // }); 162*14675a02SAndroid Build Coastguard Worker template <typename Fn> Map(Fn fn)163*14675a02SAndroid Build Coastguard Worker constexpr auto Map(Fn fn) const& { 164*14675a02SAndroid Build Coastguard Worker using U = std::invoke_result_t<Fn, T const&>; 165*14675a02SAndroid Build Coastguard Worker return ThenInternal<false>( 166*14675a02SAndroid Build Coastguard Worker *this, [fn = std::move(fn)](T const& t) { return Result<U>(fn(t)); }); 167*14675a02SAndroid Build Coastguard Worker } 168*14675a02SAndroid Build Coastguard Worker 169*14675a02SAndroid Build Coastguard Worker template <typename Fn> Map(Fn fn)170*14675a02SAndroid Build Coastguard Worker constexpr auto Map(Fn fn) && { 171*14675a02SAndroid Build Coastguard Worker using U = std::invoke_result_t<Fn, T&&>; 172*14675a02SAndroid Build Coastguard Worker return ThenInternal<true>(std::move(*this), [fn = std::move(fn)](T&& t) { 173*14675a02SAndroid Build Coastguard Worker return Result<U>(fn(std::move(t))); 174*14675a02SAndroid Build Coastguard Worker }); 175*14675a02SAndroid Build Coastguard Worker } 176*14675a02SAndroid Build Coastguard Worker 177*14675a02SAndroid Build Coastguard Worker private: 178*14675a02SAndroid Build Coastguard Worker template <bool Move, typename Fn> ThenInternal(std::conditional_t<Move,Result<T> &&,Result<T> const &> r,Fn fn)179*14675a02SAndroid Build Coastguard Worker static constexpr auto ThenInternal( 180*14675a02SAndroid Build Coastguard Worker std::conditional_t<Move, Result<T>&&, Result<T> const&> r, Fn fn) { 181*14675a02SAndroid Build Coastguard Worker using RefType = std::conditional_t<Move, T&&, T const&>; 182*14675a02SAndroid Build Coastguard Worker using RetType = std::invoke_result_t<Fn, RefType>; 183*14675a02SAndroid Build Coastguard Worker static_assert( 184*14675a02SAndroid Build Coastguard Worker result_internal::ResultTraits<RetType>::is_result(), 185*14675a02SAndroid Build Coastguard Worker "The callable provided to 'Then' must return Result<U> for " 186*14675a02SAndroid Build Coastguard Worker "some type U. When always returning a value, use Map instead."); 187*14675a02SAndroid Build Coastguard Worker 188*14675a02SAndroid Build Coastguard Worker if (r.is_error()) { 189*14675a02SAndroid Build Coastguard Worker return RetType(r.GetErrorOrDie()); 190*14675a02SAndroid Build Coastguard Worker } else { 191*14675a02SAndroid Build Coastguard Worker return fn(absl::get<T>(std::move(r).variant())); 192*14675a02SAndroid Build Coastguard Worker } 193*14675a02SAndroid Build Coastguard Worker } 194*14675a02SAndroid Build Coastguard Worker 195*14675a02SAndroid Build Coastguard Worker std::variant<Error, T> val_; 196*14675a02SAndroid Build Coastguard Worker }; 197*14675a02SAndroid Build Coastguard Worker 198*14675a02SAndroid Build Coastguard Worker // This is a deduction guide so that one can write Result(t) for a value t, 199*14675a02SAndroid Build Coastguard Worker // without explicitly specifying the value type. This one is implicitly 200*14675a02SAndroid Build Coastguard Worker // declared anyway; we make it explicit to suppress -Wctad-maybe-unsupported. 201*14675a02SAndroid Build Coastguard Worker template <typename T> 202*14675a02SAndroid Build Coastguard Worker Result(T) -> Result<T>; 203*14675a02SAndroid Build Coastguard Worker 204*14675a02SAndroid Build Coastguard Worker // ResultFrom<T> -> Result<T> 205*14675a02SAndroid Build Coastguard Worker // ResultFrom<Result<T>> -> Result<T> 206*14675a02SAndroid Build Coastguard Worker // 207*14675a02SAndroid Build Coastguard Worker // Note that ResultFrom<Error> is ill-formed (like Result<Error>). 208*14675a02SAndroid Build Coastguard Worker template <typename T> 209*14675a02SAndroid Build Coastguard Worker using ResultFrom = decltype(Result(std::declval<T>())); 210*14675a02SAndroid Build Coastguard Worker 211*14675a02SAndroid Build Coastguard Worker // ResultOf applied to the result of calling Fn with Args... 212*14675a02SAndroid Build Coastguard Worker template <typename Fn, typename... Args> 213*14675a02SAndroid Build Coastguard Worker using ResultOf = ResultFrom<std::invoke_result_t<Fn, Args...>>; 214*14675a02SAndroid Build Coastguard Worker 215*14675a02SAndroid Build Coastguard Worker namespace result_internal { 216*14675a02SAndroid Build Coastguard Worker 217*14675a02SAndroid Build Coastguard Worker template <typename R> 218*14675a02SAndroid Build Coastguard Worker struct ResultTraits { 219*14675a02SAndroid Build Coastguard Worker using ValueType = void; 220*14675a02SAndroid Build Coastguard Worker }; 221*14675a02SAndroid Build Coastguard Worker 222*14675a02SAndroid Build Coastguard Worker template <typename T> 223*14675a02SAndroid Build Coastguard Worker struct ResultTraits<Result<T>> { 224*14675a02SAndroid Build Coastguard Worker static constexpr bool is_result() { return true; } 225*14675a02SAndroid Build Coastguard Worker using ValueType = T; 226*14675a02SAndroid Build Coastguard Worker }; 227*14675a02SAndroid Build Coastguard Worker 228*14675a02SAndroid Build Coastguard Worker // This is used in FCP_TRY, to require that the parameter to FCP_TRY has type 229*14675a02SAndroid Build Coastguard Worker // Result<T> for some T. 230*14675a02SAndroid Build Coastguard Worker template <typename T> 231*14675a02SAndroid Build Coastguard Worker constexpr bool ResultIsError(Result<T> const& r) { 232*14675a02SAndroid Build Coastguard Worker return r.is_error(); 233*14675a02SAndroid Build Coastguard Worker } 234*14675a02SAndroid Build Coastguard Worker 235*14675a02SAndroid Build Coastguard Worker } // namespace result_internal 236*14675a02SAndroid Build Coastguard Worker 237*14675a02SAndroid Build Coastguard Worker class ExpectBase { 238*14675a02SAndroid Build Coastguard Worker public: 239*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectBase(SourceLocation loc) : loc_(loc) {} 240*14675a02SAndroid Build Coastguard Worker 241*14675a02SAndroid Build Coastguard Worker protected: 242*14675a02SAndroid Build Coastguard Worker Error TraceExpectError(const char* expectation) const; 243*14675a02SAndroid Build Coastguard Worker Error TraceUnexpectedStatus(fcp::StatusCode expected_code, 244*14675a02SAndroid Build Coastguard Worker const fcp::Status& actual) const; 245*14675a02SAndroid Build Coastguard Worker 246*14675a02SAndroid Build Coastguard Worker private: 247*14675a02SAndroid Build Coastguard Worker SourceLocation loc_; 248*14675a02SAndroid Build Coastguard Worker }; 249*14675a02SAndroid Build Coastguard Worker 250*14675a02SAndroid Build Coastguard Worker // Returns Result<T> if the current result has std::variant that holds a 251*14675a02SAndroid Build Coastguard Worker // value of type T; otherwise returns an error Result. 252*14675a02SAndroid Build Coastguard Worker template <typename T> 253*14675a02SAndroid Build Coastguard Worker struct ExpectIs : public ExpectBase { 254*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 255*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectIs(SourceLocation loc = SourceLocation::current()) 256*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 257*14675a02SAndroid Build Coastguard Worker 258*14675a02SAndroid Build Coastguard Worker template <typename... Us> 259*14675a02SAndroid Build Coastguard Worker constexpr Result<T> operator()(std::variant<Us...> v) const { 260*14675a02SAndroid Build Coastguard Worker if (std::holds_alternative<T>(v)) { 261*14675a02SAndroid Build Coastguard Worker return absl::get<T>(std::move(v)); 262*14675a02SAndroid Build Coastguard Worker } else { 263*14675a02SAndroid Build Coastguard Worker return TraceExpectError("ExpectIs"); 264*14675a02SAndroid Build Coastguard Worker } 265*14675a02SAndroid Build Coastguard Worker } 266*14675a02SAndroid Build Coastguard Worker }; 267*14675a02SAndroid Build Coastguard Worker 268*14675a02SAndroid Build Coastguard Worker // Returns Result<std::variant<Us...>> if the current result has 269*14675a02SAndroid Build Coastguard Worker // std::variant that holds a value of one of the types from Us... typelist; 270*14675a02SAndroid Build Coastguard Worker // otherwise returns an error Result. This operation is valid only when the 271*14675a02SAndroid Build Coastguard Worker // set of expected types Us... is a subset of the set of types Ts... in the 272*14675a02SAndroid Build Coastguard Worker // current result. 273*14675a02SAndroid Build Coastguard Worker template <typename... Ts> 274*14675a02SAndroid Build Coastguard Worker struct ExpectOneOf : public ExpectBase { 275*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 276*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectOneOf(SourceLocation loc = SourceLocation::current()) 277*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 278*14675a02SAndroid Build Coastguard Worker 279*14675a02SAndroid Build Coastguard Worker template <typename... Us> 280*14675a02SAndroid Build Coastguard Worker constexpr Result<std::variant<Ts...>> operator()( 281*14675a02SAndroid Build Coastguard Worker std::variant<Us...> v) const { 282*14675a02SAndroid Build Coastguard Worker static_assert(IsSubsetOf<Pack<Ts...>, Pack<Us...>>::value); 283*14675a02SAndroid Build Coastguard Worker 284*14675a02SAndroid Build Coastguard Worker // TODO(team): This should be expressible with Match 285*14675a02SAndroid Build Coastguard Worker return absl::visit( 286*14675a02SAndroid Build Coastguard Worker [this](auto arg) -> Result<std::variant<Ts...>> { 287*14675a02SAndroid Build Coastguard Worker if constexpr (IsTypeOneOf<std::decay_t<decltype(arg)>, Ts...>()) { 288*14675a02SAndroid Build Coastguard Worker return std::variant<Ts...>(std::move(arg)); 289*14675a02SAndroid Build Coastguard Worker } else { 290*14675a02SAndroid Build Coastguard Worker return TraceExpectError("ExpectOneOf<>"); 291*14675a02SAndroid Build Coastguard Worker } 292*14675a02SAndroid Build Coastguard Worker }, 293*14675a02SAndroid Build Coastguard Worker std::move(v)); 294*14675a02SAndroid Build Coastguard Worker } 295*14675a02SAndroid Build Coastguard Worker }; 296*14675a02SAndroid Build Coastguard Worker 297*14675a02SAndroid Build Coastguard Worker // Returns Result<Unit> if the current result has boolean 'true' value; 298*14675a02SAndroid Build Coastguard Worker // otherwise returns an error Result. 299*14675a02SAndroid Build Coastguard Worker struct ExpectTrue : public ExpectBase { 300*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 301*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectTrue(SourceLocation loc = SourceLocation::current()) 302*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 303*14675a02SAndroid Build Coastguard Worker 304*14675a02SAndroid Build Coastguard Worker template <typename... Us> 305*14675a02SAndroid Build Coastguard Worker constexpr Result<Unit> operator()(bool b) const { 306*14675a02SAndroid Build Coastguard Worker if (b) { 307*14675a02SAndroid Build Coastguard Worker return Unit{}; 308*14675a02SAndroid Build Coastguard Worker } else { 309*14675a02SAndroid Build Coastguard Worker return TraceExpectError("ExpectTrue"); 310*14675a02SAndroid Build Coastguard Worker } 311*14675a02SAndroid Build Coastguard Worker } 312*14675a02SAndroid Build Coastguard Worker }; 313*14675a02SAndroid Build Coastguard Worker 314*14675a02SAndroid Build Coastguard Worker // Returns Result<Unit> if the current result has boolean 'false' value; 315*14675a02SAndroid Build Coastguard Worker // otherwise returns an error Result. 316*14675a02SAndroid Build Coastguard Worker struct ExpectFalse : public ExpectBase { 317*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 318*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectFalse(SourceLocation loc = SourceLocation::current()) 319*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 320*14675a02SAndroid Build Coastguard Worker 321*14675a02SAndroid Build Coastguard Worker template <typename... Us> 322*14675a02SAndroid Build Coastguard Worker constexpr Result<Unit> operator()(bool b) const { 323*14675a02SAndroid Build Coastguard Worker if (!b) { 324*14675a02SAndroid Build Coastguard Worker return Unit{}; 325*14675a02SAndroid Build Coastguard Worker } else { 326*14675a02SAndroid Build Coastguard Worker return TraceExpectError("ExpectTrue"); 327*14675a02SAndroid Build Coastguard Worker } 328*14675a02SAndroid Build Coastguard Worker } 329*14675a02SAndroid Build Coastguard Worker }; 330*14675a02SAndroid Build Coastguard Worker 331*14675a02SAndroid Build Coastguard Worker // Returns Result<T> if the current result has std::optional<T> has a value; 332*14675a02SAndroid Build Coastguard Worker // otherwise returns an error Result. 333*14675a02SAndroid Build Coastguard Worker struct ExpectHasValue : public ExpectBase { 334*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 335*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectHasValue( 336*14675a02SAndroid Build Coastguard Worker SourceLocation loc = SourceLocation::current()) 337*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 338*14675a02SAndroid Build Coastguard Worker 339*14675a02SAndroid Build Coastguard Worker template <typename T> 340*14675a02SAndroid Build Coastguard Worker constexpr Result<T> operator()(std::optional<T> v) const { 341*14675a02SAndroid Build Coastguard Worker if (v.has_value()) { 342*14675a02SAndroid Build Coastguard Worker return *std::move(v); 343*14675a02SAndroid Build Coastguard Worker } else { 344*14675a02SAndroid Build Coastguard Worker return TraceExpectError("ExpectHasValue"); 345*14675a02SAndroid Build Coastguard Worker } 346*14675a02SAndroid Build Coastguard Worker } 347*14675a02SAndroid Build Coastguard Worker }; 348*14675a02SAndroid Build Coastguard Worker 349*14675a02SAndroid Build Coastguard Worker // Returns Result<Unit> if the current result has an empty std::optional; 350*14675a02SAndroid Build Coastguard Worker // otherwise returns an error Result. 351*14675a02SAndroid Build Coastguard Worker struct ExpectIsEmpty : public ExpectBase { 352*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 353*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectIsEmpty( 354*14675a02SAndroid Build Coastguard Worker SourceLocation loc = SourceLocation::current()) 355*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 356*14675a02SAndroid Build Coastguard Worker 357*14675a02SAndroid Build Coastguard Worker template <typename T> 358*14675a02SAndroid Build Coastguard Worker constexpr Result<Unit> operator()(std::optional<T> v) const { 359*14675a02SAndroid Build Coastguard Worker if (!v.has_value()) { 360*14675a02SAndroid Build Coastguard Worker return Unit{}; 361*14675a02SAndroid Build Coastguard Worker } else { 362*14675a02SAndroid Build Coastguard Worker return TraceExpectError("ExpectIsEmpty"); 363*14675a02SAndroid Build Coastguard Worker } 364*14675a02SAndroid Build Coastguard Worker } 365*14675a02SAndroid Build Coastguard Worker }; 366*14675a02SAndroid Build Coastguard Worker 367*14675a02SAndroid Build Coastguard Worker struct ExpectOk : public ExpectBase { 368*14675a02SAndroid Build Coastguard Worker using ExpectBase::ExpectBase; 369*14675a02SAndroid Build Coastguard Worker constexpr explicit ExpectOk(SourceLocation loc = SourceLocation::current()) 370*14675a02SAndroid Build Coastguard Worker : ExpectBase(loc) {} 371*14675a02SAndroid Build Coastguard Worker 372*14675a02SAndroid Build Coastguard Worker template <typename T> 373*14675a02SAndroid Build Coastguard Worker constexpr Result<T> operator()(StatusOr<T> s) const { 374*14675a02SAndroid Build Coastguard Worker if (s.ok()) { 375*14675a02SAndroid Build Coastguard Worker return std::move(s).value(); 376*14675a02SAndroid Build Coastguard Worker } else { 377*14675a02SAndroid Build Coastguard Worker return TraceUnexpectedStatus(fcp::OK, s.status()); 378*14675a02SAndroid Build Coastguard Worker } 379*14675a02SAndroid Build Coastguard Worker } 380*14675a02SAndroid Build Coastguard Worker 381*14675a02SAndroid Build Coastguard Worker Result<Unit> operator()(const Status& s) const { 382*14675a02SAndroid Build Coastguard Worker if (s.code() == fcp::OK) { 383*14675a02SAndroid Build Coastguard Worker return Unit{}; 384*14675a02SAndroid Build Coastguard Worker } else { 385*14675a02SAndroid Build Coastguard Worker return TraceUnexpectedStatus(fcp::OK, s); 386*14675a02SAndroid Build Coastguard Worker } 387*14675a02SAndroid Build Coastguard Worker } 388*14675a02SAndroid Build Coastguard Worker }; 389*14675a02SAndroid Build Coastguard Worker 390*14675a02SAndroid Build Coastguard Worker } // namespace fcp 391*14675a02SAndroid Build Coastguard Worker 392*14675a02SAndroid Build Coastguard Worker #define FCP_TRY(...) \ 393*14675a02SAndroid Build Coastguard Worker ({ \ 394*14675a02SAndroid Build Coastguard Worker auto try_tmp_value_ = (__VA_ARGS__); \ 395*14675a02SAndroid Build Coastguard Worker if (::fcp::result_internal::ResultIsError(try_tmp_value_)) { \ 396*14675a02SAndroid Build Coastguard Worker return try_tmp_value_.GetErrorOrDie(); \ 397*14675a02SAndroid Build Coastguard Worker } \ 398*14675a02SAndroid Build Coastguard Worker std::move(try_tmp_value_).GetValueOrDie(); \ 399*14675a02SAndroid Build Coastguard Worker }) 400*14675a02SAndroid Build Coastguard Worker 401*14675a02SAndroid Build Coastguard Worker #endif // FCP_BASE_RESULT_H_ 402