fangorn/sunshine-qemu
public
ref:main
/**
* @file src/platform/windows/nvprefs/undo_data.cpp
* @brief Definitions for undoing changes to nvidia preferences.
*/
// lib includes
#include <nlohmann/json.hpp>
// local includes
#include "nvprefs_common.h"
#include "undo_data.h"
/**
* @brief nlohmann JSON type used for NVPrefs undo serialization.
*/
using json = nlohmann::json;
// Separate namespace for ADL, otherwise we need to define json
// functions in the same namespace as our types
namespace nlohmann {
/**
* @brief Serialized undo-data representation.
*/
using data_t = nvprefs::undo_data_t::data_t;
/**
* @brief Serialized OpenGL swapchain profile settings.
*/
using opengl_swapchain_t = data_t::opengl_swapchain_t;
/**
* @brief Helper specialization for optional values.
*/
template<typename T>
struct adl_serializer<std::optional<T>> {
/**
* @brief Serialize the undo-data object to JSON.
*
* @param j JSON value being read from or written to.
* @param opt Optional value being serialized or restored.
*/
static void to_json(json &j, const std::optional<T> &opt) {
if (opt == std::nullopt) {
j = nullptr;
} else {
j = *opt;
}
}
/**
* @brief Deserialize the undo-data object from JSON.
*
* @param j JSON value being read from or written to.
* @param opt Optional value being serialized or restored.
*/
static void from_json(const json &j, std::optional<T> &opt) {
if (j.is_null()) {
opt = std::nullopt;
} else {
opt = j.template get<T>();
}
}
};
/**
* @brief JSON serializer specialization for undo-data records.
*/
template<>
struct adl_serializer<data_t> {
/**
* @brief Serialize the undo-data object to JSON.
*
* @param j JSON value being read from or written to.
* @param data Payload or state data to serialize, deserialize, or forward.
*/
static void to_json(json &j, const data_t &data) {
j = json {{"opengl_swapchain", data.opengl_swapchain}};
}
/**
* @brief Deserialize the undo-data object from JSON.
*
* @param j JSON value being read from or written to.
* @param data Payload or state data to serialize, deserialize, or forward.
*/
static void from_json(const json &j, data_t &data) {
j.at("opengl_swapchain").get_to(data.opengl_swapchain);
}
};
/**
* @brief JSON serializer specialization for OpenGL swapchain settings.
*/
template<>
struct adl_serializer<opengl_swapchain_t> {
/**
* @brief Serialize the undo-data object to JSON.
*
* @param j JSON value being read from or written to.
* @param opengl_swapchain Opengl swapchain.
*/
static void to_json(json &j, const opengl_swapchain_t &opengl_swapchain) {
j = json {
{"our_value", opengl_swapchain.our_value},
{"undo_value", opengl_swapchain.undo_value}
};
}
/**
* @brief Deserialize the undo-data object from JSON.
*
* @param j JSON value being read from or written to.
* @param opengl_swapchain Opengl swapchain.
*/
static void from_json(const json &j, opengl_swapchain_t &opengl_swapchain) {
j.at("our_value").get_to(opengl_swapchain.our_value);
j.at("undo_value").get_to(opengl_swapchain.undo_value);
}
};
} // namespace nlohmann
namespace nvprefs {
void undo_data_t::set_opengl_swapchain(uint32_t our_value, std::optional<uint32_t> undo_value) {
data.opengl_swapchain = data_t::opengl_swapchain_t {
our_value,
undo_value
};
}
std::optional<undo_data_t::data_t::opengl_swapchain_t> undo_data_t::get_opengl_swapchain() const {
return data.opengl_swapchain;
}
std::string undo_data_t::write() const {
try {
// Keep this assignment otherwise data will be treated as an array due to
// initializer list shenanigangs.
const json json_data = data;
return json_data.dump();
} catch (const std::exception &err) {
error_message(std::string {"failed to serialize json data"});
return {};
}
}
void undo_data_t::read(const std::vector<char> &buffer) {
try {
data = json::parse(std::begin(buffer), std::end(buffer));
} catch (const std::exception &err) {
error_message(std::string {"failed to parse json data: "} + err.what());
data = {};
}
}
void undo_data_t::merge(const undo_data_t &newer_data) {
const auto &swapchain_data = newer_data.get_opengl_swapchain();
if (swapchain_data) {
set_opengl_swapchain(swapchain_data->our_value, swapchain_data->undo_value);
}
}
} // namespace nvprefs