DocWire SDK
DocWire SDK: Award-winning modern data processing in C++20. SourceForge Community Choice & Microsoft support. AI-driven processing. Supports nearly 100 data formats, including email boxes and OCR. Boost efficiency in text extraction, web data extraction, data mining, document analysis. Offline processing possible for security and confidentiality
serialization_base.h
1 /*********************************************************************************************************************************************/
2 /* DocWire SDK: Award-winning modern data processing in C++20. SourceForge Community Choice & Microsoft support. AI-driven processing. */
3 /* Supports nearly 100 data formats, including email boxes and OCR. Boost efficiency in text extraction, web data extraction, data mining, */
4 /* document analysis. Offline processing possible for security and confidentiality */
5 /* */
6 /* Copyright (c) SILVERCODERS Ltd, http://silvercoders.com */
7 /* Project homepage: https://github.com/docwire/docwire */
8 /* */
9 /* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-DocWire-Commercial */
10 /*********************************************************************************************************************************************/
11 
12 #ifndef DOCWIRE_SERIALIZATION_BASE_H
13 #define DOCWIRE_SERIALIZATION_BASE_H
14 
15 #include "concepts_container.h"
16 #include "concepts_misc.h"
17 #include "concepts_string.h"
18 #include "concepts_variant.h"
19 #include <cstdint>
20 #include <map>
21 #include <string>
22 #include <type_traits>
23 #include <variant>
24 #include <vector>
25 #include "type_name.h"
26 
27 namespace docwire
28 {
29 
46 namespace serialization
47 {
48 
49 // Forward declarations for recursive variant types within the namespace
50 struct object;
51 struct array;
52 
59 using value = std::variant<
60  std::nullptr_t,
61  bool,
62  std::int64_t,
63  std::uint64_t,
64  double,
65  std::string,
66  array,
67  object
68 >;
69 
71 struct array { std::vector<value> v; };
72 
74 struct object { std::map<std::string, value> v; };
75 
77 enum class serializer_kind
78 {
80  arithmetic,
82  container,
84 };
85 
87 inline value decorate_with_typeid(const value& base_val, const std::string& typeid_str)
88 {
89  return object{{
90  {"typeid", typeid_str},
91  {"value", base_val}
92  }};
93 }
102 template <typename T> value full(const T& value);
103 
111 template <typename T>
112 struct serializer;
113 
114 template <typename T>
115 value full(const T& value) { return serializer<T>{}.full(value); }
116 
117 template <typename T>
118 value typed_summary(const T& value)
119 {
120  return serializer<T>{}.typed_summary(value);
121 }
122 
126 template <typename T>
127 concept value_alternative = variant_alternative<T, value>;
128 
133 template <value_alternative T>
134 struct serializer<T>
135 {
136  static constexpr serializer_kind kind = serializer_kind::value_alternative;
137  value full(const T& value) const { return value; }
138 
139  value typed_summary(const T& value) const {
140  return decorate_with_typeid(this->full(value), type_name::pretty<T>());
141  }
142 };
143 
150 template <typename T> requires(std::is_arithmetic_v<T> && !value_alternative<T>)
151 struct serializer<T>
152 {
153  static constexpr serializer_kind kind = serializer_kind::arithmetic;
154  value full(const T& value) const
155  {
156  if constexpr (std::is_integral_v<T> && std::is_signed_v<T>)
157  return static_cast<std::int64_t>(value);
158  else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>)
159  return static_cast<std::uint64_t>(value);
160  else // is_floating_point
161  return static_cast<double>(value);
162  }
163 
164  value typed_summary(const T& value) const {
165  return decorate_with_typeid(this->full(value), type_name::pretty<T>());
166  }
167 };
168 
172 template <typename T> requires string_like<T> && (!value_alternative<T>)
173 struct serializer<T>
174 {
175  static constexpr serializer_kind kind = serializer_kind::string_like;
176  value full(const T& val) const
177  {
178  if constexpr (std::is_pointer_v<std::decay_t<T>>) {
179  if (val == nullptr) {
180  return nullptr;
181  }
182  }
183  return std::string(val);
184  }
185  value typed_summary(const T& val) const { return decorate_with_typeid(this->full(val), type_name::pretty<T>()); }
186 };
187 
191 template <strong_type_alias T>
192 struct serializer<T>
193 {
194  value full(const T& value) const { return serialization::full(value.v); }
195  value typed_summary(const T& value) const { return decorate_with_typeid(full(value), type_name::pretty<T>()); }
196 };
197 
201 template <empty T>
202 struct serializer<T>
203 {
204  value full(const T& val) const { return object{}; }
205  value typed_summary(const T& val) const { return decorate_with_typeid(this->full(val), type_name::pretty<T>()); }
206 };
207 
213 template <typename T>
214 requires (dereferenceable<T> && !container<T> && !string_like<T> && !value_alternative<T>)
215 struct serializer<T>
216 {
217  static constexpr serializer_kind kind = serializer_kind::dereferenceable;
218 
219  value full(const T& dereferenceable) const
220  {
221  if (dereferenceable) {
222  return object{{{"value", serialization::full(*dereferenceable)}}};
223  }
224  return nullptr;
225  }
226 
227  value typed_summary(const T& dereferenceable) const {
228  if (dereferenceable) {
229  return object{{
230  {"typeid", type_name::pretty<T>()},
231  {"value", serialization::typed_summary(*dereferenceable)}
232  }};
233  }
234  return decorate_with_typeid(nullptr, type_name::pretty<T>());
235  }
236 };
237 
244 template <typename T> requires (container<T> && !string_like<T> && !value_alternative<T>)
245 struct serializer<T>
246 {
247  static constexpr serializer_kind kind = serializer_kind::container;
248  value full(const T& container) const
249  {
250  array arr;
251  for (const auto& item : container) { arr.v.push_back(serialization::full(item)); }
252  return arr;
253  }
254 
255  value typed_summary(const T& container) const
256  {
257  array arr;
258  for (const auto& item : container)
259  {
260  arr.v.push_back(serialization::typed_summary(item));
261  }
262  return decorate_with_typeid(arr, type_name::pretty<T>());
263  }
264 };
265 
273 template<typename... Ts>
274 struct serializer<std::variant<Ts...>>
275 {
276  value full(const std::variant<Ts...>& variant) const
277  {
278  return std::visit([](const auto& value) {
279  return object{{{"value", serialization::full(value)}}};
280  }, variant);
281  }
282 
283  value typed_summary(const std::variant<Ts...>& variant) const { return decorate_with_typeid(this->full(variant), type_name::pretty<std::variant<Ts...>>()); }
284 };
285 
286 } // namespace serialization
287 
288 } // namespace docwire
289 
290 #endif // DOCWIRE_SERIALIZATION_BASE_H
value decorate_with_typeid(const value &base_val, const std::string &typeid_str)
Helper to decorate a serialized value with a typeid string.
requires(std::is_arithmetic_v< T > &&!value_alternative< T >) struct serializer< T >
Specialization for arithmetic types (integers, floats).
std::variant< std::nullptr_t, bool, std::int64_t, std::uint64_t, double, std::string, array, object > value
A variant type representing any serialized value.
serializer_kind
An enum to identify the kind of serializer specialization.
concept value_alternative
A specific concept to check if a type T is one of the alternatives in docwire::serialization::value.
value full(const T &value)
Serializes a value of type T into a docwire::serialization::value.
The main namespace for the DocWire SDK.
Definition: ai_elements.h:19
concept container
Concept to detect if a type is a container (iterable and not self-recursive).
concept dereferenceable
Concept to detect if a type is dereferenceable like a pointer.
Definition: concepts_misc.h:30
concept string_like
Concept for string-like types that can be converted to a string view.
Represents a serialized array (list of values).
Represents a serialized object (map of string keys to values).
Specialization for types that are direct alternatives in docwire::serialization::value....
Primary template for the serializer.