Hegel 0.3.5
Property-based testing for C++
Loading...
Searching...
No Matches
nlohmann_reader.h
1#pragma once
2
6
7#include "json.h"
8#include <rfl/Bytestring.hpp>
9#include <rfl/Processors.hpp>
10#include <rfl/Result.hpp>
11#include <rfl/Vectorstring.hpp>
12#include <rfl/always_false.hpp>
13#include <rfl/json/Writer.hpp>
14#include <rfl/parsing/Parser.hpp>
15
16namespace hegel::internal {
17
20 class NlohmannReader {
21 public:
22 using InputArrayType = hegel::internal::json::json_raw_ref;
23 using InputObjectType = hegel::internal::json::json_raw_ref;
24 using InputVarType = hegel::internal::json::json_raw_ref;
25
26 template <class T> static constexpr bool has_custom_constructor = false;
27
28 rfl::Result<InputVarType>
29 get_field_from_array(const size_t _idx,
30 const InputArrayType& _arr) const noexcept {
31 if (_idx >= _arr.size()) {
32 return rfl::error("Index out of range.");
33 }
34 return InputVarType{_arr[_idx]};
35 }
36
37 rfl::Result<InputVarType>
38 get_field_from_object(const std::string& _name,
39 const InputObjectType& _obj) const noexcept {
40 auto it = _obj.find(_name);
41 if (!it.has_value()) {
42 return rfl::error("Field name '" + _name + "' not found.");
43 }
44 return InputVarType{it.value()};
45 }
46
47 bool is_empty(const InputVarType& _var) const noexcept {
48 return _var.is_null();
49 }
50
51 template <class T>
52 rfl::Result<T> to_basic_type(const InputVarType& _var) const noexcept {
53 if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
54 if (!_var.is_string()) {
55 return rfl::error("Could not cast to string.");
56 }
57 return _var.get_string();
58
59 } else if constexpr (std::is_same<std::remove_cvref_t<T>,
60 rfl::Bytestring>() ||
61 std::is_same<std::remove_cvref_t<T>,
62 rfl::Vectorstring>()) {
63 return rfl::error("Byte/vector strings not supported.");
64
65 } else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
66 if (!_var.is_boolean()) {
67 return rfl::error("Could not cast to boolean.");
68 }
69 return _var.get_bool();
70
71 } else if constexpr (std::is_floating_point<
72 std::remove_cvref_t<T>>()) {
73 if (!_var.is_number()) {
74 return rfl::error("Could not cast to double.");
75 }
76 return static_cast<T>(_var.get_double());
77
78 } else if constexpr (std::is_integral<std::remove_cvref_t<T>>()) {
79 if (_var.is_number_integer()) {
80 return static_cast<T>(_var.get_int64_t());
81 }
82 if (_var.is_number_unsigned()) {
83 return static_cast<T>(_var.get_uint64_t());
84 }
85 return rfl::error("Could not cast to integer.");
86
87 } else {
88 static_assert(rfl::always_false_v<T>, "Unsupported type.");
89 }
90 }
91
92 rfl::Result<InputArrayType>
93 to_array(const InputVarType& _var) const noexcept {
94 if (!_var.is_array()) {
95 return rfl::error("Could not cast to an array.");
96 }
97 return InputArrayType(_var);
98 }
99
100 rfl::Result<InputObjectType>
101 to_object(const InputVarType& _var) const noexcept {
102 if (!_var.is_object()) {
103 return rfl::error("Could not cast to an object.");
104 }
105 return InputObjectType(_var);
106 }
107
108 template <class ArrayReader>
109 std::optional<rfl::Error>
110 read_array(const ArrayReader& _array_reader,
111 const InputArrayType& _arr) const noexcept {
112 auto to_iterate = _arr.iterate();
113 for (auto& val : to_iterate) {
114 const auto err = _array_reader.read(InputVarType{val});
115 if (err) {
116 return err;
117 }
118 }
119 return std::nullopt;
120 }
121
122 template <class ObjectReader>
123 std::optional<rfl::Error>
124 read_object(const ObjectReader& _object_reader,
125 const InputObjectType& _obj) const noexcept {
126 auto items = _obj.items();
127 for (auto& [key, val] : items) {
128 _object_reader.read(key, InputVarType{val});
129 }
130 return std::nullopt;
131 }
132
133 template <class T>
134 rfl::Result<T>
135 use_custom_constructor(const InputVarType&) const noexcept {
136 return rfl::error("Custom constructors not supported.");
137 }
138 };
139
142 template <class T>
143 rfl::Result<T>
144 read_nlohmann(const hegel::internal::json::json_raw_ref& val) {
145 auto r = NlohmannReader();
146 return rfl::parsing::Parser<
147 NlohmannReader, rfl::json::Writer, T,
148 rfl::Processors<>>::read(r, NlohmannReader::InputVarType(val));
149 }
150
151} // namespace hegel::internal
152