Introduce IsHpbClassThatHasExtensions

EnableIfHpbClass was too restrictive in the past; it was
toggled only if <T> was extended. This has been rectified
to toggle if T extends T::Access, which reflects the
true intention.

PiperOrigin-RevId: 693368653
pull/19123/head
Hong Shin 3 weeks ago committed by Copybara-Service
parent 5129d4d24b
commit 471d66961a
  1. 17
      csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs
  2. 24
      hpb/extension.h
  3. 25
      hpb/internal/template_help.h
  4. 40
      hpb/internal/template_help_test.cc

@ -1,17 +0,0 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#endregion
namespace Google.Protobuf.Reflection;
internal sealed partial class FeatureSetDescriptor
{
// Canonical serialized form of the edition defaults, generated by embed_edition_defaults.
private const string DefaultsBase64 =
"ChMYhAciACoMCAEQAhgCIAMoATACChMY5wciACoMCAIQARgBIAIoATABChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH";
}

@ -143,7 +143,7 @@ class ExtensionRegistry {
};
template <typename T, typename Extendee, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
ABSL_MUST_USE_RESULT bool HasExtension(
Ptr<T> message,
const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
@ -152,7 +152,7 @@ ABSL_MUST_USE_RESULT bool HasExtension(
}
template <typename T, typename Extendee, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
ABSL_MUST_USE_RESULT bool HasExtension(
const T* message,
const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
@ -160,7 +160,7 @@ ABSL_MUST_USE_RESULT bool HasExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>,
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>,
typename = hpb::internal::EnableIfMutableProto<T>>
void ClearExtension(
Ptr<T> message,
@ -171,14 +171,14 @@ void ClearExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
void ClearExtension(
T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id) {
ClearExtension(Ptr(message), id);
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>,
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>,
typename = hpb::internal::EnableIfMutableProto<T>>
absl::Status SetExtension(
Ptr<T> message,
@ -192,7 +192,7 @@ absl::Status SetExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>,
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>,
typename = hpb::internal::EnableIfMutableProto<T>>
absl::Status SetExtension(
Ptr<T> message,
@ -206,7 +206,7 @@ absl::Status SetExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>,
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>,
typename = hpb::internal::EnableIfMutableProto<T>>
absl::Status SetExtension(
Ptr<T> message,
@ -223,7 +223,7 @@ absl::Status SetExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
absl::Status SetExtension(
T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
const Extension& value) {
@ -231,7 +231,7 @@ absl::Status SetExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
absl::Status SetExtension(
T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
Extension&& value) {
@ -239,7 +239,7 @@ absl::Status SetExtension(
}
template <typename T, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
absl::Status SetExtension(
T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
Ptr<Extension> value) {
@ -247,7 +247,7 @@ absl::Status SetExtension(
}
template <typename T, typename Extendee, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
absl::StatusOr<Ptr<const Extension>> GetExtension(
Ptr<T> message,
const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
@ -264,7 +264,7 @@ absl::StatusOr<Ptr<const Extension>> GetExtension(
}
template <typename T, typename Extendee, typename Extension,
typename = hpb::internal::EnableIfHpbClass<T>>
typename = hpb::internal::EnableIfHpbClassThatHasExtensions<T>>
decltype(auto) GetExtension(
const T* message,
const hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {

@ -35,10 +35,29 @@ template <typename T, typename U = RemovePtrT<T>,
typename = std::enable_if_t<!std::is_const_v<U>>>
using PtrOrRaw = T;
template <typename T, typename = void>
inline constexpr bool IsHpbClass = false;
template <typename T>
inline constexpr bool
IsHpbClass<T, std::enable_if_t<std::is_base_of_v<typename T::Access, T>>> =
true;
template <typename T>
using EnableIfHpbClass = std::enable_if_t<IsHpbClass<T>>;
template <typename T, typename = void>
inline constexpr bool IsHpbClassThatHasExtensions = false;
template <typename T>
inline constexpr bool IsHpbClassThatHasExtensions<
T, std::enable_if_t<std::is_base_of_v<typename T::Access, T> &&
std::is_base_of_v<typename T::ExtendableType, T>>> =
true;
template <typename T>
using EnableIfHpbClass = std::enable_if_t<
std::is_base_of<typename T::Access, T>::value &&
std::is_base_of<typename T::Access, typename T::ExtendableType>::value>;
using EnableIfHpbClassThatHasExtensions =
std::enable_if_t<IsHpbClassThatHasExtensions<T>>;
template <typename T>
using EnableIfMutableProto = std::enable_if_t<!std::is_const<T>::value>;

@ -0,0 +1,40 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2024 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "google/protobuf/hpb/internal/template_help.h"
#include <gtest/gtest.h>
#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h"
namespace hpb_unittest::protos {
class NonHpbClass {};
TEST(TemplateHelp, TestIsHpbClass) {
static_assert(hpb::internal::IsHpbClass<TestModel>,
"TestModel must be an hpb class");
static_assert(hpb::internal::IsHpbClass<ThemeExtension>,
"ThemeExtension must be an hpb class");
static_assert(!hpb::internal::IsHpbClass<NonHpbClass>,
"NonHpbClass must not be an hpb class");
static_assert(!hpb::internal::IsHpbClass<int>,
"primitives like int must not be an hpb class");
}
TEST(TemplateHelp, TestIsHpbExtendedClass) {
static_assert(
hpb::internal::IsHpbClassThatHasExtensions<TestModel>,
"TestModel must be an hpb extension class, for it has extensions");
static_assert(!hpb::internal::IsHpbClassThatHasExtensions<ThemeExtension>,
"ThemeExtension must not have extensions");
static_assert(!hpb::internal::IsHpbClassThatHasExtensions<NonHpbClass>,
"NonHpbClass must not be an hpb extension class");
static_assert(!hpb::internal::IsHpbClassThatHasExtensions<int>,
"primitives like int must not be an hpb extension class");
}
} // namespace hpb_unittest::protos
Loading…
Cancel
Save