The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) https://grpc.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
4.4 KiB

/*
*
* 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/codegen/grpc_types.h>
#include <grpc/slice.h>
#include <grpcpp/impl/codegen/config_protobuf.h>
#include <grpcpp/impl/codegen/core_codegen_interface.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 {
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::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_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::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 = g_core_codegen_interface->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