Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,9 @@ bazel_dep(
name = "yaml-cpp",
version = "0.9.0",
)

git_override(
module_name = "abseil-cpp",
remote = "https://github.com/abseil/abseil-cpp.git",
commit = "1ea7b9254fd6f29d72069473856d58837d19cbfc",
)
2 changes: 2 additions & 0 deletions internal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ cc_library(
deps = [
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:status_builder",
],
)

Expand Down Expand Up @@ -148,6 +149,7 @@ cc_library(
":status_builder",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:status_macros",
],
)

Expand Down
95 changes: 5 additions & 90 deletions internal/status_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,99 +15,14 @@
#ifndef THIRD_PARTY_CEL_CPP_INTERNAL_STATUS_BUILDER_H_
#define THIRD_PARTY_CEL_CPP_INTERNAL_STATUS_BUILDER_H_

#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/status/status.h"
#include "absl/base/macros.h"
#include "absl/status/status_builder.h"

namespace cel::internal {

class StatusBuilder;

template <typename Fn, typename Arg, typename Expected>
inline constexpr bool StatusBuilderResultMatches =
std::is_same_v<std::decay_t<std::invoke_result_t<Fn, Arg>>, Expected>;

template <typename Adaptor, typename Builder>
using StatusBuilderPurePolicy = std::enable_if_t<
StatusBuilderResultMatches<Adaptor, Builder, StatusBuilder>,
std::invoke_result_t<Adaptor, Builder>>;

template <typename Adaptor, typename Builder>
using StatusBuilderSideEffect =
std::enable_if_t<StatusBuilderResultMatches<Adaptor, Builder, absl::Status>,
std::invoke_result_t<Adaptor, Builder>>;

template <typename Adaptor, typename Builder>
using StatusBuilderConversion = std::enable_if_t<
!StatusBuilderResultMatches<Adaptor, Builder, StatusBuilder> &&
!StatusBuilderResultMatches<Adaptor, Builder, absl::Status>,
std::invoke_result_t<Adaptor, Builder>>;

class StatusBuilder final {
public:
StatusBuilder() = default;

explicit StatusBuilder(const absl::Status& status) : status_(status) {}

StatusBuilder(const StatusBuilder&) = default;

StatusBuilder(StatusBuilder&&) = default;

~StatusBuilder() = default;

StatusBuilder& operator=(const StatusBuilder&) = default;

StatusBuilder& operator=(StatusBuilder&&) = default;

bool ok() const { return status_.ok(); }

absl::StatusCode code() const { return status_.code(); }

operator absl::Status() const& { return status_; } // NOLINT

operator absl::Status() && { return std::move(status_); } // NOLINT

template <typename Adaptor>
auto With(
Adaptor&& adaptor) & -> StatusBuilderPurePolicy<Adaptor, StatusBuilder&> {
return std::forward<Adaptor>(adaptor)(*this);
}
template <typename Adaptor>
ABSL_MUST_USE_RESULT auto With(
Adaptor&&
adaptor) && -> StatusBuilderPurePolicy<Adaptor, StatusBuilder&&> {
return std::forward<Adaptor>(adaptor)(std::move(*this));
}

template <typename Adaptor>
auto With(
Adaptor&& adaptor) & -> StatusBuilderSideEffect<Adaptor, StatusBuilder&> {
return std::forward<Adaptor>(adaptor)(*this);
}
template <typename Adaptor>
ABSL_MUST_USE_RESULT auto With(
Adaptor&&
adaptor) && -> StatusBuilderSideEffect<Adaptor, StatusBuilder&&> {
return std::forward<Adaptor>(adaptor)(std::move(*this));
}

template <typename Adaptor>
auto With(
Adaptor&& adaptor) & -> StatusBuilderConversion<Adaptor, StatusBuilder&> {
return std::forward<Adaptor>(adaptor)(*this);
}
template <typename Adaptor>
ABSL_MUST_USE_RESULT auto With(
Adaptor&&
adaptor) && -> StatusBuilderConversion<Adaptor, StatusBuilder&&> {
return std::forward<Adaptor>(adaptor)(std::move(*this));
}

private:
absl::Status status_;
};
using StatusBuilder
[[deprecated("Use absl::StatusBuilder instead")]] ABSL_REFACTOR_INLINE =
::absl::StatusBuilder;

} // namespace cel::internal

Expand Down
136 changes: 5 additions & 131 deletions internal/status_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,138 +15,12 @@
#ifndef THIRD_PARTY_CEL_CPP_INTERNAL_STATUS_MACROS_H_
#define THIRD_PARTY_CEL_CPP_INTERNAL_STATUS_MACROS_H_

#include <utility>
#include "absl/status/status_macros.h"

#include "absl/base/optimization.h"
#include "absl/status/status.h"
#include "internal/status_builder.h"
// Deprecated: use RETURN_IF_ERROR directly.
#define CEL_RETURN_IF_ERROR(expr) RETURN_IF_ERROR(expr)

#define CEL_RETURN_IF_ERROR(expr) \
CEL_INTERNAL_STATUS_MACROS_IMPL_ELSE_BLOCKER_ \
if (::cel::internal::StatusAdaptor cel_internal_status_macro = {(expr)}) { \
} else /* NOLINT */ \
return cel_internal_status_macro.Consume()

// The GNU compiler historically emitted warnings for obscure usages of
// `if (foo) if (bar) {} else`. This suppresses that.

// clang-format off
#define CEL_INTERNAL_STATUS_MACROS_IMPL_ELSE_BLOCKER_ \
switch (0) case 0: default: /* NOLINT */
// clang-format on

