blob: 8c911f93bffe94e4abde8dee3981e8fe00aa456d [file] [log] [blame]
// 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_