parcel 0.2.2
Wrappable, wire-transferable C++23 value system with JSON serialization
Loading...
Searching...
No Matches
primitive.h
Go to the documentation of this file.
1#pragma once
2
21#include <parcel/cell.h>
22#include <parcel/common.h>
23#include <parcel/descriptor.h>
24
25#include <commons/types.hpp>
26
27#include <algorithm>
28#include <complex>
29#include <memory>
30#include <string>
31#include <string_view>
32#include <type_traits>
33#include <utility>
34
35namespace parcel::primitives {
36
40template <typename T>
41struct is_std_complex : std::false_type {};
42template <typename U>
43struct is_std_complex<std::complex<U>> : std::true_type {};
44template <typename T>
45inline constexpr bool is_std_complex_v = is_std_complex<T>::value;
46
58template <typename T>
60
62template <>
63struct PrimitiveTraits<char> {
64 static constexpr std::string_view type_id = "char";
65 static constexpr std::string_view name = "Char";
66 static constexpr std::string_view description = "Character.";
67};
68
70template <>
71struct PrimitiveTraits<bool> {
72 static constexpr std::string_view type_id = "bool";
73 static constexpr std::string_view name = "Bool";
74 static constexpr std::string_view description = "Boolean value.";
75};
76
78template <>
79struct PrimitiveTraits<comms::u8> {
80 static constexpr std::string_view type_id = "u8";
81 static constexpr std::string_view name = "U8";
82 static constexpr std::string_view description = "Unsigned 8-bit integer.";
83};
84
86template <>
87struct PrimitiveTraits<comms::u16> {
88 static constexpr std::string_view type_id = "u16";
89 static constexpr std::string_view name = "U16";
90 static constexpr std::string_view description = "Unsigned 16-bit integer.";
91};
92
94template <>
95struct PrimitiveTraits<comms::u32> {
96 static constexpr std::string_view type_id = "u32";
97 static constexpr std::string_view name = "U32";
98 static constexpr std::string_view description = "Unsigned 32-bit integer.";
99};
100
102template <>
103struct PrimitiveTraits<comms::u64> {
104 static constexpr std::string_view type_id = "u64";
105 static constexpr std::string_view name = "U64";
106 static constexpr std::string_view description = "Unsigned 64-bit integer.";
107};
108
109#ifdef COMMONS_HAS_INT128
111template <>
112struct PrimitiveTraits<comms::u128> {
113 static constexpr std::string_view type_id = "u128";
114 static constexpr std::string_view name = "U128";
115 static constexpr std::string_view description = "Unsigned 128-bit integer.";
116};
117#endif
118
120template <>
121struct PrimitiveTraits<comms::i8> {
122 static constexpr std::string_view type_id = "i8";
123 static constexpr std::string_view name = "I8";
124 static constexpr std::string_view description = "Signed 8-bit integer.";
125};
126
128template <>
129struct PrimitiveTraits<comms::i16> {
130 static constexpr std::string_view type_id = "i16";
131 static constexpr std::string_view name = "I16";
132 static constexpr std::string_view description = "Signed 16-bit integer.";
133};
134
136template <>
137struct PrimitiveTraits<comms::i32> {
138 static constexpr std::string_view type_id = "i32";
139 static constexpr std::string_view name = "I32";
140 static constexpr std::string_view description = "Signed 32-bit integer.";
141};
142
144template <>
145struct PrimitiveTraits<comms::i64> {
146 static constexpr std::string_view type_id = "i64";
147 static constexpr std::string_view name = "I64";
148 static constexpr std::string_view description = "Signed 64-bit integer.";
149};
150
151#ifdef COMMONS_HAS_INT128
153template <>
154struct PrimitiveTraits<comms::i128> {
155 static constexpr std::string_view type_id = "i128";
156 static constexpr std::string_view name = "I128";
157 static constexpr std::string_view description = "Signed 128-bit integer.";
158};
159#endif
160
162template <>
163struct PrimitiveTraits<comms::f32> {
164 static constexpr std::string_view type_id = "f32";
165 static constexpr std::string_view name = "F32";
166 static constexpr std::string_view description = "32-bit floating-point number.";
167};
168
170template <>
171struct PrimitiveTraits<comms::f64> {
172 static constexpr std::string_view type_id = "f64";
173 static constexpr std::string_view name = "F64";
174 static constexpr std::string_view description = "64-bit floating-point number.";
175};
176
177// Complex numbers. Wire form is a `[real, imaginary]` JSON array (commons'
178// adl_serializer<std::complex<T>>); the component type serializes natively.
179
181template <>
182struct PrimitiveTraits<comms::cs8> {
183 static constexpr std::string_view type_id = "cs8";
184 static constexpr std::string_view name = "CS8";
185 static constexpr std::string_view description = "Complex with signed 8-bit components.";
186};
187
189template <>
190struct PrimitiveTraits<comms::cs16> {
191 static constexpr std::string_view type_id = "cs16";
192 static constexpr std::string_view name = "CS16";
193 static constexpr std::string_view description = "Complex with signed 16-bit components.";
194};
195
197template <>
198struct PrimitiveTraits<comms::cs32> {
199 static constexpr std::string_view type_id = "cs32";
200 static constexpr std::string_view name = "CS32";
201 static constexpr std::string_view description = "Complex with signed 32-bit components.";
202};
203
205template <>
206struct PrimitiveTraits<comms::cs64> {
207 static constexpr std::string_view type_id = "cs64";
208 static constexpr std::string_view name = "CS64";
209 static constexpr std::string_view description = "Complex with signed 64-bit components.";
210};
211
213template <>
214struct PrimitiveTraits<comms::cu8> {
215 static constexpr std::string_view type_id = "cu8";
216 static constexpr std::string_view name = "CU8";
217 static constexpr std::string_view description = "Complex with unsigned 8-bit components.";
218};
219
221template <>
222struct PrimitiveTraits<comms::cu16> {
223 static constexpr std::string_view type_id = "cu16";
224 static constexpr std::string_view name = "CU16";
225 static constexpr std::string_view description = "Complex with unsigned 16-bit components.";
226};
227
229template <>
230struct PrimitiveTraits<comms::cu32> {
231 static constexpr std::string_view type_id = "cu32";
232 static constexpr std::string_view name = "CU32";
233 static constexpr std::string_view description = "Complex with unsigned 32-bit components.";
234};
235
237template <>
238struct PrimitiveTraits<comms::cu64> {
239 static constexpr std::string_view type_id = "cu64";
240 static constexpr std::string_view name = "CU64";
241 static constexpr std::string_view description = "Complex with unsigned 64-bit components.";
242};
243
245template <>
246struct PrimitiveTraits<comms::cf32> {
247 static constexpr std::string_view type_id = "cf32";
248 static constexpr std::string_view name = "CF32";
249 static constexpr std::string_view description =
250 "Complex with 32-bit floating-point components.";
251};
252
254template <>
255struct PrimitiveTraits<comms::cf64> {
256 static constexpr std::string_view type_id = "cf64";
257 static constexpr std::string_view name = "CF64";
258 static constexpr std::string_view description =
259 "Complex with 64-bit floating-point components.";
260};
261
263template <>
264struct PrimitiveTraits<std::string> {
265 static constexpr std::string_view type_id = "string";
266 static constexpr std::string_view name = "String";
267 static constexpr std::string_view description = "UTF-8 encoded string.";
268};
269
270} // namespace parcel::primitives
271
272namespace parcel {
273class ParcelRegistry;
274
285template <typename T>
287 std::same_as<T, char> || std::same_as<T, bool> || std::same_as<T, comms::u8> ||
288 std::same_as<T, comms::u16> || std::same_as<T, comms::u32> || std::same_as<T, comms::u64> ||
289 std::same_as<T, comms::i8> || std::same_as<T, comms::i16> || std::same_as<T, comms::i32> ||
290 std::same_as<T, comms::i64> || std::same_as<T, comms::f32> || std::same_as<T, comms::f64> ||
291#ifdef COMMONS_HAS_INT128
292 std::same_as<T, comms::u128> || std::same_as<T, comms::i128> ||
293#endif
294 std::same_as<T, comms::cs8> || std::same_as<T, comms::cs16> || std::same_as<T, comms::cs32> ||
295 std::same_as<T, comms::cs64> || std::same_as<T, comms::cu8> || std::same_as<T, comms::cu16> ||
296 std::same_as<T, comms::cu32> || std::same_as<T, comms::cu64> || std::same_as<T, comms::cf32> ||
297 std::same_as<T, comms::cf64> || std::same_as<T, std::string>;
298
315template <PrimitiveStorage T>
316class PrimitiveCell : public BaseCell<PrimitiveCell<T>, T> {
319
320public:
321 using base_t::base_t;
322 using base_t::operator=;
323
325 static constexpr std::string_view kind_id = trait_t::type_id;
326
338 [[nodiscard]] std::string to_string() const override {
339 if constexpr (std::same_as<T, std::string>) {
340 return this->value;
341 } else if constexpr (std::same_as<T, bool>) {
342 return this->value ? "true" : "false";
343 } else if constexpr (std::same_as<T, char>) {
344 return std::string(1, this->value);
345#ifdef COMMONS_HAS_INT128
346 } else if constexpr (std::same_as<T, comms::u128> || std::same_as<T, comms::i128>) {
347 // std::to_string has no overload for __int128_t / __uint128_t.
348 // Build the digits manually, LSB-first, then reverse.
349 if (this->value == 0) {
350 return "0";
351 }
352 using U = std::conditional_t<std::same_as<T, comms::i128>, comms::u128, T>;
353 std::string out;
354 if constexpr (std::same_as<T, comms::i128>) {
355 T v = this->value;
356 const bool neg = v < 0;
357 U u = neg ? static_cast<U>(-(v + 1)) + 1 : static_cast<U>(v);
358 while (u != 0) {
359 out.push_back(static_cast<char>('0' + (u % 10)));
360 u /= 10;
361 }
362 if (neg)
363 out.push_back('-');
364 } else {
365 U u = this->value;
366 while (u != 0) {
367 out.push_back(static_cast<char>('0' + (u % 10)));
368 u /= 10;
369 }
370 }
371 std::ranges::reverse(out);
372 return out;
373#endif
374 } else if constexpr (primitives::is_std_complex_v<T>) {
375 return "(" + std::to_string(this->value.real()) + ", " +
376 std::to_string(this->value.imag()) + ")";
377 } else {
378 return std::to_string(this->value);
379 }
380 }
381
388 static cell_t from_json(json_t const& j, ParcelRegistry const&) {
389 auto value = base_t::template cell_from_json<T>(j, trait_t::type_id);
390 auto cell = std::make_shared<PrimitiveCell<T>>(std::move(value));
392 return cell;
393 }
394
400 static const auto d =
401 std::make_shared<SimpleCellTypeDescriptor<PrimitiveCell<T>>>(DisplayInfo{
402 .name = std::string(trait_t::name),
403 .description = std::string(trait_t::description),
404 });
405
406 return d;
407 }
408};
409
456#ifdef COMMONS_HAS_INT128
461#endif
462
463} // namespace parcel
Core ICell interface, cell_t handle, BaseCell CRTP base, and CellLike concept.
std::shared_ptr< ICellTypeDescriptor > cell_type_descriptor_t
Shared handle to a runtime cell-type descriptor.
Definition cell.h:63
std::shared_ptr< ICell > cell_t
Shared handle to any ICell-derived value — the canonical cell pointer.
Definition cell.h:68
Runtime catalog of cell-type descriptors, keyed by wire kind id.
Definition registry.h:115
Leaf cell wrapping a single scalar (or complex) value of type T.
Definition primitive.h:316
static constexpr std::string_view kind_id
Wire kind id (taken from PrimitiveTraits<T>::type_id).
Definition primitive.h:325
static cell_t from_json(json_t const &j, ParcelRegistry const &)
Deserialize a PrimitiveCell<T> from JSON.
Definition primitive.h:388
std::string to_string() const override
Render the value as a string.
Definition primitive.h:338
static cell_type_descriptor_t descriptor()
Cached descriptor for this primitive type.
Definition primitive.h:399
The shared vocabulary aliases re-exported from commons and the compile-time kind-id machinery.
comms::DisplayInfo DisplayInfo
Display info attached to a cell or descriptor — re-exported from comms::DisplayInfo.
Definition common.h:75
Concept naming the set of types PrimitiveCell accepts as storage.
Definition primitive.h:286
auto cell(T &&v)
Wrap a raw value into its default cell, returning a shared_ptr to the cell.
Definition defaults.h:192
Runtime cell-type descriptors and the schema-graph mix-ins (IHasFields, ISubTypes).
nlohmann::json json_t
Project-wide alias for nlohmann::json.
Definition json.h:19
CRTP base providing default to_json / clone / kind plumbing on top of a storage type.
Definition cell.h:343
static void absorb_display_info(json_t const &j, Out &out)
Read "d" (if present) from a JSON object and assign it onto a cell.
Definition cell.h:499
T value
Held value of the cell.
Definition cell.h:348
Trait carrying wire id and default display info for a primitive storage type.
Definition primitive.h:59
Detects std::complex<U> storage (used by PrimitiveCell::to_string).
Definition primitive.h:41