diff --git a/protos/protos.h b/protos/protos.h
index bcf930c170..7b4f423acf 100644
--- a/protos/protos.h
+++ b/protos/protos.h
@@ -358,6 +358,15 @@ bool Parse(T& message, absl::string_view bytes) {
                     arena) == kUpb_DecodeStatus_Ok;
 }
 
+template <typename T>
+bool Parse(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::unique_ptr<T>& message, absl::string_view bytes) {
   _upb_Message_Clear(message->msg(), T::minitable());
@@ -430,8 +439,7 @@ absl::StatusOr<absl::string_view> Serialize(std::shared_ptr<T>& message,
 }
 
 template <typename T>
-absl::StatusOr<absl::string_view> Serialize(Ptr<const T> message,
-                                            upb::Arena& arena,
+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);
diff --git a/protos_generator/tests/BUILD b/protos_generator/tests/BUILD
index 995f556432..f5a5fb9c47 100644
--- a/protos_generator/tests/BUILD
+++ b/protos_generator/tests/BUILD
@@ -131,5 +131,6 @@ cc_test(
         ":test_model_upb_proto",
         "@com_google_googletest//:gtest_main",
         "//:upb",
+        "//protos",
     ],
 )
diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc
index 416d9f466c..d6ca24a00b 100644
--- a/protos_generator/tests/test_generated.cc
+++ b/protos_generator/tests/test_generated.cc
@@ -26,10 +26,10 @@
 #include <limits>
 
 #include "gtest/gtest.h"
+#include "protos/protos.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/string_view.h"
 
 using ::protos_generator::test::protos::ChildModel1;
 using ::protos_generator::test::protos::other_ext;
@@ -559,6 +559,23 @@ TEST(CppGeneratedCode, Parse) {
   EXPECT_EQ(false, ::protos::GetExtension(parsed_model, theme).ok());
 }
 
+TEST(CppGeneratedCode, ParseIntoPtrToModel) {
+  TestModel model;
+  model.set_str1("Test123");
+  ThemeExtension extension1;
+  extension1.set_ext_name("Hello World");
+  EXPECT_EQ(true, ::protos::SetExtension(model, theme, extension1).ok());
+  ::upb::Arena arena;
+  auto bytes = ::protos::Serialize(model, arena);
+  EXPECT_EQ(true, bytes.ok());
+  ::protos::Ptr<TestModel> parsed_model =
+      ::protos::CreateMessage<TestModel>(arena);
+  EXPECT_TRUE(::protos::Parse(parsed_model, bytes.value()));
+  EXPECT_EQ("Test123", parsed_model->str1());
+  // Should not return an extension since we did not pass ExtensionRegistry.
+  EXPECT_EQ(false, ::protos::GetExtension(parsed_model, theme).ok());
+}
+
 TEST(CppGeneratedCode, ParseWithExtensionRegistry) {
   TestModel model;
   model.set_str1("Test123");