OGLplus  (0.59.0) a C++ wrapper for rendering APIs

read.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_SERIALIZE_READ_HPP
10 #define EAGINE_SERIALIZE_READ_HPP
11 
12 #include "../math/functions.hpp"
13 #include "../memory/span_algo.hpp"
14 #include "../reflect/data_members.hpp"
15 #include "../reflect/enumerators.hpp"
16 #include "../valid_if/decl.hpp"
17 #include "fwd.hpp"
18 #include "read_backend.hpp"
19 #include <algorithm>
20 #include <array>
21 #include <chrono>
22 #include <string>
23 #include <tuple>
24 #include <type_traits>
25 #include <vector>
26 
27 namespace eagine {
28 //------------------------------------------------------------------------------
29 template <typename T>
30 class fragment_deserialize_wrapper<span<T>> {
31 public:
32  constexpr fragment_deserialize_wrapper() noexcept = default;
33 
34  constexpr fragment_deserialize_wrapper(span<T> dst) noexcept {
35  set_target(dst);
36  }
37 
38  void set_target(span<T> dst) noexcept {
39  _dst = dst;
40  _done_bits.resize(std_size(dst.size()), false);
41  _done_size = 0;
42  }
43 
44  auto slice(span_size_t offset, span_size_t size) const noexcept {
45  return memory::slice(_dst, offset, size);
46  }
47 
48  void mark_done(span_size_t offs, span_size_t size) noexcept {
49  auto i = math::minimum(_done_bits.begin() + offs, _done_bits.end());
50  auto e = math::minimum(i + size, _done_bits.end());
51  while(i != e) {
52  if(!*i) {
53  *i = true;
54  ++_done_size;
55  }
56  ++i;
57  }
58  }
59 
60  auto is_done() const noexcept -> bool {
61  return _done_size >= _dst.size();
62  }
63 
64 private:
65  span<T> _dst{};
66  std::vector<bool> _done_bits{};
67  span_size_t _done_size{0};
68 };
69 //------------------------------------------------------------------------------
70 template <typename T>
71 struct deserializer<T&> : deserializer<T> {};
72 //------------------------------------------------------------------------------
73 template <typename T>
74 struct plain_deserializer {
75 
76  template <typename Backend>
77  static auto read(T& value, Backend& backend) -> deserialization_errors {
78  span_size_t done{0};
79  return backend.read(cover_one(value), done);
80  }
81 
82  template <typename Backend>
83  static auto read(span<T> values, Backend& backend)
85  span_size_t done{0};
86  return backend.read(values, done);
87  }
88 };
89 //------------------------------------------------------------------------------
90 template <>
91 struct deserializer<bool> : plain_deserializer<bool> {};
92 template <>
93 struct deserializer<char> : plain_deserializer<char> {};
94 template <>
95 struct deserializer<std::int8_t> : plain_deserializer<std::int8_t> {};
96 template <>
97 struct deserializer<short> : plain_deserializer<short> {};
98 template <>
99 struct deserializer<int> : plain_deserializer<int> {};
100 template <>
101 struct deserializer<long> : plain_deserializer<long> {};
102 template <>
103 struct deserializer<long long> : plain_deserializer<long long> {};
104 template <>
105 struct deserializer<std::uint8_t> : plain_deserializer<std::uint8_t> {};
106 template <>
107 struct deserializer<unsigned short> : plain_deserializer<unsigned short> {};
108 template <>
109 struct deserializer<unsigned> : plain_deserializer<unsigned> {};
110 template <>
111 struct deserializer<unsigned long> : plain_deserializer<unsigned long> {};
112 template <>
113 struct deserializer<unsigned long long>
114  : plain_deserializer<unsigned long long> {};
115 template <>
116 struct deserializer<float> : plain_deserializer<float> {};
117 template <>
118 struct deserializer<double> : plain_deserializer<double> {};
119 template <>
120 struct deserializer<identifier> : plain_deserializer<identifier> {};
121 template <>
122 struct deserializer<decl_name_storage>
123  : plain_deserializer<decl_name_storage> {};
124 template <>
125 struct deserializer<std::string> : plain_deserializer<std::string> {};
126 //------------------------------------------------------------------------------
127 template <typename T>
128 struct common_deserializer {
129 
130  template <typename Backend>
131  auto read(span<T> values, Backend& backend) const {
132  using ec = deserialization_error_code;
133  deserialization_errors result{};
134  for(auto& elem : values) {
135  result |=
136  static_cast<const deserializer<T>*>(this)->read(elem, backend);
137  if(result.has(ec::not_enough_data) || result.has(ec::backend_error)) {
138  break;
139  }
140  }
141  return result;
142  }
143 };
144 //------------------------------------------------------------------------------
145 template <typename Bit>
146 struct deserializer<bitfield<Bit>> : common_deserializer<bitfield<Bit>> {
147 
148  template <typename Backend>
149  auto read(bitfield<Bit>& value, Backend& backend) const {
150  typename bitfield<Bit>::value_type temp{0};
151  auto errors{_deserializer.read(temp, backend)};
152  if(EAGINE_LIKELY(!errors)) {
153  value = bitfield<Bit>{temp};
154  }
155  return errors;
156  }
157 
158 private:
160 };
161 //------------------------------------------------------------------------------
162 template <typename Rep>
163 struct deserializer<std::chrono::duration<Rep>>
164  : common_deserializer<std::chrono::duration<Rep>> {
165 
166  template <typename Backend>
167  auto read(std::chrono::duration<Rep>& value, Backend& backend) const {
168  Rep temp{0};
169  auto errors{_deserializer.read(temp, backend)};
170  if(EAGINE_LIKELY(!errors)) {
171  value = std::chrono::duration<Rep>{temp};
172  }
173  return errors;
174  }
175 
176 private:
177  deserializer<Rep> _deserializer{};
178 };
179 //------------------------------------------------------------------------------
180 template <typename... T>
181 struct deserializer<std::tuple<T...>> : common_deserializer<std::tuple<T...>> {
182 
183  using common_deserializer<std::tuple<T...>>::read;
184 
185  template <typename Backend>
186  auto read(std::tuple<T...>& values, Backend& backend) const {
187  deserialization_errors errors{};
188  span_size_t elem_count{0};
189  errors |= backend.begin_list(elem_count);
190  if(EAGINE_UNLIKELY(elem_count < span_size(sizeof...(T)))) {
192  } else if(EAGINE_UNLIKELY(elem_count > span_size(sizeof...(T)))) {
194  }
195  if(EAGINE_LIKELY(
196  errors.has_at_most(deserialization_error_code::excess_element))) {
197  _read_elements(
198  errors, values, backend, std::make_index_sequence<sizeof...(T)>());
199  errors |= backend.finish_list();
200  }
201  return errors;
202  }
203 
204 private:
205  template <typename Tuple, typename Backend, std::size_t... I>
206  void _read_elements(
207  deserialization_errors& errors,
208  Tuple& values,
209  Backend& backend,
210  std::index_sequence<I...>) const {
211  (...,
212  _read_element(
213  errors,
214  I,
215  std::get<I>(values),
216  backend,
217  std::get<I>(_deserializers)));
218  }
219 
220  template <typename Elem, typename Backend, typename Serializer>
221  static void _read_element(
222  deserialization_errors& errors,
223  std::size_t index,
224  Elem& elem,
225  Backend& backend,
226  Serializer& serial) {
227  if(EAGINE_LIKELY(!errors)) {
228  errors |= backend.begin_element(span_size(index));
229  if(EAGINE_LIKELY(!errors)) {
230  errors |= serial.read(elem, backend);
231  errors |= backend.finish_element(span_size(index));
232  }
233  }
234  }
235 
236  std::tuple<deserializer<T>...> _deserializers{};
237 };
238 //------------------------------------------------------------------------------
239 template <typename... T>
240 struct deserializer<std::tuple<std::pair<string_view, T>...>>
241  : common_deserializer<std::tuple<std::pair<string_view, T>...>> {
242 
243  using common_deserializer<std::tuple<std::pair<string_view, T>...>>::read;
244 
245  template <typename Backend>
246  auto
247  read(std::tuple<std::pair<string_view, T>...>& values, Backend& backend) {
248  deserialization_errors errors{};
249  span_size_t memb_count{0};
250  errors |= backend.begin_struct(memb_count);
251  if(EAGINE_UNLIKELY(memb_count < span_size(sizeof...(T)))) {
253  } else if(EAGINE_UNLIKELY(memb_count > span_size(sizeof...(T)))) {
255  }
256  if(EAGINE_LIKELY(
257  errors.has_at_most(deserialization_error_code::excess_member))) {
258  _read_members(
259  errors, values, backend, std::make_index_sequence<sizeof...(T)>());
260  errors |= backend.finish_struct();
261  }
262  return errors;
263  }
264 
265 private:
266  template <typename Tuple, typename Backend, std::size_t... I>
267  void _read_members(
268  deserialization_errors& errors,
269  Tuple& values,
270  Backend& backend,
271  std::index_sequence<I...>) {
272  (...,
273  _read_member(
274  errors,
275  std::get<0>(std::get<I>(values)),
276  std::get<1>(std::get<I>(values)),
277  backend,
278  std::get<I>(_deserializers)));
279  }
280 
281  template <typename Memb, typename Backend, typename Serializer>
282  static void _read_member(
283  deserialization_errors& errors,
284  string_view name,
285  Memb& value,
286  Backend& backend,
287  Serializer& serial) {
288  if(EAGINE_LIKELY(!errors)) {
289  errors |= backend.begin_member(name);
290  if(EAGINE_LIKELY(!errors)) {
291  errors |= serial.read(value, backend);
292  errors |= backend.finish_member(name);
293  }
294  }
295  }
296 
297  std::tuple<deserializer<T>...> _deserializers{};
298 };
299 //------------------------------------------------------------------------------
300 template <typename T>
301 struct deserializer<fragment_deserialize_wrapper<span<T>>>
302  : common_deserializer<fragment_deserialize_wrapper<span<T>>> {
303 
304  using common_deserializer<fragment_deserialize_wrapper<span<T>>>::read;
305 
306  template <typename Backend>
307  auto
308  read(fragment_deserialize_wrapper<span<T>>& frag, Backend& backend) const {
309  deserialization_errors errors{};
310  span_size_t offs{0};
311  errors |= _size_deserializer.read(offs, backend);
312  if(EAGINE_LIKELY(!errors)) {
313  span_size_t size{0};
314  errors |= _size_deserializer.read(size, backend);
315  if(EAGINE_LIKELY(!errors)) {
316  span_size_t done{0};
317  errors |= backend.read(frag.slice(offs, size), done);
318  frag.mark_done(offs, done);
319  }
320  }
321  return errors;
322  }
323 
324  deserializer<span_size_t> _size_deserializer{};
325 };
326 //------------------------------------------------------------------------------
327 template <typename T, std::size_t N>
328 struct deserializer<std::array<T, N>> : common_deserializer<std::array<T, N>> {
329 
330  using common_deserializer<std::array<T, N>>::read;
331 
332  template <typename Backend>
333  auto read(std::array<T, N>& values, Backend& backend) const {
334  deserialization_errors errors{};
335  span_size_t elem_count{0};
336  errors |= backend.begin_list(elem_count);
337  if(EAGINE_UNLIKELY(elem_count < span_size(N))) {
339  } else if(EAGINE_UNLIKELY(elem_count > span_size(N))) {
341  }
342  if(EAGINE_LIKELY(
343  errors.has_at_most(deserialization_error_code::excess_element))) {
344  errors |= _elem_deserializer.read(cover(values), backend);
345  errors |= backend.finish_list();
346  }
347  return errors;
348  }
349 
350 private:
351  deserializer<T> _elem_deserializer{};
352 };
353 //------------------------------------------------------------------------------
354 template <typename T, typename A>
355 struct deserializer<std::vector<T, A>>
356  : common_deserializer<std::vector<T, A>> {
357 
358  template <typename Backend>
359  auto read(std::vector<T, A>& values, Backend& backend) const {
360  deserialization_errors errors{};
361  span_size_t elem_count{0};
362  errors |= backend.begin_list(elem_count);
363  if(EAGINE_LIKELY(!errors)) {
364  values.resize(std_size(elem_count));
365  errors |= _elem_deserializer.read(cover(values), backend);
366  errors |= backend.finish_list();
367  }
368  return errors;
369  }
370 
371 private:
372  deserializer<T> _elem_deserializer{};
373 };
374 //------------------------------------------------------------------------------
375 template <typename T, typename P>
376 struct deserializer<valid_if<T, P>> : common_deserializer<valid_if<T, P>> {
377 
378  template <typename Backend>
379  auto read(valid_if<T, P>& value, Backend& backend) const {
380  deserialization_errors errors{};
381  span_size_t elem_count{0};
382  errors |= backend.begin_list(elem_count);
383  if(EAGINE_UNLIKELY(elem_count < 0)) {
385  } else if(EAGINE_UNLIKELY(elem_count > 1)) {
387  }
388  if(EAGINE_LIKELY(!errors)) {
389  T temp{};
390  errors |= _deserializer.read(temp, backend);
391  errors |= backend.finish_list();
392  if(EAGINE_LIKELY(!errors)) {
393  _assign(value, std::move(temp));
394  }
395  }
396  return errors;
397  }
398 
399 private:
400  static void _assign(valid_if<T, P>& dest, T&& src) noexcept {
401  if constexpr(std::is_same_v<P, valid_flag_policy>) {
402  dest = {std::move(src), true};
403  } else {
404  dest = std::move(src);
405  }
406  }
407 
408  deserializer<T> _deserializer{};
409 };
410 //------------------------------------------------------------------------------
411 template <typename T>
412 struct enum_deserializer {
413 
414  template <typename Backend>
415  auto read(T& enumerator, Backend& backend) const {
416  deserialization_errors errors{};
417  if(backend.enum_as_string()) {
418  decl_name_storage temp_name{};
419  errors |= _name_deserializer.read(temp_name, backend);
420  if(EAGINE_LIKELY(!errors)) {
421  if(auto found{from_string(
422  temp_name.get(), type_identity<T>{}, default_selector)}) {
423  enumerator = extract(found);
424  } else {
426  }
427  }
428  } else {
429  std::underlying_type_t<T> temp_value{};
430  errors |= _value_deserializer.read(temp_value, backend);
431  if(EAGINE_LIKELY(!errors)) {
432  if(auto found = from_value(temp_value, type_identity<T>{})) {
433  enumerator = extract(found);
434  } else {
436  }
437  }
438  }
439  return errors;
440  }
441 
442 private:
443  deserializer<std::underlying_type_t<T>> _value_deserializer{};
444  deserializer<decl_name_storage> _name_deserializer{};
445 };
446 //------------------------------------------------------------------------------
447 template <typename T>
448 struct struct_deserializer {
449 public:
450  template <typename Backend>
451  auto read(T& instance, Backend& backend) {
452  auto member_map = map_data_members(instance);
453  return _deserializer.read(member_map, backend);
454  }
455 
456 private:
457  deserializer<decltype(map_data_members(std::declval<T&>()))> _deserializer{};
458 };
459 //------------------------------------------------------------------------------
460 template <typename T>
461 struct deserializer
462  : std::conditional_t<
463  has_enumerator_mapping_v<T>,
464  enum_deserializer<T>,
465  std::conditional_t<
466  has_data_member_mapping_v<T>,
467  struct_deserializer<T>,
468  nothing_t>> {};
469 //------------------------------------------------------------------------------
474 template <typename T, typename Backend>
475 auto deserialize(T& value, Backend& backend) -> std::enable_if_t<
476  std::is_base_of_v<deserializer_backend, Backend>,
478  deserialization_errors errors{};
479  errors |= backend.begin();
480  if(EAGINE_LIKELY(!errors)) {
481  deserializer<T> reader;
482  errors |= reader.read(value, backend);
483  errors |= backend.finish();
484  }
485  return errors;
486 }
487 //------------------------------------------------------------------------------
488 } // namespace eagine
489 
490 #endif // EAGINE_SERIALIZE_READ_HPP
value_type
Value tree value element data type enumeration.
Definition: interface.hpp:27
static constexpr auto slice(basic_span< T, P, S > s, I i, L l) noexcept -> basic_span< T, P, S >
Returns a slice of span starting at specified index with specified length.
Definition: span_algo.hpp:47
std::ptrdiff_t span_size_t
Signed span size type used by eagine.
Definition: types.hpp:36
auto from_string(string_view src) noexcept
Converts the string representation in src to a value of type T.
Definition: from_string.hpp:360
basic_string_span< const char > string_view
Alias for const string views.
Definition: string_span.hpp:116
static constexpr auto span_size(T v) noexcept
Converts argument to span size type.
Definition: types.hpp:59
Common code is placed in this namespace.
Definition: eagine.hpp:21
std::make_unsigned_t< std::underlying_type_t< bit_type > > value_type
The Integral type used to store the bits.
Definition: bitfield.hpp:25
static constexpr auto cover(T *addr, S size) noexcept -> span_if_mutable< T >
Creates a span starting at the specified pointer and specified length.
Definition: span.hpp:465
static constexpr auto extract(api_result_value< Result, api_result_validity::never > &) noexcept -> Result &
Overload of extract for api_result_value.
Definition: c_api_wrap.hpp:270
basic_span< T, T *, S > span
Default alias for basic memory spans with native pointer type.
Definition: span.hpp:415
deserialization_error_code
Deserialization error code bits enumeration.
Definition: result.hpp:53
auto deserialize(T &value, Backend &backend) -> std::enable_if_t< std::is_base_of_v< deserializer_backend, Backend >, deserialization_errors >
Deserializes a value with the specified serialization backend.
Definition: read.hpp:475
static constexpr auto std_size(T v) noexcept
Converts argument to std size type.
Definition: types.hpp:52
bitfield< deserialization_error_code > deserialization_errors
Alias for deserialization error bitfield.
Definition: result.hpp:106
@ excess_member
Superfluous data for class data member.
@ missing_element
Missing data for container element.
@ unexpected_data
Superfluous data in the deserialization source.
@ excess_element
Superfluous data for container element.
static constexpr auto minimum(T a, T b) noexcept
Returns the minimum value of a and b.
Definition: functions.hpp:47
@ missing_member
Missing data for class data member.
basic_identifier< 10, 6, default_identifier_char_set, identifier_t > identifier
Default identifier type used throughout the project.
Definition: identifier.hpp:346
constexpr const default_selector_t default_selector
The default overload selector constant.
Definition: selector.hpp:34

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).