| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FLUTTER_FML_STATUS_OR_H_ |
| #define FLUTTER_FML_STATUS_OR_H_ |
| |
| #include <optional> |
| |
| #include "flutter/fml/logging.h" |
| #include "flutter/fml/status.h" |
| |
| namespace fml { |
| |
| // TODO(https://github.com/flutter/flutter/issues/134741): Replace with |
| // absl::StatusOr. |
| /// Represents a union type of an object of type `T` and an fml::Status. |
| /// |
| /// This is often used as a replacement for C++ exceptions where a function that |
| /// could fail may return an error or a result. These are typically used for |
| /// errors that are meant to be recovered from. If there is no recovery |
| /// available `FML_CHECK` is more appropriate. |
| /// |
| /// Example: |
| /// StatusOr<int> div(int n, int d) { |
| /// if (d == 0) { |
| /// return Status(StatusCode::kFailedPrecondition, "div by zero"); |
| /// } |
| /// return n / d; |
| /// } |
| template <typename T> |
| class StatusOr { |
| public: |
| // These constructors are intended be compatible with absl::status_or. |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| StatusOr(const T& value) : status_(), value_(value) {} |
| |
| // These constructors are intended be compatible with absl::status_or. |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| StatusOr(const Status& status) : status_(status), value_() { |
| // It's not valid to construct a StatusOr with an OK status and no value. |
| FML_CHECK(!status_.ok()); |
| } |
| |
| StatusOr(const StatusOr&) = default; |
| StatusOr(StatusOr&&) = default; |
| |
| StatusOr& operator=(const StatusOr&) = default; |
| StatusOr& operator=(StatusOr&&) = default; |
| |
| StatusOr& operator=(const T& value) { |
| status_ = Status(); |
| value_ = value; |
| return *this; |
| } |
| |
| StatusOr& operator=(const T&& value) { |
| status_ = Status(); |
| value_ = std::move(value); |
| return *this; |
| } |
| |
| StatusOr& operator=(const Status& value) { |
| status_ = value; |
| value_ = std::nullopt; |
| return *this; |
| } |
| |
| const Status& status() const { return status_; } |
| |
| bool ok() const { return status_.ok(); } |
| |
| const T& value() const { |
| if (value_.has_value()) { |
| FML_DCHECK(status_.ok()); |
| return value_.value(); |
| } |
| FML_LOG(FATAL) << "StatusOr::value() called on error Status"; |
| FML_UNREACHABLE(); |
| } |
| |
| T& value() { |
| if (value_.has_value()) { |
| FML_DCHECK(status_.ok()); |
| return value_.value(); |
| } |
| FML_LOG(FATAL) << "StatusOr::value() called on error Status"; |
| FML_UNREACHABLE(); |
| } |
| |
| private: |
| Status status_; |
| std::optional<T> value_; |
| }; |
| |
| } // namespace fml |
| |
| #endif // FLUTTER_FML_STATUS_OR_H_ |