| /* |
| * |
| * 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 <type_traits> |
| |
| #include <grpc/impl/codegen/byte_buffer_reader.h> |
| #include <grpc/impl/codegen/grpc_types.h> |
| #include <grpc/impl/codegen/slice.h> |
| #include <grpcpp/impl/codegen/byte_buffer.h> |
| #include <grpcpp/impl/codegen/config_protobuf.h> |
| #include <grpcpp/impl/codegen/core_codegen_interface.h> |
| #include <grpcpp/impl/codegen/proto_buffer_reader.h> |
| #include <grpcpp/impl/codegen/proto_buffer_writer.h> |
| #include <grpcpp/impl/codegen/serialization_traits.h> |
| #include <grpcpp/impl/codegen/slice.h> |
| #include <grpcpp/impl/codegen/status.h> |
| |
| /// 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 <class ProtoBufferWriter, class T> |
| Status GenericSerialize(const grpc::protobuf::Message& 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 = 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<uint8_t*>(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 <class ProtoBufferReader, class T> |
| Status GenericDeserialize(ByteBuffer* buffer, grpc::protobuf::Message* 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 = 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 T> |
| class SerializationTraits<T, typename std::enable_if<std::is_base_of< |
| grpc::protobuf::Message, T>::value>::type> { |
| public: |
| static Status Serialize(const grpc::protobuf::Message& msg, ByteBuffer* bb, |
| bool* own_buffer) { |
| return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer); |
| } |
| |
| static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) { |
| return GenericDeserialize<ProtoBufferReader, T>(buffer, msg); |
| } |
| }; |
| #endif |
| |
| } // namespace grpc |
| |
| #endif // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H |