[slice] Mutable slice cast (#31959)

* [slice] Mutable slice cast

* fix
pull/31035/head^2
Craig Tiller 2 years ago committed by GitHub
parent cd98a12faa
commit 5664d6ee6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      include/grpc/event_engine/internal/slice_cast.h
  2. 4
      include/grpc/event_engine/slice.h
  3. 8
      src/core/lib/slice/slice.h
  4. 9
      test/core/slice/slice_test.cc

@ -22,25 +22,25 @@ namespace internal {
// Opt-in trait class for slice conversions.
// Declare a specialization of this class for any types that are compatible
// with `SliceCast`. Both ways need to be declared (i.e. if
// ConstRefSliceCastable<A,B> exists, you should declare
// ConstRefSliceCastable<B,A> too).
// SliceCastable<A,B> exists, you should declare
// SliceCastable<B,A> too).
// The type has no members, it's just the existance of the specialization that
// unlocks SliceCast usage for a type pair.
template <typename Result, typename T>
struct ConstRefSliceCastable;
struct SliceCastable;
// This is strictly too wide, but consider all types to be SliceCast-able to
// themselves.
// Unfortunately this allows `const int& x = SliceCast<int>(x);` which is kind
// of bogus.
template <typename A>
struct ConstRefSliceCastable<A, A> {};
struct SliceCastable<A, A> {};
// Cast to `const Result&` from `const T&` without any runtime checks.
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
// opted in as compatible via `ConstRefSliceCastable`.
// opted in as compatible via `SliceCastable`.
template <typename Result, typename T>
const Result& SliceCast(const T& value, ConstRefSliceCastable<Result, T> = {}) {
const Result& SliceCast(const T& value, SliceCastable<Result, T> = {}) {
// Insist upon sizes being equal to catch mismatches.
// We assume if sizes are opted in and sizes are equal then yes, these two
// types are expected to be layout compatible and actually appear to be.
@ -48,6 +48,18 @@ const Result& SliceCast(const T& value, ConstRefSliceCastable<Result, T> = {}) {
return reinterpret_cast<const Result&>(value);
}
// Cast to `Result&` from `T&` without any runtime checks.
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
// opted in as compatible via `SliceCastable`.
template <typename Result, typename T>
Result& SliceCast(T& value, SliceCastable<Result, T> = {}) {
// Insist upon sizes being equal to catch mismatches.
// We assume if sizes are opted in and sizes are equal then yes, these two
// types are expected to be layout compatible and actually appear to be.
static_assert(sizeof(Result) == sizeof(T), "size mismatch");
return reinterpret_cast<Result&>(value);
}
} // namespace internal
} // namespace experimental
} // namespace grpc_event_engine

@ -284,9 +284,9 @@ class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND Slice
namespace internal {
template <>
struct ConstRefSliceCastable<Slice, grpc_slice> {};
struct SliceCastable<Slice, grpc_slice> {};
template <>
struct ConstRefSliceCastable<grpc_slice, Slice> {};
struct SliceCastable<grpc_slice, Slice> {};
} // namespace internal
} // namespace experimental

@ -410,13 +410,13 @@ namespace grpc_event_engine {
namespace experimental {
namespace internal {
template <>
struct ConstRefSliceCastable<grpc_core::Slice, grpc_slice> {};
struct SliceCastable<grpc_core::Slice, grpc_slice> {};
template <>
struct ConstRefSliceCastable<grpc_slice, grpc_core::Slice> {};
struct SliceCastable<grpc_slice, grpc_core::Slice> {};
template <>
struct ConstRefSliceCastable<grpc_core::Slice, Slice> {};
struct SliceCastable<grpc_core::Slice, Slice> {};
template <>
struct ConstRefSliceCastable<Slice, grpc_core::Slice> {};
struct SliceCastable<Slice, grpc_core::Slice> {};
} // namespace internal
} // namespace experimental
} // namespace grpc_event_engine

@ -441,6 +441,15 @@ TEST(SliceTest, SliceCastWorks) {
EXPECT_EQ(&other, &test);
}
TEST(SliceTest, MutableSliceCastWorks) {
using ::grpc_event_engine::experimental::internal::SliceCast;
Slice test = Slice::FromCopiedString("hello world!");
grpc_slice& slice = SliceCast<grpc_slice>(test);
EXPECT_EQ(&slice, &test.c_slice());
slice = grpc_slice_from_static_string("goodbye world!");
EXPECT_EQ(test.as_string_view(), "goodbye world!");
}
} // namespace
} // namespace grpc_core

Loading…
Cancel
Save