#pragma once #include #include #include #include "cmds_basic.h" namespace validate { template class Validator { public: virtual QString name() const { return QString(); } virtual bool check(T value) const { return false; } virtual void getDepict(datas::IDataObject& self_description) { } }; template class ValidatorReceiver { public: virtual void append(Validator* inst) { } }; template struct ValidateTemplet; template<> struct ValidateTemplet<> { template bool validateFor(Inlet::SignatureImpl& value_sequence) const { return true; } virtual void getDepict(datas::IDataObject& self_description) const {} }; template struct ValidateTemplet : public ValidateTemplet { private: QList*> validator_list; public: void add(Validator* vinst) { validator_list << vinst; } bool check(Head value) const { for (auto u : validator_list) if (!u->check(value)) return false; return true; } template bool validateFor(Inlet::SignatureImpl& value_sequence) const { Head head_value = value_sequence.getArgs0(); if (!check(head_value)) return false; return ValidateTemplet::validateFor(value_sequence); } virtual void getDepict(datas::IDataObject& self_description) const { auto args_head = self_description.newObject(); for (auto vinst : validator_list) { auto vdesc = self_description.newObject(); vinst->getDepict(*vdesc); args_head->setChild(vinst->name(), vdesc); } auto args_array = std::dynamic_pointer_cast(self_description.getChild(u8"ArgsList")); args_array->append(args_head); self_description.setChild(u8"ArgsList", args_array); ValidateTemplet::getDepict(self_description); } }; template struct ElmPos; template struct ElmPos<0, ValidateTemplet> { using value_type = Head; using templet_type = ValidateTemplet; }; template struct ElmPos> { using value_type = typename ElmPos>::value_type; using templet_type = typename ElmPos>::templet_type; }; template void __validator_insert_helper(ValidateTemplet& target, Validator>::value_type>* inst) { using templet_type = typename ElmPos>::templet_type; target.templet_type::add(inst); } template class SlicePosition; template class SliceValidator : public Validator { private: std::function _proc_conv; Validator _sub_validator; public: SliceValidator(std::function proc, Validator vinst) : _proc_conv(proc), _sub_validator(vinst) { } virtual bool check(S value) const { auto t_value = _proc_conv(value); return _sub_validator.check(t_value); } }; template class ArgsPosition : public ValidatorReceiver>::value_type> { public: using Param = typename ElmPos>::value_type; ArgsPosition(ValidateTemplet& target) :_templet_bind(target) { } ArgsPosition& operator&(Validator* vinst) { append(vinst); return *this; } template SlicePosition> slice(std::function slice_fun) { return SlicePosition>(*this, slice_fun); } // ValidatorReceiver virtual void append(Validator* inst) { __validator_insert_helper(_templet_bind, inst); } private: ValidateTemplet& _templet_bind; }; template class SlicePosition> : public ValidatorReceiver { public: SlicePosition(ValidatorReceiver& host, std::function func) :_conv_func(func), _prev_bind(host) { } SlicePosition>& operator&(Validator* vinst) { append(vinst); return *this; } template SlicePosition> slice(std::function slice_fun) { return SlicePosition>(*this, slice_fun); } // ValidatorReceiver virtual void append(Validator* inst) { SliceValidator mid_validator(_conv_func, inst); _prev_bind.append(mid_validator); } private: std::function _conv_func; ValidatorReceiver& _prev_bind; }; class IValidatorTemplet { public: virtual bool doValidate(Inlet::IRunbase* inst) const = 0; virtual void getDepict(datas::IDataObject& self_description) const = 0; }; template struct ValidateImpls; template struct ValidateImpls : public ValidateTemplet, public IValidatorTemplet { quint64 address() const { return (quint64) func; } template ArgsPosition pos() { return ArgsPosition(*this); } // Ivalidatortemplet virtual bool doValidate(Inlet::IRunbase* inst) const { auto valid_data = dynamic_cast*>(inst); return ValidateTemplet::validateFor(valid_data->getArgSequence()); } virtual void getDepict(datas::IDataObject& self_description) const { self_description.setString(u8"ValidateFor", QString::number((qulonglong)func)); auto array_l = self_description.newArray(); self_description.setChild(u8"ArgsList", array_l); ValidateTemplet::getDepict(self_description); } }; }