42 static small test(
decltype(&C::fromJSON));
47 static const bool value =
sizeof(test<T>(0)) ==
sizeof(
char);
50 std::unordered_map<int, IR::Node *> &node_refs;
51 std::unique_ptr<JsonData> json_root;
54 std::unique_ptr<absl::flat_hash_set<P4::cstring, Util::Hash>> decoded;
55 bool (*errfn)(
const JSONLoader &, std::string_view msg) =
nullptr;
57 JSONLoader(
const JsonData *
json, std::unordered_map<int, IR::Node *> &refs,
59 : node_refs(refs),
json(
json), locinfo(locinfo) {}
63 : node_refs(*(
new std::unordered_map<int, IR::Node *>())), locinfo(li) {
65 json = json_root.get();
68 JSONLoader(
const JSONLoader &unpacker, std::string_view field)
69 : node_refs(unpacker.node_refs),
json(
nullptr), locinfo(unpacker.locinfo) {
70 if (!unpacker)
return;
72 if (
auto it = obj->find(field); it != obj->end()) {
73 if (unpacker.decoded) unpacker.decoded->emplace(field);
74 json = it->second.get();
79 explicit operator bool()
const {
return json !=
nullptr; }
81 [[nodiscard]]
bool is()
const {
85 [[nodiscard]]
const T &as()
const {
89 [[nodiscard]]
const T *to()
const {
90 return json ?
json->to<T>() :
nullptr;
93 std::string locdesc(
const JsonData &d)
const {
94 if (!locinfo)
return "";
95 return locinfo->desc(d);
97 std::string locdesc()
const {
99 return locdesc(*
json);
101 std::string locdesc(std::string_view field)
const {
102 if (!locinfo || !
json)
return "";
104 if (
auto it = obj->find(field); it != obj->end())
return locinfo->desc(*it->second);
108 bool error(std::string_view msg)
const {
113 void track_decode() {
114 BUG_CHECK(
json &&
json->is<
JsonObject>(),
"JSONLoader::track_decode on non-JsonObject");
115 if (!decoded) decoded = std::make_unique<absl::flat_hash_set<P4::cstring, Util::Hash>>();
118 template <
typename FN>
119 void undecoded(FN fn) {
120 BUG_CHECK(decoded,
"Called JSONLoader::undecoded without track_decode");
122 if (!decoded->count(el.first)) fn(*
this, el.first, *el.second);
126 const IR::Node *get_node(NodeFactoryFn factory =
nullptr) {
128 error(
"node is not a JsonObject");
133 auto success = load(
"Node_ID",
id) || error(
"missing field Node_ID");
134 if (!success)
return nullptr;
136 if (node_refs.find(
id) == node_refs.end()) {
139 auto success = load(
"Node_Type", type) || error(
"missing field Node_Type");
140 if (!success)
return nullptr;
141 factory = get(IR::unpacker_table, type);
144 auto *node = factory(*this)->to<
IR::Node>();
146 node_refs[id] = node;
150 node_refs[id]->sourceInfoFromJSON(*
this);
152 error(
"no Node factory for " + type);
156 return node_refs[id];
158 error(
"invalid Node_ID " + std::to_string(
id));
162 template <
typename T>
166 for (
auto &e : as<JsonVector>()) {
172 template <
typename T>
173 void unpack_json(std::set<T> &v) {
176 for (
auto &e : as<JsonVector>()) {
182 template <
typename T>
186 for (
auto &e : as<JsonVector>()) {
192 template <
typename T>
194 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->
as<
IR::Vector<T>>();
196 template <
typename T>
198 v = get_node(NodeFactoryFn(&IR::Vector<T>::fromJSON))->checkedTo<
IR::Vector<T>>();
200 template <
typename T>
204 template <
typename T>
206 v = get_node(NodeFactoryFn(&IR::IndexedVector<T>::fromJSON))
209 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
212 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
215 template <
class T,
template <
class K,
class V,
class COMP,
class ALLOC>
class MAP,
class COMP,
218 m = get_node(NodeFactoryFn(&IR::NameMap<T, MAP, COMP, ALLOC>::fromJSON))
222 template <
typename K,
typename V>
223 void unpack_json(std::map<K, V> &v) {
224 std::pair<K, V> temp;
226 if (is<JsonVector>()) {
227 for (
auto &e : as<JsonVector>()) {
232 for (
auto &e : as<JsonObject>()) {
234 load(e.second, temp.second);
239 template <
typename K,
typename V>
241 std::pair<K, V> temp;
243 if (is<JsonVector>()) {
244 for (
auto &e : as<JsonVector>()) {
249 for (
auto &e : as<JsonObject>()) {
251 load(e.second, temp.second);
256 template <
typename V>
258 std::pair<cstring, V> temp;
260 for (
auto &e : as<JsonObject>()) {
261 temp.first = e.first;
262 load(e.second, temp.second);
267 template <
typename K,
typename V>
268 void unpack_json(std::multimap<K, V> &v) {
269 std::pair<K, V> temp;
271 if (is<JsonVector>()) {
272 for (
auto &e : as<JsonVector>()) {
277 for (
auto &e : as<JsonObject>()) {
279 load(e.second, temp.second);
285 template <
typename T>
286 void unpack_json(std::vector<T> &v) {
289 for (
auto &e : as<JsonVector>()) {
295 template <
typename T,
typename U>
296 void unpack_json(std::pair<T, U> &v) {
297 load(
"first", v.first) || error(
"missing field first");
298 load(
"second", v.second) || error(
"missing field second");
301 template <
typename T>
302 void unpack_json(std::optional<T> &v) {
303 bool isValid =
false;
304 load(
"valid", isValid) || error(
"missing field valid");
310 auto success = load(
"value", value) || error(
"missing field value");
315 v = std::move(value);
318 template <
int N,
class Variant>
319 std::enable_if_t<N == std::variant_size_v<Variant>> unpack_variant(
int ,
321 BUG(
"Error traversing variant during load");
324 template <
int N,
class Variant>
325 std::enable_if_t<(N < std::variant_size_v<Variant>)> unpack_variant(
int target,
328 variant.template emplace<N>();
329 load(
"value", std::get<N>(variant)) || error(
"missing field value");
331 unpack_variant<N + 1>(target, variant);
334 template <
class... Types>
335 void unpack_json(std::variant<Types...> &v) {
337 load(
"variant_index", index) || error(
"missing field variant_index");
338 unpack_variant<0>(index, v);
341 void unpack_json(
bool &v) { v = as<JsonBoolean>(); }
343 template <
typename T>
344 std::enable_if_t<std::is_integral_v<T>> unpack_json(T &v) {
345 v = as<JsonNumber>();
347 void unpack_json(big_int &v) { v = as<JsonNumber>().val; }
348 void unpack_json(std::string &v) {
349 if (is<JsonString>()) v = as<JsonString>();
352 if (is<JsonString>())
354 else if (is<JsonNull>())
357 void unpack_json(
IR::ID &v) {
365 void unpack_json(
bitvec &v) {
369 template <
typename T>
370 std::enable_if_t<std::is_enum_v<T>> unpack_json(T &v) {
378 template <
typename T>
379 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
380 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
382 v = T::fromJSON(*
this);
385 template <
typename T>
386 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of_v<IR::INode, T> &&
387 std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
389 v = *(T::fromJSON(*
this));
392 template <
typename T>
393 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
394 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
396 v = T::fromJSON(*
this);
399 template <
typename T>
400 std::enable_if_t<has_fromJSON<T>::value && !std::is_base_of<IR::INode, T>::value &&
401 !std::is_pointer_v<decltype(T::fromJSON(std::declval<JSONLoader &>()))>>
403 v =
new T(T::fromJSON(*
this));
406 template <
typename T>
407 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(T &v) {
408 v = get_node()->as<T>();
410 template <
typename T>
411 std::enable_if_t<std::is_base_of_v<IR::INode, T>> unpack_json(
const T *&v) {
412 v = get_node()->checkedTo<T>();
415 template <
typename T,
size_t N>
416 void unpack_json(T (&v)[N]) {
418 for (
size_t i = 0; i < N && i < j->size(); ++i) {
419 load(j->at(i), v[i]);
425 template <
typename T>
427 JSONLoader(&
json, node_refs, locinfo).unpack_json(v);
430 template <
typename T>
431 void load(
const std::unique_ptr<JsonData> &
json, T &v) {
432 JSONLoader(
json.get(), node_refs, locinfo).unpack_json(v);
435 template <
typename T>
436 bool load(std::string_view field, T *&v) {
437 if (
auto loader = JSONLoader(*
this, field)) {
438 loader.unpack_json(v);
446 template <
typename T>
447 bool load(std::string_view field, T &v) {
448 if (
auto loader = JSONLoader(*
this, field)) {
449 loader.unpack_json(v);
455 template <
typename T>
456 JSONLoader &operator>>(T &v) {