StormByte 2.0.0
C++26 foundation of the StormByte suite
 
Loading...
Searching...
No Matches
serializable.hxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2024-2026 David C. Manuelda (StormBytePP)
3 *
4 * This file is part of StormByte.
5 *
6 * StormByte original source is dual-licensed:
7 *
8 * 1. GNU Lesser General Public License v3.0 (or later)
9 * You may redistribute and/or modify this file under the terms of the
10 * GNU Lesser General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option)
12 * any later version.
13 *
14 * 2. Commercial license
15 * Alternatively, this file may be used under the terms of a commercial
16 * license agreement with the copyright holder
17 * (David C. Manuelda <StormByte@gmail.com>).
18 *
19 * Both licenses apply only to original StormByte source in this repository.
20 * They do not cover other StormByte modules or any third-party material
21 * shipped with this repository (including everything under thirdparty/),
22 * which remains under its own license.
23 *
24 * Neither license grants any patent rights. Any patent licenses required
25 * to use this software or third-party components must be obtained separately
26 * from the patent holders.
27 *
28 * StormByte is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU Lesser General Public License for more details.
32 *
33 * You should have received a copy of the GNU Lesser General Public License
34 * version 3 along with StormByte. If not, see
35 * <https://www.gnu.org/licenses/lgpl-3.0.html>.
36 *
37 * SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-StormByte-Commercial
38 */
39
40#pragma once
41
48#include <StormByte/helpers.hxx>
53
54#include <array>
55#include <bit>
56#include <cstdint>
57#include <cstring>
58#include <optional>
59#include <span>
60#include <string>
61#include <tuple>
62#include <utility>
63
68namespace StormByte {
69 class DeserializeError;
70
78 namespace Detail {
83 template<typename T>
84 constexpr bool codec_always_false_v = false;
85
108 template<typename T>
109 struct Codec {
115 static ByteSize Size(const T& data) noexcept {
116 static_assert(codec_always_false_v<T>,
117 "Specialize StormByte::Detail::Codec<T> instead of Serializable<T>");
118 (void)data;
119 return ByteSize{0};
120 }
121
127 static BinaryData Write(const T& data) noexcept {
128 static_assert(codec_always_false_v<T>,
129 "Specialize StormByte::Detail::Codec<T> instead of Serializable<T>");
130 (void)data;
131 return {};
132 }
133
139 static Expected<T, DeserializeError> Read(std::span<const std::byte> data) noexcept {
140 static_assert(codec_always_false_v<T>,
141 "Specialize StormByte::Detail::Codec<T> instead of Serializable<T>");
142 (void)data;
143 return Unexpected<DeserializeError>("Codec<T> is not specialized");
144 }
145 };
146
152 template<>
153 struct Codec<std::string> {
159 static STORMBYTE_PUBLIC ByteSize Size(const std::string& data) noexcept;
160
166 static STORMBYTE_PUBLIC BinaryData Write(const std::string& data) noexcept;
167
173 static STORMBYTE_PUBLIC Expected<std::string, DeserializeError> Read(std::span<const std::byte> data) noexcept;
174 };
175
182 template<>
183 struct Codec<std::wstring> {
189 static STORMBYTE_PUBLIC ByteSize Size(const std::wstring& data) noexcept;
190
196 static STORMBYTE_PUBLIC BinaryData Write(const std::wstring& data) noexcept;
197
203 static STORMBYTE_PUBLIC Expected<std::wstring, DeserializeError> Read(std::span<const std::byte> data) noexcept;
204 };
205
211 template<>
212 struct Codec<std::u16string> {
218 static STORMBYTE_PUBLIC ByteSize Size(const std::u16string& data) noexcept;
219
225 static STORMBYTE_PUBLIC BinaryData Write(const std::u16string& data) noexcept;
226
232 static STORMBYTE_PUBLIC Expected<std::u16string, DeserializeError> Read(std::span<const std::byte> data) noexcept;
233 };
234
240 template<>
241 struct Codec<std::u32string> {
247 static STORMBYTE_PUBLIC ByteSize Size(const std::u32string& data) noexcept;
248
254 static STORMBYTE_PUBLIC BinaryData Write(const std::u32string& data) noexcept;
255
261 static STORMBYTE_PUBLIC Expected<std::u32string, DeserializeError> Read(std::span<const std::byte> data) noexcept;
262 };
263
272 template<>
273 struct Codec<Safe::CString> {
279 static STORMBYTE_PUBLIC ByteSize Size(const Safe::CString& data) noexcept;
280
286 static STORMBYTE_PUBLIC BinaryData Write(const Safe::CString& data) noexcept;
287
293 static STORMBYTE_PUBLIC Expected<Safe::CString, DeserializeError> Read(std::span<const std::byte> data) noexcept;
294 };
295
303 template<>
304 struct Codec<Safe::WCString> {
310 static STORMBYTE_PUBLIC ByteSize Size(const Safe::WCString& data) noexcept;
311
317 static STORMBYTE_PUBLIC BinaryData Write(const Safe::WCString& data) noexcept;
318
324 static STORMBYTE_PUBLIC Expected<Safe::WCString, DeserializeError> Read(std::span<const std::byte> data) noexcept;
325 };
326
330 template<>
331 struct Codec<Safe::String> {
333 static STORMBYTE_PUBLIC ByteSize Size(const Safe::String& data) noexcept;
335 static STORMBYTE_PUBLIC BinaryData Write(const Safe::String& data) noexcept;
337 static STORMBYTE_PUBLIC Expected<Safe::String, DeserializeError> Read(std::span<const std::byte> data) noexcept;
338 };
339
343 template<>
344 struct Codec<Safe::WString> {
346 static STORMBYTE_PUBLIC ByteSize Size(const Safe::WString& data) noexcept;
348 static STORMBYTE_PUBLIC BinaryData Write(const Safe::WString& data) noexcept;
350 static STORMBYTE_PUBLIC Expected<Safe::WString, DeserializeError> Read(std::span<const std::byte> data) noexcept;
351 };
352 }
353
376 template<typename T>
378 using DecayedT = std::remove_cvref_t<T>;
379
380 public:
385 Serializable(const DecayedT& data) noexcept : m_data(data) {}
386
390 Serializable(const Serializable& other) noexcept = delete;
391
395 Serializable(Serializable&& other) noexcept = delete;
396
400 ~Serializable() noexcept = default;
401
405 Serializable& operator=(const Serializable& other) noexcept = delete;
406
410 Serializable& operator=(Serializable&& other) noexcept = delete;
411
416 BinaryData Serialize() const noexcept;
417
423 static Expected<T, DeserializeError> Deserialize(std::span<const std::byte> data) noexcept;
424
430 static Expected<T, DeserializeError> Deserialize(const BinaryData& data) noexcept;
431
437 static ByteSize Size(const DecayedT& data) noexcept;
438
439 private:
440 const DecayedT& m_data;
441
454 template<typename U = T>
455 BinaryData SerializeTrivial() const noexcept
456 requires Type::TriviallyCopyable<U>;
457
463 template<typename U = T>
464 BinaryData SerializeContainer() const noexcept
465 requires Type::Container<U>;
466
472 template<typename U = T>
473 BinaryData SerializePair() const noexcept
474 requires Type::Pair<U>;
475
484 template<typename U = T>
485 BinaryData SerializeOptional() const noexcept
486 requires Type::Optional<U>;
487
494 template<typename U = T>
495 static ByteSize SizeContainer(const DecayedT& data) noexcept
496 requires Type::Container<U>;
497
504 template<typename U = T>
505 static ByteSize SizePair(const DecayedT& data) noexcept
506 requires Type::Pair<U>;
507
514 template<typename U = T>
515 static ByteSize SizeOptional(const DecayedT& data) noexcept
516 requires Type::Optional<U>;
517
528 template<typename U = T>
529 static Expected<T, DeserializeError> DeserializeTrivial(std::span<const std::byte> data) noexcept
530 requires Type::TriviallyCopyable<U>;
531
538 template<typename U = T>
539 static Expected<T, DeserializeError> DeserializeContainer(std::span<const std::byte> data) noexcept
540 requires Type::Container<U>;
541
548 template<typename U = T>
549 static Expected<T, DeserializeError> DeserializePair(std::span<const std::byte> data) noexcept
550 requires Type::Pair<U>;
551
558 template<typename U = T>
559 static Expected<T, DeserializeError> DeserializeOptional(std::span<const std::byte> data) noexcept
560 requires Type::Optional<U>;
561 };
562
563 // Explicit-instantiation declarations: suppress implicit instantiation
564 // of Serializable<T> for these T in every consumer TU. Definitions are
565 // in serializable.cxx. STORMBYTE_PUBLIC here is the export/import of
566 // those instantiations; the class template itself has no visibility
567 // so other modules can instantiate Serializable<TheirType> in their DLL.
568 //
569 // This block MUST come before `#include <StormByte/serializable.txx>`:
570 // those bodies name Serializable<bool> and Serializable<std::uint64_t>
571 // as non-dependent types. If the .txx is parsed first, those two are
572 // instantiated in this header before the extern declarations.
574 extern template class STORMBYTE_PUBLIC Serializable<bool>;
575 extern template class STORMBYTE_PUBLIC Serializable<char>;
576 extern template class STORMBYTE_PUBLIC Serializable<signed char>;
577 extern template class STORMBYTE_PUBLIC Serializable<unsigned char>;
578 extern template class STORMBYTE_PUBLIC Serializable<wchar_t>;
579 extern template class STORMBYTE_PUBLIC Serializable<char8_t>;
580 extern template class STORMBYTE_PUBLIC Serializable<char16_t>;
581 extern template class STORMBYTE_PUBLIC Serializable<char32_t>;
582 extern template class STORMBYTE_PUBLIC Serializable<short>;
583 extern template class STORMBYTE_PUBLIC Serializable<unsigned short>;
584 extern template class STORMBYTE_PUBLIC Serializable<int>;
585 extern template class STORMBYTE_PUBLIC Serializable<unsigned int>;
586 extern template class STORMBYTE_PUBLIC Serializable<long>;
587 extern template class STORMBYTE_PUBLIC Serializable<unsigned long>;
588 extern template class STORMBYTE_PUBLIC Serializable<long long>;
589 extern template class STORMBYTE_PUBLIC Serializable<unsigned long long>;
590 extern template class STORMBYTE_PUBLIC Serializable<float>;
591 extern template class STORMBYTE_PUBLIC Serializable<double>;
592 extern template class STORMBYTE_PUBLIC Serializable<long double>;
593 extern template class STORMBYTE_PUBLIC Serializable<std::string>;
594 extern template class STORMBYTE_PUBLIC Serializable<std::wstring>;
595 extern template class STORMBYTE_PUBLIC Serializable<std::u16string>;
596 extern template class STORMBYTE_PUBLIC Serializable<std::u32string>;
597 extern template class STORMBYTE_PUBLIC Serializable<Safe::CString>;
598 extern template class STORMBYTE_PUBLIC Serializable<Safe::WCString>;
599 extern template class STORMBYTE_PUBLIC Serializable<Safe::String>;
600 extern template class STORMBYTE_PUBLIC Serializable<Safe::WString>;
601 extern template class STORMBYTE_PUBLIC Serializable<BinaryData>;
603}
604
605#include <StormByte/serializable.txx>
DLL-boundary-safe owned byte sequence for the StormByte suite.
IEC octet length (uint64_t), implicit only to std::size_t.
DLL-boundary-safe owned contiguous sequence of std::byte.
Definition binary_data.hxx:106
Count of octets (uint64_t storage).
Definition byte_size.hxx:103
Thrown when deserialization fails.
Definition exception.hxx:196
Owned NUL-terminated buffer, safe to use across a DLL boundary.
Definition cstring.hxx:103
Owned UTF-8 text composed of StormByte::Safe::CString.
Definition string.hxx:97
Owned NUL-terminated wide buffer, safe to use across a DLL boundary.
Definition wcstring.hxx:104
Wide counterpart of String.
Definition wstring.hxx:96
Encodes and decodes one value of type T.
Definition serializable.hxx:377
Serializable(const DecayedT &data) noexcept
Binds data for a later StormByte::Serializable::Serialize.
Definition serializable.hxx:385
Serializable(const Serializable &other) noexcept=delete
Copy is deleted: the wrapper only holds a reference.
static Expected< T, DeserializeError > Deserialize(std::span< const std::byte > data) noexcept
Decodes one T from the start of data.
Serializable(Serializable &&other) noexcept=delete
Move is deleted: the wrapper only holds a reference.
BinaryData Serialize() const noexcept
Encodes the bound value to a little-endian blob.
~Serializable() noexcept=default
Destructor.
Count of abstract units (uint64_t storage).
Definition size.hxx:105
Private helpers.
constexpr bool codec_always_false_v
Compile-time false dependent on T.
Definition serializable.hxx:84
Root namespace of the StormByte suite.
std::conditional_t< Type::Reference< T >, std::expected< std::reference_wrapper< std::remove_reference_t< T > >, Safe::Shared< E > >, std::expected< T, Safe::Shared< E > > > Expected
std::expected alias with reference and shared-error handling.
Definition expected.hxx:66
Octet count. Defined in byte_size.hxx. Forwarded so Type::Numeral can name it.
STL namespace.
static BinaryData Write(const Safe::CString &data) noexcept
Encodes data.
static Expected< Safe::CString, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes a StormByte::Safe::CString from the start of data.
static ByteSize Size(const Safe::CString &data) noexcept
Serialized size of data.
static Expected< Safe::String, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes text.
static BinaryData Write(const Safe::String &data) noexcept
Encodes data.
static ByteSize Size(const Safe::String &data) noexcept
Serialized size of data.
static Expected< Safe::WCString, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes a StormByte::Safe::WCString from the start of data.
static ByteSize Size(const Safe::WCString &data) noexcept
Serialized size of data.
static BinaryData Write(const Safe::WCString &data) noexcept
Encodes data.
static Expected< Safe::WString, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes text.
static ByteSize Size(const Safe::WString &data) noexcept
Serialized size of data.
static BinaryData Write(const Safe::WString &data) noexcept
Encodes data.
static Expected< std::string, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes a string from the start of data.
static BinaryData Write(const std::string &data) noexcept
Encodes data.
static ByteSize Size(const std::string &data) noexcept
Serialized size of data.
static BinaryData Write(const std::u16string &data) noexcept
Encodes data.
static Expected< std::u16string, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes a UTF-16 string from the start of data.
static ByteSize Size(const std::u16string &data) noexcept
Serialized size of data.
static BinaryData Write(const std::u32string &data) noexcept
Encodes data.
static ByteSize Size(const std::u32string &data) noexcept
Serialized size of data.
static Expected< std::u32string, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes a UTF-32 string from the start of data.
static Expected< std::wstring, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes a wide string from the start of data.
static ByteSize Size(const std::wstring &data) noexcept
Serialized size of data.
static BinaryData Write(const std::wstring &data) noexcept
Encodes data.
Size / write / read for one type T.
Definition serializable.hxx:109
static ByteSize Size(const T &data) noexcept
Serialized size of data.
Definition serializable.hxx:115
static BinaryData Write(const T &data) noexcept
Encodes data to a little-endian blob.
Definition serializable.hxx:127
static Expected< T, DeserializeError > Read(std::span< const std::byte > data) noexcept
Decodes T from the start of data.
Definition serializable.hxx:139
#define STORMBYTE_PUBLIC
Definition visibility.h:52