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>
16namespace hegel::internal {
20 class NlohmannReader {
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;
26 template <
class T>
static constexpr bool has_custom_constructor =
false;
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.");
34 return InputVarType{_arr[_idx]};
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.");
44 return InputVarType{it.value()};
47 bool is_empty(
const InputVarType& _var)
const noexcept {
48 return _var.is_null();
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.");
57 return _var.get_string();
59 }
else if constexpr (std::is_same<std::remove_cvref_t<T>,
61 std::is_same<std::remove_cvref_t<T>,
62 rfl::Vectorstring>()) {
63 return rfl::error(
"Byte/vector strings not supported.");
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.");
69 return _var.get_bool();
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.");
76 return static_cast<T
>(_var.get_double());
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());
82 if (_var.is_number_unsigned()) {
83 return static_cast<T
>(_var.get_uint64_t());
85 return rfl::error(
"Could not cast to integer.");
88 static_assert(rfl::always_false_v<T>,
"Unsupported type.");
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.");
97 return InputArrayType(_var);
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.");
105 return InputObjectType(_var);
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});
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});
135 use_custom_constructor(
const InputVarType&)
const noexcept {
136 return rfl::error(
"Custom constructors not supported.");
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));