aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-16 20:38:33 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-16 20:38:33 +0300
commit8468858a796013ec5547c9292c0a80a5a9172804 (patch)
treefa5685bdc480863dcaa9b124ee12cd948eadb2d5
parent76cbe125b7d39dca64a0de7b86eee37fd575e4df (diff)
downloadydb-8468858a796013ec5547c9292c0a80a5a9172804.tar.gz
Automatically check protobuf has validate option KIKIMR-14369
ref:a62a84bad3a8555c27d06bcc0992c72a740a715c
-rw-r--r--ydb/core/grpc_services/base/base.h46
1 files changed, 41 insertions, 5 deletions
diff --git a/ydb/core/grpc_services/base/base.h b/ydb/core/grpc_services/base/base.h
index 38380586218..2b9344e8fd4 100644
--- a/ydb/core/grpc_services/base/base.h
+++ b/ydb/core/grpc_services/base/base.h
@@ -1029,22 +1029,58 @@ private:
TMaybe<NRpcService::TRlPath> RlPath;
};
+template<ui32 TRpcId, typename TReq, typename TResp, bool IsOperation, typename TDerived>
+class TGRpcRequestValidationWrapperImpl :
+ public TGRpcRequestWrapperImpl<TRpcId, TReq, TResp, IsOperation, TDerived> {
+
+public:
+ static IActor* CreateRpcActor(typename std::conditional<IsOperation, IRequestOpCtx, IRequestNoOpCtx>::type* msg);
+ TGRpcRequestValidationWrapperImpl(NGrpc::IRequestContextBase* ctx)
+ : TGRpcRequestWrapperImpl<TRpcId, TReq, TResp, IsOperation, TDerived>(ctx)
+ { }
+
+ bool Validate(TString& error) override {
+ return this->GetProtoRequest()->validate(error);
+ }
+};
+
+// SFINAE
+// Check protobuf has validate feature
+template<typename TProto>
+struct TProtoHasValidate {
+private:
+ static int Detect(...);
+ // validate function has prototype: bool validate(TProtoStringType&) const
+ static TProtoStringType Dummy_;
+ template<typename U>
+ static decltype(std::declval<U>().validate(Dummy_)) Detect(const U&);
+public:
+ static constexpr bool Value = std::is_same<bool, decltype(Detect(std::declval<TProto>()))>::value;
+};
+
class IFacilityProvider;
template <typename TReq, typename TResp, bool IsOperation>
class TGrpcRequestCall
- : public TGRpcRequestWrapperImpl<
- TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>> {
+ : public std::conditional_t<TProtoHasValidate<TReq>::Value,
+ TGRpcRequestValidationWrapperImpl<
+ TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>,
+ TGRpcRequestWrapperImpl<
+ TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>>
+ {
typedef typename std::conditional<IsOperation, IRequestOpCtx, IRequestNoOpCtx>::type TRequestIface;
public:
static constexpr bool IsOp = IsOperation;
static IActor* CreateRpcActor(typename std::conditional<IsOperation, IRequestOpCtx, IRequestNoOpCtx>::type* msg);
+ using TBase = std::conditional_t<TProtoHasValidate<TReq>::Value,
+ TGRpcRequestValidationWrapperImpl<
+ TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>,
+ TGRpcRequestWrapperImpl<
+ TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>>;
TGrpcRequestCall(NGrpc::IRequestContextBase* ctx,
void (*cb)(std::unique_ptr<TRequestIface>, const IFacilityProvider&), TRequestAuxSettings auxSettings = {})
- : TGRpcRequestWrapperImpl<
- TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation,
- TGrpcRequestCall<TReq, TResp, IsOperation>>(ctx)
+ : TBase(ctx)
, PassMethod(cb)
, AuxSettings(std::move(auxSettings))
{ }