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::MessageLite & msg,ByteBuffer * bb,bool * own_buffer)45 Status GenericSerialize(const grpc::protobuf::MessageLite& 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 = static_cast<int>(msg.ByteSizeLong());
53 if (static_cast<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::MessageLite * msg)71 Status GenericDeserialize(ByteBuffer* buffer,
72 grpc::protobuf::MessageLite* msg) {
73 static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream,
74 ProtoBufferReader>::value,
75 "ProtoBufferReader must be a subclass of "
76 "::protobuf::io::ZeroCopyInputStream");
77 if (buffer == nullptr) {
78 return Status(StatusCode::INTERNAL, "No payload");
79 }
80 Status result = g_core_codegen_interface->ok();
81 {
82 ProtoBufferReader reader(buffer);
83 if (!reader.status().ok()) {
84 return reader.status();
85 }
86 if (!msg->ParseFromZeroCopyStream(&reader)) {
87 result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
88 }
89 }
90 buffer->Clear();
91 return result;
92 }
93
94 // this is needed so the following class does not conflict with protobuf
95 // serializers that utilize internal-only tools.
96 #ifdef GRPC_OPEN_SOURCE_PROTO
97 // This class provides a protobuf serializer. It translates between protobuf
98 // objects and grpc_byte_buffers. More information about SerializationTraits can
99 // be found in include/grpcpp/impl/codegen/serialization_traits.h.
100 template <class T>
101 class SerializationTraits<
102 T, typename std::enable_if<
103 std::is_base_of<grpc::protobuf::MessageLite, T>::value>::type> {
104 public:
Serialize(const grpc::protobuf::MessageLite & msg,ByteBuffer * bb,bool * own_buffer)105 static Status Serialize(const grpc::protobuf::MessageLite& msg,
106 ByteBuffer* bb, bool* own_buffer) {
107 return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer);
108 }
109
Deserialize(ByteBuffer * buffer,grpc::protobuf::MessageLite * msg)110 static Status Deserialize(ByteBuffer* buffer,
111 grpc::protobuf::MessageLite* msg) {
112 return GenericDeserialize<ProtoBufferReader, T>(buffer, msg);
113 }
114 };
115 #endif
116
117 } // namespace grpc
118
119 #endif // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
120