Fix Serialize failing for Proxy/CProxy.
Refactor minitable access.

PiperOrigin-RevId: 542895074
diff --git a/protos/protos.h b/protos/protos.h
index 809e964..2e2fae9 100644
--- a/protos/protos.h
+++ b/protos/protos.h
@@ -199,12 +199,12 @@
 };
 
 template <typename T>
-void* GetInternalMsg(const T& message) {
-  return message.msg();
+void* GetInternalMsg(const T* message) {
+  return message->msg();
 }
 
 template <typename T>
-void* GetInternalMsg(const Ptr<T>& message) {
+void* GetInternalMsg(Ptr<T> message) {
   return message->msg();
 }
 
@@ -214,10 +214,20 @@
 }
 
 template <typename T>
-upb_Arena* GetArena(const Ptr<T>& message) {
+upb_Arena* GetArena(Ptr<T> message) {
   return static_cast<upb_Arena*>(message->GetInternalArena());
 }
 
+template <typename T>
+const upb_MiniTable* GetMiniTable(const T*) {
+  return T::minitable();
+}
+
+template <typename T>
+const upb_MiniTable* GetMiniTable(Ptr<T>) {
+  return T::minitable();
+}
+
 upb_ExtensionRegistry* GetUpbExtensions(
     const ExtensionRegistry& extension_registry);
 
@@ -328,7 +338,7 @@
   if (message_arena != extension_arena) {
     upb_Arena_Fuse(message_arena, extension_arena);
   }
-  msg_ext->data.ptr = ::protos::internal::GetInternalMsg(value);
+  msg_ext->data.ptr = ::protos::internal::GetInternalMsg(&value);
   return absl::OkStatus();
 }
 
@@ -362,7 +372,7 @@
 
 template <typename T>
 bool Parse(T& message, absl::string_view bytes) {
-  upb_Message_Clear(message.msg(), T::minitable());
+  upb_Message_Clear(message.msg(), ::protos::internal::GetMiniTable(&message));
   auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
   return upb_Decode(bytes.data(), bytes.size(), message.msg(), T::minitable(),
                     /* extreg= */ nullptr, /* options= */ 0,
@@ -372,9 +382,10 @@
 template <typename T>
 bool Parse(T& message, absl::string_view bytes,
            const ::protos::ExtensionRegistry& extension_registry) {
-  upb_Message_Clear(message.msg(), T::minitable());
+  upb_Message_Clear(message.msg(), ::protos::internal::GetMiniTable(message));
   auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message.msg(), T::minitable(),
+  return upb_Decode(bytes.data(), bytes.size(), message.msg(),
+                    ::protos::internal::GetMiniTable(message),
                     /* extreg= */
                     ::protos::internal::GetUpbExtensions(extension_registry),
                     /* options= */ 0, arena) == kUpb_DecodeStatus_Ok;
@@ -382,9 +393,10 @@
 
 template <typename T>
 bool Parse(Ptr<T>& message, absl::string_view bytes) {
-  upb_Message_Clear(message->msg(), T::minitable());
+  upb_Message_Clear(message->msg(), ::protos::internal::GetMiniTable(message));
   auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
+  return upb_Decode(bytes.data(), bytes.size(), message->msg(),
+                    ::protos::internal::GetMiniTable(message),
                     /* extreg= */ nullptr, /* options= */ 0,
                     arena) == kUpb_DecodeStatus_Ok;
 }
@@ -392,60 +404,32 @@
 template <typename T>
 bool Parse(Ptr<T>& message, absl::string_view bytes,
            const ::protos::ExtensionRegistry& extension_registry) {
-  upb_Message_Clear(message->msg(), T::minitable());
+  upb_Message_Clear(message->msg(), ::protos::internal::GetMiniTable(message));
   auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
+  return upb_Decode(bytes.data(), bytes.size(), message->msg(),
+                    ::protos::internal::GetMiniTable(message),
                     /* extreg= */
                     ::protos::internal::GetUpbExtensions(extension_registry),
                     /* options= */ 0, arena) == kUpb_DecodeStatus_Ok;
 }
 
 template <typename T>
-bool Parse(std::unique_ptr<T>& message, absl::string_view bytes) {
-  upb_Message_Clear(message->msg(), T::minitable());
+bool Parse(T* message, absl::string_view bytes) {
+  upb_Message_Clear(message->msg(), ::protos::internal::GetMiniTable(message));
   auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
+  return upb_Decode(bytes.data(), bytes.size(), message->msg(),
+                    ::protos::internal::GetMiniTable(message),
                     /* extreg= */ nullptr, /* options= */ 0,
                     arena) == kUpb_DecodeStatus_Ok;
 }
 
 template <typename T>
-bool Parse(std::unique_ptr<T>& message, absl::string_view bytes,
-           const ::protos::ExtensionRegistry& extension_registry) {
-  upb_Message_Clear(message->msg(), T::minitable());
-  auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
-                    /* extreg= */
-                    ::protos::internal::GetUpbExtensions(extension_registry),
-                    /* options= */ 0, arena) == kUpb_DecodeStatus_Ok;
-}
-
-template <typename T>
-bool Parse(std::shared_ptr<T>& message, absl::string_view bytes) {
-  upb_Message_Clear(message->msg(), T::minitable());
-  auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
-                    /* extreg= */ nullptr, /* options= */ 0,
-                    arena) == kUpb_DecodeStatus_Ok;
-}
-
-template <typename T>
-bool Parse(std::shared_ptr<T>& message, absl::string_view bytes,
-           const ::protos::ExtensionRegistry& extension_registry) {
-  upb_Message_Clear(message->msg(), T::minitable());
-  auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
-  return upb_Decode(bytes.data(), bytes.size(), message->msg(), T::minitable(),
-                    /* extreg= */
-                    ::protos::internal::GetUpbExtensions(extension_registry),
-                    /* options= */ 0, arena) == kUpb_DecodeStatus_Ok;
-}
-
-template <typename T>
 absl::StatusOr<T> Parse(absl::string_view bytes, int options = 0) {
   T message;
   auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
   upb_DecodeStatus status =
-      upb_Decode(bytes.data(), bytes.size(), message.msg(), T::minitable(),
+      upb_Decode(bytes.data(), bytes.size(), message.msg(),
+                 ::protos::internal::GetMiniTable(&message),
                  /* extreg= */ nullptr, /* options= */ 0, arena);
   if (status == kUpb_DecodeStatus_Ok) {
     return message;
@@ -460,7 +444,8 @@
   T message;
   auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
   upb_DecodeStatus status =
-      upb_Decode(bytes.data(), bytes.size(), message.msg(), T::minitable(),
+      upb_Decode(bytes.data(), bytes.size(), message.msg(),
+                 ::protos::internal::GetMiniTable(&message),
                  ::protos::internal::GetUpbExtensions(extension_registry),
                  /* options= */ 0, arena);
   if (status == kUpb_DecodeStatus_Ok) {
@@ -470,34 +455,19 @@
 }
 
 template <typename T>
-absl::StatusOr<absl::string_view> Serialize(const T& message, upb::Arena& arena,
+absl::StatusOr<absl::string_view> Serialize(const T* message, upb::Arena& arena,
                                             int options = 0) {
   return ::protos::internal::Serialize(
-      ::protos::internal::GetInternalMsg(message), T::minitable(), arena.ptr(),
+      message->msg(), ::protos::internal::GetMiniTable(message), arena.ptr(),
       options);
 }
 
 template <typename T>
-absl::StatusOr<absl::string_view> Serialize(std::unique_ptr<T>& message,
-                                            upb::Arena& arena,
-                                            int options = 0) {
-  return ::protos::internal::Serialize(message->msg(), T::minitable(),
-                                       arena.ptr(), options);
-}
-
-template <typename T>
-absl::StatusOr<absl::string_view> Serialize(std::shared_ptr<T>& message,
-                                            upb::Arena& arena,
-                                            int options = 0) {
-  return ::protos::internal::Serialize(message->msg(), T::minitable(),
-                                       arena.ptr(), options);
-}
-
-template <typename T>
 absl::StatusOr<absl::string_view> Serialize(Ptr<T> message, upb::Arena& arena,
                                             int options = 0) {
-  return ::protos::internal::Serialize(message->msg(), T::minitable(),
-                                       arena.ptr(), options);
+  return ::protos::internal::Serialize(
+      message->msg(), ::protos::internal::GetMiniTable(message), arena.ptr(),
+      options);
 }
 
 }  // namespace protos
diff --git a/protos/repeated_field.h b/protos/repeated_field.h
index a040e50..3bdb20d 100644
--- a/protos/repeated_field.h
+++ b/protos/repeated_field.h
@@ -145,8 +145,8 @@
             typename = std::enable_if_t<b>>
   void push_back(const T& t) {
     upb_MessageValue message_value;
-    message_value.msg_val =
-        upb_Message_DeepClone(GetInternalMsg(t), T::minitable(), this->arena_);
+    message_value.msg_val = upb_Message_DeepClone(
+        GetInternalMsg(&t), ::protos::internal::GetMiniTable(&t), this->arena_);
     upb_Array_Append(this->arr_, message_value, this->arena_);
   }
 
@@ -155,7 +155,7 @@
             typename = std::enable_if_t<b>>
   void push_back(T&& msg) {
     upb_MessageValue message_value;
-    message_value.msg_val = GetInternalMsg(msg);
+    message_value.msg_val = GetInternalMsg(&msg);
     upb_Arena_Fuse(GetArena(msg), this->arena_);
     upb_Array_Append(this->arr_, message_value, this->arena_);
     T moved_msg = std::move(msg);
diff --git a/protos_generator/gen_messages.cc b/protos_generator/gen_messages.cc
index 3fb5d4d..6396c07 100644
--- a/protos_generator/gen_messages.cc
+++ b/protos_generator/gen_messages.cc
@@ -31,6 +31,7 @@
 #include <vector>
 
 #include "google/protobuf/descriptor.pb.h"
+#include "absl/strings/str_cat.h"
 #include "google/protobuf/descriptor.h"
 #include "protos_generator/gen_accessors.h"
 #include "protos_generator/gen_enums.h"
@@ -127,9 +128,8 @@
         friend class $2;
         friend class $0Proxy;
         friend class $0CProxy;
-        friend void* ::protos::internal::GetInternalMsg<$2>(const $2& message);
-        friend void* ::protos::internal::GetInternalMsg<$2>(
-            const ::protos::Ptr<$2>& message);
+        friend void* ::protos::internal::GetInternalMsg<$2>(const $2* message);
+        friend void* ::protos::internal::GetInternalMsg<$2>(::protos::Ptr<$2> message);
         $1* msg_;
         upb_Arena* arena_;
       )cc",
@@ -166,7 +166,7 @@
           inline $0& operator=(const CProxy& from) {
             arena_ = owned_arena_.ptr();
             msg_ = ($2*)upb_Message_DeepClone(
-                ::protos::internal::GetInternalMsg(from), &$1, arena_);
+                ::protos::internal::GetInternalMsg(&from), &$1, arena_);
             return *this;
           }
           $0($0&& m)
@@ -223,8 +223,7 @@
             const ::protos::ExtensionRegistry& extension_registry,
             int options));
         friend upb_Arena* ::protos::internal::GetArena<$0>(const $0& message);
-        friend upb_Arena* ::protos::internal::GetArena<$0>(
-            const ::protos::Ptr<$0>& message);
+        friend upb_Arena* ::protos::internal::GetArena<$0>(::protos::Ptr<$0> message);
         friend $0(::protos::internal::MoveMessage<$0>(upb_Message* msg,
                                                       upb_Arena* arena));
       )cc",
@@ -271,9 +270,13 @@
         friend class $0Access;
         friend class ::protos::Ptr<$0>;
         friend class ::protos::Ptr<const $0>;
+        static const upb_MiniTable* minitable() { return $0::minitable(); }
+        friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0Proxy>(
+            const $0Proxy* message);
+        friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0Proxy>(
+            ::protos::Ptr<$0Proxy> message);
         friend upb_Arena* ::protos::internal::GetArena<$2>(const $2& message);
-        friend upb_Arena* ::protos::internal::GetArena<$2>(
-            const ::protos::Ptr<$2>& message);
+        friend upb_Arena* ::protos::internal::GetArena<$2>(::protos::Ptr<$2> message);
         friend $0Proxy(::protos::CloneMessage(::protos::Ptr<$2> message,
                                               ::upb::Arena& arena));
         static void Rebind($0Proxy& lhs, const $0Proxy& rhs) {
@@ -313,6 +316,12 @@
         friend class RepeatedFieldProxy;
         friend class ::protos::Ptr<$0>;
         friend class ::protos::Ptr<const $0>;
+        static const upb_MiniTable* minitable() { return $0::minitable(); }
+        friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0CProxy>(
+            const $0CProxy* message);
+        friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0CProxy>(
+            ::protos::Ptr<$0CProxy> message);
+
         static void Rebind($0CProxy& lhs, const $0CProxy& rhs) {
           lhs.msg_ = rhs.msg_;
           lhs.arena_ = rhs.arena_;
@@ -349,12 +358,12 @@
           $0::$0(const CProxy& from) : $0Access() {
             arena_ = owned_arena_.ptr();
             msg_ = ($1*)upb_Message_DeepClone(
-                ::protos::internal::GetInternalMsg(from), &$2, arena_);
+                ::protos::internal::GetInternalMsg(&from), &$2, arena_);
           }
           $0::$0(const Proxy& from) : $0(static_cast<const CProxy&>(from)) {}
           internal::$0CProxy::$0CProxy($0Proxy m) : $0Access() {
             arena_ = m.arena_;
-            msg_ = ($1*)::protos::internal::GetInternalMsg(m);
+            msg_ = ($1*)::protos::internal::GetInternalMsg(&m);
           }
         )cc",
         ClassName(descriptor), MessageName(descriptor),
diff --git a/protos_generator/tests/BUILD b/protos_generator/tests/BUILD
index 82cbf55..5e66184 100644
--- a/protos_generator/tests/BUILD
+++ b/protos_generator/tests/BUILD
@@ -147,6 +147,8 @@
         ":test_model_upb_proto",
         ":naming_conflict_upb_cc_proto",
         "@com_google_googletest//:gtest_main",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
         "//:upb",
         "//protos",
         "//protos:repeated_field",
diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc
index b2866b6..fd117a1 100644
--- a/protos_generator/tests/test_generated.cc
+++ b/protos_generator/tests/test_generated.cc
@@ -28,12 +28,15 @@
 #include <utility>
 
 #include "gtest/gtest.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
 #include "protos/protos.h"
 #include "protos/repeated_field.h"
 #include "protos/repeated_field_iterator.h"
 #include "protos_generator/tests/child_model.upb.proto.h"
 #include "protos_generator/tests/no_package.upb.proto.h"
 #include "protos_generator/tests/test_model.upb.proto.h"
+#include "upb/upb.hpp"
 
 using ::protos_generator::test::protos::ChildModel1;
 using ::protos_generator::test::protos::other_ext;
@@ -712,7 +715,20 @@
   TestModel model;
   model.set_str1("Hello World");
   ::upb::Arena arena;
-  absl::StatusOr<absl::string_view> bytes = ::protos::Serialize(model, arena);
+  absl::StatusOr<absl::string_view> bytes = ::protos::Serialize(&model, arena);
+  EXPECT_EQ(true, bytes.ok());
+  TestModel parsed_model = ::protos::Parse<TestModel>(bytes.value()).value();
+  EXPECT_EQ("Hello World", parsed_model.str1());
+}
+
+TEST(CppGeneratedCode, SerializeProxyUsingArena) {
+  ::upb::Arena message_arena;
+  TestModel::Proxy model_proxy =
+      ::protos::CreateMessage<TestModel>(message_arena);
+  model_proxy.set_str1("Hello World");
+  ::upb::Arena arena;
+  absl::StatusOr<absl::string_view> bytes =
+      ::protos::Serialize(&model_proxy, arena);
   EXPECT_EQ(true, bytes.ok());
   TestModel parsed_model = ::protos::Parse<TestModel>(bytes.value()).value();
   EXPECT_EQ("Hello World", parsed_model.str1());
@@ -736,7 +752,7 @@
   extension1.set_ext_name("Hello World");
   EXPECT_EQ(true, ::protos::SetExtension(model, theme, extension1).ok());
   ::upb::Arena arena;
-  auto bytes = ::protos::Serialize(model, arena);
+  auto bytes = ::protos::Serialize(&model, arena);
   EXPECT_EQ(true, bytes.ok());
   TestModel parsed_model = ::protos::Parse<TestModel>(bytes.value()).value();
   EXPECT_EQ("Test123", parsed_model.str1());
@@ -751,7 +767,7 @@
   extension1.set_ext_name("Hello World");
   EXPECT_EQ(true, ::protos::SetExtension(model, theme, extension1).ok());
   ::upb::Arena arena;
-  auto bytes = ::protos::Serialize(model, arena);
+  auto bytes = ::protos::Serialize(&model, arena);
   EXPECT_EQ(true, bytes.ok());
   ::protos::Ptr<TestModel> parsed_model =
       ::protos::CreateMessage<TestModel>(arena);
@@ -771,7 +787,7 @@
                                          extension1)
                       .ok());
   ::upb::Arena arena;
-  auto bytes = ::protos::Serialize(model, arena);
+  auto bytes = ::protos::Serialize(&model, arena);
   EXPECT_EQ(true, bytes.ok());
   ::protos::ExtensionRegistry extensions(
       {&theme, &other_ext, &ThemeExtension::theme_extension}, arena);
@@ -799,15 +815,15 @@
 TEST(CppGeneratedCode, SharedPointer) {
   std::shared_ptr<TestModel> model = std::make_shared<TestModel>();
   ::upb::Arena arena;
-  auto bytes = protos::Serialize(model, arena);
-  EXPECT_TRUE(protos::Parse(model, bytes.value()));
+  auto bytes = protos::Serialize(model.get(), arena);
+  EXPECT_TRUE(protos::Parse(model.get(), bytes.value()));
 }
 
 TEST(CppGeneratedCode, UniquePointer) {
   auto model = std::make_unique<TestModel>();
   ::upb::Arena arena;
-  auto bytes = protos::Serialize(model, arena);
-  EXPECT_TRUE(protos::Parse(model, bytes.value()));
+  auto bytes = protos::Serialize(model.get(), arena);
+  EXPECT_TRUE(protos::Parse(model.get(), bytes.value()));
 }
 
 TEST(CppGeneratedCode, Assignment) {