1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-27 12:41:00 +01:00

Add some infrastructure changes for better JSON ref<T> impls

Also skip a trailing semicolon inside a macro so the caller can use it
instead, which is generally nicer to the formatter.
This commit is contained in:
John Ericson 2025-11-24 14:15:06 -05:00
parent f198e9a0b3
commit f78e88c973
3 changed files with 43 additions and 11 deletions

View file

@ -5,6 +5,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "nix/util/types.hh" #include "nix/util/types.hh"
#include "nix/util/ref.hh"
#include "nix/util/file-system.hh" #include "nix/util/file-system.hh"
#include "nix/util/tests/characterization.hh" #include "nix/util/tests/characterization.hh"
@ -39,6 +40,25 @@ void writeJsonTest(CharacterizationTest & test, PathView testStem, const T & val
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); });
} }
/**
* Specialization for when we need to do "JSON -> `ref<T>`" in one
* direction, but "`const T &` -> JSON" in the other direction.
*
* We can't just return `const T &`, but it would be wasteful to
* requires a `const ref<T> &` double indirection (and mandatory shared
* pointer), so we break the symmetry as the best remaining option.
*/
template<typename T>
void writeJsonTest(CharacterizationTest & test, PathView testStem, const ref<T> & value)
{
using namespace nlohmann;
test.writeTest(
Path{testStem} + ".json",
[&]() -> json { return static_cast<json>(*value); },
[](const auto & file) { return json::parse(readFile(file)); },
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); });
}
/** /**
* Golden test in the middle of something * Golden test in the middle of something
*/ */

View file

@ -6,18 +6,30 @@
#include "nix/util/experimental-features.hh" #include "nix/util/experimental-features.hh"
// Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types // Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
#define JSON_IMPL_INNER_TO(TYPE) \
struct adl_serializer<TYPE> \
{ \
static void to_json(json & json, const TYPE & t); \
}
#define JSON_IMPL_INNER_FROM(TYPE) \
struct adl_serializer<TYPE> \
{ \
static TYPE from_json(const json & json); \
}
#define JSON_IMPL_INNER(TYPE) \ #define JSON_IMPL_INNER(TYPE) \
struct adl_serializer<TYPE> \ struct adl_serializer<TYPE> \
{ \ { \
static TYPE from_json(const json & json); \ static TYPE from_json(const json & json); \
static void to_json(json & json, const TYPE & t); \ static void to_json(json & json, const TYPE & t); \
}; }
#define JSON_IMPL(TYPE) \ #define JSON_IMPL(TYPE) \
namespace nlohmann { \ namespace nlohmann { \
using namespace nix; \ using namespace nix; \
template<> \ template<> \
JSON_IMPL_INNER(TYPE) \ JSON_IMPL_INNER(TYPE); \
} }
#define JSON_IMPL_WITH_XP_FEATURES(TYPE) \ #define JSON_IMPL_WITH_XP_FEATURES(TYPE) \

View file

@ -188,23 +188,23 @@ using namespace nix;
#define ARG fso::Regular<RegularContents> #define ARG fso::Regular<RegularContents>
template<typename RegularContents> template<typename RegularContents>
JSON_IMPL_INNER(ARG) JSON_IMPL_INNER(ARG);
#undef ARG #undef ARG
#define ARG fso::DirectoryT<Child> #define ARG fso::DirectoryT<Child>
template<typename Child> template<typename Child>
JSON_IMPL_INNER(ARG) JSON_IMPL_INNER(ARG);
#undef ARG #undef ARG
template<> template<>
JSON_IMPL_INNER(fso::Symlink) JSON_IMPL_INNER(fso::Symlink);
template<> template<>
JSON_IMPL_INNER(fso::Opaque) JSON_IMPL_INNER(fso::Opaque);
#define ARG fso::VariantT<RegularContents, recur> #define ARG fso::VariantT<RegularContents, recur>
template<typename RegularContents, bool recur> template<typename RegularContents, bool recur>
JSON_IMPL_INNER(ARG) JSON_IMPL_INNER(ARG);
#undef ARG #undef ARG
} // namespace nlohmann } // namespace nlohmann