Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

147 рядки
4.2 KiB

#pragma once
#include "UserScript.h"
#include "UserScriptWizardry.h"
#include <concepts>
#include <span>
#include <ranges>
/*template<size_t arg_number>
struct verifier_base {
static constexpr size_t argument_id = arg_number;
};*/
namespace details {
template<size_t argument_counter, typename T>
struct TypeVerifier {
static constexpr size_t argument_id = argument_counter;
bool verify(scripting::UserScript* self, std::vector<scripting::argument>& args) {
if(argument_id >= args.size()) return false;
if(args.size() -1 -argument_id < 0) return false;
auto& argument = args[args.size() -1 -argument_id];
std::optional<std::reference_wrapper<scripting::script_value>> v = std::visit(
wizardry::overloaded{
[&](scripting::script_variable& v) -> std::optional<std::reference_wrapper<scripting::script_value>> {return self->getValue(v.name);},
[&](scripting::script_value& v) -> std::optional<std::reference_wrapper<scripting::script_value>> {return v;},
},
argument
);
if(not v) return false;
return std::visit(wizardry::overloaded{
[](T& ) {return true;},
[](auto&) {return false;}
}, v.value().get());
}
};
template<size_t argument_counter>
struct VariableVerifier {
static constexpr size_t argument_id = argument_counter;
bool verify(scripting::UserScript* self, std::vector<scripting::argument>& args) {
if(argument_id >= args.size()) return false;
if(args.size() -1 -argument_id < 0) return false;
auto& argument = args[args.size() -1 -argument_id];
return std::visit(
wizardry::overloaded{
[&](scripting::script_variable& v) -> bool {return self->getValue(v.name).has_value();},
[&](scripting::script_value& v) {return false;},
},
argument
);
}
};
template<size_t skip = 0>
struct NoArrays {
bool verify(scripting::UserScript* self, std::vector<scripting::argument> args) {
for(auto& elem : std::ranges::reverse_view(args) | std::ranges::views::drop(skip)) {
std::optional<std::reference_wrapper<scripting::script_value>> v;
std::visit(
wizardry::overloaded{
[&](scripting::script_variable& n) {v = self->getValue(n.name);},
[&](scripting::script_value& n) {v = n;},
},
elem
);
if(not v) return false;
if(std::visit(wizardry::overloaded{
[](scripting::array&) {return true;},
[](auto&) {return false;}
}, v.value().get())) {
return false;
}
}
return true;
}
};
template<size_t sz = 0>
struct SizeEquals {
bool verify(scripting::UserScript*, std::vector<scripting::argument> args) {
return args.size() == sz;
}
};
template<size_t sz = 0>
struct SizeAtLeast {
bool verify(scripting::UserScript*, std::vector<scripting::argument> args) {
return args.size() >= sz;
}
};
template<size_t argument_counter>
struct OctetArrayVerifier {
static constexpr size_t argument_id = argument_counter;
bool verify(scripting::UserScript* self, std::vector<scripting::argument>& args) {
if(argument_id >= args.size()) return false;
if(args.size() -1 -argument_id < 0) return false;
auto& argument = args[args.size() -1 -argument_id];
std::optional<std::reference_wrapper<scripting::script_value>> v;
std::visit(
wizardry::overloaded{
[&](scripting::script_variable& elem) {v = self->getValue(elem.name);},
[&](scripting::script_value& elem) {v = elem;}
},
argument
);
if(not v) return false;
return std::visit(
wizardry::overloaded{
[](scripting::array& ary) -> bool {
for(auto& elem : ary.value) {
if(std::holds_alternative<int32_t>(elem)) {
if(auto& byte = std::get<int32_t>(elem); byte < 0 || byte > 255) {
return false;
}
} else {
return false;
}
}
return true;
},
[] (auto&) -> bool {return false;}
},
v.value().get()
);
}
};
}
template<typename... verifiers>
struct Verify;
template<typename n, typename... verifiers>
struct Verify<n, verifiers...> {
bool verify(scripting::UserScript* self, std::vector<scripting::argument>& args) {
return n{}.verify(self, args) && Verify<verifiers...>{}.verify(self, args);
}
};
template<>
struct Verify<> {
bool verify(scripting::UserScript*, const std::vector<scripting::argument>&) {
return true;
}
};