1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
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
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 */
18
19 #ifndef GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
20 #define GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
21
22 #include <type_traits>
23
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>
35
36 /// This header provides serialization and deserialization between gRPC
37 /// messages serialized using protobuf and the C++ objects they represent.
38
39 namespace grpc {
40
41 extern CoreCodegenInterface* g_core_codegen_interface;
42
43 // ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream.
44 template <class ProtoBufferWriter, class T>
GenericSerialize(const grpc::protobuf::Message & msg,ByteBuffer * bb,bool * own_buffer)45 Status GenericSerialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
46 bool* own_buffer) {
47 static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream,
48 ProtoBufferWriter>::value,
49 "ProtoBufferWriter must be a subclass of "
50 "::protobuf::io::ZeroCopyOutputStream");
51 *own_buffer = true;
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);
59 bb->Swap(&tmp);
60
61 return g_core_codegen_interface->ok();
62 }
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");
67 }
68
69 // BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream.
70 template <class ProtoBufferReader, class T>
GenericDeserialize(ByteBuffer * buffer,grpc::protobuf::Message * msg)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");
78 }
79 Status result = g_core_codegen_interface->ok();
80 {
81 ProtoBufferReader reader(buffer);
82 if (!reader.status().ok()) {
83 return reader.status();
84 }
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());
89 }
90 if (!decoder.ConsumedEntireMessage()) {
91 result = Status(StatusCode::INTERNAL, "Did not read entire message");
92 }
93 }
94 buffer->Clear();
95 return result;
96 }
97
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.
104 template <class T>
105 class SerializationTraits<T, typename std::enable_if<std::is_base_of<
106 grpc::protobuf::Message, T>::value>::type> {
107 public:
Serialize(const grpc::protobuf::Message & msg,ByteBuffer * bb,bool * own_buffer)108 static Status Serialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
109 bool* own_buffer) {
110 return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer);
111 }
112
Deserialize(ByteBuffer * buffer,grpc::protobuf::Message * msg)113 static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
114 return GenericDeserialize<ProtoBufferReader, T>(buffer, msg);
115 }
116 };
117 #endif
118
119 } // namespace grpc
120
121 #endif // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
122