• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPCPP_IMPL_GENERIC_SERIALIZE_H
16 #define GRPCPP_IMPL_GENERIC_SERIALIZE_H
17 
18 #include <grpc/byte_buffer_reader.h>
19 #include <grpc/impl/grpc_types.h>
20 #include <grpc/slice.h>
21 #include <grpcpp/impl/codegen/config_protobuf.h>
22 #include <grpcpp/impl/serialization_traits.h>
23 #include <grpcpp/support/byte_buffer.h>
24 #include <grpcpp/support/proto_buffer_reader.h>
25 #include <grpcpp/support/proto_buffer_writer.h>
26 #include <grpcpp/support/slice.h>
27 #include <grpcpp/support/status.h>
28 
29 #include <type_traits>
30 
31 #include "absl/log/absl_check.h"
32 
33 /// This header provides serialization and deserialization between gRPC
34 /// messages serialized using protobuf and the C++ objects they represent.
35 
36 namespace grpc {
37 
38 // ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream.
39 template <class ProtoBufferWriter, class T>
GenericSerialize(const grpc::protobuf::MessageLite & msg,ByteBuffer * bb,bool * own_buffer)40 Status GenericSerialize(const grpc::protobuf::MessageLite& msg, ByteBuffer* bb,
41                         bool* own_buffer) {
42   static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream,
43                                 ProtoBufferWriter>::value,
44                 "ProtoBufferWriter must be a subclass of "
45                 "::protobuf::io::ZeroCopyOutputStream");
46   *own_buffer = true;
47   int byte_size = static_cast<int>(msg.ByteSizeLong());
48   if (static_cast<size_t>(byte_size) <= GRPC_SLICE_INLINED_SIZE) {
49     Slice slice(byte_size);
50     // We serialize directly into the allocated slices memory
51     ABSL_CHECK(slice.end() == msg.SerializeWithCachedSizesToArray(
52                                   const_cast<uint8_t*>(slice.begin())));
53     ByteBuffer tmp(&slice, 1);
54     bb->Swap(&tmp);
55 
56     return grpc::Status::OK;
57   }
58   ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size);
59   protobuf::io::CodedOutputStream cs(&writer);
60   msg.SerializeWithCachedSizes(&cs);
61   return !cs.HadError()
62              ? grpc::Status::OK
63              : Status(StatusCode::INTERNAL, "Failed to serialize message");
64 }
65 
66 // BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream.
67 template <class ProtoBufferReader, class T>
GenericDeserialize(ByteBuffer * buffer,grpc::protobuf::MessageLite * msg)68 Status GenericDeserialize(ByteBuffer* buffer,
69                           grpc::protobuf::MessageLite* msg) {
70   static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream,
71                                 ProtoBufferReader>::value,
72                 "ProtoBufferReader must be a subclass of "
73                 "::protobuf::io::ZeroCopyInputStream");
74   if (buffer == nullptr) {
75     return Status(StatusCode::INTERNAL, "No payload");
76   }
77   Status result = grpc::Status::OK;
78   {
79     ProtoBufferReader reader(buffer);
80     if (!reader.status().ok()) {
81       return reader.status();
82     }
83     if (!msg->ParseFromZeroCopyStream(&reader)) {
84       result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
85     }
86   }
87   buffer->Clear();
88   return result;
89 }
90 
91 }  // namespace grpc
92 
93 #endif  // GRPCPP_IMPL_GENERIC_SERIALIZE_H
94