This is an automated email from the ASF dual-hosted git repository.

felipecrv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 9fb1129367 GH-43258: [C++][Flight] Use a Base CRTP type for the types 
used in RPC calls (#43255)
9fb1129367 is described below

commit 9fb11293678c3c23c9ed97630592dac768a2b4ac
Author: Felipe Oliveira Carvalho <[email protected]>
AuthorDate: Thu Jul 18 23:18:07 2024 -0300

    GH-43258: [C++][Flight] Use a Base CRTP type for the types used in RPC 
calls (#43255)
    
    ### Rationale for this change
    
    Flight should eventually be buildable without a specific protobuf version. 
As such, all the protobuf types are wrapped in hand-written classes. Uniformity 
of the interface is not enforced even though it's desirable. Extending the 
interface requires adding functions to every struct. A common base class can 
mitigates risks and reduce the amount of hand-written code.
    
    ### What changes are included in this PR?
    
     - Definition of a BaseType<> template (a CRTP)
     - Add constructors that aren't implicitly defined anymore
     - Having a default value for some fields that would be undefined values 
otherwise
     - Leverage this structure to add `SerializeToBuffer` to all the types
     - ~30KiB in binary size reduction
    
    ### Are these changes tested?
    
    By existing tests.
    * GitHub Issue: #43258
    
    Authored-by: Felipe Oliveira Carvalho <[email protected]>
    Signed-off-by: Felipe Oliveira Carvalho <[email protected]>
---
 cpp/src/arrow/flight/client.cc                     |  20 +-
 cpp/src/arrow/flight/flight_internals_test.cc      |  41 +-
 cpp/src/arrow/flight/flight_test.cc                |   3 +-
 cpp/src/arrow/flight/serialization_internal.cc     |  45 +-
 cpp/src/arrow/flight/serialization_internal.h      |   4 +-
 cpp/src/arrow/flight/sql/example/sqlite_server.cc  |   4 +-
 cpp/src/arrow/flight/sql/server.cc                 |  35 +-
 cpp/src/arrow/flight/test_util.cc                  |  10 +-
 cpp/src/arrow/flight/transport/grpc/grpc_client.cc |  12 +-
 cpp/src/arrow/flight/transport/ucx/ucx_server.cc   |   4 +-
 cpp/src/arrow/flight/types.cc                      | 212 ++++----
 cpp/src/arrow/flight/types.h                       | 569 +++++++++++++--------
 12 files changed, 543 insertions(+), 416 deletions(-)

diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc
index 58a3ba4ab8..d0aee8ab9b 100644
--- a/cpp/src/arrow/flight/client.cc
+++ b/cpp/src/arrow/flight/client.cc
@@ -584,8 +584,8 @@ arrow::Result<std::unique_ptr<ResultStream>> 
FlightClient::DoAction(
 
 arrow::Result<CancelFlightInfoResult> FlightClient::CancelFlightInfo(
     const FlightCallOptions& options, const CancelFlightInfoRequest& request) {
-  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString());
-  Action action{ActionType::kCancelFlightInfo.type, Buffer::FromString(body)};
+  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToBuffer());
+  Action action{ActionType::kCancelFlightInfo.type, std::move(body)};
   ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action));
   ARROW_ASSIGN_OR_RAISE(auto result, stream->Next());
   ARROW_ASSIGN_OR_RAISE(auto cancel_result, 
CancelFlightInfoResult::Deserialize(
@@ -596,8 +596,8 @@ arrow::Result<CancelFlightInfoResult> 
FlightClient::CancelFlightInfo(
 
 arrow::Result<FlightEndpoint> FlightClient::RenewFlightEndpoint(
     const FlightCallOptions& options, const RenewFlightEndpointRequest& 
request) {
-  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString());
-  Action action{ActionType::kRenewFlightEndpoint.type, 
Buffer::FromString(body)};
+  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToBuffer());
+  Action action{ActionType::kRenewFlightEndpoint.type, std::move(body)};
   ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action));
   ARROW_ASSIGN_OR_RAISE(auto result, stream->Next());
   ARROW_ASSIGN_OR_RAISE(auto renewed_endpoint,
@@ -716,8 +716,8 @@ arrow::Result<FlightClient::DoExchangeResult> 
FlightClient::DoExchange(
 ::arrow::Result<SetSessionOptionsResult> FlightClient::SetSessionOptions(
     const FlightCallOptions& options, const SetSessionOptionsRequest& request) 
{
   RETURN_NOT_OK(CheckOpen());
-  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString());
-  Action action{ActionType::kSetSessionOptions.type, Buffer::FromString(body)};
+  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToBuffer());
+  Action action{ActionType::kSetSessionOptions.type, std::move(body)};
   ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action));
   ARROW_ASSIGN_OR_RAISE(auto result, stream->Next());
   ARROW_ASSIGN_OR_RAISE(
@@ -730,8 +730,8 @@ arrow::Result<FlightClient::DoExchangeResult> 
FlightClient::DoExchange(
 ::arrow::Result<GetSessionOptionsResult> FlightClient::GetSessionOptions(
     const FlightCallOptions& options, const GetSessionOptionsRequest& request) 
{
   RETURN_NOT_OK(CheckOpen());
-  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString());
-  Action action{ActionType::kGetSessionOptions.type, Buffer::FromString(body)};
+  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToBuffer());
+  Action action{ActionType::kGetSessionOptions.type, std::move(body)};
   ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action));
   ARROW_ASSIGN_OR_RAISE(auto result, stream->Next());
   ARROW_ASSIGN_OR_RAISE(
@@ -744,8 +744,8 @@ arrow::Result<FlightClient::DoExchangeResult> 
FlightClient::DoExchange(
 ::arrow::Result<CloseSessionResult> FlightClient::CloseSession(
     const FlightCallOptions& options, const CloseSessionRequest& request) {
   RETURN_NOT_OK(CheckOpen());
-  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString());
-  Action action{ActionType::kCloseSession.type, Buffer::FromString(body)};
+  ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToBuffer());
+  Action action{ActionType::kCloseSession.type, std::move(body)};
   ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action));
   ARROW_ASSIGN_OR_RAISE(auto result, stream->Next());
   ARROW_ASSIGN_OR_RAISE(auto close_session_result,
diff --git a/cpp/src/arrow/flight/flight_internals_test.cc 
b/cpp/src/arrow/flight/flight_internals_test.cc
index 57f4f3e030..caab357ef8 100644
--- a/cpp/src/arrow/flight/flight_internals_test.cc
+++ b/cpp/src/arrow/flight/flight_internals_test.cc
@@ -79,8 +79,9 @@ void TestRoundtrip(const std::vector<FlightType>& values,
     ASSERT_OK(internal::ToProto(values[i], &pb_value));
 
     if constexpr (std::is_same_v<FlightType, FlightInfo>) {
-      ASSERT_OK_AND_ASSIGN(FlightInfo value, internal::FromProto(pb_value));
-      EXPECT_EQ(values[i], value);
+      FlightInfo::Data info_data;
+      ASSERT_OK(internal::FromProto(pb_value, &info_data));
+      EXPECT_EQ(values[i], FlightInfo{std::move(info_data)});
     } else if constexpr (std::is_same_v<FlightType, SchemaResult>) {
       std::string data;
       ASSERT_OK(internal::FromProto(pb_value, &data));
@@ -152,9 +153,11 @@ TEST(FlightTypes, BasicAuth) {
 }
 
 TEST(FlightTypes, Criteria) {
-  std::vector<Criteria> values = {{""}, {"criteria"}};
-  std::vector<std::string> reprs = {"<Criteria expression=''>",
-                                    "<Criteria expression='criteria'>"};
+  std::vector<Criteria> values = {Criteria{""}, Criteria{"criteria"}};
+  std::vector<std::string> reprs = {
+      "<Criteria expression=''>",
+      "<Criteria expression='criteria'>",
+  };
   ASSERT_NO_FATAL_FAILURE(TestRoundtrip<pb::Criteria>(values, reprs));
 }
 
@@ -191,14 +194,14 @@ TEST(FlightTypes, FlightEndpoint) {
   Timestamp expiration_time(
       
std::chrono::duration_cast<Timestamp::duration>(expiration_time_duration));
   std::vector<FlightEndpoint> values = {
-      {{""}, {}, std::nullopt, {}},
-      {{"foo"}, {}, std::nullopt, {}},
-      {{"bar"}, {}, std::nullopt, {"\xDE\xAD\xBE\xEF"}},
-      {{"foo"}, {}, expiration_time, {}},
-      {{"foo"}, {location1}, std::nullopt, {}},
-      {{"bar"}, {location1}, std::nullopt, {}},
-      {{"foo"}, {location2}, std::nullopt, {}},
-      {{"foo"}, {location1, location2}, std::nullopt, {"\xba\xdd\xca\xfe"}},
+      {Ticket{""}, {}, std::nullopt, {}},
+      {Ticket{"foo"}, {}, std::nullopt, {}},
+      {Ticket{"bar"}, {}, std::nullopt, {"\xDE\xAD\xBE\xEF"}},
+      {Ticket{"foo"}, {}, expiration_time, {}},
+      {Ticket{"foo"}, {location1}, std::nullopt, {}},
+      {Ticket{"bar"}, {location1}, std::nullopt, {}},
+      {Ticket{"foo"}, {location2}, std::nullopt, {}},
+      {Ticket{"foo"}, {location1, location2}, std::nullopt, 
{"\xba\xdd\xca\xfe"}},
   };
   std::vector<std::string> reprs = {
       "<FlightEndpoint ticket=<Ticket ticket=''> locations=[] "
@@ -299,9 +302,9 @@ TEST(FlightTypes, PollInfo) {
 
 TEST(FlightTypes, Result) {
   std::vector<Result> values = {
-      {Buffer::FromString("")},
-      {Buffer::FromString("foo")},
-      {Buffer::FromString("bar")},
+      Result{Buffer::FromString("")},
+      Result{Buffer::FromString("foo")},
+      Result{Buffer::FromString("bar")},
   };
   std::vector<std::string> reprs = {
       "<Result body=(0 bytes)>",
@@ -333,9 +336,9 @@ TEST(FlightTypes, SchemaResult) {
 
 TEST(FlightTypes, Ticket) {
   std::vector<Ticket> values = {
-      {""},
-      {"foo"},
-      {"bar"},
+      Ticket{""},
+      Ticket{"foo"},
+      Ticket{"bar"},
   };
   std::vector<std::string> reprs = {
       "<Ticket ticket=''>",
diff --git a/cpp/src/arrow/flight/flight_test.cc 
b/cpp/src/arrow/flight/flight_test.cc
index e179f3406d..101bb06b21 100644
--- a/cpp/src/arrow/flight/flight_test.cc
+++ b/cpp/src/arrow/flight/flight_test.cc
@@ -998,7 +998,8 @@ TEST_F(TestFlightClient, ListFlights) {
 }
 
 TEST_F(TestFlightClient, ListFlightsWithCriteria) {
-  ASSERT_OK_AND_ASSIGN(auto listing, client_->ListFlights(FlightCallOptions(), 
{"foo"}));
+  ASSERT_OK_AND_ASSIGN(auto listing,
+                       client_->ListFlights(FlightCallOptions{}, 
Criteria{"foo"}));
   std::unique_ptr<FlightInfo> info;
   ASSERT_OK_AND_ASSIGN(info, listing->Next());
   ASSERT_TRUE(info == nullptr);
diff --git a/cpp/src/arrow/flight/serialization_internal.cc 
b/cpp/src/arrow/flight/serialization_internal.cc
index 10600d055b..fedfc7d5cd 100644
--- a/cpp/src/arrow/flight/serialization_internal.cc
+++ b/cpp/src/arrow/flight/serialization_internal.cc
@@ -251,22 +251,28 @@ Status ToProto(const FlightDescriptor& descriptor, 
pb::FlightDescriptor* pb_desc
 
 // FlightInfo
 
-arrow::Result<FlightInfo> FromProto(const pb::FlightInfo& pb_info) {
-  FlightInfo::Data info;
-  RETURN_NOT_OK(FromProto(pb_info.flight_descriptor(), &info.descriptor));
+Status FromProto(const pb::FlightInfo& pb_info, FlightInfo::Data* info) {
+  RETURN_NOT_OK(FromProto(pb_info.flight_descriptor(), &info->descriptor));
 
-  info.schema = pb_info.schema();
+  info->schema = pb_info.schema();
 
-  info.endpoints.resize(pb_info.endpoint_size());
+  info->endpoints.resize(pb_info.endpoint_size());
   for (int i = 0; i < pb_info.endpoint_size(); ++i) {
-    RETURN_NOT_OK(FromProto(pb_info.endpoint(i), &info.endpoints[i]));
+    RETURN_NOT_OK(FromProto(pb_info.endpoint(i), &info->endpoints[i]));
   }
 
-  info.total_records = pb_info.total_records();
-  info.total_bytes = pb_info.total_bytes();
-  info.ordered = pb_info.ordered();
-  info.app_metadata = pb_info.app_metadata();
-  return FlightInfo(std::move(info));
+  info->total_records = pb_info.total_records();
+  info->total_bytes = pb_info.total_bytes();
+  info->ordered = pb_info.ordered();
+  info->app_metadata = pb_info.app_metadata();
+  return Status::OK();
+}
+
+Status FromProto(const pb::FlightInfo& pb_info, std::unique_ptr<FlightInfo>* 
info) {
+  FlightInfo::Data info_data;
+  RETURN_NOT_OK(FromProto(pb_info, &info_data));
+  *info = std::make_unique<FlightInfo>(std::move(info_data));
+  return Status::OK();
 }
 
 Status FromProto(const pb::BasicAuth& pb_basic_auth, BasicAuth* basic_auth) {
@@ -315,8 +321,9 @@ Status ToProto(const FlightInfo& info, pb::FlightInfo* 
pb_info) {
 
 Status FromProto(const pb::PollInfo& pb_info, PollInfo* info) {
   if (pb_info.has_info()) {
-    ARROW_ASSIGN_OR_RAISE(auto flight_info, FromProto(pb_info.info()));
-    info->info = std::make_unique<FlightInfo>(std::move(flight_info));
+    FlightInfo::Data info_data;
+    RETURN_NOT_OK(FromProto(pb_info.info(), &info_data));
+    info->info = std::make_unique<FlightInfo>(std::move(info_data));
   }
   if (pb_info.has_flight_descriptor()) {
     FlightDescriptor descriptor;
@@ -340,6 +347,13 @@ Status FromProto(const pb::PollInfo& pb_info, PollInfo* 
info) {
   return Status::OK();
 }
 
+Status FromProto(const pb::PollInfo& pb_info, std::unique_ptr<PollInfo>* info) 
{
+  PollInfo poll_info;
+  RETURN_NOT_OK(FromProto(pb_info, &poll_info));
+  *info = std::make_unique<PollInfo>(std::move(poll_info));
+  return Status::OK();
+}
+
 Status ToProto(const PollInfo& info, pb::PollInfo* pb_info) {
   if (info.info) {
     RETURN_NOT_OK(ToProto(*info.info, pb_info->mutable_info()));
@@ -360,8 +374,9 @@ Status ToProto(const PollInfo& info, pb::PollInfo* pb_info) 
{
 
 Status FromProto(const pb::CancelFlightInfoRequest& pb_request,
                  CancelFlightInfoRequest* request) {
-  ARROW_ASSIGN_OR_RAISE(FlightInfo info, FromProto(pb_request.info()));
-  request->info = std::make_unique<FlightInfo>(std::move(info));
+  FlightInfo::Data info_data;
+  RETURN_NOT_OK(FromProto(pb_request.info(), &info_data));
+  request->info = std::make_unique<FlightInfo>(std::move(info_data));
   return Status::OK();
 }
 
diff --git a/cpp/src/arrow/flight/serialization_internal.h 
b/cpp/src/arrow/flight/serialization_internal.h
index 90dde87d3a..ffde47d43c 100644
--- a/cpp/src/arrow/flight/serialization_internal.h
+++ b/cpp/src/arrow/flight/serialization_internal.h
@@ -60,8 +60,10 @@ Status FromProto(const pb::FlightDescriptor& pb_descr, 
FlightDescriptor* descr);
 Status FromProto(const pb::FlightEndpoint& pb_endpoint, FlightEndpoint* 
endpoint);
 Status FromProto(const pb::RenewFlightEndpointRequest& pb_request,
                  RenewFlightEndpointRequest* request);
-arrow::Result<FlightInfo> FromProto(const pb::FlightInfo& pb_info);
+Status FromProto(const pb::FlightInfo& pb_info, FlightInfo::Data* info);
+Status FromProto(const pb::FlightInfo& pb_info, std::unique_ptr<FlightInfo>* 
info);
 Status FromProto(const pb::PollInfo& pb_info, PollInfo* info);
+Status FromProto(const pb::PollInfo& pb_info, std::unique_ptr<PollInfo>* info);
 Status FromProto(const pb::CancelFlightInfoRequest& pb_request,
                  CancelFlightInfoRequest* request);
 Status FromProto(const pb::SchemaResult& pb_result, std::string* result);
diff --git a/cpp/src/arrow/flight/sql/example/sqlite_server.cc 
b/cpp/src/arrow/flight/sql/example/sqlite_server.cc
index 20b234e90a..0651e6111c 100644
--- a/cpp/src/arrow/flight/sql/example/sqlite_server.cc
+++ b/cpp/src/arrow/flight/sql/example/sqlite_server.cc
@@ -126,7 +126,7 @@ arrow::Result<std::unique_ptr<FlightDataStream>> 
DoGetSQLiteQuery(
 arrow::Result<std::unique_ptr<FlightInfo>> GetFlightInfoForCommand(
     const FlightDescriptor& descriptor, const std::shared_ptr<Schema>& schema) 
{
   std::vector<FlightEndpoint> endpoints{
-      FlightEndpoint{{descriptor.cmd}, {}, std::nullopt, ""}};
+      FlightEndpoint{Ticket{descriptor.cmd}, {}, std::nullopt, ""}};
   ARROW_ASSIGN_OR_RAISE(auto result,
                         FlightInfo::Make(*schema, descriptor, endpoints, -1, 
-1, false))
 
@@ -389,7 +389,7 @@ class SQLiteFlightSqlServer::Impl {
       const ServerCallContext& context, const GetTables& command,
       const FlightDescriptor& descriptor) {
     std::vector<FlightEndpoint> endpoints{
-        FlightEndpoint{{descriptor.cmd}, {}, std::nullopt, ""}};
+        FlightEndpoint{Ticket{descriptor.cmd}, {}, std::nullopt, ""}};
 
     bool include_schema = command.include_schema;
     ARROW_LOG(INFO) << "GetTables include_schema=" << include_schema;
diff --git a/cpp/src/arrow/flight/sql/server.cc 
b/cpp/src/arrow/flight/sql/server.cc
index 63d1f5c522..ac89976690 100644
--- a/cpp/src/arrow/flight/sql/server.cc
+++ b/cpp/src/arrow/flight/sql/server.cc
@@ -477,13 +477,11 @@ arrow::Result<Result> 
PackActionResult(ActionBeginTransactionResult result) {
 }
 
 arrow::Result<Result> PackActionResult(CancelFlightInfoResult result) {
-  ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString());
-  return Result{Buffer::FromString(std::move(serialized))};
+  return result.SerializeToBuffer();
 }
 
 arrow::Result<Result> PackActionResult(const FlightEndpoint& endpoint) {
-  ARROW_ASSIGN_OR_RAISE(auto serialized, endpoint.SerializeToString());
-  return Result{Buffer::FromString(std::move(serialized))};
+  return endpoint.SerializeToBuffer();
 }
 
 arrow::Result<Result> PackActionResult(CancelResult result) {
@@ -525,21 +523,6 @@ arrow::Result<Result> 
PackActionResult(ActionCreatePreparedStatementResult resul
   return PackActionResult(pb_result);
 }
 
-arrow::Result<Result> PackActionResult(SetSessionOptionsResult result) {
-  ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString());
-  return Result{Buffer::FromString(std::move(serialized))};
-}
-
-arrow::Result<Result> PackActionResult(GetSessionOptionsResult result) {
-  ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString());
-  return Result{Buffer::FromString(std::move(serialized))};
-}
-
-arrow::Result<Result> PackActionResult(CloseSessionResult result) {
-  ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString());
-  return Result{Buffer::FromString(std::move(serialized))};
-}
-
 }  // namespace
 
 arrow::Result<StatementQueryTicket> StatementQueryTicket::Deserialize(
@@ -908,23 +891,23 @@ Status FlightSqlServerBase::DoAction(const 
ServerCallContext& context,
     std::string_view body(*action.body);
     ARROW_ASSIGN_OR_RAISE(auto request, 
SetSessionOptionsRequest::Deserialize(body));
     ARROW_ASSIGN_OR_RAISE(auto result, SetSessionOptions(context, request));
-    ARROW_ASSIGN_OR_RAISE(auto packed_result, 
PackActionResult(std::move(result)));
+    ARROW_ASSIGN_OR_RAISE(auto packed_result, result.SerializeToBuffer());
 
-    results.push_back(std::move(packed_result));
+    results.emplace_back(std::move(packed_result));
   } else if (action.type == ActionType::kGetSessionOptions.type) {
     std::string_view body(*action.body);
     ARROW_ASSIGN_OR_RAISE(auto request, 
GetSessionOptionsRequest::Deserialize(body));
     ARROW_ASSIGN_OR_RAISE(auto result, GetSessionOptions(context, request));
-    ARROW_ASSIGN_OR_RAISE(auto packed_result, 
PackActionResult(std::move(result)));
+    ARROW_ASSIGN_OR_RAISE(auto packed_result, result.SerializeToBuffer());
 
-    results.push_back(std::move(packed_result));
+    results.emplace_back(std::move(packed_result));
   } else if (action.type == ActionType::kCloseSession.type) {
     std::string_view body(*action.body);
     ARROW_ASSIGN_OR_RAISE(auto request, 
CloseSessionRequest::Deserialize(body));
     ARROW_ASSIGN_OR_RAISE(auto result, CloseSession(context, request));
-    ARROW_ASSIGN_OR_RAISE(auto packed_result, 
PackActionResult(std::move(result)));
+    ARROW_ASSIGN_OR_RAISE(auto packed_result, result.SerializeToBuffer());
 
-    results.push_back(std::move(packed_result));
+    results.emplace_back(std::move(packed_result));
   } else {
     google::protobuf::Any any;
     if (!any.ParseFromArray(action.body->data(), 
static_cast<int>(action.body->size()))) {
@@ -1063,7 +1046,7 @@ arrow::Result<std::unique_ptr<FlightInfo>> 
FlightSqlServerBase::GetFlightInfoSql
   }
 
   std::vector<FlightEndpoint> endpoints{
-      FlightEndpoint{{descriptor.cmd}, {}, std::nullopt, {}}};
+      FlightEndpoint{Ticket{descriptor.cmd}, {}, std::nullopt, {}}};
   ARROW_ASSIGN_OR_RAISE(
       auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(), 
descriptor, endpoints,
                                     -1, -1, false))
diff --git a/cpp/src/arrow/flight/test_util.cc 
b/cpp/src/arrow/flight/test_util.cc
index bf2f4c2b4e..8b4245e74e 100644
--- a/cpp/src/arrow/flight/test_util.cc
+++ b/cpp/src/arrow/flight/test_util.cc
@@ -604,11 +604,11 @@ std::vector<FlightInfo> ExampleFlightInfo() {
   Location location4 = *Location::ForGrpcTcp("foo4.bar.com", 12345);
   Location location5 = *Location::ForGrpcTcp("foo5.bar.com", 12345);
 
-  FlightEndpoint endpoint1({{"ticket-ints-1"}, {location1}, std::nullopt, {}});
-  FlightEndpoint endpoint2({{"ticket-ints-2"}, {location2}, std::nullopt, {}});
-  FlightEndpoint endpoint3({{"ticket-cmd"}, {location3}, std::nullopt, {}});
-  FlightEndpoint endpoint4({{"ticket-dicts-1"}, {location4}, std::nullopt, 
{}});
-  FlightEndpoint endpoint5({{"ticket-floats-1"}, {location5}, std::nullopt, 
{}});
+  FlightEndpoint endpoint1({Ticket{"ticket-ints-1"}, {location1}, 
std::nullopt, {}});
+  FlightEndpoint endpoint2({Ticket{"ticket-ints-2"}, {location2}, 
std::nullopt, {}});
+  FlightEndpoint endpoint3({Ticket{"ticket-cmd"}, {location3}, std::nullopt, 
{}});
+  FlightEndpoint endpoint4({Ticket{"ticket-dicts-1"}, {location4}, 
std::nullopt, {}});
+  FlightEndpoint endpoint5({Ticket{"ticket-floats-1"}, {location5}, 
std::nullopt, {}});
 
   FlightDescriptor descr1{FlightDescriptor::PATH, "", {"examples", "ints"}};
   FlightDescriptor descr2{FlightDescriptor::CMD, "my_command", {}};
diff --git a/cpp/src/arrow/flight/transport/grpc/grpc_client.cc 
b/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
index f799ba761c..6d8d40c2eb 100644
--- a/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
+++ b/cpp/src/arrow/flight/transport/grpc/grpc_client.cc
@@ -648,10 +648,10 @@ class UnaryUnaryAsyncCall : public 
::grpc::ClientUnaryReactor, public internal::
 
   void OnDone(const ::grpc::Status& status) override {
     if (status.ok()) {
-      auto result = internal::FromProto(pb_response);
-      client_status = result.status();
+      FlightInfo::Data info_data;
+      client_status = internal::FromProto(pb_response, &info_data);
       if (client_status.ok()) {
-        listener->OnNext(std::move(result).MoveValueUnsafe());
+        listener->OnNext(FlightInfo{std::move(info_data)});
       }
     }
     Finish(status);
@@ -889,7 +889,8 @@ class GrpcClientImpl : public internal::ClientTransport {
 
     pb::FlightInfo pb_info;
     while (!options.stop_token.IsStopRequested() && stream->Read(&pb_info)) {
-      ARROW_ASSIGN_OR_RAISE(FlightInfo info_data, 
internal::FromProto(pb_info));
+      FlightInfo::Data info_data;
+      RETURN_NOT_OK(internal::FromProto(pb_info, &info_data));
       flights.emplace_back(std::move(info_data));
     }
     if (options.stop_token.IsStopRequested()) rpc.context.TryCancel();
@@ -939,7 +940,8 @@ class GrpcClientImpl : public internal::ClientTransport {
         stub_->GetFlightInfo(&rpc.context, pb_descriptor, &pb_response), 
&rpc.context);
     RETURN_NOT_OK(s);
 
-    ARROW_ASSIGN_OR_RAISE(auto info_data, internal::FromProto(pb_response));
+    FlightInfo::Data info_data;
+    RETURN_NOT_OK(internal::FromProto(pb_response, &info_data));
     *info = std::make_unique<FlightInfo>(std::move(info_data));
     return Status::OK();
   }
diff --git a/cpp/src/arrow/flight/transport/ucx/ucx_server.cc 
b/cpp/src/arrow/flight/transport/ucx/ucx_server.cc
index cb9c8948cc..55ff138348 100644
--- a/cpp/src/arrow/flight/transport/ucx/ucx_server.cc
+++ b/cpp/src/arrow/flight/transport/ucx/ucx_server.cc
@@ -376,7 +376,7 @@ class UcxServerImpl : public 
arrow::flight::internal::ServerTransport {
     std::unique_ptr<FlightInfo> info;
     std::string response;
     SERVER_RETURN_NOT_OK(driver, base_->GetFlightInfo(context, descriptor, 
&info));
-    SERVER_RETURN_NOT_OK(driver, info->SerializeToString().Value(&response));
+    SERVER_RETURN_NOT_OK(driver, info->DoSerializeToString(&response));
     RETURN_NOT_OK(driver->SendFrame(FrameType::kBuffer,
                                     reinterpret_cast<const 
uint8_t*>(response.data()),
                                     static_cast<int64_t>(response.size())));
@@ -397,7 +397,7 @@ class UcxServerImpl : public 
arrow::flight::internal::ServerTransport {
     std::unique_ptr<PollInfo> info;
     std::string response;
     SERVER_RETURN_NOT_OK(driver, base_->PollFlightInfo(context, descriptor, 
&info));
-    SERVER_RETURN_NOT_OK(driver, info->SerializeToString().Value(&response));
+    SERVER_RETURN_NOT_OK(driver, info->DoSerializeToString(&response));
     RETURN_NOT_OK(driver->SendFrame(FrameType::kBuffer,
                                     reinterpret_cast<const 
uint8_t*>(response.data()),
                                     static_cast<int64_t>(response.size())));
diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc
index a04956a4ea..170fbfe239 100644
--- a/cpp/src/arrow/flight/types.cc
+++ b/cpp/src/arrow/flight/types.cc
@@ -81,20 +81,17 @@ Status SerializeToString(const char* name, const T& in, 
PBType* out_pb,
 // Result-returning ser/de functions (more convenient)
 
 template <class PBType, class T>
-arrow::Result<T> DeserializeProtoString(const char* name, std::string_view 
serialized) {
+arrow::Status DeserializeProtoString(const char* name, std::string_view 
serialized,
+                                     T* out) {
   PBType pb;
   RETURN_NOT_OK(ParseFromString(name, serialized, &pb));
-  T out;
-  RETURN_NOT_OK(internal::FromProto(pb, &out));
-  return out;
+  return internal::FromProto(pb, out);
 }
 
 template <class PBType, class T>
-arrow::Result<std::string> SerializeToProtoString(const char* name, const T& 
in) {
+Status SerializeToProtoString(const char* name, const T& in, std::string* out) 
{
   PBType pb;
-  std::string out;
-  RETURN_NOT_OK(SerializeToString<PBType>(name, in, &pb, &out));
-  return out;
+  return SerializeToString<PBType>(name, in, &pb, out);
 }
 
 }  // namespace
@@ -230,24 +227,25 @@ bool SchemaResult::Equals(const SchemaResult& other) 
const {
   return raw_schema_ == other.raw_schema_;
 }
 
-arrow::Result<std::string> SchemaResult::SerializeToString() const {
-  return SerializeToProtoString<pb::SchemaResult>("SchemaResult", *this);
+arrow::Status SchemaResult::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::SchemaResult>("SchemaResult", *this, out);
 }
 
-arrow::Result<SchemaResult> SchemaResult::Deserialize(std::string_view 
serialized) {
+arrow::Status SchemaResult::Deserialize(std::string_view serialized, 
SchemaResult* out) {
   pb::SchemaResult pb_schema_result;
   RETURN_NOT_OK(ParseFromString("SchemaResult", serialized, 
&pb_schema_result));
-  return SchemaResult{pb_schema_result.schema()};
+  *out = SchemaResult{pb_schema_result.schema()};
+  return Status::OK();
 }
 
-arrow::Result<std::string> FlightDescriptor::SerializeToString() const {
-  return SerializeToProtoString<pb::FlightDescriptor>("FlightDescriptor", 
*this);
+arrow::Status FlightDescriptor::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::FlightDescriptor>("FlightDescriptor", 
*this, out);
 }
 
-arrow::Result<FlightDescriptor> FlightDescriptor::Deserialize(
-    std::string_view serialized) {
+arrow::Status FlightDescriptor::Deserialize(std::string_view serialized,
+                                            FlightDescriptor* out) {
   return DeserializeProtoString<pb::FlightDescriptor, FlightDescriptor>(
-      "FlightDescriptor", serialized);
+      "FlightDescriptor", serialized, out);
 }
 
 std::string Ticket::ToString() const {
@@ -258,12 +256,12 @@ std::string Ticket::ToString() const {
 
 bool Ticket::Equals(const Ticket& other) const { return ticket == 
other.ticket; }
 
-arrow::Result<std::string> Ticket::SerializeToString() const {
-  return SerializeToProtoString<pb::Ticket>("Ticket", *this);
+arrow::Status Ticket::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::Ticket>("Ticket", *this, out);
 }
 
-arrow::Result<Ticket> Ticket::Deserialize(std::string_view serialized) {
-  return DeserializeProtoString<pb::Ticket, Ticket>("Ticket", serialized);
+arrow::Status Ticket::Deserialize(std::string_view serialized, Ticket* out) {
+  return DeserializeProtoString<pb::Ticket, Ticket>("Ticket", serialized, out);
 }
 
 arrow::Result<FlightInfo> FlightInfo::Make(const Schema& schema,
@@ -279,7 +277,7 @@ arrow::Result<FlightInfo> FlightInfo::Make(const Schema& 
schema,
   data.ordered = ordered;
   data.app_metadata = std::move(app_metadata);
   RETURN_NOT_OK(internal::SchemaToString(schema, &data.schema));
-  return FlightInfo(data);
+  return FlightInfo(std::move(data));
 }
 
 arrow::Result<std::shared_ptr<Schema>> FlightInfo::GetSchema(
@@ -294,16 +292,14 @@ arrow::Result<std::shared_ptr<Schema>> 
FlightInfo::GetSchema(
   return schema_;
 }
 
-arrow::Result<std::string> FlightInfo::SerializeToString() const {
-  return SerializeToProtoString<pb::FlightInfo>("FlightInfo", *this);
+arrow::Status FlightInfo::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::FlightInfo>("FlightInfo", *this, out);
 }
 
-arrow::Result<std::unique_ptr<FlightInfo>> FlightInfo::Deserialize(
-    std::string_view serialized) {
-  pb::FlightInfo pb_info;
-  RETURN_NOT_OK(ParseFromString("FlightInfo", serialized, &pb_info));
-  ARROW_ASSIGN_OR_RAISE(FlightInfo info, internal::FromProto(pb_info));
-  return std::make_unique<FlightInfo>(std::move(info));
+arrow::Status FlightInfo::Deserialize(std::string_view serialized,
+                                      std::unique_ptr<FlightInfo>* out) {
+  return DeserializeProtoString<pb::FlightInfo, std::unique_ptr<FlightInfo>>(
+      "FlightInfo", serialized, out);
 }
 
 std::string FlightInfo::ToString() const {
@@ -340,17 +336,14 @@ bool FlightInfo::Equals(const FlightInfo& other) const {
          data_.app_metadata == other.data_.app_metadata;
 }
 
-arrow::Result<std::string> PollInfo::SerializeToString() const {
-  return SerializeToProtoString<pb::PollInfo>("PollInfo", *this);
+arrow::Status PollInfo::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::PollInfo>("PollInfo", *this, out);
 }
 
-arrow::Result<std::unique_ptr<PollInfo>> PollInfo::Deserialize(
-    std::string_view serialized) {
-  pb::PollInfo pb_info;
-  RETURN_NOT_OK(ParseFromString("PollInfo", serialized, &pb_info));
-  PollInfo info;
-  RETURN_NOT_OK(internal::FromProto(pb_info, &info));
-  return std::make_unique<PollInfo>(std::move(info));
+arrow::Status PollInfo::Deserialize(std::string_view serialized,
+                                    std::unique_ptr<PollInfo>* out) {
+  return DeserializeProtoString<pb::PollInfo, 
std::unique_ptr<PollInfo>>("PollInfo",
+                                                                         
serialized, out);
 }
 
 std::string PollInfo::ToString() const {
@@ -427,15 +420,15 @@ bool CancelFlightInfoRequest::Equals(const 
CancelFlightInfoRequest& other) const
   return info == other.info;
 }
 
-arrow::Result<std::string> CancelFlightInfoRequest::SerializeToString() const {
+arrow::Status CancelFlightInfoRequest::SerializeToString(std::string* out) 
const {
   return 
SerializeToProtoString<pb::CancelFlightInfoRequest>("CancelFlightInfoRequest",
-                                                             *this);
+                                                             *this, out);
 }
 
-arrow::Result<CancelFlightInfoRequest> CancelFlightInfoRequest::Deserialize(
-    std::string_view serialized) {
+arrow::Status CancelFlightInfoRequest::Deserialize(std::string_view serialized,
+                                                   CancelFlightInfoRequest* 
out) {
   return DeserializeProtoString<pb::CancelFlightInfoRequest, 
CancelFlightInfoRequest>(
-      "CancelFlightInfoRequest", serialized);
+      "CancelFlightInfoRequest", serialized, out);
 }
 
 static const char* const SetSessionOptionStatusNames[] = {"Unspecified", 
"InvalidName",
@@ -556,15 +549,15 @@ bool SetSessionOptionsRequest::Equals(const 
SetSessionOptionsRequest& other) con
   return CompareSessionOptionMaps(session_options, other.session_options);
 }
 
-arrow::Result<std::string> SetSessionOptionsRequest::SerializeToString() const 
{
+arrow::Status SetSessionOptionsRequest::SerializeToString(std::string* out) 
const {
   return 
SerializeToProtoString<pb::SetSessionOptionsRequest>("SetSessionOptionsRequest",
-                                                              *this);
+                                                              *this, out);
 }
 
-arrow::Result<SetSessionOptionsRequest> SetSessionOptionsRequest::Deserialize(
-    std::string_view serialized) {
+arrow::Status SetSessionOptionsRequest::Deserialize(std::string_view 
serialized,
+                                                    SetSessionOptionsRequest* 
out) {
   return DeserializeProtoString<pb::SetSessionOptionsRequest, 
SetSessionOptionsRequest>(
-      "SetSessionOptionsRequest", serialized);
+      "SetSessionOptionsRequest", serialized, out);
 }
 
 // SetSessionOptionsResult
@@ -584,15 +577,15 @@ bool SetSessionOptionsResult::Equals(const 
SetSessionOptionsResult& other) const
   return true;
 }
 
-arrow::Result<std::string> SetSessionOptionsResult::SerializeToString() const {
+arrow::Status SetSessionOptionsResult::SerializeToString(std::string* out) 
const {
   return 
SerializeToProtoString<pb::SetSessionOptionsResult>("SetSessionOptionsResult",
-                                                             *this);
+                                                             *this, out);
 }
 
-arrow::Result<SetSessionOptionsResult> SetSessionOptionsResult::Deserialize(
-    std::string_view serialized) {
+arrow::Status SetSessionOptionsResult::Deserialize(std::string_view serialized,
+                                                   SetSessionOptionsResult* 
out) {
   return DeserializeProtoString<pb::SetSessionOptionsResult, 
SetSessionOptionsResult>(
-      "SetSessionOptionsResult", serialized);
+      "SetSessionOptionsResult", serialized, out);
 }
 
 // GetSessionOptionsRequest
@@ -605,15 +598,15 @@ bool GetSessionOptionsRequest::Equals(const 
GetSessionOptionsRequest& other) con
   return true;
 }
 
-arrow::Result<std::string> GetSessionOptionsRequest::SerializeToString() const 
{
+arrow::Status GetSessionOptionsRequest::SerializeToString(std::string* out) 
const {
   return 
SerializeToProtoString<pb::GetSessionOptionsRequest>("GetSessionOptionsRequest",
-                                                              *this);
+                                                              *this, out);
 }
 
-arrow::Result<GetSessionOptionsRequest> GetSessionOptionsRequest::Deserialize(
-    std::string_view serialized) {
+arrow::Status GetSessionOptionsRequest::Deserialize(std::string_view 
serialized,
+                                                    GetSessionOptionsRequest* 
out) {
   return DeserializeProtoString<pb::GetSessionOptionsRequest, 
GetSessionOptionsRequest>(
-      "GetSessionOptionsRequest", serialized);
+      "GetSessionOptionsRequest", serialized, out);
 }
 
 // GetSessionOptionsResult
@@ -628,15 +621,15 @@ bool GetSessionOptionsResult::Equals(const 
GetSessionOptionsResult& other) const
   return CompareSessionOptionMaps(session_options, other.session_options);
 }
 
-arrow::Result<std::string> GetSessionOptionsResult::SerializeToString() const {
+arrow::Status GetSessionOptionsResult::SerializeToString(std::string* out) 
const {
   return 
SerializeToProtoString<pb::GetSessionOptionsResult>("GetSessionOptionsResult",
-                                                             *this);
+                                                             *this, out);
 }
 
-arrow::Result<GetSessionOptionsResult> GetSessionOptionsResult::Deserialize(
-    std::string_view serialized) {
+arrow::Status GetSessionOptionsResult::Deserialize(std::string_view serialized,
+                                                   GetSessionOptionsResult* 
out) {
   return DeserializeProtoString<pb::GetSessionOptionsResult, 
GetSessionOptionsResult>(
-      "GetSessionOptionsResult", serialized);
+      "GetSessionOptionsResult", serialized, out);
 }
 
 // CloseSessionRequest
@@ -645,14 +638,15 @@ std::string CloseSessionRequest::ToString() const { 
return "<CloseSessionRequest
 
 bool CloseSessionRequest::Equals(const CloseSessionRequest& other) const { 
return true; }
 
-arrow::Result<std::string> CloseSessionRequest::SerializeToString() const {
-  return 
SerializeToProtoString<pb::CloseSessionRequest>("CloseSessionRequest", *this);
+arrow::Status CloseSessionRequest::SerializeToString(std::string* out) const {
+  return 
SerializeToProtoString<pb::CloseSessionRequest>("CloseSessionRequest", *this,
+                                                         out);
 }
 
-arrow::Result<CloseSessionRequest> CloseSessionRequest::Deserialize(
-    std::string_view serialized) {
+arrow::Status CloseSessionRequest::Deserialize(std::string_view serialized,
+                                               CloseSessionRequest* out) {
   return DeserializeProtoString<pb::CloseSessionRequest, CloseSessionRequest>(
-      "CloseSessionRequest", serialized);
+      "CloseSessionRequest", serialized, out);
 }
 
 // CloseSessionResult
@@ -669,14 +663,14 @@ bool CloseSessionResult::Equals(const CloseSessionResult& 
other) const {
   return status == other.status;
 }
 
-arrow::Result<std::string> CloseSessionResult::SerializeToString() const {
-  return SerializeToProtoString<pb::CloseSessionResult>("CloseSessionResult", 
*this);
+arrow::Status CloseSessionResult::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::CloseSessionResult>("CloseSessionResult", 
*this, out);
 }
 
-arrow::Result<CloseSessionResult> CloseSessionResult::Deserialize(
-    std::string_view serialized) {
+arrow::Status CloseSessionResult::Deserialize(std::string_view serialized,
+                                              CloseSessionResult* out) {
   return DeserializeProtoString<pb::CloseSessionResult, CloseSessionResult>(
-      "CloseSessionResult", serialized);
+      "CloseSessionResult", serialized, out);
 }
 
 Location::Location() { uri_ = std::make_shared<arrow::util::Uri>(); }
@@ -781,13 +775,14 @@ bool FlightEndpoint::Equals(const FlightEndpoint& other) 
const {
   return true;
 }
 
-arrow::Result<std::string> FlightEndpoint::SerializeToString() const {
-  return SerializeToProtoString<pb::FlightEndpoint>("FlightEndpoint", *this);
+arrow::Status FlightEndpoint::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::FlightEndpoint>("FlightEndpoint", *this, 
out);
 }
 
-arrow::Result<FlightEndpoint> FlightEndpoint::Deserialize(std::string_view 
serialized) {
+arrow::Status FlightEndpoint::Deserialize(std::string_view serialized,
+                                          FlightEndpoint* out) {
   return DeserializeProtoString<pb::FlightEndpoint, 
FlightEndpoint>("FlightEndpoint",
-                                                                    
serialized);
+                                                                    
serialized, out);
 }
 
 std::string RenewFlightEndpointRequest::ToString() const {
@@ -800,16 +795,16 @@ bool RenewFlightEndpointRequest::Equals(const 
RenewFlightEndpointRequest& other)
   return endpoint == other.endpoint;
 }
 
-arrow::Result<std::string> RenewFlightEndpointRequest::SerializeToString() 
const {
+arrow::Status RenewFlightEndpointRequest::SerializeToString(std::string* out) 
const {
   return SerializeToProtoString<pb::RenewFlightEndpointRequest>(
-      "RenewFlightEndpointRequest", *this);
+      "RenewFlightEndpointRequest", *this, out);
 }
 
-arrow::Result<RenewFlightEndpointRequest> 
RenewFlightEndpointRequest::Deserialize(
-    std::string_view serialized) {
+arrow::Status RenewFlightEndpointRequest::Deserialize(std::string_view 
serialized,
+                                                      
RenewFlightEndpointRequest* out) {
   return DeserializeProtoString<pb::RenewFlightEndpointRequest,
                                 
RenewFlightEndpointRequest>("RenewFlightEndpointRequest",
-                                                            serialized);
+                                                            serialized, out);
 }
 
 std::string ActionType::ToString() const {
@@ -847,12 +842,13 @@ bool ActionType::Equals(const ActionType& other) const {
   return type == other.type && description == other.description;
 }
 
-arrow::Result<std::string> ActionType::SerializeToString() const {
-  return SerializeToProtoString<pb::ActionType>("ActionType", *this);
+arrow::Status ActionType::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::ActionType>("ActionType", *this, out);
 }
 
-arrow::Result<ActionType> ActionType::Deserialize(std::string_view serialized) 
{
-  return DeserializeProtoString<pb::ActionType, ActionType>("ActionType", 
serialized);
+arrow::Status ActionType::Deserialize(std::string_view serialized, ActionType* 
out) {
+  return DeserializeProtoString<pb::ActionType, ActionType>("ActionType", 
serialized,
+                                                            out);
 }
 
 std::string Criteria::ToString() const {
@@ -863,12 +859,12 @@ bool Criteria::Equals(const Criteria& other) const {
   return expression == other.expression;
 }
 
-arrow::Result<std::string> Criteria::SerializeToString() const {
-  return SerializeToProtoString<pb::Criteria>("Criteria", *this);
+arrow::Status Criteria::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::Criteria>("Criteria", *this, out);
 }
 
-arrow::Result<Criteria> Criteria::Deserialize(std::string_view serialized) {
-  return DeserializeProtoString<pb::Criteria, Criteria>("Criteria", 
serialized);
+arrow::Status Criteria::Deserialize(std::string_view serialized, Criteria* 
out) {
+  return DeserializeProtoString<pb::Criteria, Criteria>("Criteria", 
serialized, out);
 }
 
 std::string Action::ToString() const {
@@ -889,12 +885,12 @@ bool Action::Equals(const Action& other) const {
          ((body == other.body) || (body && other.body && 
body->Equals(*other.body)));
 }
 
-arrow::Result<std::string> Action::SerializeToString() const {
-  return SerializeToProtoString<pb::Action>("Action", *this);
+arrow::Status Action::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::Action>("Action", *this, out);
 }
 
-arrow::Result<Action> Action::Deserialize(std::string_view serialized) {
-  return DeserializeProtoString<pb::Action, Action>("Action", serialized);
+arrow::Status Action::Deserialize(std::string_view serialized, Action* out) {
+  return DeserializeProtoString<pb::Action, Action>("Action", serialized, out);
 }
 
 std::string Result::ToString() const {
@@ -912,12 +908,12 @@ bool Result::Equals(const Result& other) const {
   return (body == other.body) || (body && other.body && 
body->Equals(*other.body));
 }
 
-arrow::Result<std::string> Result::SerializeToString() const {
-  return SerializeToProtoString<pb::Result>("Result", *this);
+arrow::Status Result::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::Result>("Result", *this, out);
 }
 
-arrow::Result<Result> Result::Deserialize(std::string_view serialized) {
-  return DeserializeProtoString<pb::Result, Result>("Result", serialized);
+arrow::Status Result::Deserialize(std::string_view serialized, Result* out) {
+  return DeserializeProtoString<pb::Result, Result>("Result", serialized, out);
 }
 
 std::string CancelFlightInfoResult::ToString() const {
@@ -930,15 +926,15 @@ bool CancelFlightInfoResult::Equals(const 
CancelFlightInfoResult& other) const {
   return status == other.status;
 }
 
-arrow::Result<std::string> CancelFlightInfoResult::SerializeToString() const {
+arrow::Status CancelFlightInfoResult::SerializeToString(std::string* out) 
const {
   return 
SerializeToProtoString<pb::CancelFlightInfoResult>("CancelFlightInfoResult",
-                                                            *this);
+                                                            *this, out);
 }
 
-arrow::Result<CancelFlightInfoResult> CancelFlightInfoResult::Deserialize(
-    std::string_view serialized) {
+arrow::Status CancelFlightInfoResult::Deserialize(std::string_view serialized,
+                                                  CancelFlightInfoResult* out) 
{
   return DeserializeProtoString<pb::CancelFlightInfoResult, 
CancelFlightInfoResult>(
-      "CancelFlightInfoResult", serialized);
+      "CancelFlightInfoResult", serialized, out);
 }
 
 std::ostream& operator<<(std::ostream& os, CancelStatus status) {
@@ -1055,12 +1051,12 @@ bool BasicAuth::Equals(const BasicAuth& other) const {
   return (username == other.username) && (password == other.password);
 }
 
-arrow::Result<BasicAuth> BasicAuth::Deserialize(std::string_view serialized) {
-  return DeserializeProtoString<pb::BasicAuth, BasicAuth>("BasicAuth", 
serialized);
+arrow::Status BasicAuth::Deserialize(std::string_view serialized, BasicAuth* 
out) {
+  return DeserializeProtoString<pb::BasicAuth, BasicAuth>("BasicAuth", 
serialized, out);
 }
 
-arrow::Result<std::string> BasicAuth::SerializeToString() const {
-  return SerializeToProtoString<pb::BasicAuth>("BasicAuth", *this);
+arrow::Status BasicAuth::SerializeToString(std::string* out) const {
+  return SerializeToProtoString<pb::BasicAuth>("BasicAuth", *this, out);
 }
 
 //------------------------------------------------------------
diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h
index cdf03f2104..8061df4dde 100644
--- a/cpp/src/arrow/flight/types.h
+++ b/cpp/src/arrow/flight/types.h
@@ -31,6 +31,7 @@
 #include <variant>
 #include <vector>
 
+#include "arrow/buffer.h"
 #include "arrow/flight/type_fwd.h"
 #include "arrow/flight/visibility.h"
 #include "arrow/ipc/options.h"
@@ -159,29 +160,88 @@ struct ARROW_FLIGHT_EXPORT CertKeyPair {
   std::string pem_key;
 };
 
+namespace internal {
+
+template <typename T>
+struct remove_unique_ptr {
+  using type = T;
+};
+
+template <typename T>
+struct remove_unique_ptr<std::unique_ptr<T>> {
+  using type = T;
+};
+
+// Base CRTP type
+template <class T>
+struct BaseType {
+ protected:
+  using SuperT = BaseType<T>;
+  using SelfT = typename remove_unique_ptr<T>::type;
+
+  const SelfT& self() const { return static_cast<const SelfT&>(*this); }
+  SelfT& self() { return static_cast<SelfT&>(*this); }
+
+ public:
+  BaseType() = default;
+
+  friend bool operator==(const SelfT& left, const SelfT& right) {
+    return left.Equals(right);
+  }
+  friend bool operator!=(const SelfT& left, const SelfT& right) {
+    return !left.Equals(right);
+  }
+
+  /// \brief Serialize this message to its wire-format representation.
+  inline arrow::Result<std::string> SerializeToString() const {
+    std::string out;
+    ARROW_RETURN_NOT_OK(self().SelfT::SerializeToString(&out));
+    return out;
+  }
+
+  inline static arrow::Result<T> Deserialize(std::string_view serialized) {
+    T out;
+    ARROW_RETURN_NOT_OK(SelfT::Deserialize(serialized, &out));
+    return out;
+  }
+
+  inline arrow::Result<std::shared_ptr<Buffer>> SerializeToBuffer() const {
+    std::string out;
+    ARROW_RETURN_NOT_OK(self().SelfT::SerializeToString(&out));
+    return Buffer::FromString(std::move(out));
+  }
+};
+
+}  // namespace internal
+
 /// \brief A type of action that can be performed with the DoAction RPC.
-struct ARROW_FLIGHT_EXPORT ActionType {
+struct ARROW_FLIGHT_EXPORT ActionType : public internal::BaseType<ActionType> {
   /// \brief The name of the action.
   std::string type;
 
   /// \brief A human-readable description of the action.
   std::string description;
 
+  ActionType() = default;
+
+  ActionType(std::string type, std::string description)
+      : type(std::move(type)), description(std::move(description)) {}
+
   std::string ToString() const;
   bool Equals(const ActionType& other) const;
 
-  friend bool operator==(const ActionType& left, const ActionType& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const ActionType& left, const ActionType& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<ActionType> Deserialize(std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, ActionType* 
out);
 
   static const ActionType kCancelFlightInfo;
   static const ActionType kRenewFlightEndpoint;
@@ -191,71 +251,83 @@ struct ARROW_FLIGHT_EXPORT ActionType {
 };
 
 /// \brief Opaque selection criteria for ListFlights RPC
-struct ARROW_FLIGHT_EXPORT Criteria {
+struct ARROW_FLIGHT_EXPORT Criteria : public internal::BaseType<Criteria> {
   /// Opaque criteria expression, dependent on server implementation
   std::string expression;
 
+  Criteria() = default;
+  Criteria(std::string expression)  // NOLINT runtime/explicit
+      : expression(std::move(expression)) {}
+
   std::string ToString() const;
   bool Equals(const Criteria& other) const;
 
-  friend bool operator==(const Criteria& left, const Criteria& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const Criteria& left, const Criteria& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<Criteria> Deserialize(std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, Criteria* out);
 };
 
 /// \brief An action to perform with the DoAction RPC
-struct ARROW_FLIGHT_EXPORT Action {
+struct ARROW_FLIGHT_EXPORT Action : public internal::BaseType<Action> {
   /// The action type
   std::string type;
 
   /// The action content as a Buffer
   std::shared_ptr<Buffer> body;
 
+  Action() = default;
+  Action(std::string type, std::shared_ptr<Buffer> body)
+      : type(std::move(type)), body(std::move(body)) {}
+
   std::string ToString() const;
   bool Equals(const Action& other) const;
 
-  friend bool operator==(const Action& left, const Action& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const Action& left, const Action& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<Action> Deserialize(std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, Action* out);
 };
 
 /// \brief Opaque result returned after executing an action
-struct ARROW_FLIGHT_EXPORT Result {
+struct ARROW_FLIGHT_EXPORT Result : public internal::BaseType<Result> {
   std::shared_ptr<Buffer> body;
 
+  Result() = default;
+  Result(std::shared_ptr<Buffer> body)  // NOLINT runtime/explicit
+      : body(std::move(body)) {}
+
   std::string ToString() const;
   bool Equals(const Result& other) const;
 
-  friend bool operator==(const Result& left, const Result& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const Result& left, const Result& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<Result> Deserialize(std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, Result* out);
 };
 
 enum class CancelStatus {
@@ -275,54 +347,64 @@ enum class CancelStatus {
 };
 
 /// \brief The result of the CancelFlightInfo action.
-struct ARROW_FLIGHT_EXPORT CancelFlightInfoResult {
-  CancelStatus status;
+struct ARROW_FLIGHT_EXPORT CancelFlightInfoResult
+    : public internal::BaseType<CancelFlightInfoResult> {
+  CancelStatus status = CancelStatus::kUnspecified;
+
+  CancelFlightInfoResult() = default;
+  CancelFlightInfoResult(CancelStatus status)  // NOLINT runtime/explicit
+      : status(status) {}
 
   std::string ToString() const;
   bool Equals(const CancelFlightInfoResult& other) const;
 
-  friend bool operator==(const CancelFlightInfoResult& left,
-                         const CancelFlightInfoResult& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const CancelFlightInfoResult& left,
-                         const CancelFlightInfoResult& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<CancelFlightInfoResult> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   CancelFlightInfoResult* out);
 };
 
 ARROW_FLIGHT_EXPORT
 std::ostream& operator<<(std::ostream& os, CancelStatus status);
 
 /// \brief message for simple auth
-struct ARROW_FLIGHT_EXPORT BasicAuth {
+struct ARROW_FLIGHT_EXPORT BasicAuth : public internal::BaseType<BasicAuth> {
   std::string username;
   std::string password;
 
+  BasicAuth() = default;
+  BasicAuth(std::string username, std::string password)
+      : username(std::move(username)), password(std::move(password)) {}
+
   std::string ToString() const;
   bool Equals(const BasicAuth& other) const;
 
-  friend bool operator==(const BasicAuth& left, const BasicAuth& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const BasicAuth& left, const BasicAuth& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
-  /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<BasicAuth> Deserialize(std::string_view serialized);
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
+
+  /// \brief Deserialize this message from its wire-format representation.
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, BasicAuth* 
out);
 };
 
 /// \brief A request to retrieve or generate a dataset
-struct ARROW_FLIGHT_EXPORT FlightDescriptor {
+struct ARROW_FLIGHT_EXPORT FlightDescriptor
+    : public internal::BaseType<FlightDescriptor> {
   enum DescriptorType {
     UNKNOWN = 0,  /// Unused
     PATH = 1,     /// Named path identifying a dataset
@@ -330,7 +412,7 @@ struct ARROW_FLIGHT_EXPORT FlightDescriptor {
   };
 
   /// The descriptor type
-  DescriptorType type;
+  DescriptorType type = UNKNOWN;
 
   /// Opaque value used to express a command. Should only be defined when type
   /// is CMD
@@ -340,22 +422,34 @@ struct ARROW_FLIGHT_EXPORT FlightDescriptor {
   /// when type is PATH
   std::vector<std::string> path;
 
+  FlightDescriptor() = default;
+
+  FlightDescriptor(DescriptorType type, std::string cmd, 
std::vector<std::string> path)
+      : type(type), cmd(std::move(cmd)), path(std::move(path)) {}
+
   bool Equals(const FlightDescriptor& other) const;
 
   /// \brief Get a human-readable form of this descriptor.
   std::string ToString() const;
 
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
+
   /// \brief Get the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Parse the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  static arrow::Result<FlightDescriptor> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, 
FlightDescriptor* out);
 
   // Convenience factory functions
 
@@ -366,41 +460,38 @@ struct ARROW_FLIGHT_EXPORT FlightDescriptor {
   static FlightDescriptor Path(const std::vector<std::string>& p) {
     return FlightDescriptor{PATH, "", p};
   }
-
-  friend bool operator==(const FlightDescriptor& left, const FlightDescriptor& 
right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const FlightDescriptor& left, const FlightDescriptor& 
right) {
-    return !(left == right);
-  }
 };
 
 /// \brief Data structure providing an opaque identifier or credential to use
 /// when requesting a data stream with the DoGet RPC
-struct ARROW_FLIGHT_EXPORT Ticket {
+struct ARROW_FLIGHT_EXPORT Ticket : public internal::BaseType<Ticket> {
   std::string ticket;
 
+  Ticket() = default;
+  Ticket(std::string ticket)  // NOLINT runtime/explicit
+      : ticket(std::move(ticket)) {}
+
   std::string ToString() const;
   bool Equals(const Ticket& other) const;
 
-  friend bool operator==(const Ticket& left, const Ticket& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const Ticket& left, const Ticket& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Get the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Parse the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  static arrow::Result<Ticket> Deserialize(std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, Ticket* out);
 };
 
 class FlightClient;
@@ -416,7 +507,7 @@ ARROW_FLIGHT_EXPORT
 extern const char* kSchemeGrpcTls;
 
 /// \brief A host location (a URI)
-struct ARROW_FLIGHT_EXPORT Location {
+struct ARROW_FLIGHT_EXPORT Location : public internal::BaseType<Location> {
  public:
   /// \brief Initialize a blank location.
   Location();
@@ -464,13 +555,6 @@ struct ARROW_FLIGHT_EXPORT Location {
 
   bool Equals(const Location& other) const;
 
-  friend bool operator==(const Location& left, const Location& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const Location& left, const Location& right) {
-    return !(left == right);
-  }
-
  private:
   friend class FlightClient;
   friend class FlightServerBase;
@@ -479,7 +563,7 @@ struct ARROW_FLIGHT_EXPORT Location {
 
 /// \brief A flight ticket and list of locations where the ticket can be
 /// redeemed
-struct ARROW_FLIGHT_EXPORT FlightEndpoint {
+struct ARROW_FLIGHT_EXPORT FlightEndpoint : public 
internal::BaseType<FlightEndpoint> {
   /// Opaque ticket identify; use with DoGet RPC
   Ticket ticket;
 
@@ -496,45 +580,56 @@ struct ARROW_FLIGHT_EXPORT FlightEndpoint {
   /// Opaque Application-defined metadata
   std::string app_metadata;
 
+  FlightEndpoint() = default;
+  FlightEndpoint(Ticket ticket, std::vector<Location> locations,
+                 std::optional<Timestamp> expiration_time, std::string 
app_metadata)
+      : ticket(std::move(ticket)),
+        locations(std::move(locations)),
+        expiration_time(expiration_time),
+        app_metadata(std::move(app_metadata)) {}
+
   std::string ToString() const;
   bool Equals(const FlightEndpoint& other) const;
 
-  friend bool operator==(const FlightEndpoint& left, const FlightEndpoint& 
right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const FlightEndpoint& left, const FlightEndpoint& 
right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<FlightEndpoint> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, 
FlightEndpoint* out);
 };
 
 /// \brief The request of the RenewFlightEndpoint action.
-struct ARROW_FLIGHT_EXPORT RenewFlightEndpointRequest {
+struct ARROW_FLIGHT_EXPORT RenewFlightEndpointRequest
+    : public internal::BaseType<RenewFlightEndpointRequest> {
   FlightEndpoint endpoint;
 
+  RenewFlightEndpointRequest() = default;
+  explicit RenewFlightEndpointRequest(FlightEndpoint endpoint)
+      : endpoint(std::move(endpoint)) {}
+
   std::string ToString() const;
   bool Equals(const RenewFlightEndpointRequest& other) const;
 
-  friend bool operator==(const RenewFlightEndpointRequest& left,
-                         const RenewFlightEndpointRequest& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const RenewFlightEndpointRequest& left,
-                         const RenewFlightEndpointRequest& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<RenewFlightEndpointRequest> Deserialize(
-      std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   RenewFlightEndpointRequest* out);
 };
 
 /// \brief Staging data structure for messages about to be put on the wire
@@ -545,12 +640,19 @@ struct ARROW_FLIGHT_EXPORT FlightPayload {
   std::shared_ptr<Buffer> app_metadata;
   ipc::IpcPayload ipc_message;
 
+  FlightPayload() = default;
+  FlightPayload(std::shared_ptr<Buffer> descriptor, std::shared_ptr<Buffer> 
app_metadata,
+                ipc::IpcPayload ipc_message)
+      : descriptor(std::move(descriptor)),
+        app_metadata(std::move(app_metadata)),
+        ipc_message(std::move(ipc_message)) {}
+
   /// \brief Check that the payload can be written to the wire.
   Status Validate() const;
 };
 
 /// \brief Schema result returned after a schema request RPC
-struct ARROW_FLIGHT_EXPORT SchemaResult {
+struct ARROW_FLIGHT_EXPORT SchemaResult : public 
internal::BaseType<SchemaResult> {
  public:
   SchemaResult() = default;
   explicit SchemaResult(std::string schema) : raw_schema_(std::move(schema)) {}
@@ -570,18 +672,18 @@ struct ARROW_FLIGHT_EXPORT SchemaResult {
   std::string ToString() const;
   bool Equals(const SchemaResult& other) const;
 
-  friend bool operator==(const SchemaResult& left, const SchemaResult& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const SchemaResult& left, const SchemaResult& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<SchemaResult> Deserialize(std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, SchemaResult* 
out);
 
  private:
   std::string raw_schema_;
@@ -589,7 +691,8 @@ struct ARROW_FLIGHT_EXPORT SchemaResult {
 
 /// \brief The access coordinates for retrieval of a dataset, returned by
 /// GetFlightInfo
-class ARROW_FLIGHT_EXPORT FlightInfo {
+class ARROW_FLIGHT_EXPORT FlightInfo
+    : public internal::BaseType<std::unique_ptr<FlightInfo>> {
  public:
   struct Data {
     std::string schema;
@@ -641,18 +744,25 @@ class ARROW_FLIGHT_EXPORT FlightInfo {
   /// Application-defined opaque metadata
   const std::string& app_metadata() const { return data_.app_metadata; }
 
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
+
   /// \brief Get the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Parse the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  static arrow::Result<std::unique_ptr<FlightInfo>> Deserialize(
-      std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   std::unique_ptr<FlightInfo>* out);
 
   std::string ToString() const;
 
@@ -661,13 +771,6 @@ class ARROW_FLIGHT_EXPORT FlightInfo {
   /// the schemas.
   bool Equals(const FlightInfo& other) const;
 
-  friend bool operator==(const FlightInfo& left, const FlightInfo& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const FlightInfo& left, const FlightInfo& right) {
-    return !(left == right);
-  }
-
  private:
   Data data_;
   mutable std::shared_ptr<Schema> schema_;
@@ -675,7 +778,8 @@ class ARROW_FLIGHT_EXPORT FlightInfo {
 };
 
 /// \brief The information to process a long-running query.
-class ARROW_FLIGHT_EXPORT PollInfo {
+class ARROW_FLIGHT_EXPORT PollInfo
+    : public internal::BaseType<std::unique_ptr<PollInfo>> {
  public:
   /// The currently available results so far.
   std::unique_ptr<FlightInfo> info = NULLPTR;
@@ -696,22 +800,19 @@ class ARROW_FLIGHT_EXPORT PollInfo {
         progress(std::nullopt),
         expiration_time(std::nullopt) {}
 
-  explicit PollInfo(std::unique_ptr<FlightInfo> info,
-                    std::optional<FlightDescriptor> descriptor,
-                    std::optional<double> progress,
-                    std::optional<Timestamp> expiration_time)
+  PollInfo(std::unique_ptr<FlightInfo> info, std::optional<FlightDescriptor> 
descriptor,
+           std::optional<double> progress, std::optional<Timestamp> 
expiration_time)
       : info(std::move(info)),
         descriptor(std::move(descriptor)),
         progress(progress),
         expiration_time(expiration_time) {}
 
-  // Must not be explicit; to declare one we must declare all ("rule of five")
-  PollInfo(const PollInfo& other)  // NOLINT(runtime/explicit)
+  PollInfo(const PollInfo& other)
       : info(other.info ? std::make_unique<FlightInfo>(*other.info) : NULLPTR),
         descriptor(other.descriptor),
         progress(other.progress),
         expiration_time(other.expiration_time) {}
-  PollInfo(PollInfo&& other) noexcept = default;  // NOLINT(runtime/explicit)
+  PollInfo(PollInfo&& other) noexcept = default;
   ~PollInfo() = default;
   PollInfo& operator=(const PollInfo& other) {
     info = other.info ? std::make_unique<FlightInfo>(*other.info) : NULLPTR;
@@ -722,18 +823,25 @@ class ARROW_FLIGHT_EXPORT PollInfo {
   }
   PollInfo& operator=(PollInfo&& other) = default;
 
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
+
   /// \brief Get the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Parse the wire-format representation of this type.
   ///
   /// Useful when interoperating with non-Flight systems (e.g. REST
   /// services) that may want to return Flight types.
-  static arrow::Result<std::unique_ptr<PollInfo>> Deserialize(
-      std::string_view serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   std::unique_ptr<PollInfo>* out);
 
   std::string ToString() const;
 
@@ -741,36 +849,33 @@ class ARROW_FLIGHT_EXPORT PollInfo {
   /// serialized schema representations, NOT the logical equality of
   /// the schemas.
   bool Equals(const PollInfo& other) const;
-
-  friend bool operator==(const PollInfo& left, const PollInfo& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const PollInfo& left, const PollInfo& right) {
-    return !(left == right);
-  }
 };
 
 /// \brief The request of the CancelFlightInfoRequest action.
-struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest {
+struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest
+    : public internal::BaseType<CancelFlightInfoRequest> {
   std::unique_ptr<FlightInfo> info;
 
+  CancelFlightInfoRequest() = default;
+  CancelFlightInfoRequest(std::unique_ptr<FlightInfo> info)  // NOLINT 
runtime/explicit
+      : info(std::move(info)) {}
+
   std::string ToString() const;
   bool Equals(const CancelFlightInfoRequest& other) const;
 
-  friend bool operator==(const CancelFlightInfoRequest& left,
-                         const CancelFlightInfoRequest& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const CancelFlightInfoRequest& left,
-                         const CancelFlightInfoRequest& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<CancelFlightInfoRequest> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   CancelFlightInfoRequest* out);
 };
 
 /// \brief Variant supporting all possible value types for 
{Set,Get}SessionOptions
@@ -821,30 +926,36 @@ std::string ToString(const CloseSessionStatus& status);
 std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& status);
 
 /// \brief A request to set a set of session options by name/value.
-struct ARROW_FLIGHT_EXPORT SetSessionOptionsRequest {
+struct ARROW_FLIGHT_EXPORT SetSessionOptionsRequest
+    : public internal::BaseType<SetSessionOptionsRequest> {
   std::map<std::string, SessionOptionValue> session_options;
 
+  SetSessionOptionsRequest() = default;
+  explicit SetSessionOptionsRequest(
+      std::map<std::string, SessionOptionValue> session_options)
+      : session_options(std::move(session_options)) {}
+
   std::string ToString() const;
   bool Equals(const SetSessionOptionsRequest& other) const;
 
-  friend bool operator==(const SetSessionOptionsRequest& left,
-                         const SetSessionOptionsRequest& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const SetSessionOptionsRequest& left,
-                         const SetSessionOptionsRequest& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<SetSessionOptionsRequest> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   SetSessionOptionsRequest* out);
 };
 
 /// \brief The result(s) of setting session option(s).
-struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult {
+struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult
+    : public internal::BaseType<SetSessionOptionsResult> {
   struct Error {
     SetSessionOptionErrorValue value;
 
@@ -859,111 +970,125 @@ struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult {
 
   std::map<std::string, Error> errors;
 
+  SetSessionOptionsResult() = default;
+  SetSessionOptionsResult(std::map<std::string, Error> errors)  // NOLINT 
runtime/explicit
+      : errors(std::move(errors)) {}
+
   std::string ToString() const;
   bool Equals(const SetSessionOptionsResult& other) const;
 
-  friend bool operator==(const SetSessionOptionsResult& left,
-                         const SetSessionOptionsResult& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const SetSessionOptionsResult& left,
-                         const SetSessionOptionsResult& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<SetSessionOptionsResult> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   SetSessionOptionsResult* out);
 };
 
 /// \brief A request to get current session options.
-struct ARROW_FLIGHT_EXPORT GetSessionOptionsRequest {
+struct ARROW_FLIGHT_EXPORT GetSessionOptionsRequest
+    : public internal::BaseType<GetSessionOptionsRequest> {
+  GetSessionOptionsRequest() = default;
+
   std::string ToString() const;
   bool Equals(const GetSessionOptionsRequest& other) const;
 
-  friend bool operator==(const GetSessionOptionsRequest& left,
-                         const GetSessionOptionsRequest& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const GetSessionOptionsRequest& left,
-                         const GetSessionOptionsRequest& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<GetSessionOptionsRequest> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   GetSessionOptionsRequest* out);
 };
 
 /// \brief The current session options.
-struct ARROW_FLIGHT_EXPORT GetSessionOptionsResult {
+struct ARROW_FLIGHT_EXPORT GetSessionOptionsResult
+    : public internal::BaseType<GetSessionOptionsResult> {
   std::map<std::string, SessionOptionValue> session_options;
 
+  GetSessionOptionsResult() = default;
+  GetSessionOptionsResult(  // NOLINT runtime/explicit
+      std::map<std::string, SessionOptionValue> session_options)
+      : session_options(std::move(session_options)) {}
+
   std::string ToString() const;
   bool Equals(const GetSessionOptionsResult& other) const;
 
-  friend bool operator==(const GetSessionOptionsResult& left,
-                         const GetSessionOptionsResult& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const GetSessionOptionsResult& left,
-                         const GetSessionOptionsResult& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<GetSessionOptionsResult> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized,
+                                   GetSessionOptionsResult* out);
 };
 
 /// \brief A request to close the open client session.
-struct ARROW_FLIGHT_EXPORT CloseSessionRequest {
+struct ARROW_FLIGHT_EXPORT CloseSessionRequest
+    : public internal::BaseType<CloseSessionRequest> {
+  CloseSessionRequest() = default;
+
   std::string ToString() const;
   bool Equals(const CloseSessionRequest& other) const;
 
-  friend bool operator==(const CloseSessionRequest& left,
-                         const CloseSessionRequest& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const CloseSessionRequest& left,
-                         const CloseSessionRequest& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<CloseSessionRequest> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, 
CloseSessionRequest* out);
 };
 
 /// \brief The result of attempting to close the client session.
-struct ARROW_FLIGHT_EXPORT CloseSessionResult {
+struct ARROW_FLIGHT_EXPORT CloseSessionResult
+    : public internal::BaseType<CloseSessionResult> {
   CloseSessionStatus status;
 
+  CloseSessionResult() = default;
+  CloseSessionResult(CloseSessionStatus status)  // NOLINT runtime/explicit
+      : status(status) {}
+
   std::string ToString() const;
   bool Equals(const CloseSessionResult& other) const;
 
-  friend bool operator==(const CloseSessionResult& left,
-                         const CloseSessionResult& right) {
-    return left.Equals(right);
-  }
-  friend bool operator!=(const CloseSessionResult& left,
-                         const CloseSessionResult& right) {
-    return !(left == right);
-  }
+  using SuperT::Deserialize;
+  using SuperT::SerializeToString;
 
   /// \brief Serialize this message to its wire-format representation.
-  arrow::Result<std::string> SerializeToString() const;
+  ///
+  /// Use `SerializeToString()` if you want a Result-returning version.
+  arrow::Status SerializeToString(std::string* out) const;
 
   /// \brief Deserialize this message from its wire-format representation.
-  static arrow::Result<CloseSessionResult> Deserialize(std::string_view 
serialized);
+  ///
+  /// Use `Deserialize(serialized)` if you want a Result-returning version.
+  static arrow::Status Deserialize(std::string_view serialized, 
CloseSessionResult* out);
 };
 
 /// \brief An iterator to FlightInfo instances returned by ListFlights.

Reply via email to