#define CEL_ASSIGN_OR_RETURN(...) \
CEL_INTERNAL_STATUS_MACROS_GET_VARIADIC_( \
(__VA_ARGS__, CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_3_, \
CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_2_)) \
(__VA_ARGS__)

// The following are macro magic to select either the 2 arg variant or 3 arg
// variant of CEL_ASSIGN_OR_RETURN.

#define CEL_INTERNAL_STATUS_MACROS_GET_VARIADIC_HELPER_(_1, _2, _3, NAME, ...) \
NAME
#define CEL_INTERNAL_STATUS_MACROS_GET_VARIADIC_(args) \
CEL_INTERNAL_STATUS_MACROS_GET_VARIADIC_HELPER_ args

#define CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_2_(lhs, rexpr) \
CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_( \
CEL_INTERNAL_STATUS_MACROS_CONCAT(_status_or_value, __LINE__), lhs, \
rexpr, \
return absl::Status(std::move(CEL_INTERNAL_STATUS_MACROS_CONCAT( \
_status_or_value, __LINE__)) \
.status()))

#define CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_3_(lhs, rexpr, \
error_expression) \
CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_( \
CEL_INTERNAL_STATUS_MACROS_CONCAT(_status_or_value, __LINE__), lhs, \
rexpr, \
::cel::internal::StatusBuilder _( \
std::move( \
CEL_INTERNAL_STATUS_MACROS_CONCAT(_status_or_value, __LINE__)) \
.status()); \
(void)_; /* error_expression is allowed to not use this variable */ \
return (error_expression))

// Common implementation of CEL_ASSIGN_OR_RETURN. Both the 2 arg variant and 3
// arg variant are implemented by this macro.

#define CEL_INTERNAL_STATUS_MACROS_ASSIGN_OR_RETURN_(statusor, lhs, rexpr, \
error_expression) \
auto statusor = (rexpr); \
if (ABSL_PREDICT_FALSE(!statusor.ok())) { \
error_expression; \
} \
CEL_INTERNAL_STATUS_MACROS_UNPARENTHESIZE_IF_PARENTHESIZED(lhs) = \
std::move(statusor).value()

#define CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_INNER(...) \
CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_INNER_HELPER((__VA_ARGS__, 0, 1))

// MSVC historically expands variadic macros incorrectly, so another level of
// indirection is required.
#define CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_INNER_HELPER(args) \
CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_INNER_I args
#define CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_INNER_I(e0, e1, is_empty, ...) \
is_empty

#define CEL_INTERNAL_STATUS_MACROS_IS_EMPTY(...) \
CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_I(__VA_ARGS__)
#define CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_I(...) \
CEL_INTERNAL_STATUS_MACROS_IS_EMPTY_INNER(_, ##__VA_ARGS__)

#define CEL_INTERNAL_STATUS_MACROS_IF_1(_Then, _Else) _Then
#define CEL_INTERNAL_STATUS_MACROS_IF_0(_Then, _Else) _Else
#define CEL_INTERNAL_STATUS_MACROS_IF(_Cond, _Then, _Else) \
CEL_INTERNAL_STATUS_MACROS_CONCAT(CEL_INTERNAL_STATUS_MACROS_IF_, _Cond) \
(_Then, _Else)

#define CEL_INTERNAL_STATUS_MACROS_EAT(...)
#define CEL_INTERNAL_STATUS_MACROS_REM(...) __VA_ARGS__
#define CEL_INTERNAL_STATUS_MACROS_EMPTY()

// Expands to 1 if the input is surrounded by parenthesis, 0 otherwise.
#define CEL_INTERNAL_STATUS_MACROS_IS_PARENTHESIZED(...) \
CEL_INTERNAL_STATUS_MACROS_IS_EMPTY( \
CEL_INTERNAL_STATUS_MACROS_EAT __VA_ARGS__)

// If the input is surrounded by parenthesis, remove them. Otherwise expand it
// unchanged.
#define CEL_INTERNAL_STATUS_MACROS_UNPARENTHESIZE_IF_PARENTHESIZED(...) \
CEL_INTERNAL_STATUS_MACROS_IF( \
CEL_INTERNAL_STATUS_MACROS_IS_PARENTHESIZED(__VA_ARGS__), \
CEL_INTERNAL_STATUS_MACROS_REM, CEL_INTERNAL_STATUS_MACROS_EMPTY()) \
__VA_ARGS__

#define CEL_INTERNAL_STATUS_MACROS_CONCAT_HELPER(x, y) x##y
#define CEL_INTERNAL_STATUS_MACROS_CONCAT(x, y) \
CEL_INTERNAL_STATUS_MACROS_CONCAT_HELPER(x, y)

namespace cel::internal {

class StatusAdaptor final {
public:
StatusAdaptor() = default;

StatusAdaptor(const StatusAdaptor&) = delete;

StatusAdaptor(StatusAdaptor&&) = delete;

StatusAdaptor(const absl::Status& status) : builder_(status) {} // NOLINT

StatusAdaptor& operator=(const StatusAdaptor&) = delete;

StatusAdaptor& operator=(StatusAdaptor&&) = delete;

StatusBuilder&& Consume() { return std::move(builder_); }

explicit operator bool() const { return ABSL_PREDICT_TRUE(builder_.ok()); }

private:
StatusBuilder builder_;
};

} // namespace cel::internal
// Deprecated: use ASSIGN_OR_RETURN directly.
#define CEL_ASSIGN_OR_RETURN(...) ASSIGN_OR_RETURN(__VA_ARGS__)

#endif // THIRD_PARTY_CEL_CPP_INTERNAL_STATUS_MACROS_H_