Skip to content

Commit a3b32ac

Browse files
committed
feat: support floating point in ser-des
1 parent 237f329 commit a3b32ac

1 file changed

Lines changed: 63 additions & 14 deletions

File tree

include/json/serdes.hpp

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
// This code is licensed under MIT license (see LICENSE for details)
33

44
#pragma once
5+
#include <chrono>
56
#include <optional>
67
#include <json/json.hpp>
78

89
using namespace std::literals;
910

1011
namespace json {
11-
enum class conv_result { ok, opt, failed, updated };
12+
enum class conv_result : int { ok, opt, failed, updated };
1213
inline constexpr bool is_ok(conv_result res) noexcept {
1314
return res < conv_result::failed;
1415
}
@@ -19,11 +20,10 @@ namespace json {
1920
};
2021

2122
template <typename T>
22-
concept LoadsJsonRaw = requires(T& lval,
23-
node const& data,
24-
std::string& dbg) {
25-
{ lval.from_json(data, dbg) } -> std::convertible_to<conv_result>;
26-
};
23+
concept LoadsJsonRaw =
24+
requires(T& lval, node const& data, std::string& dbg) {
25+
{ lval.from_json(data, dbg) } -> std::convertible_to<conv_result>;
26+
};
2727

2828
template <typename T>
2929
concept LoadsJson = requires(T& lval, map const& data, std::string& dbg) {
@@ -32,12 +32,13 @@ namespace json {
3232
};
3333

3434
template <typename T, typename... Kind>
35-
concept LoadsJsonEx = requires(T& lval,
36-
Kind const*... data,
37-
std::string& dbg) {
38-
(NodeType<Kind> && ...);
39-
{ lval.from_json(data..., dbg) } -> std::convertible_to<conv_result>;
40-
};
35+
concept LoadsJsonEx =
36+
requires(T& lval, Kind const*... data, std::string& dbg) {
37+
(NodeType<Kind> && ...);
38+
{
39+
lval.from_json(data..., dbg)
40+
} -> std::convertible_to<conv_result>;
41+
};
4142

4243
inline auto to_json(StoresJson auto const& obj) { return obj.to_json(); }
4344
inline long long to_json(std::integral auto val) {
@@ -99,6 +100,20 @@ namespace json {
99100
return conv_result::ok;
100101
}
101102

103+
template <std::floating_point Float>
104+
inline conv_result load(node const& src, Float& val, std::string&) {
105+
auto const float_data = cast<double>(src);
106+
auto const int_data = cast<long long>(src);
107+
if (float_data) {
108+
val = static_cast<Float>(*float_data);
109+
} else if (int_data) {
110+
val = static_cast<Float>(*int_data);
111+
} else {
112+
return conv_result::opt;
113+
}
114+
return conv_result::ok;
115+
}
116+
102117
inline conv_result load(node const& src, bool& val, std::string&) {
103118
auto const data = cast<bool>(src);
104119
val = data ? *data : false;
@@ -152,8 +167,9 @@ namespace json {
152167
}
153168

154169
template <typename T>
155-
concept LoadableJsonValue = LoadsJson<T> || LoadsJsonRaw<T> ||
156-
std::integral<T> || std::same_as<T, std::chrono::sys_seconds> ||
170+
concept LoadableJsonValue =
171+
LoadsJson<T> || LoadsJsonRaw<T> || std::integral<T> ||
172+
std::floating_point<T> || std::same_as<T, std::chrono::sys_seconds> ||
157173
std::same_as<T, string> || std::same_as<T, std::string>;
158174

159175
inline void append_name(conv_result res,
@@ -249,6 +265,25 @@ namespace json {
249265
return result;
250266
}
251267

268+
template <LoadableJsonValue ValueType>
269+
inline conv_result load(map const& src,
270+
std::map<string, ValueType>& value,
271+
std::string& dbg) {
272+
auto result = conv_result::ok;
273+
value.clear();
274+
// value.reserve(src.size());
275+
for (auto& [key, node_item] : src.items()) {
276+
auto insert_result = value.insert({key, {}});
277+
auto it = insert_result.first;
278+
auto const res = json::load(node_item, it->second, dbg);
279+
if (res == conv_result::failed || res == conv_result::opt)
280+
value.erase(it);
281+
if (!is_ok(res)) result = res;
282+
if (result == conv_result::failed) break;
283+
}
284+
return result;
285+
}
286+
252287
template <LoadableJsonValue ValueType>
253288
inline conv_result load(map const& src,
254289
string const& key,
@@ -281,6 +316,20 @@ namespace json {
281316
return conv_result::ok;
282317
}
283318

319+
template <LoadableJsonValue ValueType>
320+
inline conv_result load(map const& src,
321+
string const& key,
322+
std::map<string, ValueType>& value,
323+
std::string& dbg) {
324+
auto it = src.find(key);
325+
if (it == src.end()) return conv_result::opt;
326+
auto const arr = cast<map>(it->second);
327+
if (!arr) return conv_result::opt;
328+
auto res = json::load(*arr, value, dbg);
329+
append_name(res, key, dbg);
330+
return res;
331+
}
332+
284333
template <typename T>
285334
concept JsonStorableValue = requires(T const& obj) {
286335
{ to_json(obj) } -> std::convertible_to<node>;

0 commit comments

Comments
 (0)