/* * * Copyright 2015 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H #define GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H #include #include #include #include #include #include #include #include #include #include #include #include /// This header provides serialization and deserialization between gRPC /// messages serialized using protobuf and the C++ objects they represent. namespace grpc { extern CoreCodegenInterface* g_core_codegen_interface; // ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream. template Status GenericSerialize(const grpc::protobuf::MessageLite& msg, ByteBuffer* bb, bool* own_buffer) { static_assert(std::is_base_of::value, "ProtoBufferWriter must be a subclass of " "::protobuf::io::ZeroCopyOutputStream"); *own_buffer = true; int byte_size = msg.ByteSize(); if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) { Slice slice(byte_size); // We serialize directly into the allocated slices memory GPR_CODEGEN_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray( const_cast(slice.begin()))); ByteBuffer tmp(&slice, 1); bb->Swap(&tmp); return g_core_codegen_interface->ok(); } ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size); return msg.SerializeToZeroCopyStream(&writer) ? g_core_codegen_interface->ok() : Status(StatusCode::INTERNAL, "Failed to serialize message"); } // BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream. template Status GenericDeserialize(ByteBuffer* buffer, grpc::protobuf::MessageLite* msg) { static_assert(std::is_base_of::value, "ProtoBufferReader must be a subclass of " "::protobuf::io::ZeroCopyInputStream"); if (buffer == nullptr) { return Status(StatusCode::INTERNAL, "No payload"); } Status result = g_core_codegen_interface->ok(); { ProtoBufferReader reader(buffer); if (!reader.status().ok()) { return reader.status(); } ::grpc::protobuf::io::CodedInputStream decoder(&reader); decoder.SetTotalBytesLimit(INT_MAX, INT_MAX); if (!msg->ParseFromCodedStream(&decoder)) { result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); } if (!decoder.ConsumedEntireMessage()) { result = Status(StatusCode::INTERNAL, "Did not read entire message"); } } buffer->Clear(); return result; } // this is needed so the following class does not conflict with protobuf // serializers that utilize internal-only tools. #ifdef GRPC_OPEN_SOURCE_PROTO // This class provides a protobuf serializer. It translates between protobuf // objects and grpc_byte_buffers. More information about SerializationTraits can // be found in include/grpcpp/impl/codegen/serialization_traits.h. template class SerializationTraits::value>::type> { public: static Status Serialize(const grpc::protobuf::MessageLite& msg, ByteBuffer* bb, bool* own_buffer) { return GenericSerialize(msg, bb, own_buffer); } static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::MessageLite* msg) { return GenericDeserialize(buffer, msg); } }; #endif } // namespace grpc #endif // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H