File indexing completed on 2026-05-10 08:43:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
0033 #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEPACKEDSERIALIZATION_H
0034
0035 #include "llvm/ADT/STLExtras.h"
0036 #include "llvm/ADT/SmallVector.h"
0037 #include "llvm/ADT/StringMap.h"
0038 #include "llvm/ADT/StringRef.h"
0039 #include "llvm/Support/Error.h"
0040 #include "llvm/Support/SwapByteOrder.h"
0041
0042 #include <limits>
0043 #include <optional>
0044 #include <string>
0045 #include <tuple>
0046 #include <type_traits>
0047 #include <utility>
0048 #include <vector>
0049
0050 namespace llvm {
0051 namespace orc {
0052 namespace shared {
0053
0054
0055 class SPSOutputBuffer {
0056 public:
0057 SPSOutputBuffer(char *Buffer, size_t Remaining)
0058 : Buffer(Buffer), Remaining(Remaining) {}
0059 bool write(const char *Data, size_t Size) {
0060 assert(Data && "Data must not be null");
0061 if (Size > Remaining)
0062 return false;
0063 memcpy(Buffer, Data, Size);
0064 Buffer += Size;
0065 Remaining -= Size;
0066 return true;
0067 }
0068
0069 private:
0070 char *Buffer = nullptr;
0071 size_t Remaining = 0;
0072 };
0073
0074
0075 class SPSInputBuffer {
0076 public:
0077 SPSInputBuffer() = default;
0078 SPSInputBuffer(const char *Buffer, size_t Remaining)
0079 : Buffer(Buffer), Remaining(Remaining) {}
0080 bool read(char *Data, size_t Size) {
0081 if (Size > Remaining)
0082 return false;
0083 memcpy(Data, Buffer, Size);
0084 Buffer += Size;
0085 Remaining -= Size;
0086 return true;
0087 }
0088
0089 const char *data() const { return Buffer; }
0090 bool skip(size_t Size) {
0091 if (Size > Remaining)
0092 return false;
0093 Buffer += Size;
0094 Remaining -= Size;
0095 return true;
0096 }
0097
0098 private:
0099 const char *Buffer = nullptr;
0100 size_t Remaining = 0;
0101 };
0102
0103
0104
0105 template <typename SPSTagT, typename ConcreteT, typename _ = void>
0106 class SPSSerializationTraits;
0107
0108
0109 template <typename... ArgTs> class SPSArgList;
0110
0111
0112 template <> class SPSArgList<> {
0113 public:
0114 static size_t size() { return 0; }
0115
0116 static bool serialize(SPSOutputBuffer &OB) { return true; }
0117 static bool deserialize(SPSInputBuffer &IB) { return true; }
0118
0119 static bool serializeToSmallVector(SmallVectorImpl<char> &V) { return true; }
0120
0121 static bool deserializeFromSmallVector(const SmallVectorImpl<char> &V) {
0122 return true;
0123 }
0124 };
0125
0126
0127 template <typename SPSTagT, typename... SPSTagTs>
0128 class SPSArgList<SPSTagT, SPSTagTs...> {
0129 public:
0130
0131
0132 using OutputBuffer = SPSOutputBuffer;
0133
0134 template <typename ArgT, typename... ArgTs>
0135 static size_t size(const ArgT &Arg, const ArgTs &...Args) {
0136 return SPSSerializationTraits<SPSTagT, ArgT>::size(Arg) +
0137 SPSArgList<SPSTagTs...>::size(Args...);
0138 }
0139
0140 template <typename ArgT, typename... ArgTs>
0141 static bool serialize(SPSOutputBuffer &OB, const ArgT &Arg,
0142 const ArgTs &...Args) {
0143 return SPSSerializationTraits<SPSTagT, ArgT>::serialize(OB, Arg) &&
0144 SPSArgList<SPSTagTs...>::serialize(OB, Args...);
0145 }
0146
0147 template <typename ArgT, typename... ArgTs>
0148 static bool deserialize(SPSInputBuffer &IB, ArgT &Arg, ArgTs &...Args) {
0149 return SPSSerializationTraits<SPSTagT, ArgT>::deserialize(IB, Arg) &&
0150 SPSArgList<SPSTagTs...>::deserialize(IB, Args...);
0151 }
0152 };
0153
0154
0155 template <typename SPSTagT>
0156 class SPSSerializationTraits<
0157 SPSTagT, SPSTagT,
0158 std::enable_if_t<std::is_same<SPSTagT, bool>::value ||
0159 std::is_same<SPSTagT, char>::value ||
0160 std::is_same<SPSTagT, int8_t>::value ||
0161 std::is_same<SPSTagT, int16_t>::value ||
0162 std::is_same<SPSTagT, int32_t>::value ||
0163 std::is_same<SPSTagT, int64_t>::value ||
0164 std::is_same<SPSTagT, uint8_t>::value ||
0165 std::is_same<SPSTagT, uint16_t>::value ||
0166 std::is_same<SPSTagT, uint32_t>::value ||
0167 std::is_same<SPSTagT, uint64_t>::value>> {
0168 public:
0169 static size_t size(const SPSTagT &Value) { return sizeof(SPSTagT); }
0170
0171 static bool serialize(SPSOutputBuffer &OB, const SPSTagT &Value) {
0172 SPSTagT Tmp = Value;
0173 if (sys::IsBigEndianHost)
0174 sys::swapByteOrder(Tmp);
0175 return OB.write(reinterpret_cast<const char *>(&Tmp), sizeof(Tmp));
0176 }
0177
0178 static bool deserialize(SPSInputBuffer &IB, SPSTagT &Value) {
0179 SPSTagT Tmp;
0180 if (!IB.read(reinterpret_cast<char *>(&Tmp), sizeof(Tmp)))
0181 return false;
0182 if (sys::IsBigEndianHost)
0183 sys::swapByteOrder(Tmp);
0184 Value = Tmp;
0185 return true;
0186 }
0187 };
0188
0189
0190 class SPSEmpty {};
0191
0192
0193
0194
0195
0196 template <typename... SPSTagTs> class SPSTuple {
0197 public:
0198
0199 typedef SPSArgList<SPSTagTs...> AsArgList;
0200 };
0201
0202
0203
0204
0205
0206
0207
0208 template <typename SPSTagT> class SPSOptional {};
0209
0210
0211
0212
0213
0214 template <typename SPSElementTagT> class SPSSequence;
0215
0216
0217 using SPSString = SPSSequence<char>;
0218
0219
0220
0221
0222 template <typename SPSTagT1, typename SPSTagT2>
0223 using SPSMap = SPSSequence<SPSTuple<SPSTagT1, SPSTagT2>>;
0224
0225
0226 template <> class SPSSerializationTraits<SPSEmpty, SPSEmpty> {
0227 public:
0228 static size_t size(const SPSEmpty &EP) { return 0; }
0229 static bool serialize(SPSOutputBuffer &OB, const SPSEmpty &BE) {
0230 return true;
0231 }
0232 static bool deserialize(SPSInputBuffer &IB, SPSEmpty &BE) { return true; }
0233 };
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 template <typename SPSElementTagT, typename ConcreteSequenceT>
0245 class TrivialSPSSequenceSerialization {
0246 public:
0247 static constexpr bool available = false;
0248 };
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 template <typename SPSElementTagT, typename ConcreteSequenceT>
0261 class TrivialSPSSequenceDeserialization {
0262 public:
0263 static constexpr bool available = false;
0264 };
0265
0266
0267 template <> class TrivialSPSSequenceSerialization<char, std::string> {
0268 public:
0269 static constexpr bool available = true;
0270 };
0271
0272
0273 template <> class TrivialSPSSequenceDeserialization<char, std::string> {
0274 public:
0275 static constexpr bool available = true;
0276
0277 using element_type = char;
0278
0279 static void reserve(std::string &S, uint64_t Size) { S.reserve(Size); }
0280 static bool append(std::string &S, char C) {
0281 S.push_back(C);
0282 return true;
0283 }
0284 };
0285
0286
0287 template <typename SPSElementTagT, typename T>
0288 class TrivialSPSSequenceSerialization<SPSElementTagT, std::vector<T>> {
0289 public:
0290 static constexpr bool available = true;
0291 };
0292
0293
0294 template <typename SPSElementTagT, typename T>
0295 class TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>> {
0296 public:
0297 static constexpr bool available = true;
0298
0299 using element_type = typename std::vector<T>::value_type;
0300
0301 static void reserve(std::vector<T> &V, uint64_t Size) { V.reserve(Size); }
0302 static bool append(std::vector<T> &V, T E) {
0303 V.push_back(std::move(E));
0304 return true;
0305 }
0306 };
0307
0308
0309 template <typename SPSElementTagT, typename T>
0310 class TrivialSPSSequenceSerialization<SPSElementTagT, SmallVectorImpl<T>> {
0311 public:
0312 static constexpr bool available = true;
0313 };
0314
0315
0316 template <typename SPSElementTagT, typename T>
0317 class TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVectorImpl<T>> {
0318 public:
0319 static constexpr bool available = true;
0320
0321 using element_type = typename SmallVectorImpl<T>::value_type;
0322
0323 static void reserve(SmallVectorImpl<T> &V, uint64_t Size) { V.reserve(Size); }
0324 static bool append(SmallVectorImpl<T> &V, T E) {
0325 V.push_back(std::move(E));
0326 return true;
0327 }
0328 };
0329
0330
0331 template <typename SPSElementTagT, typename T, unsigned N>
0332 class TrivialSPSSequenceSerialization<SPSElementTagT, SmallVector<T, N>>
0333 : public TrivialSPSSequenceSerialization<SPSElementTagT,
0334 SmallVectorImpl<T>> {};
0335
0336
0337 template <typename SPSElementTagT, typename T, unsigned N>
0338 class TrivialSPSSequenceDeserialization<SPSElementTagT, SmallVector<T, N>>
0339 : public TrivialSPSSequenceDeserialization<SPSElementTagT,
0340 SmallVectorImpl<T>> {};
0341
0342
0343 template <typename SPSElementTagT, typename T>
0344 class TrivialSPSSequenceSerialization<SPSElementTagT, ArrayRef<T>> {
0345 public:
0346 static constexpr bool available = true;
0347 };
0348
0349
0350
0351
0352 template <> class SPSSerializationTraits<SPSSequence<char>, ArrayRef<char>> {
0353 public:
0354 static size_t size(const ArrayRef<char> &A) {
0355 return SPSArgList<uint64_t>::size(static_cast<uint64_t>(A.size())) +
0356 A.size();
0357 }
0358
0359 static bool serialize(SPSOutputBuffer &OB, const ArrayRef<char> &A) {
0360 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(A.size())))
0361 return false;
0362 if (A.empty())
0363 return true;
0364 return OB.write(A.data(), A.size());
0365 }
0366
0367 static bool deserialize(SPSInputBuffer &IB, ArrayRef<char> &A) {
0368 uint64_t Size;
0369 if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0370 return false;
0371 if (Size > std::numeric_limits<size_t>::max())
0372 return false;
0373 A = {Size ? IB.data() : nullptr, static_cast<size_t>(Size)};
0374 return IB.skip(Size);
0375 }
0376 };
0377
0378
0379
0380
0381 template <typename SPSElementTagT, typename SequenceT>
0382 class SPSSerializationTraits<SPSSequence<SPSElementTagT>, SequenceT,
0383 std::enable_if_t<TrivialSPSSequenceSerialization<
0384 SPSElementTagT, SequenceT>::available>> {
0385 public:
0386 static size_t size(const SequenceT &S) {
0387 size_t Size = SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size()));
0388 for (const auto &E : S)
0389 Size += SPSArgList<SPSElementTagT>::size(E);
0390 return Size;
0391 }
0392
0393 static bool serialize(SPSOutputBuffer &OB, const SequenceT &S) {
0394 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
0395 return false;
0396 for (const auto &E : S)
0397 if (!SPSArgList<SPSElementTagT>::serialize(OB, E))
0398 return false;
0399 return true;
0400 }
0401
0402 static bool deserialize(SPSInputBuffer &IB, SequenceT &S) {
0403 using TBSD = TrivialSPSSequenceDeserialization<SPSElementTagT, SequenceT>;
0404 uint64_t Size;
0405 if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0406 return false;
0407 TBSD::reserve(S, Size);
0408 for (size_t I = 0; I != Size; ++I) {
0409 typename TBSD::element_type E;
0410 if (!SPSArgList<SPSElementTagT>::deserialize(IB, E))
0411 return false;
0412 if (!TBSD::append(S, std::move(E)))
0413 return false;
0414 }
0415 return true;
0416 }
0417 };
0418
0419
0420 template <typename... SPSTagTs, typename... Ts>
0421 class SPSSerializationTraits<SPSTuple<SPSTagTs...>, std::tuple<Ts...>> {
0422 private:
0423 using TupleArgList = typename SPSTuple<SPSTagTs...>::AsArgList;
0424 using ArgIndices = std::make_index_sequence<sizeof...(Ts)>;
0425
0426 template <std::size_t... I>
0427 static size_t size(const std::tuple<Ts...> &T, std::index_sequence<I...>) {
0428 return TupleArgList::size(std::get<I>(T)...);
0429 }
0430
0431 template <std::size_t... I>
0432 static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T,
0433 std::index_sequence<I...>) {
0434 return TupleArgList::serialize(OB, std::get<I>(T)...);
0435 }
0436
0437 template <std::size_t... I>
0438 static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T,
0439 std::index_sequence<I...>) {
0440 return TupleArgList::deserialize(IB, std::get<I>(T)...);
0441 }
0442
0443 public:
0444 static size_t size(const std::tuple<Ts...> &T) {
0445 return size(T, ArgIndices{});
0446 }
0447
0448 static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T) {
0449 return serialize(OB, T, ArgIndices{});
0450 }
0451
0452 static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T) {
0453 return deserialize(IB, T, ArgIndices{});
0454 }
0455 };
0456
0457
0458 template <typename SPSTagT1, typename SPSTagT2, typename T1, typename T2>
0459 class SPSSerializationTraits<SPSTuple<SPSTagT1, SPSTagT2>, std::pair<T1, T2>> {
0460 public:
0461 static size_t size(const std::pair<T1, T2> &P) {
0462 return SPSArgList<SPSTagT1>::size(P.first) +
0463 SPSArgList<SPSTagT2>::size(P.second);
0464 }
0465
0466 static bool serialize(SPSOutputBuffer &OB, const std::pair<T1, T2> &P) {
0467 return SPSArgList<SPSTagT1>::serialize(OB, P.first) &&
0468 SPSArgList<SPSTagT2>::serialize(OB, P.second);
0469 }
0470
0471 static bool deserialize(SPSInputBuffer &IB, std::pair<T1, T2> &P) {
0472 return SPSArgList<SPSTagT1>::deserialize(IB, P.first) &&
0473 SPSArgList<SPSTagT2>::deserialize(IB, P.second);
0474 }
0475 };
0476
0477
0478 template <typename SPSTagT, typename T>
0479 class SPSSerializationTraits<SPSOptional<SPSTagT>, std::optional<T>> {
0480 public:
0481 static size_t size(const std::optional<T> &Value) {
0482 size_t Size = SPSArgList<bool>::size(!!Value);
0483 if (Value)
0484 Size += SPSArgList<SPSTagT>::size(*Value);
0485 return Size;
0486 }
0487
0488 static bool serialize(SPSOutputBuffer &OB, const std::optional<T> &Value) {
0489 if (!SPSArgList<bool>::serialize(OB, !!Value))
0490 return false;
0491 if (Value)
0492 return SPSArgList<SPSTagT>::serialize(OB, *Value);
0493 return true;
0494 }
0495
0496 static bool deserialize(SPSInputBuffer &IB, std::optional<T> &Value) {
0497 bool HasValue;
0498 if (!SPSArgList<bool>::deserialize(IB, HasValue))
0499 return false;
0500 if (HasValue) {
0501 Value = T();
0502 return SPSArgList<SPSTagT>::deserialize(IB, *Value);
0503 } else
0504 Value = std::optional<T>();
0505 return true;
0506 }
0507 };
0508
0509
0510
0511
0512
0513 template <> class SPSSerializationTraits<SPSString, StringRef> {
0514 public:
0515 static size_t size(const StringRef &S) {
0516 return SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size())) +
0517 S.size();
0518 }
0519
0520 static bool serialize(SPSOutputBuffer &OB, StringRef S) {
0521 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
0522 return false;
0523 if (S.empty())
0524 return true;
0525 return OB.write(S.data(), S.size());
0526 }
0527
0528 static bool deserialize(SPSInputBuffer &IB, StringRef &S) {
0529 const char *Data = nullptr;
0530 uint64_t Size;
0531 if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0532 return false;
0533 Data = IB.data();
0534 if (!IB.skip(Size))
0535 return false;
0536 S = StringRef(Size ? Data : nullptr, Size);
0537 return true;
0538 }
0539 };
0540
0541
0542 template <typename SPSValueT, typename ValueT>
0543 class SPSSerializationTraits<SPSSequence<SPSTuple<SPSString, SPSValueT>>,
0544 StringMap<ValueT>> {
0545 public:
0546 static size_t size(const StringMap<ValueT> &M) {
0547 size_t Sz = SPSArgList<uint64_t>::size(static_cast<uint64_t>(M.size()));
0548 for (auto &E : M)
0549 Sz += SPSArgList<SPSString, SPSValueT>::size(E.first(), E.second);
0550 return Sz;
0551 }
0552
0553 static bool serialize(SPSOutputBuffer &OB, const StringMap<ValueT> &M) {
0554 if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(M.size())))
0555 return false;
0556
0557 for (auto &E : M)
0558 if (!SPSArgList<SPSString, SPSValueT>::serialize(OB, E.first(), E.second))
0559 return false;
0560
0561 return true;
0562 }
0563
0564 static bool deserialize(SPSInputBuffer &IB, StringMap<ValueT> &M) {
0565 uint64_t Size;
0566 assert(M.empty() && "M already contains elements");
0567
0568 if (!SPSArgList<uint64_t>::deserialize(IB, Size))
0569 return false;
0570
0571 while (Size--) {
0572 StringRef S;
0573 ValueT V;
0574 if (!SPSArgList<SPSString, SPSValueT>::deserialize(IB, S, V))
0575 return false;
0576 if (!M.insert(std::make_pair(S, V)).second)
0577 return false;
0578 }
0579
0580 return true;
0581 }
0582 };
0583
0584
0585 class SPSError;
0586
0587
0588
0589 template <typename SPSTagT> class SPSExpected;
0590
0591 namespace detail {
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 struct SPSSerializableError {
0603 bool HasError = false;
0604 std::string ErrMsg;
0605 };
0606
0607
0608
0609
0610
0611
0612 template <typename T> struct SPSSerializableExpected {
0613 bool HasValue = false;
0614 T Value{};
0615 std::string ErrMsg;
0616 };
0617
0618 inline SPSSerializableError toSPSSerializable(Error Err) {
0619 if (Err)
0620 return {true, toString(std::move(Err))};
0621 return {false, {}};
0622 }
0623
0624 inline Error fromSPSSerializable(SPSSerializableError BSE) {
0625 if (BSE.HasError)
0626 return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
0627 return Error::success();
0628 }
0629
0630 template <typename T>
0631 SPSSerializableExpected<T> toSPSSerializable(Expected<T> E) {
0632 if (E)
0633 return {true, std::move(*E), {}};
0634 else
0635 return {false, T(), toString(E.takeError())};
0636 }
0637
0638 template <typename T>
0639 Expected<T> fromSPSSerializable(SPSSerializableExpected<T> BSE) {
0640 if (BSE.HasValue)
0641 return std::move(BSE.Value);
0642 else
0643 return make_error<StringError>(BSE.ErrMsg, inconvertibleErrorCode());
0644 }
0645
0646 }
0647
0648
0649 template <>
0650 class SPSSerializationTraits<SPSError, detail::SPSSerializableError> {
0651 public:
0652 static size_t size(const detail::SPSSerializableError &BSE) {
0653 size_t Size = SPSArgList<bool>::size(BSE.HasError);
0654 if (BSE.HasError)
0655 Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
0656 return Size;
0657 }
0658
0659 static bool serialize(SPSOutputBuffer &OB,
0660 const detail::SPSSerializableError &BSE) {
0661 if (!SPSArgList<bool>::serialize(OB, BSE.HasError))
0662 return false;
0663 if (BSE.HasError)
0664 if (!SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg))
0665 return false;
0666 return true;
0667 }
0668
0669 static bool deserialize(SPSInputBuffer &IB,
0670 detail::SPSSerializableError &BSE) {
0671 if (!SPSArgList<bool>::deserialize(IB, BSE.HasError))
0672 return false;
0673
0674 if (!BSE.HasError)
0675 return true;
0676
0677 return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
0678 }
0679 };
0680
0681
0682
0683 template <typename SPSTagT, typename T>
0684 class SPSSerializationTraits<SPSExpected<SPSTagT>,
0685 detail::SPSSerializableExpected<T>> {
0686 public:
0687 static size_t size(const detail::SPSSerializableExpected<T> &BSE) {
0688 size_t Size = SPSArgList<bool>::size(BSE.HasValue);
0689 if (BSE.HasValue)
0690 Size += SPSArgList<SPSTagT>::size(BSE.Value);
0691 else
0692 Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
0693 return Size;
0694 }
0695
0696 static bool serialize(SPSOutputBuffer &OB,
0697 const detail::SPSSerializableExpected<T> &BSE) {
0698 if (!SPSArgList<bool>::serialize(OB, BSE.HasValue))
0699 return false;
0700
0701 if (BSE.HasValue)
0702 return SPSArgList<SPSTagT>::serialize(OB, BSE.Value);
0703
0704 return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
0705 }
0706
0707 static bool deserialize(SPSInputBuffer &IB,
0708 detail::SPSSerializableExpected<T> &BSE) {
0709 if (!SPSArgList<bool>::deserialize(IB, BSE.HasValue))
0710 return false;
0711
0712 if (BSE.HasValue)
0713 return SPSArgList<SPSTagT>::deserialize(IB, BSE.Value);
0714
0715 return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
0716 }
0717 };
0718
0719
0720 template <typename SPSTagT>
0721 class SPSSerializationTraits<SPSExpected<SPSTagT>,
0722 detail::SPSSerializableError> {
0723 public:
0724 static size_t size(const detail::SPSSerializableError &BSE) {
0725 assert(BSE.HasError && "Cannot serialize expected from a success value");
0726 return SPSArgList<bool>::size(false) +
0727 SPSArgList<SPSString>::size(BSE.ErrMsg);
0728 }
0729
0730 static bool serialize(SPSOutputBuffer &OB,
0731 const detail::SPSSerializableError &BSE) {
0732 assert(BSE.HasError && "Cannot serialize expected from a success value");
0733 if (!SPSArgList<bool>::serialize(OB, false))
0734 return false;
0735 return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
0736 }
0737 };
0738
0739
0740 template <typename SPSTagT, typename T>
0741 class SPSSerializationTraits<SPSExpected<SPSTagT>, T> {
0742 public:
0743 static size_t size(const T &Value) {
0744 return SPSArgList<bool>::size(true) + SPSArgList<SPSTagT>::size(Value);
0745 }
0746
0747 static bool serialize(SPSOutputBuffer &OB, const T &Value) {
0748 if (!SPSArgList<bool>::serialize(OB, true))
0749 return false;
0750 return SPSArgList<SPSTagT>::serialize(Value);
0751 }
0752 };
0753
0754 }
0755 }
0756 }
0757
0758 #endif