Skip to content

Commit

Permalink
[promises] Add some niceties for StatusFlag, ValueOrFailure
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 586804010
  • Loading branch information
ctiller authored and paulosjca committed Dec 8, 2023
1 parent cbdec73 commit 7a9f746
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
38 changes: 35 additions & 3 deletions src/core/lib/promise/status_flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,31 @@

namespace grpc_core {

struct Failure {};
struct Success {};

inline bool IsStatusOk(Failure) { return false; }
inline bool IsStatusOk(Success) { return true; }

template <>
struct StatusCastImpl<absl::Status, Success> {
static absl::Status Cast(Success) { return absl::OkStatus(); }
};

template <>
struct StatusCastImpl<absl::Status, const Success&> {
static absl::Status Cast(Success) { return absl::OkStatus(); }
};

// A boolean representing whether an operation succeeded (true) or failed
// (false).
class StatusFlag {
public:
explicit StatusFlag(bool value) : value_(value) {}
// NOLINTNEXTLINE(google-explicit-constructor)
StatusFlag(Failure) : value_(false) {}
// NOLINTNEXTLINE(google-explicit-constructor)
StatusFlag(Success) : value_(true) {}

bool ok() const { return value_; }

Expand All @@ -46,14 +66,21 @@ struct StatusCastImpl<absl::Status, StatusFlag> {
}
};

struct Failure {};
template <>
struct StatusCastImpl<absl::Status, const StatusFlag&> {
static absl::Status Cast(StatusFlag flag) {
return flag.ok() ? absl::OkStatus() : absl::CancelledError();
}
};

// A value if an operation was successful, or a failure flag if not.
template <typename T>
class ValueOrFailure {
public:
explicit ValueOrFailure(T value) : value_(std::move(value)) {}
explicit ValueOrFailure(Failure) {}
// NOLINTNEXTLINE(google-explicit-constructor)
ValueOrFailure(T value) : value_(std::move(value)) {}
// NOLINTNEXTLINE(google-explicit-constructor)
ValueOrFailure(Failure) {}

static ValueOrFailure FromOptional(absl::optional<T> value) {
return ValueOrFailure{std::move(value)};
Expand All @@ -75,6 +102,11 @@ inline bool IsStatusOk(const ValueOrFailure<T>& value) {
return value.ok();
}

template <typename T>
inline T TakeValue(ValueOrFailure<T>&& value) {
return std::move(value.value());
}

template <typename T>
struct StatusCastImpl<absl::Status, ValueOrFailure<T>> {
static absl::Status Cast(const ValueOrFailure<T> flag) {
Expand Down
2 changes: 2 additions & 0 deletions test/core/promise/status_flag_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ TEST(StatusFlagTest, Basics) {
EXPECT_EQ(ValueOrFailure<int>(42).value(), 42);
EXPECT_EQ(StatusCast<absl::StatusOr<int>>(ValueOrFailure<int>(42)).value(),
42);
EXPECT_TRUE(IsStatusOk(Success{}));
EXPECT_FALSE(IsStatusOk(Failure{}));
}

} // namespace grpc_core
Expand Down

0 comments on commit 7a9f746

Please sign in to comment.