Skip to content

Commit

Permalink
feat: make most types json serializable
Browse files Browse the repository at this point in the history
  • Loading branch information
Guekka committed Aug 19, 2023
1 parent d11f04c commit e2dd6ba
Show file tree
Hide file tree
Showing 14 changed files with 384 additions and 124 deletions.
1 change: 1 addition & 0 deletions cmake/config.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ find_dependency("tl-expected")
find_dependency("directxtex")
find_dependency("bc7enc")
find_dependency("mpsc_channel")
find_dependency("nlohmann_json")
if(@BETHUTIL_HKX@)
find_dependency("reproc++")
endif()
Expand Down
14 changes: 14 additions & 0 deletions include/btu/bsa/detail/archive_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#pragma once

#include <nlohmann/json.hpp>

#include <cstdint>

namespace btu::bsa {
Expand All @@ -27,4 +29,16 @@ enum class ArchiveVersion : std::uint32_t
fo4dx = 808540228,
};

NLOHMANN_JSON_SERIALIZE_ENUM(ArchiveType,
{{ArchiveType::Textures, "textures"}, {ArchiveType::Standard, "standard"}})

NLOHMANN_JSON_SERIALIZE_ENUM(ArchiveVersion,
{{ArchiveVersion::tes3, "tes3"},
{ArchiveVersion::tes4, "tes4"},
{ArchiveVersion::fo3, "fo3"},
{ArchiveVersion::tes5, "tes5"},
{ArchiveVersion::sse, "sse"},
{ArchiveVersion::fo4, "fo4"},
{ArchiveVersion::fo4dx, "fo4dx"}})

} // namespace btu::bsa
26 changes: 26 additions & 0 deletions include/btu/bsa/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "btu/common/games.hpp"
#include "btu/common/metaprogramming.hpp"

#include <btu/common/json.hpp>

#include <array>
#include <iostream>
#include <optional>
Expand Down Expand Up @@ -49,6 +51,14 @@ enum class FileTypes
BSA
};

NLOHMANN_JSON_SERIALIZE_ENUM(FileTypes,
{{FileTypes::Standard, "standard"},
{FileTypes::Texture, "texture"},
{FileTypes::Incompressible, "incompressible"},
{FileTypes::Blacklist, "blacklist"},
{FileTypes::Plugin, "plugin"},
{FileTypes::BSA, "bsa"}})

static constexpr auto k_bsa_ext = u8".bsa";
static constexpr auto k_ba2_ext = u8".ba2";

Expand All @@ -64,6 +74,8 @@ struct AllowedPath
[[nodiscard]] auto check(const Path &filepath, const Path &root) const -> bool;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AllowedPath, extension, directories)

struct Settings
{
Game game{};
Expand All @@ -88,6 +100,20 @@ struct Settings
[[nodiscard]] static auto get(Game game) -> const Settings &;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Settings,
game,
max_size,
version,
texture_version,
suffix,
texture_suffix,
extension,
plugin_extensions,
s_dummy_plugin,
standard_files,
texture_files,
incompressible_files)

[[nodiscard]] inline auto Settings::get(Game game) -> const Settings &
{
constexpr auto megabyte = 1024ULL * 1024ULL;
Expand Down
11 changes: 11 additions & 0 deletions include/btu/common/games.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <btu/common/json.hpp>

namespace btu {
enum class Game
{
Expand All @@ -12,4 +14,13 @@ enum class Game
Custom
};

NLOHMANN_JSON_SERIALIZE_ENUM(Game,
{{Game::TES3, "tes3"},
{Game::TES4, "tes4"},
{Game::FNV, "fnv"},
{Game::SLE, "sle"},
{Game::SSE, "sse"},
{Game::FO4, "fo4"},
{Game::Custom, "custom"}})

} // namespace btu
119 changes: 119 additions & 0 deletions include/btu/common/json.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#pragma once

#include <btu/common/string.hpp>
#include <nlohmann/json.hpp>

#include <optional>
#include <variant>

// variant from https://github.com/nlohmann/json/issues/1261#issuecomment-426209912

namespace detail {
template<std::size_t N>
struct variant_switch
{
template<typename Variant>
void operator()(int index, nlohmann::json const &value, Variant &v) const
{
if (index == N)
v = value.get<std::variant_alternative_t<N, Variant>>();
else
variant_switch<N - 1>{}(index, value, v);
}
};

template<>
struct variant_switch<0>
{
template<typename Variant>
void operator()(int index, nlohmann::json const &value, Variant &v) const
{
if (index == 0)
v = value.get<std::variant_alternative_t<0, Variant>>();
else
{
throw std::runtime_error("while converting json to variant: invalid index");
}
}
};
} // namespace detail

// yes, we are polluting std. But it's for the greater good (hopefully)
namespace std {
inline void to_json(nlohmann::json &j, const u8string &str)
{
j = ::btu::common::as_ascii(str);
}

inline void from_json(const nlohmann::json &j, u8string &str)
{
str = ::btu::common::as_utf8(j.get<std::string>());
}

inline void to_json(nlohmann::json &j, const u8string_view &str)
{
j = ::btu::common::as_ascii(str);
}

inline void from_json(const nlohmann::json &j, u8string_view &str)
{
str = ::btu::common::as_utf8(j.get<std::string>());
}

} // namespace std

namespace nlohmann {

template<typename T>
struct adl_serializer<::std::optional<T>>
{
static void to_json(json &j, const std::optional<T> &opt)
{
if (opt == std::nullopt)
j = nullptr;
else
j = *opt;
}

static void from_json(const json &j, std::optional<T> &opt)
{
if (j.is_null())
opt = std::nullopt;
else
opt = j.template get<T>();
}
};

template<typename... Args>
struct adl_serializer<::std::variant<Args...>>
{
static void to_json(json &j, std::variant<Args...> const &v)
{
std::visit(
[&](auto &&value) {
j["index"] = v.index();
j["value"] = std::forward<decltype(value)>(value);
},
v);
}

static void from_json(json const &j, std::variant<Args...> &v)
{
auto const index = j.at("index").get<int>();
::detail::variant_switch<sizeof...(Args) - 1>{}(index, j.at("value"), v);
}
};

template<>
struct adl_serializer<::std::monostate>
{
static void to_json(json &j, std::monostate const &) { j = nullptr; }

static void from_json(json const &j, std::monostate &)
{
if (!j.is_null())
throw std::runtime_error("while converting json to variant: invalid index");
}
};

} // namespace nlohmann
5 changes: 5 additions & 0 deletions include/btu/nif/optimize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "btu/common/games.hpp"
#include "btu/nif/detail/common.hpp"

#include <btu/common/json.hpp>
#include <nifly/BasicTypes.hpp>

#include <optional>
Expand All @@ -21,6 +22,10 @@ struct Settings
std::vector<std::u8string> headpart_meshes = {};
};

// NOTE: we ignore headpart_meshes on purpose. While this could result in a loss of data, it is a compromise
// to reduce the amount of data that needs to be stored in the settings file. This list tends to be very long
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Settings, game, rename_referenced_textures)

struct OptimizationSteps
{
bool rename_referenced_textures = true;
Expand Down
Loading

0 comments on commit e2dd6ba

Please sign in to comment.