43 static small test(
decltype(&C::fromJSON));
48 static const bool value =
sizeof(test<T>(0)) ==
sizeof(
char);
51 using NodeReferences = std::unordered_map<int, IR::Node *>;
52 std::shared_ptr<NodeReferences> node_refs;
53 std::unique_ptr<JsonData> json_root;
56 std::unique_ptr<absl::flat_hash_set<P4::cstring, Util::Hash>> decoded;
57 bool (*errfn)(
const JSONLoader &, std::string_view msg) =
nullptr;
59 JSONLoader(
const JsonData *
json, std::shared_ptr<NodeReferences> refs,
61 : node_refs(std::move(refs)),
json(
json), locinfo(locinfo) {}
65 : node_refs(std::make_shared<NodeReferences>()), locinfo(li) {
67 json = json_root.get();
70 JSONLoader(
const JSONLoader &unpacker, std::string_view field)
71 : node_refs(unpacker.node_refs),
json(
nullptr), locinfo(unpacker.locinfo) {
72 if (!unpacker)
return;
74 if (
auto it = obj->find(field); it != obj->end()) {
75 if (unpacker.decoded) unpacker.decoded->emplace(field);
76 json = it->second.get();
81 explicit operator bool()
const {
return json !=
nullptr; }
83 [[nodiscard]]
bool is()
const {
87 [[nodiscard]]
const T &as()
const {
91 [[nodiscard]]
const T *to()
const {
92 return json ?
json->to<T>() :
nullptr;
95 std::string locdesc(
const JsonData &d)
const {
96 if (!locinfo)
return "";
97 return locinfo->desc(d);
99 std::string locdesc()
const {
100 if (!
json)
return "";
101 return locdesc(*
json);
103 std::string locdesc(std::string_view field)
const {
104 if (!locinfo || !
json)
return "";
106 if (
auto it = obj->find(field); it != obj->end())
return locinfo->desc(*it->second);
110 bool error(std::string_view msg)
const {
115 void track_decode() {
116 BUG_CHECK(
json &&
json->is<
JsonObject>(),
"JSONLoader::track_decode on non-JsonObject");
117 if (!decoded) decoded = std::make_unique<absl::flat_hash_set<P4::cstring, Util::Hash>>();
120 template <
typename FN>
121 void undecoded(FN fn) {
122 BUG_CHECK(decoded,
"Called JSONLoader::undecoded without track_decode");
124 if (!decoded->count(el.first)) fn(*
this, el.first, *el.second);
128 const IR::Node *get_node(NodeFactoryFn factory =
nullptr) {
130 error(
"node is not a JsonObject");
135 auto success = load(
"Node_ID",
id) || error(
"missing field Node_ID");
136 if (!success)
return nullptr;
138 if (node_refs->find(
id) == node_refs->end()) {
141 auto success = load(
"Node_Type", type) || error(
"missing field Node_Type");
142 if (!success)
return nullptr;
143 factory = get(IR::unpacker_table, type);
146 auto *node = factory(*this)->to<
IR::Node>();
148 node_refs->emplace(
id, node);
152 node->sourceInfoFromJSON(*
this);
154 error(
"no Node factory for " + type);
158 return node_refs->at(
id);
160 error(
"invalid Node_ID " + std::to_string(
id));
164 template <
typename T>
168 for (
auto &e : as<JsonVector>()) {
174 template <
typename T>
175 void unpack_json(std::set<T> &v) {
178 for (
auto &e : as<JsonVector>()) {
184 template <
typename T>
188 for (
auto &e : as<JsonVector>()) {
194 template <
typename T>
196 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->
as<
IR::Vector<T>>();
198 template <
typename T>
200 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->checkedTo<
IR::Vector<T>>();
202 template <
typename T>
206 template <
typename T>
208 v = get_node(NodeFactoryFn(&IR::IndexedVector<T>::fromJSON))
211 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
214 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
217 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
220 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
224 template <
typename K,
typename V>
225 void unpack_json(std::map<K, V> &v) {
226 std::pair<K, V> temp;
228 if (is<JsonVector>()) {
229 for (
auto &e : as<JsonVector>()) {
234 for (
auto &e : as<JsonObject>()) {
236 load(e.second, temp.second);
241 template <
typename K,
typename V>
243 std::pair<K, V> temp;
245 if (is<JsonVector>()) {
246 for (
auto &e : as<JsonVector>()) {
251 for (
auto &e : as<JsonObject>()) {
253 load(e.second, temp.second);
258 template <
typename V>
260 std::pair<cstring, V> temp;
262 for (
auto &e : as<JsonObject>()) {
263 temp.first = e.first;
264 load(e.second, temp.second);
269 template <
typename K,
typename V>
270 void unpack_json(std::multimap<K, V> &v) {
271 std::pair<K, V> temp;
273 if (is<JsonVector>()) {
274 for (
auto &e : as<JsonVector>()) {
279 for (
auto &e : as<JsonObject>()) {
281 load(e.second, temp.second);
287 template <
typename T>
288 void unpack_json(std::vector<T> &v) {
291 for (
auto &e : as<JsonVector>()) {
297 template <
typename T,
typename U>
298 void unpack_json(std::pair<T, U> &v) {
299 load(
"first", v.first) || error(
"missing field first");
300 load(
"second", v.second) || error(
"missing field second");
303 template <
typename T>
304 void unpack_json(std::optional<T> &v) {
305 bool isValid =
false;
306 load(
"valid", isValid) || error(
"missing field valid");
312 auto success = load(
"value", value) || error(
"missing field value");
317 v = std::move(value);
320 template <
int N,
class Variant>
321 std::enable_if_t<N == std::variant_size_v<Variant>> unpack_variant(
int ,
323 BUG(
"Error traversing variant during load");
326 template <
int N,
class Variant>
327 std::enable_if_t<(N < std::variant_size_v<Variant>)> unpack_variant(
int target,
330 variant.template emplace<N>();
331 load(
"value", std::get<N>(variant)) || error(
"missing field value");
333 unpack_variant<N + 1>(target, variant);
336 template <
class... Types>
337 void unpack_json(std::variant<Types...> &v) {
339 load(
"variant_index", index) || error(
"missing field variant_index");
340 unpack_variant<0>(index, v);
343 void unpack_json(
bool &v) { v = as<JsonBoolean>(); }
345 template <
typename T>
346 std::enable_if_t<std::is_integral_v<T>> unpack_json(T &v) {
347 v = as<JsonNumber>();
349 void unpack_json(big_int &v) { v = as<JsonNumber>().val; }
350 void unpack_json(std::string &v) {
351 if (is<JsonString>()) v = as<JsonString>();
354 if (is<JsonString>())
356 else if (is<JsonNull>())
359 void unpack_json(
IR::ID &v) {
367 void unpack_json(
bitvec &v) {
371 template <
typename T>
372 std::enable_if_t<std::is_enum_v<T>> unpack_json(T &v) {
380 template <
typename T>
381 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
382 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
384 v = T::fromJSON(*
this);
387 template <
typename T>
388 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
389 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
391 v = *(T::fromJSON(*
this));
394 template <
typename T>
395 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
396 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
398 v = T::fromJSON(*
this);
401 template <
typename T>
402 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
403 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
405 v =
new T(T::fromJSON(*
this));
408 template <
typename T>
409 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(T &v) {
410 v = get_node()->as<T>();
412 template <
typename T>
413 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(
const T *&v) {
414 v = get_node()->checkedTo<T>();
417 template <
typename T,
size_t N>
418 void unpack_json(T (&v)[N]) {
420 for (
size_t i = 0; i < N && i < j->size(); ++i) {
421 load(j->at(i), v[i]);
427 template <
typename T>
429 JSONLoader(&
json, node_refs, locinfo).unpack_json(v);
432 template <
typename T>
433 void load(
const std::unique_ptr<JsonData> &
json, T &v) {
434 JSONLoader(
json.get(), node_refs, locinfo).unpack_json(v);
437 template <
typename T>
438 bool load(std::string_view field, T *&v) {
439 if (
auto loader = JSONLoader(*
this, field)) {
440 loader.unpack_json(v);
448 template <
typename T>
449 bool load(std::string_view field, T &v) {
450 if (
auto loader = JSONLoader(*
this, field)) {
451 loader.unpack_json(v);
457 template <
typename T>
458 JSONLoader &operator>>(T &v) {