// This file Copyright © 2022 Mnemosyne LLC. // It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only), // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. #include #include "transmission.h" #include "log.h" // for tr_log_level #include "net.h" // for tr_port #include "utils.h" // for tr_strvStrip(), tr_strlower() #include "variant.h" using namespace std::literals; namespace libtransmission { template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = bool{}; tr_variantGetBool(src, &val)) { return val; } return {}; } template<> void VariantConverter::save(tr_variant* tgt, bool const& val) { tr_variantInitBool(tgt, val); } /// template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = double{}; tr_variantGetReal(src, &val)) { return val; } return {}; } template<> void VariantConverter::save(tr_variant* tgt, double const& val) { tr_variantInitReal(tgt, val); } /// namespace EncryptionHelpers { // clang-format off static auto constexpr Keys = std::array, 3>{{ { "required", TR_ENCRYPTION_REQUIRED }, { "preferred", TR_ENCRYPTION_PREFERRED }, { "allowed", TR_CLEAR_PREFERRED } }}; // clang-format on } // namespace EncryptionHelpers template<> std::optional VariantConverter::load(tr_variant* src) { using namespace EncryptionHelpers; if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) { auto const needle = tr_strlower(tr_strvStrip(val)); for (auto const& [key, encryption] : Keys) { if (key == needle) { return encryption; } } } if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { for (auto const& [key, encryption] : Keys) { if (encryption == val) { return encryption; } } } return {}; } template<> void VariantConverter::save(tr_variant* tgt, tr_encryption_mode const& val) { tr_variantInitInt(tgt, val); } /// namespace LogLevelHelpers { // clang-format off static auto constexpr Keys = std::array, 7>{ { { "critical", TR_LOG_CRITICAL }, { "debug", TR_LOG_DEBUG }, { "error", TR_LOG_ERROR }, { "info", TR_LOG_INFO }, { "off", TR_LOG_OFF }, { "trace", TR_LOG_TRACE }, { "warn", TR_LOG_WARN }, }}; // clang-format on } // namespace LogLevelHelpers template<> std::optional VariantConverter::load(tr_variant* src) { using namespace LogLevelHelpers; if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) { auto const needle = tr_strlower(tr_strvStrip(val)); for (auto const& [name, log_level] : Keys) { if (needle == name) { return log_level; } } } if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { for (auto const& [name, log_level] : Keys) { if (log_level == val) { return log_level; } } } return {}; } template<> void VariantConverter::save(tr_variant* tgt, tr_log_level const& val) { tr_variantInitInt(tgt, val); } /// template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) { if (auto const mode = tr_parseNum(val, nullptr, 8); mode) { return static_cast(*mode); } } if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { return static_cast(val); } return {}; } template<> void VariantConverter::save(tr_variant* tgt, tr_mode_t const& val) { tr_variantInitStr(tgt, fmt::format("{:#03o}", val)); } /// template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { return tr_port::fromHost(val); } return {}; } template<> void VariantConverter::save(tr_variant* tgt, tr_port const& val) { tr_variantInitInt(tgt, val.host()); } /// namespace PreallocationModeHelpers { // clang-format off static auto constexpr Keys = std::array, 5>{{ { "off", TR_PREALLOCATE_NONE }, { "none", TR_PREALLOCATE_NONE }, { "fast", TR_PREALLOCATE_SPARSE }, { "sparse", TR_PREALLOCATE_SPARSE }, { "full", TR_PREALLOCATE_FULL }, }}; // clang-format on } // namespace PreallocationModeHelpers template<> std::optional VariantConverter::load(tr_variant* src) { using namespace PreallocationModeHelpers; if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) { auto const needle = tr_strlower(tr_strvStrip(val)); for (auto const& [name, value] : Keys) { if (name == needle) { return value; } } } if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { for (auto const& [name, value] : Keys) { if (value == val) { return value; } } } return {}; } template<> void VariantConverter::save(tr_variant* tgt, tr_preallocation_mode const& val) { tr_variantInitInt(tgt, val); } /// template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { return static_cast(val); } return {}; } template<> void VariantConverter::save(tr_variant* tgt, size_t const& val) { tr_variantInitInt(tgt, val); } /// template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) { return std::string{ val }; } return {}; } template<> void VariantConverter::save(tr_variant* tgt, std::string const& val) { tr_variantInitStr(tgt, val); } /// template<> std::optional VariantConverter::load(tr_variant* src) { if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) { return tr_tos_t::from_string(val); } if (auto val = int64_t{}; tr_variantGetInt(src, &val)) { return tr_tos_t{ static_cast(val) }; } return {}; } template<> void VariantConverter::save(tr_variant* tgt, tr_tos_t const& val) { tr_variantInitStr(tgt, val.toString()); } } // namespace libtransmission