Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
json.hh
1#pragma once
9
10#include "lix/libutil/error.hh"
11#include "lix/libutil/fmt.hh"
12#include "lix/libutil/json-fwd.hh" // IWYU pragma: export
13#include <concepts>
14#include <nlohmann/json.hpp> // IWYU pragma: export
15#include <list>
16#include <string_view>
17#include <type_traits>
18
19namespace nix {
20
27const JSON & ensureType(
28 const JSON & value,
29 JSON::value_type expectedType);
30
31namespace json {
32
36template<typename T>
38 : std::bool_constant<std::is_integral_v<T> || std::is_floating_point_v<T> || IntegralEnum<T>>
39{};
40
41template<>
42struct avoids_null<std::nullptr_t> : std::false_type {};
43
44template<>
45struct avoids_null<bool> : std::true_type {};
46
47template<>
48struct avoids_null<std::string> : std::true_type {};
49
50template<typename T>
51struct avoids_null<std::vector<T>> : std::true_type {};
52
53template<typename T>
54struct avoids_null<std::list<T>> : std::true_type {};
55
56template<typename K, typename V>
57struct avoids_null<std::map<K, V>> : std::true_type {};
58
59namespace detail {
60template<typename Json, typename T>
61 requires requires(Json & j, T value) { to_json(j, value); }
62void call_to_json(Json & j, const T & value)
63{
64 to_json(j, value);
65}
66
67template<typename Json, typename T>
68 requires requires(Json && j, T & value) { from_json(std::forward<Json>(j), value); }
69void call_from_json(Json && j, T & value)
70{
71 from_json(std::forward<Json>(j), value);
72}
73}
74
75template<typename T>
76struct adl_serializer<T, void>
77{
78 template<typename Json>
79 requires requires(Json & j, T value) { detail::call_to_json(j, value); }
80 static void to_json(Json & j, const T & value)
81 {
82 detail::call_to_json(j, value);
83 }
84
85 template<typename Json>
86 requires requires(Json && j, T & value) {
87 detail::call_from_json(std::forward<Json>(j), value);
88 }
89 static void from_json(Json && j, T & value)
90 {
91 detail::call_from_json(std::forward<Json>(j), value);
92 }
93
94 // Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
95 template<typename Json>
96 requires requires(Json & j, T value) { T::to_json(j, value); }
97 static void to_json(Json & j, const T & value)
98 {
99 T::to_json(j, value);
100 }
101
102 template<typename Json>
103 requires requires(Json && j) {
104 {
105 T::from_json(std::forward<Json>(j))
106 } -> std::same_as<T>;
107 }
108 static auto from_json(Json && j)
109 {
110 return T::from_json(std::forward<Json>(j));
111 }
112
113 template<typename Json>
114 requires IntegralEnum<T>
115 static void to_json(Json && json, const T & value)
116 {
117 json = static_cast<std::underlying_type_t<T>>(value);
118 }
119
120 template<typename Json>
121 requires IntegralEnum<T>
122 static void from_json(const Json & json, T & value)
123 {
124 value = static_cast<T>(json.template get<std::underlying_type_t<T>>());
125 }
126};
127
128template<typename T>
129struct adl_serializer<std::optional<T>>
130{
135 static void from_json(const auto & json, std::optional<T> & t)
136 {
137 static_assert(avoids_null<T>::value, "null is already in use for underlying type's JSON");
138 t = json.is_null() ? std::nullopt : std::make_optional(json.template get<T>());
139 }
140
145 static void to_json(auto & json, const std::optional<T> & t)
146 {
147 static_assert(avoids_null<T>::value, "null is already in use for underlying type's JSON");
148 if (t) {
149 json = *t;
150 } else {
151 json = nullptr;
152 }
153 }
154};
155
156MakeError(ParseError, Error);
157
162template<typename Source>
163JSON parse(Source && source, std::optional<std::string_view> context = {})
164{
165 try {
166 // NOLINTNEXTLINE(lix-disallowed-decls): this is the wrapper for that
167 return JSON::parse(std::forward<Source>(source));
168 } catch (JSON::exception & e) { // NOLINT(lix-foreign-exceptions)
169 ParseError error{"failed to parse JSON: %s", e.what()};
170 if (context) {
171 error.addTrace(nullptr, fmt("while parsing %s", *context));
172 }
173 throw error;
174 }
175}
176}
177
178}
Definition json-fwd.hh:24
This file defines two main structs/classes used in nix error handling.
std::string fmt(const std::string &s)
Definition fmt.hh:127
Definition serialise.hh:66
static void to_json(auto &json, const std::optional< T > &t)
Convert an optional type to a JSON type treating std::nullopt as null.
Definition json.hh:145
static void from_json(const auto &json, std::optional< T > &t)
Convert a JSON type to an optional<T> treating null as std::nullopt.
Definition json.hh:135
Definition json-fwd.hh:27
Definition json.hh:39