3 * Copyright 2015 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #ifndef GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
20 #define GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
22 #include <type_traits>
24 #include <grpc/impl/codegen/byte_buffer_reader.h>
25 #include <grpc/impl/codegen/grpc_types.h>
26 #include <grpc/impl/codegen/slice.h>
27 #include <grpcpp/impl/codegen/byte_buffer.h>
28 #include <grpcpp/impl/codegen/config_protobuf.h>
29 #include <grpcpp/impl/codegen/core_codegen_interface.h>
30 #include <grpcpp/impl/codegen/proto_buffer_reader.h>
31 #include <grpcpp/impl/codegen/proto_buffer_writer.h>
32 #include <grpcpp/impl/codegen/serialization_traits.h>
33 #include <grpcpp/impl/codegen/slice.h>
34 #include <grpcpp/impl/codegen/status.h>
36 /// This header provides serialization and deserialization between gRPC
37 /// messages serialized using protobuf and the C++ objects they represent.
41 extern CoreCodegenInterface* g_core_codegen_interface;
43 // ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream.
44 template <class ProtoBufferWriter, class T>
45 Status GenericSerialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
47 static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream,
48 ProtoBufferWriter>::value,
49 "ProtoBufferWriter must be a subclass of "
50 "::protobuf::io::ZeroCopyOutputStream");
52 int byte_size = msg.ByteSize();
53 if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) {
54 Slice slice(byte_size);
55 // We serialize directly into the allocated slices memory
56 GPR_CODEGEN_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray(
57 const_cast<uint8_t*>(slice.begin())));
58 ByteBuffer tmp(&slice, 1);
61 return g_core_codegen_interface->ok();
63 ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size);
64 return msg.SerializeToZeroCopyStream(&writer)
65 ? g_core_codegen_interface->ok()
66 : Status(StatusCode::INTERNAL, "Failed to serialize message");
69 // BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream.
70 template <class ProtoBufferReader, class T>
71 Status GenericDeserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
72 static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream,
73 ProtoBufferReader>::value,
74 "ProtoBufferReader must be a subclass of "
75 "::protobuf::io::ZeroCopyInputStream");
76 if (buffer == nullptr) {
77 return Status(StatusCode::INTERNAL, "No payload");
79 Status result = g_core_codegen_interface->ok();
81 ProtoBufferReader reader(buffer);
82 if (!reader.status().ok()) {
83 return reader.status();
85 ::grpc::protobuf::io::CodedInputStream decoder(&reader);
86 decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
87 if (!msg->ParseFromCodedStream(&decoder)) {
88 result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
90 if (!decoder.ConsumedEntireMessage()) {
91 result = Status(StatusCode::INTERNAL, "Did not read entire message");
98 // this is needed so the following class does not conflict with protobuf
99 // serializers that utilize internal-only tools.
100 #ifdef GRPC_OPEN_SOURCE_PROTO
101 // This class provides a protobuf serializer. It translates between protobuf
102 // objects and grpc_byte_buffers. More information about SerializationTraits can
103 // be found in include/grpcpp/impl/codegen/serialization_traits.h.
105 class SerializationTraits<T, typename std::enable_if<std::is_base_of<
106 grpc::protobuf::Message, T>::value>::type> {
108 static Status Serialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
110 return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer);
113 static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
114 return GenericDeserialize<ProtoBufferReader, T>(buffer, msg);
121 #endif // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H