1*cc02d7e2SAndroid Build Coastguard Worker //
2*cc02d7e2SAndroid Build Coastguard Worker //
3*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2015 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker //
5*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker //
9*cc02d7e2SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker //
11*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker //
17*cc02d7e2SAndroid Build Coastguard Worker //
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker #ifndef GRPCPP_IMPL_PROTO_UTILS_H
20*cc02d7e2SAndroid Build Coastguard Worker #define GRPCPP_IMPL_PROTO_UTILS_H
21*cc02d7e2SAndroid Build Coastguard Worker
22*cc02d7e2SAndroid Build Coastguard Worker #include <type_traits>
23*cc02d7e2SAndroid Build Coastguard Worker
24*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/byte_buffer_reader.h>
25*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/impl/grpc_types.h>
26*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/slice.h>
27*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/log.h>
28*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/codegen/config_protobuf.h>
29*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/serialization_traits.h>
30*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/byte_buffer.h>
31*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/proto_buffer_reader.h>
32*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/proto_buffer_writer.h>
33*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/slice.h>
34*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/support/status.h>
35*cc02d7e2SAndroid Build Coastguard Worker
36*cc02d7e2SAndroid Build Coastguard Worker /// This header provides serialization and deserialization between gRPC
37*cc02d7e2SAndroid Build Coastguard Worker /// messages serialized using protobuf and the C++ objects they represent.
38*cc02d7e2SAndroid Build Coastguard Worker
39*cc02d7e2SAndroid Build Coastguard Worker namespace grpc {
40*cc02d7e2SAndroid Build Coastguard Worker
41*cc02d7e2SAndroid Build Coastguard Worker // ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream.
42*cc02d7e2SAndroid Build Coastguard Worker template <class ProtoBufferWriter, class T>
GenericSerialize(const grpc::protobuf::MessageLite & msg,ByteBuffer * bb,bool * own_buffer)43*cc02d7e2SAndroid Build Coastguard Worker Status GenericSerialize(const grpc::protobuf::MessageLite& msg, ByteBuffer* bb,
44*cc02d7e2SAndroid Build Coastguard Worker bool* own_buffer) {
45*cc02d7e2SAndroid Build Coastguard Worker static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream,
46*cc02d7e2SAndroid Build Coastguard Worker ProtoBufferWriter>::value,
47*cc02d7e2SAndroid Build Coastguard Worker "ProtoBufferWriter must be a subclass of "
48*cc02d7e2SAndroid Build Coastguard Worker "::protobuf::io::ZeroCopyOutputStream");
49*cc02d7e2SAndroid Build Coastguard Worker *own_buffer = true;
50*cc02d7e2SAndroid Build Coastguard Worker int byte_size = static_cast<int>(msg.ByteSizeLong());
51*cc02d7e2SAndroid Build Coastguard Worker if (static_cast<size_t>(byte_size) <= GRPC_SLICE_INLINED_SIZE) {
52*cc02d7e2SAndroid Build Coastguard Worker Slice slice(byte_size);
53*cc02d7e2SAndroid Build Coastguard Worker // We serialize directly into the allocated slices memory
54*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray(
55*cc02d7e2SAndroid Build Coastguard Worker const_cast<uint8_t*>(slice.begin())));
56*cc02d7e2SAndroid Build Coastguard Worker ByteBuffer tmp(&slice, 1);
57*cc02d7e2SAndroid Build Coastguard Worker bb->Swap(&tmp);
58*cc02d7e2SAndroid Build Coastguard Worker
59*cc02d7e2SAndroid Build Coastguard Worker return grpc::Status::OK;
60*cc02d7e2SAndroid Build Coastguard Worker }
61*cc02d7e2SAndroid Build Coastguard Worker ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size);
62*cc02d7e2SAndroid Build Coastguard Worker return msg.SerializeToZeroCopyStream(&writer)
63*cc02d7e2SAndroid Build Coastguard Worker ? grpc::Status::OK
64*cc02d7e2SAndroid Build Coastguard Worker : Status(StatusCode::INTERNAL, "Failed to serialize message");
65*cc02d7e2SAndroid Build Coastguard Worker }
66*cc02d7e2SAndroid Build Coastguard Worker
67*cc02d7e2SAndroid Build Coastguard Worker // BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream.
68*cc02d7e2SAndroid Build Coastguard Worker template <class ProtoBufferReader, class T>
GenericDeserialize(ByteBuffer * buffer,grpc::protobuf::MessageLite * msg)69*cc02d7e2SAndroid Build Coastguard Worker Status GenericDeserialize(ByteBuffer* buffer,
70*cc02d7e2SAndroid Build Coastguard Worker grpc::protobuf::MessageLite* msg) {
71*cc02d7e2SAndroid Build Coastguard Worker static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream,
72*cc02d7e2SAndroid Build Coastguard Worker ProtoBufferReader>::value,
73*cc02d7e2SAndroid Build Coastguard Worker "ProtoBufferReader must be a subclass of "
74*cc02d7e2SAndroid Build Coastguard Worker "::protobuf::io::ZeroCopyInputStream");
75*cc02d7e2SAndroid Build Coastguard Worker if (buffer == nullptr) {
76*cc02d7e2SAndroid Build Coastguard Worker return Status(StatusCode::INTERNAL, "No payload");
77*cc02d7e2SAndroid Build Coastguard Worker }
78*cc02d7e2SAndroid Build Coastguard Worker Status result = grpc::Status::OK;
79*cc02d7e2SAndroid Build Coastguard Worker {
80*cc02d7e2SAndroid Build Coastguard Worker ProtoBufferReader reader(buffer);
81*cc02d7e2SAndroid Build Coastguard Worker if (!reader.status().ok()) {
82*cc02d7e2SAndroid Build Coastguard Worker return reader.status();
83*cc02d7e2SAndroid Build Coastguard Worker }
84*cc02d7e2SAndroid Build Coastguard Worker if (!msg->ParseFromZeroCopyStream(&reader)) {
85*cc02d7e2SAndroid Build Coastguard Worker result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
86*cc02d7e2SAndroid Build Coastguard Worker }
87*cc02d7e2SAndroid Build Coastguard Worker }
88*cc02d7e2SAndroid Build Coastguard Worker buffer->Clear();
89*cc02d7e2SAndroid Build Coastguard Worker return result;
90*cc02d7e2SAndroid Build Coastguard Worker }
91*cc02d7e2SAndroid Build Coastguard Worker
92*cc02d7e2SAndroid Build Coastguard Worker // this is needed so the following class does not conflict with protobuf
93*cc02d7e2SAndroid Build Coastguard Worker // serializers that utilize internal-only tools.
94*cc02d7e2SAndroid Build Coastguard Worker #ifdef GRPC_OPEN_SOURCE_PROTO
95*cc02d7e2SAndroid Build Coastguard Worker // This class provides a protobuf serializer. It translates between protobuf
96*cc02d7e2SAndroid Build Coastguard Worker // objects and grpc_byte_buffers. More information about SerializationTraits can
97*cc02d7e2SAndroid Build Coastguard Worker // be found in include/grpcpp/impl/codegen/serialization_traits.h.
98*cc02d7e2SAndroid Build Coastguard Worker template <class T>
99*cc02d7e2SAndroid Build Coastguard Worker class SerializationTraits<
100*cc02d7e2SAndroid Build Coastguard Worker T, typename std::enable_if<
101*cc02d7e2SAndroid Build Coastguard Worker std::is_base_of<grpc::protobuf::MessageLite, T>::value>::type> {
102*cc02d7e2SAndroid Build Coastguard Worker public:
Serialize(const grpc::protobuf::MessageLite & msg,ByteBuffer * bb,bool * own_buffer)103*cc02d7e2SAndroid Build Coastguard Worker static Status Serialize(const grpc::protobuf::MessageLite& msg,
104*cc02d7e2SAndroid Build Coastguard Worker ByteBuffer* bb, bool* own_buffer) {
105*cc02d7e2SAndroid Build Coastguard Worker return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer);
106*cc02d7e2SAndroid Build Coastguard Worker }
107*cc02d7e2SAndroid Build Coastguard Worker
Deserialize(ByteBuffer * buffer,grpc::protobuf::MessageLite * msg)108*cc02d7e2SAndroid Build Coastguard Worker static Status Deserialize(ByteBuffer* buffer,
109*cc02d7e2SAndroid Build Coastguard Worker grpc::protobuf::MessageLite* msg) {
110*cc02d7e2SAndroid Build Coastguard Worker return GenericDeserialize<ProtoBufferReader, T>(buffer, msg);
111*cc02d7e2SAndroid Build Coastguard Worker }
112*cc02d7e2SAndroid Build Coastguard Worker };
113*cc02d7e2SAndroid Build Coastguard Worker #endif
114*cc02d7e2SAndroid Build Coastguard Worker
115*cc02d7e2SAndroid Build Coastguard Worker } // namespace grpc
116*cc02d7e2SAndroid Build Coastguard Worker
117*cc02d7e2SAndroid Build Coastguard Worker #endif // GRPCPP_IMPL_PROTO_UTILS_H
118