| // |
| // |
| // 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_PROTO_UTILS_H |
| #define GRPCPP_IMPL_PROTO_UTILS_H |
| |
| #include <type_traits> |
| |
| #include <grpc/byte_buffer_reader.h> |
| #include <grpc/impl/grpc_types.h> |
| #include <grpc/slice.h> |
| #include <grpc/support/log.h> |
| #include <grpcpp/impl/codegen/config_protobuf.h> |
| #include <grpcpp/impl/serialization_traits.h> |
| #include <grpcpp/support/byte_buffer.h> |
| #include <grpcpp/support/proto_buffer_reader.h> |
| #include <grpcpp/support/proto_buffer_writer.h> |
| #include <grpcpp/support/slice.h> |
| #include <grpcpp/support/status.h> |
| |
| /// This header provides serialization and deserialization between gRPC |
| /// messages serialized using protobuf and the C++ objects they represent. |
| |
| namespace grpc { |
| |
| // ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream. |
| template <class ProtoBufferWriter, class T> |
| Status GenericSerialize(const grpc::protobuf::MessageLite& msg, ByteBuffer* bb, |
| bool* own_buffer) { |
| static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream, |
| ProtoBufferWriter>::value, |
| "ProtoBufferWriter must be a subclass of " |
| "::protobuf::io::ZeroCopyOutputStream"); |
| *own_buffer = true; |
| int byte_size = static_cast<int>(msg.ByteSizeLong()); |
| if (static_cast<size_t>(byte_size) <= GRPC_SLICE_INLINED_SIZE) { |
| Slice slice(byte_size); |
| // We serialize directly into the allocated slices memory |
| GPR_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray( |
| const_cast<uint8_t*>(slice.begin()))); |
| ByteBuffer tmp(&slice, 1); |
| bb->Swap(&tmp); |
| |
| return grpc::Status::OK; |
| } |
| ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size); |
| return msg.SerializeToZeroCopyStream(&writer) |
| ? grpc::Status::OK |
| : Status(StatusCode::INTERNAL, "Failed to serialize message"); |
| } |
| |
| // BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream. |
| template <class ProtoBufferReader, class T> |
| Status GenericDeserialize(ByteBuffer* buffer, |
| grpc::protobuf::MessageLite* msg) { |
| static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream, |
| ProtoBufferReader>::value, |
| "ProtoBufferReader must be a subclass of " |
| "::protobuf::io::ZeroCopyInputStream"); |
| if (buffer == nullptr) { |
| return Status(StatusCode::INTERNAL, "No payload"); |
| } |
| Status result = grpc::Status::OK; |
| { |
| ProtoBufferReader reader(buffer); |
| if (!reader.status().ok()) { |
| return reader.status(); |
| } |
| if (!msg->ParseFromZeroCopyStream(&reader)) { |
| result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); |
| } |
| } |
| 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 T> |
| class SerializationTraits< |
| T, typename std::enable_if< |
| std::is_base_of<grpc::protobuf::MessageLite, T>::value>::type> { |
| public: |
| static Status Serialize(const grpc::protobuf::MessageLite& msg, |
| ByteBuffer* bb, bool* own_buffer) { |
| return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer); |
| } |
| |
| static Status Deserialize(ByteBuffer* buffer, |
| grpc::protobuf::MessageLite* msg) { |
| return GenericDeserialize<ProtoBufferReader, T>(buffer, msg); |
| } |
| }; |
| #endif |
| |
| } // namespace grpc |
| |
| #endif // GRPCPP_IMPL_PROTO_UTILS_H |