123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- #pragma once
- #include "traits.h"
- #include <google/protobuf/descriptor.h>
- #include <google/protobuf/message.h>
- #include <util/generic/cast.h>
- namespace NProtoBuf {
- // C++ compatible conversions of FieldDescriptor::CppType's
- using ECppType = FieldDescriptor::CppType;
- namespace NCast {
- template <ECppType src, ECppType dst>
- struct TIsCompatibleCppType {
- enum {
- Result = src == dst ||
- (TIsNumericCppType<src>::Result && TIsNumericCppType<dst>::Result)
- };
- };
- template <ECppType src, ECppType dst>
- struct TIsEnumToNumericCppType {
- enum {
- Result = (src == FieldDescriptor::CPPTYPE_ENUM && TIsNumericCppType<dst>::Result)
- };
- };
- template <ECppType src, ECppType dst, bool compatible> // compatible == true
- struct TCompatCastBase {
- static const bool IsCompatible = true;
- typedef typename TCppTypeTraits<src>::T TSrc;
- typedef typename TCppTypeTraits<dst>::T TDst;
- static inline TDst Cast(TSrc value) {
- return value;
- }
- };
- template <ECppType src, ECppType dst> // compatible == false
- struct TCompatCastBase<src, dst, false> {
- static const bool IsCompatible = false;
- typedef typename TCppTypeTraits<src>::T TSrc;
- typedef typename TCppTypeTraits<dst>::T TDst;
- static inline TDst Cast(TSrc) {
- ythrow TBadCastException() << "Incompatible FieldDescriptor::CppType conversion: #"
- << (size_t)src << " to #" << (size_t)dst;
- }
- };
- template <ECppType src, ECppType dst, bool isEnumToNum> // enum -> numeric
- struct TCompatCastImpl {
- static const bool IsCompatible = true;
- typedef typename TCppTypeTraits<dst>::T TDst;
- static inline TDst Cast(const EnumValueDescriptor* value) {
- Y_ASSERT(value != nullptr);
- return value->number();
- }
- };
- template <ECppType src, ECppType dst>
- struct TCompatCastImpl<src, dst, false>: public TCompatCastBase<src, dst, TIsCompatibleCppType<src, dst>::Result> {
- using TCompatCastBase<src, dst, TIsCompatibleCppType<src, dst>::Result>::IsCompatible;
- };
- template <ECppType src, ECppType dst>
- struct TCompatCast: public TCompatCastImpl<src, dst, TIsEnumToNumericCppType<src, dst>::Result> {
- typedef TCompatCastImpl<src, dst, TIsEnumToNumericCppType<src, dst>::Result> TBase;
- typedef typename TCppTypeTraits<src>::T TSrc;
- typedef typename TCppTypeTraits<dst>::T TDst;
- using TBase::Cast;
- using TBase::IsCompatible;
- inline bool Try(TSrc value, TDst& res) {
- if (IsCompatible) {
- res = Cast(value);
- return true;
- }
- return false;
- }
- };
- }
- template <ECppType src, ECppType dst>
- inline typename TCppTypeTraits<dst>::T CompatCast(typename TCppTypeTraits<src>::T value) {
- return NCast::TCompatCast<src, dst>::Cast(value);
- }
- template <ECppType src, ECppType dst>
- inline bool TryCompatCast(typename TCppTypeTraits<src>::T value, typename TCppTypeTraits<dst>::T& res) {
- return NCast::TCompatCast<src, dst>::Try(value, res);
- }
- // Message static/dynamic checked casts
- template <typename TpMessage>
- inline const TpMessage* TryCast(const Message* msg) {
- if (!msg || TpMessage::descriptor() != msg->GetDescriptor())
- return NULL;
- return CheckedCast<const TpMessage*>(msg);
- }
- template <typename TpMessage>
- inline const TpMessage* TryCast(const Message* msg, const TpMessage*& ret) {
- ret = TryCast<TpMessage>(msg);
- return ret;
- }
- template <typename TpMessage>
- inline TpMessage* TryCast(Message* msg) {
- if (!msg || TpMessage::descriptor() != msg->GetDescriptor())
- return nullptr;
- return CheckedCast<TpMessage*>(msg);
- }
- template <typename TpMessage>
- inline TpMessage* TryCast(Message* msg, TpMessage*& ret) {
- ret = TryCast<TpMessage>(msg);
- return ret;
- }
- // specialize for Message itself
- template <>
- inline const Message* TryCast<Message>(const Message* msg) {
- return msg;
- }
- template <>
- inline Message* TryCast<Message>(Message* msg) {
- return msg;
- }
- // Binary serialization compatible conversion
- inline bool TryBinaryCast(const Message* from, Message* to, TString* buffer = nullptr) {
- TString tmpbuf;
- if (!buffer)
- buffer = &tmpbuf;
- if (!from->SerializeToString(buffer))
- return false;
- return to->ParseFromString(*buffer);
- }
- }
|