Iros
 
Loading...
Searching...
No Matches
json_serializer.h
Go to the documentation of this file.
1#pragma once
2
11#include "di/io/prelude.h"
12#include "di/io/string_writer.h"
13#include "di/io/write_exactly.h"
14#include "di/meta/core.h"
15#include "di/meta/language.h"
16#include "di/meta/operations.h"
17#include "di/meta/util.h"
20#include "di/reflect/field.h"
21#include "di/reflect/reflect.h"
24#include "di/util/declval.h"
25#include "di/util/exchange.h"
32
33namespace di::serialization {
34struct JsonFormat;
35
37public:
39
40 constexpr auto pretty() const -> JsonSerializerConfig {
41 auto config = *this;
42 config.m_pretty = true;
43 return config;
44 }
45
46 constexpr auto indent_width(int width) const -> JsonSerializerConfig {
47 auto config = *this;
48 config.m_indent_width = width;
49 return config;
50 }
51
52 constexpr auto is_pretty() const -> bool { return m_pretty; }
53 constexpr auto indent_width() const -> int { return m_indent_width; }
54
55private:
56 bool m_pretty { false };
57 int m_indent_width { 4 };
58};
59
60template<concepts::Impl<Writer> Writer>
62private:
63 enum class State {
64 First,
65 Value,
66 Normal,
67 };
68
69 class ObjectSerializerProxy {
70 public:
71 constexpr explicit ObjectSerializerProxy(JsonSerializer& serializer) : m_serializer(serializer) {}
72
74 DI_TRY(m_serializer.get().serialize_key(key));
75 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
76 return m_serializer.get().serialize_bool(value);
77 }
78
80 DI_TRY(m_serializer.get().serialize_key(key));
81 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
82 return m_serializer.get().serialize_null();
83 }
84
87 DI_TRY(m_serializer.get().serialize_key(key));
88 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
89 return m_serializer.get().serialize_string(view);
90 }
91
92 constexpr auto serialize_number(container::StringView key, concepts::Integral auto number)
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_number(number);
97 }
98
99 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, JsonSerializer&> F>
101 DI_TRY(m_serializer.get().serialize_key(key));
102 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
103 return m_serializer.get().serialize_array(util::forward<F>(function));
104 }
105
106 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, ObjectSerializerProxy&> F>
108 DI_TRY(m_serializer.get().serialize_key(key));
109 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
110 return m_serializer.get().serialize_object(util::forward<F>(function));
111 }
112
113 template<concepts::Serializable<JsonSerializer> T>
114 constexpr auto serialize(container::StringView key, T&& value) -> meta::WriterResult<void, Writer> {
115 DI_TRY(m_serializer.get().serialize_key(key));
116 auto guard = util::ScopeValueChange(m_serializer.get().m_state, State::Value);
117 return serialization::serialize(m_serializer.get(), value);
118 }
119
120 private:
122 };
123
124public:
126
127 template<typename T>
129 constexpr explicit JsonSerializer(T&& writer, JsonSerializerConfig config = {})
130 : m_writer(util::forward<T>(writer)), m_config(config) {}
131
133 DI_TRY(serialize_comma());
134
135 DI_TRY(io::write_exactly(m_writer, "null"_sv));
136 return {};
137 }
138
139 constexpr auto serialize_bool(bool value) -> meta::WriterResult<void, Writer> {
140 if (value) {
141 return serialize_true();
142 }
143 return serialize_false();
144 }
145
147 DI_TRY(serialize_comma());
148
149 DI_TRY(io::write_exactly(m_writer, '"'));
150 // FIXME: escape the string if needed.
151 DI_TRY(io::write_exactly(m_writer, view));
152 DI_TRY(io::write_exactly(m_writer, '"'));
153 return {};
154 }
155
157 DI_TRY(serialize_comma());
158
161 auto context = TargetContext {};
163 di::container::string::StringViewImpl<Enc>(encoding::assume_valid, u8"{}", 2),
165
166 DI_TRY(io::write_exactly(m_writer, context.output()));
167 return {};
168 }
169
170 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, JsonSerializer&> F>
172 DI_TRY(serialize_array_begin());
173 auto guard = util::ScopeValueChange(m_state, State::First);
174 DI_TRY(function::invoke(util::forward<F>(function), *this));
175 return serialize_array_end();
176 }
177
178 template<concepts::InvocableTo<meta::WriterResult<void, Writer>, ObjectSerializerProxy&> F>
180 DI_TRY(serialize_object_begin());
181 auto guard = util::ScopeValueChange(m_state, State::First);
182 auto proxy = ObjectSerializerProxy(*this);
183 DI_TRY(function::invoke(util::forward<F>(function), proxy));
184 return serialize_object_end();
185 }
186
187 template<typename T, concepts::InstanceOf<reflection::Fields> M>
188 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
192 constexpr auto name = container::fixed_string_to_utf8_string_view<field.name>();
193
194 using Type = meta::Type<decltype(field)>;
195 if constexpr (concepts::Optional<Type>) {
196 if (!field.get(value).has_value()) {
197 return {};
198 }
199 return serializer.serialize(name, *field.get(value));
200 } else {
201 return serializer.serialize(name, field.get(value));
202 }
203 },
204 M {});
205 });
206 }
207
208 template<typename T, concepts::InstanceOf<reflection::Enumerators> M>
209 constexpr auto serialize(T value, M) -> meta::WriterResult<void, Writer> {
211 }
212
213 template<typename T, concepts::InstanceOf<reflection::Atom> M>
214 requires(M::is_bool() || M::is_string() || M::is_integer())
215 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
216 if constexpr (M::is_bool()) {
217 return serialize_bool(M::get(value));
218 } else if constexpr (M::is_string()) {
219 return serialize_string(M::get(value));
220 } else if constexpr (M::is_integer()) {
221 return serialize_number(M::get(value));
222 }
223 }
224
225 template<typename T, concepts::InstanceOf<reflection::Atom> M>
227 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
228 return serialize_array([&](auto& serializer) {
229 return container::sequence(M::get(value), [&](auto&& element) {
230 return serialization::serialize(serializer, element);
231 });
232 });
233 }
234
235 template<typename T, concepts::InstanceOf<reflection::Atom> M>
239 constexpr auto serialize(T&& value, M) -> meta::WriterResult<void, Writer> {
240 return serialize_object([&](auto& serializer) {
241 return container::sequence(M::get(value), [&](concepts::TupleLike auto&& element) {
242 return serializer.serialize(util::get<0>(element), util::get<1>(element));
243 });
244 });
245 }
246
247 constexpr auto writer() & -> Writer& { return m_writer; }
248 constexpr auto writer() const& -> Writer const& { return m_writer; }
249 constexpr auto writer() && -> Writer&& { return util::move(*this).m_writer; }
250
251private:
252 constexpr auto serialize_true() -> meta::WriterResult<void, Writer> {
253 DI_TRY(serialize_comma());
254
255 DI_TRY(io::write_exactly(m_writer, "true"_sv));
256 return {};
257 }
258
259 constexpr auto serialize_false() -> meta::WriterResult<void, Writer> {
260 DI_TRY(serialize_comma());
261
262 DI_TRY(io::write_exactly(m_writer, "false"_sv));
263 return {};
264 }
265
266 constexpr auto serialize_comma() -> meta::WriterResult<void, Writer> {
267 if (m_state == State::Value) {
268 return {};
269 }
270 if (util::exchange(m_state, State::Normal) == State::Normal) {
271 DI_TRY(io::write_exactly(m_writer, ','));
272 DI_TRY(serialize_newline());
273 DI_TRY(serialize_indent());
274 } else if (m_indent > 0) {
275 DI_TRY(serialize_newline());
276 DI_TRY(serialize_indent());
277 }
278 return {};
279 }
280
281 constexpr auto serialize_object_begin() -> meta::WriterResult<void, Writer> {
282 DI_TRY(serialize_comma());
283 DI_TRY(io::write_exactly(m_writer, '{'));
284 ++m_indent;
285 return {};
286 }
287
288 constexpr auto serialize_object_end() -> meta::WriterResult<void, Writer> {
289 --m_indent;
290 if (m_state != State::First) {
291 DI_TRY(serialize_newline());
292 DI_TRY(serialize_indent());
293 }
294 DI_TRY(io::write_exactly(m_writer, '}'));
295 return {};
296 }
297
298 constexpr auto serialize_array_begin() -> meta::WriterResult<void, Writer> {
299 DI_TRY(serialize_comma());
300 DI_TRY(io::write_exactly(m_writer, '['));
301 ++m_indent;
302 return {};
303 }
304
305 constexpr auto serialize_array_end() -> meta::WriterResult<void, Writer> {
306 --m_indent;
307 if (m_state != State::First) {
308 DI_TRY(serialize_newline());
309 DI_TRY(serialize_indent());
310 }
311 DI_TRY(io::write_exactly(m_writer, ']'));
312 return {};
313 }
314
315 constexpr auto serialize_key(container::StringView key) -> meta::WriterResult<void, Writer> {
317 DI_TRY(io::write_exactly(m_writer, ':'));
318 if (pretty_print()) {
319 DI_TRY(io::write_exactly(m_writer, ' '));
320 }
321 return {};
322 }
323
324 constexpr auto serialize_newline() -> meta::WriterResult<void, Writer> {
325 if (!pretty_print()) {
326 return {};
327 }
328 return io::write_exactly(m_writer, '\n');
329 }
330
331 constexpr auto serialize_indent() -> meta::WriterResult<void, Writer> {
332 if (!pretty_print()) {
333 return {};
334 }
335 return view::range(m_indent * m_config.indent_width()) | container::sequence([&](auto) {
336 return io::write_exactly(m_writer, ' ');
337 });
338 }
339
340 constexpr auto pretty_print() const -> bool { return m_config.is_pretty(); }
341
342 Writer m_writer;
343 JsonSerializerConfig m_config;
344 usize m_indent { 0 };
345 State m_state { State::First };
346};
347
348template<typename T>
350
351template<typename T>
353
354template<concepts::Impl<io::Reader> Reader>
356
358 template<concepts::Impl<io::Writer> Writer, typename... Args>
360 constexpr static auto serializer(Writer&& writer, Args&&... args) {
361 return JsonSerializer<meta::RemoveCVRef<Writer>>(util::forward<Writer>(writer), util::forward<Args>(args)...);
362 }
363
364 template<concepts::Impl<io::Reader> Reader, typename... Args>
366 constexpr static auto deserializer(Reader&& reader, Args&&... args) {
367 return JsonDeserializer<meta::RemoveCVRef<Reader>>(util::forward<Reader>(reader), util::forward<Args>(args)...);
368 }
369};
370
371constexpr inline auto json_format = JsonFormat {};
372
373namespace detail {
375 template<concepts::Serializable<JsonSerializer<io::StringWriter<>>> T, typename... Args>
377 constexpr auto operator()(T&& value, Args&&... args) const {
378 return serialization::serialize_string(json_format, value, util::forward<Args>(args)...);
379 }
380 };
381}
382
384
385namespace detail {
387 template<concepts::Impl<io::Writer> Writer, concepts::Serializable<JsonSerializer<Writer>> T, typename... Args>
390 constexpr auto operator()(Writer&& writer, T&& value, Args&&... args) const {
391 return serialize(json_format, util::ref(writer), value, util::forward<Args>(args)...);
392 }
393 };
394}
395
397}
398
399namespace di {
400using serialization::JsonFormat;
402using serialization::JsonSerializerConfig;
403
407}
Definition string_view_impl_forward_declaration.h:7
Definition utf8_encoding.h:107
Definition bounded_format_context.h:9
Definition string_writer.h:14
A deserializer for the JSON format.
Definition json_serializer.h:355
constexpr JsonDeserializer(T &&reader)
Definition json_deserializer.h:46
Definition json_serializer.h:36
constexpr auto pretty() const -> JsonSerializerConfig
Definition json_serializer.h:40
constexpr auto indent_width(int width) const -> JsonSerializerConfig
Definition json_serializer.h:46
constexpr auto is_pretty() const -> bool
Definition json_serializer.h:52
constexpr auto indent_width() const -> int
Definition json_serializer.h:53
Definition json_serializer.h:61
constexpr auto serialize_array(F &&function) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:171
constexpr auto writer() &-> Writer &
Definition json_serializer.h:247
constexpr auto serialize(T value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:209
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:188
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:239
constexpr auto writer() &&-> Writer &&
Definition json_serializer.h:249
JsonFormat SerializationFormat
Definition json_serializer.h:125
constexpr auto serialize_null() -> meta::WriterResult< void, Writer >
Definition json_serializer.h:132
constexpr auto serialize_number(concepts::Integral auto number) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:156
constexpr auto serialize_string(container::StringView view) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:146
constexpr JsonSerializer(T &&writer, JsonSerializerConfig config={})
Definition json_serializer.h:129
constexpr auto serialize_bool(bool value) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:139
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:227
constexpr auto serialize(T &&value, M) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:215
constexpr auto serialize_object(F &&function) -> meta::WriterResult< void, Writer >
Definition json_serializer.h:179
constexpr auto writer() const &-> Writer const &
Definition json_serializer.h:248
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
Definition constant_string.h:8
constexpr usize width
Definition gfx_test.cpp:21
#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 > Writer
Definition writer.h:59
Definition json_deserializer.h:532
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:64
constexpr auto enum_to_string
Definition enum_to_string.h:25
Definition binary_deserializer.h:33
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:371
constexpr auto serialize_json
Definition json_serializer.h:396
constexpr auto to_json_string
Definition json_serializer.h:383
constexpr auto serializer
Definition serialize.h:43
size_t usize
Definition integers.h:33
__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 zstring_parser.h:9
constexpr auto field
Definition field.h:42
Definition json_serializer.h:357
static constexpr auto serializer(Writer &&writer, Args &&... args)
Definition json_serializer.h:360
static constexpr auto deserializer(Reader &&reader, Args &&... args)
Definition json_serializer.h:366
Definition json_serializer.h:386
Definition json_serializer.h:374