-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
See #2722 (comment) inspired by unreflectable_message of @oathdruid.
- Loading branch information
Showing
2 changed files
with
232 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Licensed to the Apache Software Foundation (ASF) under one | ||
// or more contributor license agreements. See the NOTICE file | ||
// distributed with this work for additional information | ||
// regarding copyright ownership. The ASF licenses this file | ||
// to you 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 BRPC_MESSAGE_HELPER_H | ||
#define BRPC_MESSAGE_HELPER_H | ||
|
||
#include "brpc/nonreflectable_message.h" | ||
|
||
namespace brpc { | ||
|
||
template <typename T> | ||
struct MessageHelper { | ||
using BaseType = NonreflectableMessage<T>; | ||
}; | ||
|
||
} // namespace brpc | ||
|
||
#endif // BRPC_MESSAGE_HELPER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
// Licensed to the Apache Software Foundation (ASF) under one | ||
// or more contributor license agreements. See the NOTICE file | ||
// distributed with this work for additional information | ||
// regarding copyright ownership. The ASF licenses this file | ||
// to you 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 BRPC_NONREFLECTABLE_MESSAGE_H | ||
#define BRPC_NONREFLECTABLE_MESSAGE_H | ||
|
||
#include <google/protobuf/message.h> | ||
|
||
namespace brpc { | ||
|
||
// | ||
// In bRPC, some non-Protobuf based protocol messages are also designed to implement | ||
// Protobuf Message interfaces, to provide a unified protocol message. | ||
// The API of Protobuf Message changes frequently, and these non-Protobuf based protocol | ||
// messages do not rely on the reflection functionality of Protobuf. | ||
// | ||
// NonreflectableMessage is designed to isolate upstream API changes and | ||
// provides basic implementations to simplify the adaptation process. | ||
// | ||
// Function implementations are kept order with the upstream, | ||
// and use only #if version_check #endif, to make maintenance easier. | ||
// | ||
template <typename T> | ||
class NonreflectableMessage : public ::google::protobuf::Message { | ||
public: | ||
#if GOOGLE_PROTOBUF_VERSION < 3019000 | ||
Message* New() const override { | ||
return new T(); | ||
} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION >= 3000000 | ||
Message* New(::google::protobuf::Arena* arena) const override { | ||
return ::google::protobuf::Arena::Create<T>(arena); | ||
} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 3021000 | ||
void CopyFrom(const ::google::protobuf::Message& other) override { | ||
if (&other == this) { | ||
return; | ||
} | ||
Clear(); | ||
MergeFrom(other); | ||
} | ||
#endif | ||
|
||
inline void CopyFrom(const NonreflectableMessage& other) { | ||
if (&other == this) { | ||
return; | ||
} | ||
Clear(); | ||
MergeFrom(other); | ||
} | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 5026000 | ||
void MergeFrom(const ::google::protobuf::Message& other) override { | ||
if (&other == this) { | ||
return; | ||
} | ||
|
||
// Cross-type merging is meaningless, call implementation of subclass | ||
#if GOOGLE_PROTOBUF_VERSION >= 3007000 | ||
const T* same_type_other = ::google::protobuf::DynamicCastToGenerated<T>(&other); | ||
#elif GOOGLE_PROTOBUF_VERSION >= 3000000 | ||
const T* same_type_other = ::google::protobuf::internal::DynamicCastToGenerated<const T>(&other); | ||
#endif // GOOGLE_PROTOBUF_VERSION | ||
if (same_type_other != nullptr) { | ||
MergeFrom(*same_type_other); | ||
} else { | ||
Message::MergeFrom(other); | ||
} | ||
} | ||
#endif // member function closure | ||
|
||
virtual void MergeFrom(const T&) = 0; | ||
|
||
#if GOOGLE_PROTOBUF_VERSION > 3019000 && GOOGLE_PROTOBUF_VERSION < 5026000 | ||
// Unsupported by default. | ||
std::string InitializationErrorString() const override { | ||
return "unknown error"; | ||
} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 3019000 | ||
// Unsupported by default. | ||
void DiscardUnknownFields() override {} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 5026000 | ||
// Unsupported by default. | ||
size_t SpaceUsedLong() const override { | ||
return 0; | ||
} | ||
#endif | ||
|
||
// Unsupported by default. | ||
::std::string GetTypeName() const override { | ||
return {}; | ||
} | ||
|
||
void Clear() override {} | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 3010000 | ||
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream*) override { | ||
return true; | ||
} | ||
#endif | ||
|
||
// Quickly check if all required fields have values set. | ||
// Unsupported by default. | ||
bool IsInitialized() const override { | ||
return true; | ||
} | ||
|
||
#if GOOGLE_PROTOBUF_VERSION >= 3010000 && GOOGLE_PROTOBUF_VERSION <= 5026000 | ||
const char* _InternalParse( | ||
const char* ptr, ::google::protobuf::internal::ParseContext*) override { | ||
return ptr; | ||
} | ||
#endif | ||
|
||
// Size of bytes after serialization. | ||
size_t ByteSizeLong() const override { | ||
return 0; | ||
} | ||
|
||
#if GOOGLE_PROTOBUF_VERSION >= 3007000 && GOOGLE_PROTOBUF_VERSION < 3010000 | ||
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream*) const override {} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION >= 3010000 && GOOGLE_PROTOBUF_VERSION < 3011000 | ||
uint8_t* InternalSerializeWithCachedSizesToArray( | ||
uint8_t* ptr, ::google::protobuf::io::EpsCopyOutputStream*) const override { | ||
return ptr; | ||
} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION >= 3011000 | ||
uint8_t* _InternalSerialize( | ||
uint8_t* ptr, ::google::protobuf::io::EpsCopyOutputStream*) const override { | ||
return ptr; | ||
} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 4025000 | ||
// Unnecessary for Nonreflectable message. | ||
int GetCachedSize() const override { | ||
return 0; | ||
} | ||
#endif | ||
|
||
#if GOOGLE_PROTOBUF_VERSION < 4025000 | ||
// Unnecessary for Nonreflectable message. | ||
void SetCachedSize(int) const override {} | ||
#endif | ||
|
||
public: | ||
// Only can be used to determine whether the Types are the same. | ||
::google::protobuf::Metadata GetMetadata() const override { | ||
::google::protobuf::Metadata metadata{}; | ||
// can only be used to | ||
metadata.descriptor = reinterpret_cast<const ::google::protobuf::Descriptor*>(&_instance); | ||
metadata.reflection = reinterpret_cast<const ::google::protobuf::Reflection*>(&_instance); | ||
return metadata; | ||
} | ||
|
||
// Only can be used to determine whether the Types are the same. | ||
inline static const ::google::protobuf::Descriptor* descriptor() noexcept { | ||
return default_instance().GetMetadata().descriptor; | ||
} | ||
|
||
inline static const T& default_instance() noexcept { | ||
return _instance; | ||
} | ||
|
||
private: | ||
static T _instance; | ||
}; | ||
|
||
template <typename T> | ||
T NonreflectableMessage<T>::_instance; | ||
|
||
} // namespace brpc | ||
|
||
#endif // BRPC_NONREFLECTABLE_MESSAGE_H |