/* ** sandbox-serial-util.h ** ** This file is part of mkxp. ** ** Copyright (C) 2013 - 2021 Amaryllis Kulla ** ** mkxp is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) any later version. ** ** mkxp is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with mkxp. If not, see . */ #ifndef MKXPZ_SANDBOX_SERIAL_UTIL_H #define MKXPZ_SANDBOX_SERIAL_UTIL_H #include #include #include #include #include #include "binding-util.h" #include "quadarray.h" namespace mkxp_sandbox { extern std::vector> extra_objects; template using sandbox_serialize_member_declaration = decltype(std::declval().sandbox_serialize(std::declval(), std::declval())); template typename std::enable_if::value, bool>::type sandbox_serialize(T value, void *&data, wasm_size_t &max_size); template typename std::enable_if::value, bool>::type sandbox_serialize(T value, void *&data, wasm_size_t &max_size); template typename std::enable_if::value && !std::is_enum::value && (std::is_integral::value || std::is_floating_point::value), bool>::type sandbox_serialize(T value, void *&data, wasm_size_t &max_size); template bool sandbox_serialize(const std::vector &value, void *&data, wasm_size_t &max_size); template bool sandbox_serialize(const QuadArray &value, void *&data, wasm_size_t &max_size); template typename std::enable_if::value, bool>::type sandbox_serialize(const T *value, void *&data, wasm_size_t &max_size); template typename std::enable_if::value, bool>::type sandbox_serialize(const T *value, void *&data, wasm_size_t &max_size); template typename std::enable_if::value && boost::is_detected::value, bool>::type sandbox_serialize(const T &value, void *&data, wasm_size_t &max_size); template typename std::enable_if::value && !boost::is_detected::value, bool>::type sandbox_serialize(const T &value, void *&data, wasm_size_t &max_size); template struct sandbox_ptr_map { private: struct info { mkxp_sandbox::wasm_objkey_t key; bool is_extra; }; static std::unordered_map map; static bool is_serializing; public: static void sandbox_serialize_begin() { using namespace mkxp_sandbox; if (is_serializing) { return; } is_serializing = true; map.clear(); extra_objects.clear(); wasm_objkey_t key = 0; for (const auto &object : sb()->get_objects()) { ++key; if (object.typenum == get_typenum::value) { map.emplace((T *)object.inner.ptr, (struct info){.key = key, .is_extra = false}); } } } static bool sandbox_serialize(const T *ptr, void *&data, wasm_size_t &max_size) { using namespace mkxp_sandbox; if (ptr == nullptr) { if (!mkxp_sandbox::sandbox_serialize((uint8_t)2, data, max_size)) return false; } else { const auto &it = map.find(ptr); if (it != map.end()) { if (!mkxp_sandbox::sandbox_serialize((uint8_t)(it->second.is_extra ? 1 : 0), data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(it->second.key, data, max_size)) return false; } else { if (!mkxp_sandbox::sandbox_serialize((uint8_t)1, data, max_size)) return false; constexpr wasm_size_t typenum = get_typenum::value; extra_objects.emplace_back((const void *)ptr, typenum); map.emplace(ptr, (struct info){.key = (wasm_objkey_t)extra_objects.size(), .is_extra = true}); if (!mkxp_sandbox::sandbox_serialize((wasm_objkey_t)extra_objects.size(), data, max_size)) return false; } } return true; } static void sandbox_serialize_end() { is_serializing = false; map.clear(); extra_objects.clear(); } }; template std::unordered_map::info> sandbox_ptr_map::map; template bool sandbox_ptr_map::is_serializing = false; template typename std::enable_if::value, bool>::type sandbox_serialize(const T *value, void *&data, wasm_size_t &max_size) { return sandbox_ptr_map::sandbox_serialize(value, data, max_size); } template bool sandbox_serialize(const std::vector &value, void *&data, wasm_size_t &max_size) { if (!sandbox_serialize((wasm_size_t)value.size(), data, max_size)) return false; for (const T &item : value) { if (!sandbox_serialize(item, data, max_size)) return false; } return true; } template bool sandbox_serialize(const QuadArray &value, void *&data, wasm_size_t &max_size) { return sandbox_serialize(value.vertices, data, max_size); } template typename std::enable_if::value, bool>::type sandbox_serialize(T value, void *&data, wasm_size_t &max_size) { return sandbox_serialize((int32_t)value, data, max_size); } template typename std::enable_if::value && boost::is_detected::value, bool>::type sandbox_serialize(const T &value, void *&data, wasm_size_t &max_size) { return value.sandbox_serialize(data, max_size); } } #endif // MKXPZ_SANDBOX_SERIAL_UTIL_H