mirror of https://github.com/grpc/grpc.git
[promises] Add some status-like types for TrySeq (#34906)
`StatusFlag` acts like a status, but is just a boolean (we don't want to accidentally treat a boolean as something that indicates failure in case it's not) Similarly `ValueOrFailure` looks like `StatusOr` but reduces the failure space to one value. --------- Co-authored-by: ctiller <ctiller@users.noreply.github.com>pull/34918/head
parent
b99d63f423
commit
dc41f42073
7 changed files with 303 additions and 40 deletions
@ -0,0 +1,95 @@ |
||||
// Copyright 2023 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_SRC_CORE_LIB_PROMISE_STATUS_FLAG_H |
||||
#define GRPC_SRC_CORE_LIB_PROMISE_STATUS_FLAG_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "absl/status/status.h" |
||||
#include "absl/status/statusor.h" |
||||
#include "absl/types/optional.h" |
||||
|
||||
#include "src/core/lib/promise/detail/status.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// A boolean representing whether an operation succeeded (true) or failed
|
||||
// (false).
|
||||
class StatusFlag { |
||||
public: |
||||
explicit StatusFlag(bool value) : value_(value) {} |
||||
|
||||
bool ok() const { return value_; } |
||||
|
||||
private: |
||||
bool value_; |
||||
}; |
||||
|
||||
inline bool IsStatusOk(const StatusFlag& flag) { return flag.ok(); } |
||||
|
||||
template <> |
||||
struct StatusCastImpl<absl::Status, StatusFlag> { |
||||
static absl::Status Cast(StatusFlag flag) { |
||||
return flag.ok() ? absl::OkStatus() : absl::CancelledError(); |
||||
} |
||||
}; |
||||
|
||||
struct Failure {}; |
||||
|
||||
// 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) {} |
||||
|
||||
static ValueOrFailure FromOptional(absl::optional<T> value) { |
||||
return ValueOrFailure{std::move(value)}; |
||||
} |
||||
|
||||
bool ok() const { return value_.has_value(); } |
||||
|
||||
const T& value() const { return value_.value(); } |
||||
T& value() { return value_.value(); } |
||||
const T& operator*() const { return *value_; } |
||||
T& operator*() { return *value_; } |
||||
|
||||
private: |
||||
absl::optional<T> value_; |
||||
}; |
||||
|
||||
template <typename T> |
||||
inline bool IsStatusOk(const ValueOrFailure<T>& value) { |
||||
return value.ok(); |
||||
} |
||||
|
||||
template <typename T> |
||||
struct StatusCastImpl<absl::Status, ValueOrFailure<T>> { |
||||
static absl::Status Cast(const ValueOrFailure<T> flag) { |
||||
return flag.ok() ? absl::OkStatus() : absl::CancelledError(); |
||||
} |
||||
}; |
||||
|
||||
template <typename T> |
||||
struct StatusCastImpl<absl::StatusOr<T>, ValueOrFailure<T>> { |
||||
static absl::StatusOr<T> Cast(ValueOrFailure<T> value) { |
||||
return value.ok() ? absl::StatusOr<T>(std::move(value.value())) |
||||
: absl::CancelledError(); |
||||
} |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_LIB_PROMISE_STATUS_FLAG_H
|
@ -0,0 +1,43 @@ |
||||
// Copyright 2023 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/lib/promise/status_flag.h" |
||||
|
||||
#include <memory> |
||||
#include <utility> |
||||
|
||||
#include "gtest/gtest.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
TEST(StatusFlagTest, Basics) { |
||||
EXPECT_TRUE(StatusFlag(true).ok()); |
||||
EXPECT_FALSE(StatusFlag(false).ok()); |
||||
EXPECT_TRUE(StatusCast<absl::Status>(StatusFlag(true)).ok()); |
||||
EXPECT_FALSE(StatusCast<absl::Status>(StatusFlag(false)).ok()); |
||||
EXPECT_TRUE(ValueOrFailure<int>(42).ok()); |
||||
EXPECT_FALSE(ValueOrFailure<int>(Failure{}).ok()); |
||||
EXPECT_TRUE(StatusCast<absl::Status>(ValueOrFailure<int>(42)).ok()); |
||||
EXPECT_FALSE(StatusCast<absl::Status>(ValueOrFailure<int>(Failure{})).ok()); |
||||
EXPECT_EQ(ValueOrFailure<int>(42).value(), 42); |
||||
EXPECT_EQ(StatusCast<absl::StatusOr<int>>(ValueOrFailure<int>(42)).value(), |
||||
42); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
return RUN_ALL_TESTS(); |
||||
} |
Loading…
Reference in new issue