|
|
- #include "UserScript.h"
- #include <algorithm>
- #include <span>
- #include <utility>
- #include "UserScriptWizardry.h"
- #include "UserScriptRequire.h"
-
- using interpreter = decltype(scripting::prepare_interpreter({}));
- using namespace scripting;
-
- namespace bad_cryptography {
-
- struct encode_n_parameters {
- uint8_t spin;
- uint8_t clash;
- uint8_t maim;
- };
-
- static constexpr uint8_t encode_n_1(uint8_t value, const encode_n_parameters ¶ms) {
- value += 42;
- value ^= 0b01010101;
- value += params.clash;
- value = std::rotl(value, params.spin);
- value ^= 0b10101010;
- value ^= params.maim;
- return value;
- }
-
- static constexpr uint8_t decode_n_1(uint8_t value, const encode_n_parameters ¶ms) {
- value ^= params.maim;
- value ^= 0b10101010;
- value = std::rotl(value, -params.spin);
- value -= params.clash;
- value ^= 0b01010101;
- value -= 42;
- return value;
- }
-
- namespace eliminated_001 {
- constexpr encode_n_parameters params{.spin = 3, .clash = 17, .maim = 54};
- static_assert(0 == decode_n_1(encode_n_1(0, params), params));
- static_assert(10 == decode_n_1(encode_n_1(10, params), params));
- static_assert(100 == decode_n_1(encode_n_1(100, params), params));
- static_assert(20 == decode_n_1(encode_n_1(20, params), params));
- static_assert(200 == decode_n_1(encode_n_1(200, params), params));
- static_assert(117 == decode_n_1(encode_n_1(117, params), params));
- static_assert(42 == decode_n_1(encode_n_1(42, params), params));
- };
-
- namespace eliminated_002 {
- constexpr encode_n_parameters params{.spin = 7, .clash = 97, .maim = 154};
- static_assert(0 == decode_n_1(encode_n_1(0, params), params));
- static_assert(10 == decode_n_1(encode_n_1(10, params), params));
- static_assert(100 == decode_n_1(encode_n_1(100, params), params));
- static_assert(20 == decode_n_1(encode_n_1(20, params), params));
- static_assert(200 == decode_n_1(encode_n_1(200, params), params));
- static_assert(117 == decode_n_1(encode_n_1(117, params), params));
- static_assert(42 == decode_n_1(encode_n_1(42, params), params));
- };
- }
-
- namespace scripting {
- struct fn_string_to_binary final : public scripting::function_impl {
- int32_t array_size_limit;
- explicit fn_string_to_binary(int32_t _array_size_limit)
- : array_size_limit(_array_size_limit)
- {}
-
- std::optional<script_value> apply(UserScript* self, std::vector<argument> n, std::optional<script_error>& error) final {
- if(n.size() != 1) {
- error = script_error{
- .message = "/string_to_binary takes exactly 1 argument of type string"
- };
- return std::nullopt;
- }
-
- auto& arg = n.front();
- script_value target;
-
- if(std::holds_alternative<scripting::script_value>(arg)) {
- target = std::get<scripting::script_value>(arg);
- } else {
- target = self->resolve(std::get<scripting::script_variable>(arg).name);
- }
-
- if(not std::holds_alternative<std::string>(target)) {
- error = script_error{
- .message = "/string_to_binary takes exactly 1 argument of type string"
- };
- return std::nullopt;
- }
-
- auto& str = std::get<std::string>(target);
-
- array result;
-
- std::transform(str.begin(), str.end(), std::back_inserter(result.value), [&](char value) -> script_value {
- return (int32_t)value;
- });
-
- return result;
- }
-
- ~fn_string_to_binary() final = default;
- };
-
- struct fn_binary_to_string final : public scripting::function_impl {
- int32_t string_size_limit;
- explicit fn_binary_to_string(int32_t _string_size_limit)
- : string_size_limit(_string_size_limit) {}
-
- std::optional<script_value> apply(UserScript* self, std::vector<argument> n, std::optional<script_error>& error) final {
- if(n.size() != 1) {
- error = script_error{
- .message = "/binary_to_string takes exactly 1 argument of type array"
- };
- return std::nullopt;
- }
-
- auto& arg = n.front();
- script_value target;
-
- if(std::holds_alternative<scripting::script_value>(arg)) {
- target = std::get<scripting::script_value>(arg);
- } else {
- target = self->resolve(std::get<scripting::script_variable>(arg).name);
- }
-
- if(not std::holds_alternative<array>(target)) {
- error = script_error{
- .message = "/binary_to_string takes exactly 1 argument of type array"
- };
- return std::nullopt;
- }
-
- auto& ary = std::get<array>(target);
-
- if(ary.value.size() > string_size_limit) {
- error = script_error{
- .message = "/binary_to_string: array is too bit to fit string type"
- };
- return std::nullopt;
- }
-
- std::string result;
-
- const bool valid = std::any_of(ary.value.begin(), ary.value.end(), [](auto val) {
- return std::visit(
- wizardry::overloaded{
- [](int32_t v) { return 0 <= v && v <= 255; },
- [](auto v) { return false; }
- },
- val
- );
- });
-
- if(not valid) {
- error = script_error{
- .message = "/binary_to_string takes exactly 1 argument of type array of which contents must be numbers between 0 and 255 included"
- };
- return std::nullopt;
- }
-
- constexpr auto byte_convert = [](int32_t v) -> char {
- const uint32_t v2 = v;
- const uint8_t v3 = v2 & 0b1111'1111;
- return char(v3);
- };
-
- std::transform(ary.value.begin(), ary.value.end(), std::back_inserter(result), [&](const script_value& value) -> char {
- return std::visit(
- wizardry::overloaded{
- byte_convert,
- [](auto v) { return '\0'; }
- },
- value
- );
- });
-
- return result;
- }
-
- ~fn_binary_to_string() final = default;
- };
-
- struct fn_encode_n final : public scripting::function_impl {
- int32_t string_size_limit;
- explicit fn_encode_n(int32_t _string_size_limit)
- : string_size_limit(_string_size_limit) {}
-
- std::optional<script_value> apply(UserScript* self, std::vector<argument> n, std::optional<script_error>& error) final {
- using verifier = Verify<
- details::SizeEquals<4>,
- details::TypeVerifier<0, int32_t>,
- details::TypeVerifier<1, int32_t>,
- details::TypeVerifier<2, int32_t>,
- details::OctetArrayVerifier<3>
- >;
-
- if(not verifier{}.verify(self, n)) {
- error = script_error{
- .message = "/encode_n takes exactly 3 arguments of type integer and an argument of type array"
- };
- return std::nullopt;
- }
-
- auto& arg = n.front();
- script_value target;
-
- if(std::holds_alternative<scripting::script_value>(arg)) {
- target = std::get<scripting::script_value>(arg);
- } else {
- target = self->resolve(std::get<scripting::script_variable>(arg).name);
- }
-
- bad_cryptography::encode_n_parameters params;
-
- {
- auto& arg = n[3];
- script_value target;
-
- if (std::holds_alternative<scripting::script_value>(arg)) {
- target = std::get<scripting::script_value>(arg);
- } else {
- target = self->resolve(std::get<scripting::script_variable>(arg).name);
- }
-
- params.spin = std::get<int32_t>(target);
- }
-
- {
- auto& arg = n[2];
- script_value target;
-
- if (std::holds_alternative<scripting::script_value>(arg)) {
- target = std::get<scripting::script_value>(arg);
- } else {
- target = self->resolve(std::get<scripting::script_variable>(arg).name);
- }
-
- params.clash = std::get<int32_t>(target);
- }
-
- {
- auto& arg = n[1];
- script_value target;
-
- if (std::holds_alternative<scripting::script_value>(arg)) {
- target = std::get<scripting::script_value>(arg);
- } else {
- target = self->resolve(std::get<scripting::script_variable>(arg).name);
- }
-
- params.maim = std::get<int32_t>(target);
- }
-
- auto ary = std::get<array>(target);
-
- if(ary.value.size() > string_size_limit) {
- error = script_error{
- .message = "/encode_n: array is too bit to fit string type"
- };
- return std::nullopt;
- }
-
- std::transform(ary.value.begin(), ary.value.end(), ary.value.begin(), [&](const script_value& value) {
- return std::visit(
- wizardry::overloaded{
- [&](int32_t v) -> script_value { return script_value{bad_cryptography::encode_n_1(v, params)};},
- [](auto v) -> script_value { return null{}; }
- },
- value
- );
- });
-
- return ary;
- }
-
- ~fn_encode_n() final = default;
- };
-
- interpreter register_crypto_lib(interpreter target, int32_t array_size_limit, int32_t string_size_limit) {
- target->registerFunction("string_to_binary", std::make_unique<fn_string_to_binary>(array_size_limit));
- target->registerFunction("binary_to_string", std::make_unique<fn_binary_to_string>(string_size_limit));
- target->registerFunction("encode_n", std::make_unique<fn_encode_n>(string_size_limit));
- return std::move(target);
- }
- }
|