di 0.1.0
Loading...
Searching...
No Matches
json_serializer.h
Go to the documentation of this file.
1#pragma once
2
10#include "di/function/invoke.h"
12#include "di/io/prelude.h"
13#include "di/io/string_writer.h"
14#include "di/io/write_exactly.h"
15#include "di/meta/core.h"
16#include "di/meta/language.h"
17#include "di/meta/operations.h"
18#include "di/meta/util.h"
21#include "di/reflect/field.h"
22#include "di/reflect/reflect.h"
26#include "di/util/declval.h"
27#include "di/util/exchange.h"
37
38namespace di::serialization {
39struct JsonFormat;
40
41namespace detail {
42 template<typename S, typename T>
43 struct AllSerializable {
44 constexpr static auto value = false;
45 };
46
47 template<typename S, typename... Types>
48 struct AllSerializable<S, meta::List<Types...>> {
49 constexpr static auto value = (concepts::Serializable<Types, S> && ...);
50 };
51
52 template<typename S, concepts::TypeList T>
53 constexpr static auto all_serializable = AllSerializable<S, T>::value;
54}
55
57public:
59
60 constexpr auto pretty() const -> JsonSerializerConfig {
61 auto config = *this;
62 config.m_pretty = true;
63 return config;
64 }
65
66 constexpr auto indent_width(int width) const -> JsonSerializerConfig {
67 auto config = *this;
68 config.m_indent_width = width;
69 return config;
70 }
71
72 constexpr auto is_pretty() const -> bool { return m_pretty; }
73 constexpr auto indent_width() const -> int { return m_indent_width; }
74
75private:
76 bool m_pretty { false };
77 int m_indent_width { 4 };
78};
79
80template<concepts::Impl<Writer> Writer>
82private:
83 enum class State {
84 First,
85 Value,
86 Normal,
87 };
88
89 class ObjectSerializerProxy {
90 public:
91 constexpr explicit ObjectSerializerProxy(JsonSerializer& serializer) : m_serializer(serializer) {}
92
94 DI_TRY(m_serializer.get().serialize_key(key));
95 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
96 return m_serializer.get().serialize_bool(value);
97 }
98
100 DI_TRY(m_serializer.get().serialize_key(key));
101 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
102 return m_serializer.get().serialize_null();
103 }
104
107 DI_TRY(m_serializer.get().serialize_key(key));
108 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
109 return m_serializer.get().serialize_string(view);
110 }
111
112 constexpr auto serialize_number(container::StringView key, concepts::Integral auto number)
114 DI_TRY(m_serializer.get().serialize_key(key));
115 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
116 return m_serializer.get().serialize_number(number);
117 }
118
119 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, JsonSerializer&> F>
121 DI_TRY(m_serializer.get().serialize_key(key));
122 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
123 return m_serializer.get().serialize_array(util::forward<F>(function));
124 }
125
126 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, ObjectSerializerProxy&> F>
128 DI_TRY(m_serializer.get().serialize_key(key));
129 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
130 return m_serializer.get().serialize_object(util::forward<F>(function));
131 }
132
133 template<concepts::Serializable<JsonSerializer> T>
134 constexpr auto serialize(container::StringView key, T&& value) -> meta::WriterResult<void, Writer> {
135 DI_TRY(m_serializer.get().serialize_key(key));
136 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
137 return serialization::serialize(m_serializer.get(), value);
138 }
139
140 private:
142 };
143
144 constexpr static auto to_hex_digit(u8 value) -> c8 {
145 DI_ASSERT(value < 16);
146 if (value < 10) {
147 return value + c8('0');
148 }
149 return (value - 10) + c8('A');
150 }
151
152public:
154
155 template<typename T>
157 constexpr explicit JsonSerializer(T&& writer, JsonSerializerConfig config = {})
158 : m_writer(util::forward<T>(writer)), m_config(config) {}
159
161 DI_TRY(serialize_comma());
162
163 DI_TRY(io::write_exactly(m_writer, "null"_sv));
164 return {};
165 }
166
167 constexpr auto serialize_bool(bool value) -> meta::WriterResult<void, Writer> {
168 if (value) {
169 return serialize_true();
170 }
171 return serialize_false();
172 }
173
175 DI_TRY(serialize_comma());
176
177 DI_TRY(io::write_exactly(m_writer, '"'));
178 for (auto code_point_view : slide(view, 1)) {
179 auto code_point = *front(code_point_view);
180 // Check if we need to escape the code point
181 if (code_point == U'"' || code_point == U'\\' || code_point <= 0x1Fu) {
182 switch (code_point) {
183 case U'"':
184 DI_TRY(io::write_exactly(m_writer, "\\\""_sv));
185 continue;
186 case U'\\':
187 DI_TRY(io::write_exactly(m_writer, "\\\\"_sv));
188 continue;
189 case U'\b':
190 DI_TRY(io::write_exactly(m_writer, "\\b"_sv));
191 continue;
192 case U'\f':
193 DI_TRY(io::write_exactly(m_writer, "\\f"_sv));
194 continue;
195 case U'\n':
196 DI_TRY(io::write_exactly(m_writer, "\\n"_sv));
197 continue;
198 case U'\r':
199 DI_TRY(io::write_exactly(m_writer, "\\r"_sv));
200 continue;
201 case U'\t':
202 DI_TRY(io::write_exactly(m_writer, "\\t"_sv));
203 continue;
204 default:
205 auto text = di::Array { c8('\\'), c8('u'), c8('0'), c8('0'), c8('0'), c8('0') };
206 text[4] = to_hex_digit((code_point >> 4) & 0xF);
207 text[5] = to_hex_digit(code_point & 0xF);
208 DI_TRY(io::write_exactly(m_writer, StringView(encoding::assume_valid, text)));
209 continue;
210 }
211 }
212 DI_TRY(io::write_exactly(m_writer, code_point_view));
213 }
214 DI_TRY(io::write_exactly(m_writer, '"'));
215 return {};
216 }
217
219 DI_TRY(serialize_comma());
220
223 auto context = TargetContext {};
225 di::container::string::StringViewImpl<Enc>(encoding::assume_valid, u8"{}", 2),
227
228 DI_TRY(io::write_exactly(m_writer, context.output()));
229 return {};
230 }
231
232 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, JsonSerializer&> F>
234 DI_TRY(serialize_array_begin());
235 auto guard = util::ScopeValueChange(m_state, State::First);
236 DI_TRY(function::invoke(util::forward<F>(function), *this));
237 return serialize_array_end();
238 }
239
240 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, ObjectSerializerProxy&> F>
242 DI_TRY(serialize_object_begin());
243 auto guard = util::ScopeValueChange(m_state, State::First);
244 auto proxy = ObjectSerializerProxy(*this);
245 DI_TRY(function::invoke(util::forward<F>(function), proxy));
246 return serialize_object_end();
247 }
248
249 template<typename T, concepts::InstanceOf<reflection::Fields> M>
250 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
254 constexpr auto name = container::fixed_string_to_utf8_string_view<field.name>();
255
256 using Type = meta::Type<decltype(field)>;
257 if constexpr (concepts::Optional<Type>) {
258 if (!field.get(value).has_value()) {
259 return {};
260 }
261 return serializer.serialize(name, *field.get(value));
262 } else {
263 return serializer.serialize(name, field.get(value));
264 }
265 },
266 M {});
267 });
268 }
269
270 template<typename T, concepts::InstanceOf<reflection::Enumerators> M>
271 constexpr auto serialize(T value, M) -> meta::WriterResult<void, Writer> {
273 }
274
275 template<typename T, concepts::InstanceOf<reflection::Atom> M>
276 requires(M::is_bool() || M::is_string() || M::is_integer())
277 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
278 if constexpr (M::is_bool()) {
279 return serialize_bool(M::get(value));
280 } else if constexpr (M::is_string()) {
281 return serialize_string(M::get(value));
282 } else if constexpr (M::is_integer()) {
283 return serialize_number(M::get(value));
284 }
285 }
286
287 template<typename T, concepts::InstanceOf<reflection::Atom> M>
288 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer>
289 requires(M::is_custom_atom() && requires { di::to_string(value); })
290 {
291 auto string = di::to_string(value);
292 return serialize_string(string.view());
293 }
294
295 template<typename T, concepts::InstanceOf<reflection::Atom> M>
296 requires(M::is_tuple() && detail::all_serializable<JsonSerializer, meta::TupleElements<T>>)
297 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
298 return serialize_array([&](auto& serializer) {
300 [&](auto&& element) -> meta::WriterResult<void, Writer> {
301 return serialization::serialize(serializer, element);
302 },
303 M::get(value));
304 });
305 }
306
307 template<typename T, concepts::InstanceOf<reflection::Atom> M>
308 requires(M::is_variant() && detail::all_serializable<JsonSerializer, meta::VariantTypes<T>>)
309 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
310 return serialize_object([&](auto& serializer) {
311 return di::visit(
312 [&]<typename U>(U&& element) -> meta::WriterResult<void, Writer> {
314 return serializer.serialize(name, element);
315 },
316 M::get(value));
317 });
318 }
319
320 template<typename T, concepts::InstanceOf<reflection::Atom> M>
322 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
323 if (!value) {
324 return serialize_null();
325 }
326 return serialization::serialize(*this, *value);
327 }
328
329 template<typename T, concepts::InstanceOf<reflection::Atom> M>
331 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
332 return serialize_array([&](auto& serializer) {
333 return container::sequence(M::get(value), [&](auto&& element) {
334 return serialization::serialize(serializer, element);
335 });
336 });
337 }
338
339 template<typename T, concepts::InstanceOf<reflection::Atom> M>
340 requires(M::is_map() && concepts::detail::ConstantString<meta::TupleElement<meta::ContainerValue<T>, 0>> &&
343 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
344 return serialize_object([&](auto& serializer) {
345 return container::sequence(M::get(value), [&](concepts::TupleLike auto&& element) {
346 return serializer.serialize(util::get<0>(element), util::get<1>(element));
347 });
348 });
349 }
350
351 constexpr auto writer() & -> Writer& { return m_writer; }
352 constexpr auto writer() const& -> Writer const& { return m_writer; }
353 constexpr auto writer() && -> Writer&& { return util::move(*this).m_writer; }
354
355private:
356 constexpr auto serialize_true() -> meta::WriterResult<void, Writer> {
357 DI_TRY(serialize_comma());
358
359 DI_TRY(io::write_exactly(m_writer, "true"_sv));
360 return {};
361 }
362
363 constexpr auto serialize_false() -> meta::WriterResult<void, Writer> {
364 DI_TRY(serialize_comma());
365
366 DI_TRY(io::write_exactly(m_writer, "false"_sv));
367 return {};
368 }
369
370 constexpr auto serialize_comma() -> meta::WriterResult<void, Writer> {
371 if (m_state == State::Value) {
372 return {};
373 }
374 if (util::exchange(m_state, State::Normal) == State::Normal) {
375 DI_TRY(io::write_exactly(m_writer, ','));
376 DI_TRY(serialize_newline());
377 DI_TRY(serialize_indent());
378 } else if (m_indent > 0) {
379 DI_TRY(serialize_newline());
380 DI_TRY(serialize_indent());
381 }
382 return {};
383 }
384
385 constexpr auto serialize_object_begin() -> meta::WriterResult<void, Writer> {
386 DI_TRY(serialize_comma());
387 DI_TRY(io::write_exactly(m_writer, '{'));
388 ++m_indent;
389 return {};
390 }
391
392 constexpr auto serialize_object_end() -> meta::WriterResult<void, Writer> {
393 --m_indent;
394 if (m_state != State::First) {
395 DI_TRY(serialize_newline());
396 DI_TRY(serialize_indent());
397 }
398 DI_TRY(io::write_exactly(m_writer, '}'));
399 return {};
400 }
401
402 constexpr auto serialize_array_begin() -> meta::WriterResult<void, Writer> {
403 DI_TRY(serialize_comma());
404 DI_TRY(io::write_exactly(m_writer, '['));
405 ++m_indent;
406 return {};
407 }
408
409 constexpr auto serialize_array_end() -> meta::WriterResult<void, Writer> {
410 --m_indent;
411 if (m_state != State::First) {
412 DI_TRY(serialize_newline());
413 DI_TRY(serialize_indent());
414 }
415 DI_TRY(io::write_exactly(m_writer, ']'));
416 return {};
417 }
418
419 constexpr auto serialize_key(container::StringView key) -> meta::WriterResult<void, Writer> {
421 DI_TRY(io::write_exactly(m_writer, ':'));
422 if (pretty_print()) {
423 DI_TRY(io::write_exactly(m_writer, ' '));
424 }
425 return {};
426 }
427
428 constexpr auto serialize_newline() -> meta::WriterResult<void, Writer> {
429 if (!pretty_print()) {
430 return {};
431 }
432 return io::write_exactly(m_writer, '\n');
433 }
434
435 constexpr auto serialize_indent() -> meta::WriterResult<void, Writer> {
436 if (!pretty_print()) {
437 return {};
438 }
439 return view::range(m_indent * m_config.indent_width()) | container::sequence([&](auto) {
440 return io::write_exactly(m_writer, ' ');
441 });
442 }
443
444 constexpr auto pretty_print() const -> bool { return m_config.is_pretty(); }
445
446 Writer m_writer;
447 JsonSerializerConfig m_config;
448 usize m_indent { 0 };
449 State m_state { State::First };
450};
451
452template<typename T>
454
455template<typename T>
457
458template<concepts::Impl<io::Reader> Reader>
459class JsonDeserializer;
460
462 template<concepts::Impl<io::Writer> Writer, typename... Args>
464 constexpr static auto serializer(Writer&& writer, Args&&... args) {
465 return JsonSerializer<meta::RemoveCVRef<Writer>>(util::forward<Writer>(writer), util::forward<Args>(args)...);
466 }
467
468 template<concepts::Impl<io::Reader> Reader, typename... Args>
470 constexpr static auto deserializer(Reader&& reader, Args&&... args) {
471 return JsonDeserializer<meta::RemoveCVRef<Reader>>(util::forward<Reader>(reader), util::forward<Args>(args)...);
472 }
473};
474
475constexpr inline auto json_format = JsonFormat {};
476
477namespace detail {
478 struct ToJsonStringFunction {
479 template<concepts::Serializable<JsonSerializer<io::StringWriter<>>> T, typename... Args>
481 constexpr auto operator()(T&& value, Args&&... args) const {
482 return serialization::serialize_string(json_format, value, util::forward<Args>(args)...);
483 }
484 };
485}
486
487constexpr inline auto to_json_string = detail::ToJsonStringFunction {};
488
489namespace detail {
490 struct SerializeJsonFunction {
491 template<concepts::Impl<io::Writer> Writer, concepts::Serializable<JsonSerializer<Writer>> T, typename... Args>
494 constexpr auto operator()(Writer&& writer, T&& value, Args&&... args) const {
495 return serialize(json_format, util::ref(writer), value, util::forward<Args>(args)...);
496 }
497 };
498}
499
500constexpr inline auto serialize_json = detail::SerializeJsonFunction {};
501}
502
503namespace di {
504using serialization::JsonFormat;
506using serialization::JsonSerializerConfig;
507
511}
#define DI_ASSERT(...)
Definition assert_bool.h:7
constexpr auto serialize_array(F &&function) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:233
constexpr auto serialize_number(concepts::Integral auto number) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:218
constexpr JsonSerializer(T &&writer, JsonSerializerConfig config={})
Definition json_serializer.h:157
constexpr auto serialize_bool(bool value) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:167
constexpr auto serialize_object(F &&function) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:241
Definition string_view_impl.h:19
Definition utf8_encoding.h:107
Definition bounded_format_context.h:9
Definition string_writer.h:14
A deserializer for the JSON format.
Definition json_deserializer.h:56
Definition json_serializer.h:56
constexpr auto pretty() const -> JsonSerializerConfig
Definition json_serializer.h:60
constexpr auto indent_width(int width) const -> JsonSerializerConfig
Definition json_serializer.h:66
constexpr auto is_pretty() const -> bool
Definition json_serializer.h:72
constexpr auto indent_width() const -> int
Definition json_serializer.h:73
Definition json_serializer.h:81
constexpr auto serialize_array(F &&function) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:233
constexpr auto writer() &-> Writer &
Definition json_serializer.h:351
constexpr auto serialize(T value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:271
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:250
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:343
constexpr auto writer() &&-> Writer &&
Definition json_serializer.h:353
JsonFormat SerializationFormat
Definition json_serializer.h:153
constexpr auto serialize_null() -> meta::WriterResult< void, Writer >
Definition json_serializer.h:160
constexpr auto serialize_number(concepts::Integral auto number) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:218
constexpr auto serialize_string(container::StringView view) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:174
constexpr JsonSerializer(T &&writer, JsonSerializerConfig config={})
Definition json_serializer.h:157
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:309
return serialize_string(string.view())
constexpr auto serialize_bool(bool value) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:167
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:331
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer > requires(M::is_custom_atom() &&
Definition json_serializer.h:288
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:322
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:277
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:297
constexpr auto serialize_object(F &&function) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:241
constexpr auto writer() const &-> Writer const &
Definition json_serializer.h:352
Definition reference_wrapper.h:14
Definition operations.h:11
Definition language.h:224
Definition vocab.h:77
Definition serialize.h:175
Definition tuple_like.h:38
#define DI_TRY(...)
Definition monad_try.h:13
string::StringViewImpl< string::Utf8Encoding > StringView
Definition string_view.h:12
constexpr auto sequence
Definition sequence.h:34
constexpr auto fixed_string_to_utf8_string_view
Definition fixed_string_to_utf8_string_view.h:32
constexpr auto make_format_args(Types &&... values)
Definition make_format_args.h:9
constexpr auto vpresent_encoded_context
Definition vpresent_encoded_context.h:61
Definition as_bool.h:8
constexpr auto invoke
Definition invoke.h:100
constexpr auto write_exactly
Definition write_exactly.h:51
meta::List< ReadSome > Reader
Definition reader.h:34
meta::List< WriteSome, Flush, InteractiveDevice > Writer
Definition writer.h:85
decltype(util::get< index >(util::declval< Tup >())) TupleValue
Definition tuple_value.h:10
T::Type Type
Definition core.h:26
meta::LikeExpected< decltype(io::write_some(util::declval< Writer & >(), util::declval< Span< Byte const > >())), T > WriterResult
Definition writer.h:90
constexpr auto enum_to_string
Definition enum_to_string.h:72
Definition base64.h:16
JsonSerializer(T &&) -> JsonSerializer< T >
constexpr auto serialize_string
Definition serialize_string.h:23
constexpr auto serialize
Definition serialize.h:130
constexpr auto json_format
Definition json_serializer.h:475
constexpr auto serialize_json
Definition json_serializer.h:500
constexpr auto to_json_string
Definition json_serializer.h:487
constexpr auto serializer
Definition serialize.h:43
size_t usize
Definition integers.h:33
char8_t c8
Definition char.h:4
__UINT8_TYPE__ u8
Definition integers.h:9
Definition vocab.h:96
constexpr auto get(T &&value) -> decltype(auto)
Definition get.h:8
constexpr auto ref
Definition reference_wrapper.h:98
auto declval() -> meta::AddRValueReference< T >
Definition declval.h:8
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
ScopeValueChange(T &, T) -> ScopeValueChange< T >
constexpr auto tuple_sequence
Definition tuple_sequence.h:36
Definition any_storable.h:9
constexpr auto front
Definition access.h:58
constexpr auto visit(Vis &&visitor, Vars &&... variants) -> R
Definition visit.h:39
constexpr auto field
Definition field.h:46
constexpr auto tuple_sequence
Definition tuple_sequence.h:36
constexpr auto json_format
Definition json_serializer.h:475
constexpr auto to_string
Definition to_string.h:14
constexpr auto serializer
Definition serialize.h:43
Definition json_serializer.h:461
static constexpr auto serializer(Writer &&writer, Args &&... args)
Definition json_serializer.h:464
static constexpr auto deserializer(Reader &&reader, Args &&... args)
Definition json_serializer.h:470
Definition array.h:27