10#include <fmt/ranges.h>
30 using std::invalid_argument::invalid_argument;
43 return fmt::format(
"At {}: {}",
pointer(), what());
52 inline void to_json(nlohmann::json& j,
const std::optional<T>& t)
61 inline void from_json(
const nlohmann::json& j, std::optional<T>& t)
70 inline void to_json(nlohmann::json& j,
const std::vector<T>& t)
72 if constexpr (std::is_same_v<T, uint8_t>)
78 j = nlohmann::json::array();
79 for (
const auto& e : t)
87 inline void from_json(
const nlohmann::json& j, std::vector<T>& t)
89 if constexpr (std::is_same_v<T, uint8_t>)
98 catch (
const std::exception& e)
101 "Vector of bytes object \"{}\" is not valid base64", j.dump()));
113 fmt::format(
"Vector object \"{}\" is not an array", j.dump()));
116 for (
size_t i = 0; i < j.size(); ++i)
120 t.push_back(j.at(i).template get<T>());
135#pragma clang diagnostic push
136#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
138#define __FOR_JSON_COUNT_NN( \
173#define _FOR_JSON_COUNT_NN_WITH_0(...) \
174 __FOR_JSON_COUNT_NN( \
207#define _FOR_JSON_COUNT_NN(...) _FOR_JSON_COUNT_NN_WITH_0(DUMMY, ##__VA_ARGS__)
209#define _FOR_JSON_0(POP_N) _FOR_JSON_0_##POP_N
210#define _FOR_JSON_1(POP_N) _FOR_JSON_1_##POP_N
211#define _FOR_JSON_2(POP_N) _FOR_JSON_2_##POP_N
212#define _FOR_JSON_3(POP_N) _FOR_JSON_3_##POP_N
213#define _FOR_JSON_4(POP_N) _FOR_JSON_4_##POP_N
214#define _FOR_JSON_5(POP_N) _FOR_JSON_5_##POP_N
215#define _FOR_JSON_6(POP_N) _FOR_JSON_6_##POP_N
216#define _FOR_JSON_7(POP_N) _FOR_JSON_7_##POP_N
217#define _FOR_JSON_8(POP_N) _FOR_JSON_8_##POP_N
218#define _FOR_JSON_9(POP_N) _FOR_JSON_9_##POP_N
219#define _FOR_JSON_10(POP_N) _FOR_JSON_10_##POP_N
220#define _FOR_JSON_11(POP_N) _FOR_JSON_11_##POP_N
221#define _FOR_JSON_12(POP_N) _FOR_JSON_12_##POP_N
222#define _FOR_JSON_13(POP_N) _FOR_JSON_13_##POP_N
223#define _FOR_JSON_14(POP_N) _FOR_JSON_14_##POP_N
224#define _FOR_JSON_15(POP_N) _FOR_JSON_15_##POP_N
225#define _FOR_JSON_16(POP_N) _FOR_JSON_16_##POP_N
226#define _FOR_JSON_17(POP_N) _FOR_JSON_17_##POP_N
227#define _FOR_JSON_18(POP_N) _FOR_JSON_18_##POP_N
228#define _FOR_JSON_19(POP_N) _FOR_JSON_19_##POP_N
229#define _FOR_JSON_20(POP_N) _FOR_JSON_20_##POP_N
230#define _FOR_JSON_21(POP_N) _FOR_JSON_21_##POP_N
231#define _FOR_JSON_22(POP_N) _FOR_JSON_22_##POP_N
232#define _FOR_JSON_23(POP_N) _FOR_JSON_23_##POP_N
233#define _FOR_JSON_24(POP_N) _FOR_JSON_24_##POP_N
234#define _FOR_JSON_25(POP_N) _FOR_JSON_25_##POP_N
235#define _FOR_JSON_26(POP_N) _FOR_JSON_26_##POP_N
236#define _FOR_JSON_27(POP_N) _FOR_JSON_27_##POP_N
237#define _FOR_JSON_28(POP_N) _FOR_JSON_28_##POP_N
238#define _FOR_JSON_29(POP_N) _FOR_JSON_29_##POP_N
239#define _FOR_JSON_30(POP_N) _FOR_JSON_30_##POP_N
242#define _FOR_JSON_0_POP1(FUNC, TYPE)
243#define _FOR_JSON_1_POP1(FUNC, TYPE, ARG1) _FOR_JSON_FINAL(FUNC, TYPE, ARG1)
244#define _FOR_JSON_2_POP1(FUNC, TYPE, ARG1, ...) \
245 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
246 _FOR_JSON_1_POP1(FUNC, TYPE, ##__VA_ARGS__)
247#define _FOR_JSON_3_POP1(FUNC, TYPE, ARG1, ...) \
248 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
249 _FOR_JSON_2_POP1(FUNC, TYPE, ##__VA_ARGS__)
250#define _FOR_JSON_4_POP1(FUNC, TYPE, ARG1, ...) \
251 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
252 _FOR_JSON_3_POP1(FUNC, TYPE, ##__VA_ARGS__)
253#define _FOR_JSON_5_POP1(FUNC, TYPE, ARG1, ...) \
254 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
255 _FOR_JSON_4_POP1(FUNC, TYPE, ##__VA_ARGS__)
256#define _FOR_JSON_6_POP1(FUNC, TYPE, ARG1, ...) \
257 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
258 _FOR_JSON_5_POP1(FUNC, TYPE, ##__VA_ARGS__)
259#define _FOR_JSON_7_POP1(FUNC, TYPE, ARG1, ...) \
260 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
261 _FOR_JSON_6_POP1(FUNC, TYPE, ##__VA_ARGS__)
262#define _FOR_JSON_8_POP1(FUNC, TYPE, ARG1, ...) \
263 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
264 _FOR_JSON_7_POP1(FUNC, TYPE, ##__VA_ARGS__)
265#define _FOR_JSON_9_POP1(FUNC, TYPE, ARG1, ...) \
266 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
267 _FOR_JSON_8_POP1(FUNC, TYPE, ##__VA_ARGS__)
268#define _FOR_JSON_10_POP1(FUNC, TYPE, ARG1, ...) \
269 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
270 _FOR_JSON_9_POP1(FUNC, TYPE, ##__VA_ARGS__)
271#define _FOR_JSON_11_POP1(FUNC, TYPE, ARG1, ...) \
272 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
273 _FOR_JSON_10_POP1(FUNC, TYPE, ##__VA_ARGS__)
274#define _FOR_JSON_12_POP1(FUNC, TYPE, ARG1, ...) \
275 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
276 _FOR_JSON_11_POP1(FUNC, TYPE, ##__VA_ARGS__)
277#define _FOR_JSON_13_POP1(FUNC, TYPE, ARG1, ...) \
278 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
279 _FOR_JSON_12_POP1(FUNC, TYPE, ##__VA_ARGS__)
280#define _FOR_JSON_14_POP1(FUNC, TYPE, ARG1, ...) \
281 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
282 _FOR_JSON_13_POP1(FUNC, TYPE, ##__VA_ARGS__)
283#define _FOR_JSON_15_POP1(FUNC, TYPE, ARG1, ...) \
284 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
285 _FOR_JSON_14_POP1(FUNC, TYPE, ##__VA_ARGS__)
286#define _FOR_JSON_16_POP1(FUNC, TYPE, ARG1, ...) \
287 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
288 _FOR_JSON_15_POP1(FUNC, TYPE, ##__VA_ARGS__)
289#define _FOR_JSON_17_POP1(FUNC, TYPE, ARG1, ...) \
290 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
291 _FOR_JSON_16_POP1(FUNC, TYPE, ##__VA_ARGS__)
292#define _FOR_JSON_18_POP1(FUNC, TYPE, ARG1, ...) \
293 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
294 _FOR_JSON_17_POP1(FUNC, TYPE, ##__VA_ARGS__)
295#define _FOR_JSON_19_POP1(FUNC, TYPE, ARG1, ...) \
296 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
297 _FOR_JSON_18_POP1(FUNC, TYPE, ##__VA_ARGS__)
298#define _FOR_JSON_20_POP1(FUNC, TYPE, ARG1, ...) \
299 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
300 _FOR_JSON_19_POP1(FUNC, TYPE, ##__VA_ARGS__)
301#define _FOR_JSON_21_POP1(FUNC, TYPE, ARG1, ...) \
302 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
303 _FOR_JSON_20_POP1(FUNC, TYPE, ##__VA_ARGS__)
304#define _FOR_JSON_22_POP1(FUNC, TYPE, ARG1, ...) \
305 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
306 _FOR_JSON_21_POP1(FUNC, TYPE, ##__VA_ARGS__)
307#define _FOR_JSON_23_POP1(FUNC, TYPE, ARG1, ...) \
308 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
309 _FOR_JSON_22_POP1(FUNC, TYPE, ##__VA_ARGS__)
310#define _FOR_JSON_24_POP1(FUNC, TYPE, ARG1, ...) \
311 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
312 _FOR_JSON_23_POP1(FUNC, TYPE, ##__VA_ARGS__)
313#define _FOR_JSON_25_POP1(FUNC, TYPE, ARG1, ...) \
314 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
315 _FOR_JSON_24_POP1(FUNC, TYPE, ##__VA_ARGS__)
316#define _FOR_JSON_26_POP1(FUNC, TYPE, ARG1, ...) \
317 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
318 _FOR_JSON_25_POP1(FUNC, TYPE, ##__VA_ARGS__)
319#define _FOR_JSON_27_POP1(FUNC, TYPE, ARG1, ...) \
320 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
321 _FOR_JSON_26_POP1(FUNC, TYPE, ##__VA_ARGS__)
322#define _FOR_JSON_28_POP1(FUNC, TYPE, ARG1, ...) \
323 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
324 _FOR_JSON_27_POP1(FUNC, TYPE, ##__VA_ARGS__)
325#define _FOR_JSON_29_POP1(FUNC, TYPE, ARG1, ...) \
326 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
327 _FOR_JSON_28_POP1(FUNC, TYPE, ##__VA_ARGS__)
328#define _FOR_JSON_30_POP1(FUNC, TYPE, ARG1, ...) \
329 _FOR_JSON_NEXT(FUNC, TYPE, ARG1) \
330 _FOR_JSON_29_POP1(FUNC, TYPE, ##__VA_ARGS__)
333#define _FOR_JSON_0_POP2(FUNC, TYPE)
334#define _FOR_JSON_1_POP2(FUNC, TYPE, ARG1) INVALID_ODD_ARGS
335#define _FOR_JSON_2_POP2(FUNC, TYPE, ARG1, ARG2) \
336 _FOR_JSON_FINAL(FUNC, TYPE, ARG1, ARG2)
337#define _FOR_JSON_3_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
338#define _FOR_JSON_4_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
339 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
340 _FOR_JSON_2_POP2(FUNC, TYPE, ##__VA_ARGS__)
341#define _FOR_JSON_5_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
342#define _FOR_JSON_6_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
343 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
344 _FOR_JSON_4_POP2(FUNC, TYPE, ##__VA_ARGS__)
345#define _FOR_JSON_7_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
346#define _FOR_JSON_8_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
347 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
348 _FOR_JSON_6_POP2(FUNC, TYPE, ##__VA_ARGS__)
349#define _FOR_JSON_9_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
350#define _FOR_JSON_10_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
351 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
352 _FOR_JSON_8_POP2(FUNC, TYPE, ##__VA_ARGS__)
353#define _FOR_JSON_11_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
354#define _FOR_JSON_12_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
355 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
356 _FOR_JSON_10_POP2(FUNC, TYPE, ##__VA_ARGS__)
357#define _FOR_JSON_13_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
358#define _FOR_JSON_14_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
359 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
360 _FOR_JSON_12_POP2(FUNC, TYPE, ##__VA_ARGS__)
361#define _FOR_JSON_15_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
362#define _FOR_JSON_16_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
363 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
364 _FOR_JSON_14_POP2(FUNC, TYPE, ##__VA_ARGS__)
365#define _FOR_JSON_17_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
366#define _FOR_JSON_18_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
367 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
368 _FOR_JSON_16_POP2(FUNC, TYPE, ##__VA_ARGS__)
369#define _FOR_JSON_19_POP2(FUNC, TYPE, ARG1, ARG2, ...) INVALID_ODD_ARGS
370#define _FOR_JSON_20_POP2(FUNC, TYPE, ARG1, ARG2, ...) \
371 _FOR_JSON_NEXT(FUNC, TYPE, ARG1, ARG2) \
372 _FOR_JSON_18_POP2(FUNC, TYPE, ##__VA_ARGS__)
375#define _FOR_JSON_NEXT(FUNC, ...) FUNC##_FOR_JSON_NEXT(__VA_ARGS__)
376#define _FOR_JSON_FINAL(FUNC, ...) FUNC##_FOR_JSON_FINAL(__VA_ARGS__)
378#define WRITE_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD) \
380 j[JSON_FIELD] = t.C_FIELD; \
382#define WRITE_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL(TYPE, C_FIELD, JSON_FIELD) \
383 WRITE_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD)
385#define WRITE_REQUIRED_FOR_JSON_NEXT(TYPE, FIELD) \
386 WRITE_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
387#define WRITE_REQUIRED_FOR_JSON_FINAL(TYPE, FIELD) \
388 WRITE_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, #FIELD)
390#define WRITE_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD) \
392 if (t.C_FIELD != t_default.C_FIELD) \
394 j[JSON_FIELD] = t.C_FIELD; \
397#define WRITE_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, C_FIELD, JSON_FIELD) \
398 WRITE_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD)
400#define WRITE_OPTIONAL_FOR_JSON_NEXT(TYPE, FIELD) \
401 WRITE_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
402#define WRITE_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \
403 WRITE_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, #FIELD)
405#define READ_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD) \
407 const auto it = j.find(JSON_FIELD); \
410 throw ccf::JsonParseError( \
411 "Missing required field '" JSON_FIELD "' in object: " + j.dump()); \
415 t.C_FIELD = it->get<decltype(TYPE::C_FIELD)>(); \
417 catch (ccf::JsonParseError & jpe) \
419 jpe.pointer_elements.emplace_back(JSON_FIELD); \
423#define READ_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL(TYPE, C_FIELD, JSON_FIELD) \
424 READ_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD)
426#define READ_REQUIRED_FOR_JSON_NEXT(TYPE, FIELD) \
427 READ_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
428#define READ_REQUIRED_FOR_JSON_FINAL(TYPE, FIELD) \
429 READ_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, #FIELD)
431#define READ_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD) \
433 const auto it = j.find(JSON_FIELD); \
436 t.C_FIELD = it->get<decltype(TYPE::C_FIELD)>(); \
439#define READ_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, C_FIELD, JSON_FIELD) \
440 READ_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD)
442#define READ_OPTIONAL_FOR_JSON_NEXT(TYPE, FIELD) \
443 READ_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
444#define READ_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \
445 READ_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, #FIELD)
447#define FILL_SCHEMA_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT( \
448 TYPE, C_FIELD, JSON_FIELD) \
449 j["properties"][JSON_FIELD] = \
450 ccf::ds::json::schema_element<decltype(TYPE::C_FIELD)>(); \
451 j["required"].push_back(JSON_FIELD);
452#define FILL_SCHEMA_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL( \
453 TYPE, C_FIELD, JSON_FIELD) \
454 FILL_SCHEMA_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD)
456#define FILL_SCHEMA_REQUIRED_FOR_JSON_NEXT(TYPE, FIELD) \
457 FILL_SCHEMA_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
458#define FILL_SCHEMA_REQUIRED_FOR_JSON_FINAL(TYPE, FIELD) \
459 FILL_SCHEMA_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, #FIELD)
461#define FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT( \
462 TYPE, C_FIELD, JSON_FIELD) \
463 j["properties"][JSON_FIELD] = \
464 ccf::ds::json::schema_element<decltype(TYPE::C_FIELD)>();
465#define FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL( \
466 TYPE, C_FIELD, JSON_FIELD) \
467 FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD)
469#define FILL_SCHEMA_OPTIONAL_FOR_JSON_NEXT(TYPE, FIELD) \
470 FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
471#define FILL_SCHEMA_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \
472 FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, #FIELD)
474#define ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT( \
475 TYPE, C_FIELD, JSON_FIELD) \
476 j["properties"][JSON_FIELD] = \
477 doc.template add_schema_component<decltype(TYPE::C_FIELD)>(); \
478 j["required"].push_back(JSON_FIELD);
479#define ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL( \
480 TYPE, C_FIELD, JSON_FIELD) \
481 ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT( \
482 TYPE, C_FIELD, JSON_FIELD)
484#define ADD_SCHEMA_COMPONENTS_REQUIRED_FOR_JSON_NEXT(TYPE, FIELD) \
485 ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
486#define ADD_SCHEMA_COMPONENTS_REQUIRED_FOR_JSON_FINAL(TYPE, FIELD) \
487 ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL( \
490#define ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT( \
491 TYPE, C_FIELD, JSON_FIELD) \
492 j["properties"][JSON_FIELD] = \
493 doc.template add_schema_component<decltype(TYPE::C_FIELD)>();
494#define ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL( \
495 TYPE, C_FIELD, JSON_FIELD) \
496 ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT( \
497 TYPE, C_FIELD, JSON_FIELD)
499#define ADD_SCHEMA_COMPONENTS_OPTIONAL_FOR_JSON_NEXT(TYPE, FIELD) \
500 ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, #FIELD)
501#define ADD_SCHEMA_COMPONENTS_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \
502 ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL( \
505#define JSON_FIELD_FOR_JSON_NEXT(TYPE, FIELD) \
506 ccf::JsonField<decltype(TYPE::FIELD)>{#FIELD},
507#define JSON_FIELD_FOR_JSON_FINAL(TYPE, FIELD) \
508 ccf::JsonField<decltype(TYPE::FIELD)> \
615#define DECLARE_JSON_TYPE_IMPL( \
625 void to_json_required_fields(nlohmann::json& j, const TYPE& t); \
626 void to_json_optional_fields(nlohmann::json& j, const TYPE& t); \
627 void from_json_required_fields(const nlohmann::json& j, TYPE& t); \
628 void from_json_optional_fields(const nlohmann::json& j, TYPE& t); \
629 void fill_json_schema_required_fields(nlohmann::json& j, const TYPE*); \
630 void fill_json_schema_optional_fields(nlohmann::json& j, const TYPE*); \
631 template <typename T> \
632 void add_schema_components_required_fields( \
633 T& doc, nlohmann::json& j, const TYPE*); \
634 template <typename T> \
635 void add_schema_components_optional_fields( \
636 T& doc, nlohmann::json& j, const TYPE*); \
637 inline void to_json(nlohmann::json& j, const TYPE& t) \
640 to_json_required_fields(j, t); \
643 inline void from_json(const nlohmann::json& j, TYPE& t) \
646 from_json_required_fields(j, t); \
649 inline void fill_json_schema(nlohmann::json& j, const TYPE* t) \
652 fill_json_schema_required_fields(j, t); \
655 inline std::string schema_name(const TYPE*) \
659 template <typename T> \
660 void add_schema_components(T& doc, nlohmann::json& j, const TYPE* t) \
663 add_schema_components_required_fields(doc, j, t); \
667#define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , , , )
669#define DECLARE_JSON_TYPE_WITH_BASE(TYPE, BASE) \
670 DECLARE_JSON_TYPE_IMPL( \
672 to_json(j, static_cast<const BASE&>(t)), \
674 from_json(j, static_cast<BASE&>(t)), \
676 fill_json_schema(j, static_cast<const BASE*>(t)), \
678 add_schema_components(doc, j, static_cast<const BASE*>(t)), )
680#define DECLARE_JSON_TYPE_WITH_2BASES(TYPE, BASE1, BASE2) \
681 DECLARE_JSON_TYPE_IMPL( \
682 TYPE, to_json(j, static_cast<const BASE1&>(t)); \
683 to_json(j, static_cast<const BASE2&>(t)), \
685 from_json(j, static_cast<BASE1&>(t)); \
686 from_json(j, static_cast<BASE2&>(t)), \
688 fill_json_schema(j, static_cast<const BASE1*>(t)); \
689 fill_json_schema(j, static_cast<const BASE2*>(t)), \
691 add_schema_components(doc, j, static_cast<const BASE1*>(t)); \
692 add_schema_components(doc, j, static_cast<const BASE2*>(t)), )
694#define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE) \
695 DECLARE_JSON_TYPE_IMPL( \
698 to_json_optional_fields(j, t), \
700 from_json_optional_fields(j, t), \
702 fill_json_schema_optional_fields(j, t), \
704 add_schema_components_optional_fields(doc, j, t))
706#define DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(TYPE, BASE) \
707 DECLARE_JSON_TYPE_IMPL( \
709 to_json(j, static_cast<const BASE&>(t)), \
710 to_json_optional_fields(j, t), \
711 from_json(j, static_cast<BASE&>(t)), \
712 from_json_optional_fields(j, t), \
713 fill_json_schema(j, static_cast<const BASE*>(t)), \
714 fill_json_schema_optional_fields(j, t), \
715 add_schema_components(doc, j, static_cast<const BASE*>(t)), \
716 add_schema_components_optional_fields(doc, j, t))
718#define DECLARE_JSON_REQUIRED_FIELDS(TYPE, ...) \
719 _Pragma("clang diagnostic push"); \
720 _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\""); \
721 inline void to_json_required_fields( \
722 nlohmann::json& j, [[maybe_unused]] const TYPE& t) \
724 if (!j.is_object()) \
726 j = nlohmann::json::object(); \
728 _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)(WRITE_REQUIRED, TYPE, ##__VA_ARGS__) \
730 inline void from_json_required_fields( \
731 const nlohmann::json& j, [[maybe_unused]] TYPE& t) \
733 if (!j.is_object()) \
735 throw ccf::JsonParseError("Expected object, found: " + j.dump()); \
737 _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)(READ_REQUIRED, TYPE, ##__VA_ARGS__) \
739 inline void fill_json_schema_required_fields( \
740 nlohmann::json& j, [[maybe_unused]] const TYPE*) \
742 j["type"] = "object"; \
743 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
744 (POP1)(FILL_SCHEMA_REQUIRED, TYPE, ##__VA_ARGS__) \
746 template <typename T> \
747 void add_schema_components_required_fields( \
748 [[maybe_unused]] T& doc, nlohmann::json& j, [[maybe_unused]] const TYPE*) \
750 j["type"] = "object"; \
751 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
752 (POP1)(ADD_SCHEMA_COMPONENTS_REQUIRED, TYPE, ##__VA_ARGS__); \
754 _Pragma("clang diagnostic pop");
756#define DECLARE_JSON_REQUIRED_FIELDS_WITH_RENAMES(TYPE, ...) \
757 inline void to_json_required_fields(nlohmann::json& j, const TYPE& t) \
759 if (!j.is_object()) \
761 j = nlohmann::json::object(); \
763 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
764 (POP2)(WRITE_REQUIRED_WITH_RENAMES, TYPE, ##__VA_ARGS__) \
766 inline void from_json_required_fields(const nlohmann::json& j, TYPE& t) \
768 if (!j.is_object()) \
770 throw ccf::JsonParseError("Expected object, found: " + j.dump()); \
772 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
773 (POP2)(READ_REQUIRED_WITH_RENAMES, TYPE, ##__VA_ARGS__) \
775 inline void fill_json_schema_required_fields(nlohmann::json& j, const TYPE*) \
777 j["type"] = "object"; \
778 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
779 (POP2)(FILL_SCHEMA_REQUIRED_WITH_RENAMES, TYPE, ##__VA_ARGS__) \
781 template <typename T> \
782 void add_schema_components_required_fields( \
783 T& doc, nlohmann::json& j, const TYPE*) \
785 j["type"] = "object"; \
786 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
787 (POP2)(ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES, TYPE, ##__VA_ARGS__); \
790#define DECLARE_JSON_OPTIONAL_FIELDS(TYPE, ...) \
791 inline void to_json_optional_fields(nlohmann::json& j, const TYPE& t) \
793 const TYPE t_default{}; \
794 _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)(WRITE_OPTIONAL, TYPE, ##__VA_ARGS__) \
796 inline void from_json_optional_fields(const nlohmann::json& j, TYPE& t) \
798 _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)(READ_OPTIONAL, TYPE, ##__VA_ARGS__) \
800 inline void fill_json_schema_optional_fields(nlohmann::json& j, const TYPE*) \
802 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
803 (POP1)(FILL_SCHEMA_OPTIONAL, TYPE, ##__VA_ARGS__) \
805 template <typename T> \
806 void add_schema_components_optional_fields( \
807 T& doc, nlohmann::json& j, const TYPE*) \
809 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
810 (POP1)(ADD_SCHEMA_COMPONENTS_OPTIONAL, TYPE, ##__VA_ARGS__); \
813#define DECLARE_JSON_OPTIONAL_FIELDS_WITH_RENAMES(TYPE, ...) \
814 inline void to_json_optional_fields(nlohmann::json& j, const TYPE& t) \
816 const TYPE t_default{}; \
817 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
818 (POP2)(WRITE_OPTIONAL_WITH_RENAMES, TYPE, ##__VA_ARGS__) \
820 inline void from_json_optional_fields(const nlohmann::json& j, TYPE& t) \
822 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
823 (POP2)(READ_OPTIONAL_WITH_RENAMES, TYPE, ##__VA_ARGS__) \
825 inline void fill_json_schema_optional_fields( \
826 nlohmann::json& j, [[maybe_unused]] const TYPE*) \
828 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
829 (POP2)(FILL_SCHEMA_OPTIONAL_WITH_RENAMES, TYPE, ##__VA_ARGS__) \
831 template <typename T> \
832 void add_schema_components_optional_fields( \
833 T& doc, nlohmann::json& j, [[maybe_unused]] const TYPE*) \
835 _FOR_JSON_COUNT_NN(__VA_ARGS__) \
836 (POP2)(ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES, TYPE, ##__VA_ARGS__); \
841#define DECLARE_JSON_ENUM(TYPE, ...) \
842 template <typename BasicJsonType> \
843 inline void to_json(BasicJsonType& j, const TYPE& e) \
845 static_assert(std::is_enum_v<TYPE>, #TYPE " must be an enum!"); \
846 static const std::pair<TYPE, BasicJsonType> m[] = __VA_ARGS__; \
847 auto it = std::find_if( \
850 [e](const std::pair<TYPE, BasicJsonType>& ej_pair) -> bool { \
851 return ej_pair.first == e; \
853 if (it == std::end(m)) \
855 throw ccf::JsonParseError(fmt::format( \
856 "Value {} in enum " #TYPE " has no specified JSON conversion", \
861 template <typename BasicJsonType> \
862 inline void from_json(const BasicJsonType& j, TYPE& e) \
864 static_assert(std::is_enum_v<TYPE>, #TYPE " must be an enum!"); \
865 static const std::pair<TYPE, BasicJsonType> m[] = __VA_ARGS__; \
866 auto it = std::find_if( \
869 [&j](const std::pair<TYPE, BasicJsonType>& ej_pair) -> bool { \
870 return ej_pair.second == j; \
872 if (it == std::end(m)) \
874 throw ccf::JsonParseError( \
875 fmt::format("{} is not convertible to " #TYPE, j.dump())); \
879 inline std::string schema_name(const TYPE*) \
883 inline void fill_enum_schema(nlohmann::json& j, const TYPE*) \
885 static const std::pair<TYPE, nlohmann::json> m[] = __VA_ARGS__; \
886 auto enums = nlohmann::json::array(); \
887 for (const auto& p : m) \
889 enums.push_back(p.second); \
892 j["type"] = "string"; \
895#pragma clang diagnostic pop
std::string describe() const
Definition json.h:41
std::vector< std::string > pointer_elements
Definition json.h:28
std::string pointer() const
Definition json.h:34
JsonParseError(const JsonParseError &other) noexcept=default
std::vector< uint8_t > raw_from_b64(const std::string_view &b64_string)
Definition base64.cpp:12
std::string b64_from_raw(const uint8_t *data, size_t size)
Definition base64.cpp:41
Definition app_interface.h:14
void to_json(nlohmann::json &j, const std::optional< T > &t)
Definition json.h:52
void from_json(const nlohmann::json &j, std::optional< T > &t)
Definition json.h:61
char const * name
Definition json.h:22
T Target
Definition json.h:21