Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/orc/simple_packed_serialization.h
39566 views
1
//===--- simple_packed_serialization.h - simple serialization ---*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file is a part of the ORC runtime support library.
10
//
11
// The behavior of the utilities in this header must be synchronized with the
12
// behavior of the utilities in
13
// llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h.
14
//
15
// The Simple Packed Serialization (SPS) utilities are used to generate
16
// argument and return buffers for wrapper functions using the following
17
// serialization scheme:
18
//
19
// Primitives:
20
// bool, char, int8_t, uint8_t -- Two's complement 8-bit (0=false, 1=true)
21
// int16_t, uint16_t -- Two's complement 16-bit little endian
22
// int32_t, uint32_t -- Two's complement 32-bit little endian
23
// int64_t, int64_t -- Two's complement 64-bit little endian
24
//
25
// Sequence<T>:
26
// Serialized as the sequence length (as a uint64_t) followed by the
27
// serialization of each of the elements without padding.
28
//
29
// Tuple<T1, ..., TN>:
30
// Serialized as each of the element types from T1 to TN without padding.
31
//
32
//===----------------------------------------------------------------------===//
33
34
#ifndef ORC_RT_SIMPLE_PACKED_SERIALIZATION_H
35
#define ORC_RT_SIMPLE_PACKED_SERIALIZATION_H
36
37
#include "adt.h"
38
#include "endianness.h"
39
#include "error.h"
40
#include "stl_extras.h"
41
42
#include <optional>
43
#include <string>
44
#include <string_view>
45
#include <tuple>
46
#include <type_traits>
47
#include <unordered_map>
48
#include <utility>
49
#include <vector>
50
51
namespace __orc_rt {
52
53
/// Output char buffer with overflow check.
54
class SPSOutputBuffer {
55
public:
56
SPSOutputBuffer(char *Buffer, size_t Remaining)
57
: Buffer(Buffer), Remaining(Remaining) {}
58
bool write(const char *Data, size_t Size) {
59
if (Size > Remaining)
60
return false;
61
memcpy(Buffer, Data, Size);
62
Buffer += Size;
63
Remaining -= Size;
64
return true;
65
}
66
67
private:
68
char *Buffer = nullptr;
69
size_t Remaining = 0;
70
};
71
72
/// Input char buffer with underflow check.
73
class SPSInputBuffer {
74
public:
75
SPSInputBuffer() = default;
76
SPSInputBuffer(const char *Buffer, size_t Remaining)
77
: Buffer(Buffer), Remaining(Remaining) {}
78
bool read(char *Data, size_t Size) {
79
if (Size > Remaining)
80
return false;
81
memcpy(Data, Buffer, Size);
82
Buffer += Size;
83
Remaining -= Size;
84
return true;
85
}
86
87
const char *data() const { return Buffer; }
88
bool skip(size_t Size) {
89
if (Size > Remaining)
90
return false;
91
Buffer += Size;
92
Remaining -= Size;
93
return true;
94
}
95
96
private:
97
const char *Buffer = nullptr;
98
size_t Remaining = 0;
99
};
100
101
/// Specialize to describe how to serialize/deserialize to/from the given
102
/// concrete type.
103
template <typename SPSTagT, typename ConcreteT, typename _ = void>
104
class SPSSerializationTraits;
105
106
/// A utility class for serializing to a blob from a variadic list.
107
template <typename... ArgTs> class SPSArgList;
108
109
// Empty list specialization for SPSArgList.
110
template <> class SPSArgList<> {
111
public:
112
static size_t size() { return 0; }
113
114
static bool serialize(SPSOutputBuffer &OB) { return true; }
115
static bool deserialize(SPSInputBuffer &IB) { return true; }
116
};
117
118
// Non-empty list specialization for SPSArgList.
119
template <typename SPSTagT, typename... SPSTagTs>
120
class SPSArgList<SPSTagT, SPSTagTs...> {
121
public:
122
template <typename ArgT, typename... ArgTs>
123
static size_t size(const ArgT &Arg, const ArgTs &...Args) {
124
return SPSSerializationTraits<SPSTagT, ArgT>::size(Arg) +
125
SPSArgList<SPSTagTs...>::size(Args...);
126
}
127
128
template <typename ArgT, typename... ArgTs>
129
static bool serialize(SPSOutputBuffer &OB, const ArgT &Arg,
130
const ArgTs &...Args) {
131
return SPSSerializationTraits<SPSTagT, ArgT>::serialize(OB, Arg) &&
132
SPSArgList<SPSTagTs...>::serialize(OB, Args...);
133
}
134
135
template <typename ArgT, typename... ArgTs>
136
static bool deserialize(SPSInputBuffer &IB, ArgT &Arg, ArgTs &...Args) {
137
return SPSSerializationTraits<SPSTagT, ArgT>::deserialize(IB, Arg) &&
138
SPSArgList<SPSTagTs...>::deserialize(IB, Args...);
139
}
140
};
141
142
/// SPS serialization for integral types, bool, and char.
143
template <typename SPSTagT>
144
class SPSSerializationTraits<
145
SPSTagT, SPSTagT,
146
std::enable_if_t<std::is_same<SPSTagT, bool>::value ||
147
std::is_same<SPSTagT, char>::value ||
148
std::is_same<SPSTagT, int8_t>::value ||
149
std::is_same<SPSTagT, int16_t>::value ||
150
std::is_same<SPSTagT, int32_t>::value ||
151
std::is_same<SPSTagT, int64_t>::value ||
152
std::is_same<SPSTagT, uint8_t>::value ||
153
std::is_same<SPSTagT, uint16_t>::value ||
154
std::is_same<SPSTagT, uint32_t>::value ||
155
std::is_same<SPSTagT, uint64_t>::value>> {
156
public:
157
static size_t size(const SPSTagT &Value) { return sizeof(SPSTagT); }
158
159
static bool serialize(SPSOutputBuffer &OB, const SPSTagT &Value) {
160
SPSTagT Tmp = Value;
161
if (IsBigEndianHost)
162
swapByteOrder(Tmp);
163
return OB.write(reinterpret_cast<const char *>(&Tmp), sizeof(Tmp));
164
}
165
166
static bool deserialize(SPSInputBuffer &IB, SPSTagT &Value) {
167
SPSTagT Tmp;
168
if (!IB.read(reinterpret_cast<char *>(&Tmp), sizeof(Tmp)))
169
return false;
170
if (IsBigEndianHost)
171
swapByteOrder(Tmp);
172
Value = Tmp;
173
return true;
174
}
175
};
176
177
/// Any empty placeholder suitable as a substitute for void when deserializing
178
class SPSEmpty {};
179
180
/// Represents an address in the executor.
181
class SPSExecutorAddr {};
182
183
/// SPS tag type for tuples.
184
///
185
/// A blob tuple should be serialized by serializing each of the elements in
186
/// sequence.
187
template <typename... SPSTagTs> class SPSTuple {
188
public:
189
/// Convenience typedef of the corresponding arg list.
190
typedef SPSArgList<SPSTagTs...> AsArgList;
191
};
192
193
/// SPS tag type for optionals.
194
///
195
/// SPSOptionals should be serialized as a bool with true indicating that an
196
/// SPSTagT value is present, and false indicating that there is no value.
197
/// If the boolean is true then the serialized SPSTagT will follow immediately
198
/// after it.
199
template <typename SPSTagT> class SPSOptional {};
200
201
/// SPS tag type for sequences.
202
///
203
/// SPSSequences should be serialized as a uint64_t sequence length,
204
/// followed by the serialization of each of the elements.
205
template <typename SPSElementTagT> class SPSSequence;
206
207
/// SPS tag type for strings, which are equivalent to sequences of chars.
208
using SPSString = SPSSequence<char>;
209
210
/// SPS tag type for maps.
211
///
212
/// SPS maps are just sequences of (Key, Value) tuples.
213
template <typename SPSTagT1, typename SPSTagT2>
214
using SPSMap = SPSSequence<SPSTuple<SPSTagT1, SPSTagT2>>;
215
216
/// Serialization for SPSEmpty type.
217
template <> class SPSSerializationTraits<SPSEmpty, SPSEmpty> {
218
public:
219
static size_t size(const SPSEmpty &EP) { return 0; }
220
static bool serialize(SPSOutputBuffer &OB, const SPSEmpty &BE) {
221
return true;
222
}
223
static bool deserialize(SPSInputBuffer &IB, SPSEmpty &BE) { return true; }
224
};
225
226
/// Specialize this to implement 'trivial' sequence serialization for
227
/// a concrete sequence type.
228
///
229
/// Trivial sequence serialization uses the sequence's 'size' member to get the
230
/// length of the sequence, and uses a range-based for loop to iterate over the
231
/// elements.
232
///
233
/// Specializing this template class means that you do not need to provide a
234
/// specialization of SPSSerializationTraits for your type.
235
template <typename SPSElementTagT, typename ConcreteSequenceT>
236
class TrivialSPSSequenceSerialization {
237
public:
238
static constexpr bool available = false;
239
};
240
241
/// Specialize this to implement 'trivial' sequence deserialization for
242
/// a concrete sequence type.
243
///
244
/// Trivial deserialization calls a static 'reserve(SequenceT&)' method on your
245
/// specialization (you must implement this) to reserve space, and then calls
246
/// a static 'append(SequenceT&, ElementT&) method to append each of the
247
/// deserialized elements.
248
///
249
/// Specializing this template class means that you do not need to provide a
250
/// specialization of SPSSerializationTraits for your type.
251
template <typename SPSElementTagT, typename ConcreteSequenceT>
252
class TrivialSPSSequenceDeserialization {
253
public:
254
static constexpr bool available = false;
255
};
256
257
/// Trivial std::string -> SPSSequence<char> serialization.
258
template <> class TrivialSPSSequenceSerialization<char, std::string> {
259
public:
260
static constexpr bool available = true;
261
};
262
263
/// Trivial SPSSequence<char> -> std::string deserialization.
264
template <> class TrivialSPSSequenceDeserialization<char, std::string> {
265
public:
266
static constexpr bool available = true;
267
268
using element_type = char;
269
270
static void reserve(std::string &S, uint64_t Size) { S.reserve(Size); }
271
static bool append(std::string &S, char C) {
272
S.push_back(C);
273
return true;
274
}
275
};
276
277
/// Trivial std::vector<T> -> SPSSequence<SPSElementTagT> serialization.
278
template <typename SPSElementTagT, typename T>
279
class TrivialSPSSequenceSerialization<SPSElementTagT, std::vector<T>> {
280
public:
281
static constexpr bool available = true;
282
};
283
284
/// Trivial span<T> -> SPSSequence<SPSElementTagT> serialization.
285
template <typename SPSElementTagT, typename T>
286
class TrivialSPSSequenceSerialization<SPSElementTagT, span<T>> {
287
public:
288
static constexpr bool available = true;
289
};
290
291
/// Trivial SPSSequence<SPSElementTagT> -> std::vector<T> deserialization.
292
template <typename SPSElementTagT, typename T>
293
class TrivialSPSSequenceDeserialization<SPSElementTagT, std::vector<T>> {
294
public:
295
static constexpr bool available = true;
296
297
using element_type = typename std::vector<T>::value_type;
298
299
static void reserve(std::vector<T> &V, uint64_t Size) { V.reserve(Size); }
300
static bool append(std::vector<T> &V, T E) {
301
V.push_back(std::move(E));
302
return true;
303
}
304
};
305
306
/// Trivial std::unordered_map<K, V> -> SPSSequence<SPSTuple<SPSKey, SPSValue>>
307
/// serialization.
308
template <typename SPSKeyTagT, typename SPSValueTagT, typename K, typename V>
309
class TrivialSPSSequenceSerialization<SPSTuple<SPSKeyTagT, SPSValueTagT>,
310
std::unordered_map<K, V>> {
311
public:
312
static constexpr bool available = true;
313
};
314
315
/// Trivial SPSSequence<SPSTuple<SPSKey, SPSValue>> -> std::unordered_map<K, V>
316
/// deserialization.
317
template <typename SPSKeyTagT, typename SPSValueTagT, typename K, typename V>
318
class TrivialSPSSequenceDeserialization<SPSTuple<SPSKeyTagT, SPSValueTagT>,
319
std::unordered_map<K, V>> {
320
public:
321
static constexpr bool available = true;
322
323
using element_type = std::pair<K, V>;
324
325
static void reserve(std::unordered_map<K, V> &M, uint64_t Size) {
326
M.reserve(Size);
327
}
328
static bool append(std::unordered_map<K, V> &M, element_type E) {
329
return M.insert(std::move(E)).second;
330
}
331
};
332
333
/// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size
334
/// followed by a for-earch loop over the elements of the sequence to serialize
335
/// each of them.
336
template <typename SPSElementTagT, typename SequenceT>
337
class SPSSerializationTraits<SPSSequence<SPSElementTagT>, SequenceT,
338
std::enable_if_t<TrivialSPSSequenceSerialization<
339
SPSElementTagT, SequenceT>::available>> {
340
public:
341
static size_t size(const SequenceT &S) {
342
size_t Size = SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size()));
343
for (const auto &E : S)
344
Size += SPSArgList<SPSElementTagT>::size(E);
345
return Size;
346
}
347
348
static bool serialize(SPSOutputBuffer &OB, const SequenceT &S) {
349
if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
350
return false;
351
for (const auto &E : S)
352
if (!SPSArgList<SPSElementTagT>::serialize(OB, E))
353
return false;
354
return true;
355
}
356
357
static bool deserialize(SPSInputBuffer &IB, SequenceT &S) {
358
using TBSD = TrivialSPSSequenceDeserialization<SPSElementTagT, SequenceT>;
359
uint64_t Size;
360
if (!SPSArgList<uint64_t>::deserialize(IB, Size))
361
return false;
362
TBSD::reserve(S, Size);
363
for (size_t I = 0; I != Size; ++I) {
364
typename TBSD::element_type E;
365
if (!SPSArgList<SPSElementTagT>::deserialize(IB, E))
366
return false;
367
if (!TBSD::append(S, std::move(E)))
368
return false;
369
}
370
return true;
371
}
372
};
373
374
/// Trivial serialization / deserialization for span<char>
375
template <> class SPSSerializationTraits<SPSSequence<char>, span<const char>> {
376
public:
377
static size_t size(const span<const char> &S) {
378
return SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size())) +
379
S.size();
380
}
381
static bool serialize(SPSOutputBuffer &OB, const span<const char> &S) {
382
if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
383
return false;
384
return OB.write(S.data(), S.size());
385
}
386
static bool deserialize(SPSInputBuffer &IB, span<const char> &S) {
387
uint64_t Size;
388
if (!SPSArgList<uint64_t>::deserialize(IB, Size))
389
return false;
390
S = span<const char>(IB.data(), Size);
391
return IB.skip(Size);
392
}
393
};
394
395
/// SPSTuple serialization for std::tuple.
396
template <typename... SPSTagTs, typename... Ts>
397
class SPSSerializationTraits<SPSTuple<SPSTagTs...>, std::tuple<Ts...>> {
398
private:
399
using TupleArgList = typename SPSTuple<SPSTagTs...>::AsArgList;
400
using ArgIndices = std::make_index_sequence<sizeof...(Ts)>;
401
402
template <std::size_t... I>
403
static size_t size(const std::tuple<Ts...> &T, std::index_sequence<I...>) {
404
return TupleArgList::size(std::get<I>(T)...);
405
}
406
407
template <std::size_t... I>
408
static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T,
409
std::index_sequence<I...>) {
410
return TupleArgList::serialize(OB, std::get<I>(T)...);
411
}
412
413
template <std::size_t... I>
414
static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T,
415
std::index_sequence<I...>) {
416
return TupleArgList::deserialize(IB, std::get<I>(T)...);
417
}
418
419
public:
420
static size_t size(const std::tuple<Ts...> &T) {
421
return size(T, ArgIndices{});
422
}
423
424
static bool serialize(SPSOutputBuffer &OB, const std::tuple<Ts...> &T) {
425
return serialize(OB, T, ArgIndices{});
426
}
427
428
static bool deserialize(SPSInputBuffer &IB, std::tuple<Ts...> &T) {
429
return deserialize(IB, T, ArgIndices{});
430
}
431
};
432
433
/// SPSTuple serialization for std::pair.
434
template <typename SPSTagT1, typename SPSTagT2, typename T1, typename T2>
435
class SPSSerializationTraits<SPSTuple<SPSTagT1, SPSTagT2>, std::pair<T1, T2>> {
436
public:
437
static size_t size(const std::pair<T1, T2> &P) {
438
return SPSArgList<SPSTagT1>::size(P.first) +
439
SPSArgList<SPSTagT2>::size(P.second);
440
}
441
442
static bool serialize(SPSOutputBuffer &OB, const std::pair<T1, T2> &P) {
443
return SPSArgList<SPSTagT1>::serialize(OB, P.first) &&
444
SPSArgList<SPSTagT2>::serialize(OB, P.second);
445
}
446
447
static bool deserialize(SPSInputBuffer &IB, std::pair<T1, T2> &P) {
448
return SPSArgList<SPSTagT1>::deserialize(IB, P.first) &&
449
SPSArgList<SPSTagT2>::deserialize(IB, P.second);
450
}
451
};
452
453
/// SPSOptional serialization for std::optional.
454
template <typename SPSTagT, typename T>
455
class SPSSerializationTraits<SPSOptional<SPSTagT>, std::optional<T>> {
456
public:
457
static size_t size(const std::optional<T> &Value) {
458
size_t Size = SPSArgList<bool>::size(!!Value);
459
if (Value)
460
Size += SPSArgList<SPSTagT>::size(*Value);
461
return Size;
462
}
463
464
static bool serialize(SPSOutputBuffer &OB, const std::optional<T> &Value) {
465
if (!SPSArgList<bool>::serialize(OB, !!Value))
466
return false;
467
if (Value)
468
return SPSArgList<SPSTagT>::serialize(OB, *Value);
469
return true;
470
}
471
472
static bool deserialize(SPSInputBuffer &IB, std::optional<T> &Value) {
473
bool HasValue;
474
if (!SPSArgList<bool>::deserialize(IB, HasValue))
475
return false;
476
if (HasValue) {
477
Value = T();
478
return SPSArgList<SPSTagT>::deserialize(IB, *Value);
479
} else
480
Value = std::optional<T>();
481
return true;
482
}
483
};
484
485
/// Serialization for string_views.
486
///
487
/// Serialization is as for regular strings. Deserialization points directly
488
/// into the blob.
489
template <> class SPSSerializationTraits<SPSString, std::string_view> {
490
public:
491
static size_t size(const std::string_view &S) {
492
return SPSArgList<uint64_t>::size(static_cast<uint64_t>(S.size())) +
493
S.size();
494
}
495
496
static bool serialize(SPSOutputBuffer &OB, const std::string_view &S) {
497
if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(S.size())))
498
return false;
499
return OB.write(S.data(), S.size());
500
}
501
502
static bool deserialize(SPSInputBuffer &IB, std::string_view &S) {
503
const char *Data = nullptr;
504
uint64_t Size;
505
if (!SPSArgList<uint64_t>::deserialize(IB, Size))
506
return false;
507
if (Size > std::numeric_limits<size_t>::max())
508
return false;
509
Data = IB.data();
510
if (!IB.skip(Size))
511
return false;
512
S = {Data, static_cast<size_t>(Size)};
513
return true;
514
}
515
};
516
517
/// SPS tag type for errors.
518
class SPSError;
519
520
/// SPS tag type for expecteds, which are either a T or a string representing
521
/// an error.
522
template <typename SPSTagT> class SPSExpected;
523
524
namespace detail {
525
526
/// Helper type for serializing Errors.
527
///
528
/// llvm::Errors are move-only, and not inspectable except by consuming them.
529
/// This makes them unsuitable for direct serialization via
530
/// SPSSerializationTraits, which needs to inspect values twice (once to
531
/// determine the amount of space to reserve, and then again to serialize).
532
///
533
/// The SPSSerializableError type is a helper that can be
534
/// constructed from an llvm::Error, but inspected more than once.
535
struct SPSSerializableError {
536
bool HasError = false;
537
std::string ErrMsg;
538
};
539
540
/// Helper type for serializing Expected<T>s.
541
///
542
/// See SPSSerializableError for more details.
543
///
544
// FIXME: Use std::variant for storage once we have c++17.
545
template <typename T> struct SPSSerializableExpected {
546
bool HasValue = false;
547
T Value{};
548
std::string ErrMsg;
549
};
550
551
inline SPSSerializableError toSPSSerializable(Error Err) {
552
if (Err)
553
return {true, toString(std::move(Err))};
554
return {false, {}};
555
}
556
557
inline Error fromSPSSerializable(SPSSerializableError BSE) {
558
if (BSE.HasError)
559
return make_error<StringError>(BSE.ErrMsg);
560
return Error::success();
561
}
562
563
template <typename T>
564
SPSSerializableExpected<T> toSPSSerializable(Expected<T> E) {
565
if (E)
566
return {true, std::move(*E), {}};
567
else
568
return {false, {}, toString(E.takeError())};
569
}
570
571
template <typename T>
572
Expected<T> fromSPSSerializable(SPSSerializableExpected<T> BSE) {
573
if (BSE.HasValue)
574
return std::move(BSE.Value);
575
else
576
return make_error<StringError>(BSE.ErrMsg);
577
}
578
579
} // end namespace detail
580
581
/// Serialize to a SPSError from a detail::SPSSerializableError.
582
template <>
583
class SPSSerializationTraits<SPSError, detail::SPSSerializableError> {
584
public:
585
static size_t size(const detail::SPSSerializableError &BSE) {
586
size_t Size = SPSArgList<bool>::size(BSE.HasError);
587
if (BSE.HasError)
588
Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
589
return Size;
590
}
591
592
static bool serialize(SPSOutputBuffer &OB,
593
const detail::SPSSerializableError &BSE) {
594
if (!SPSArgList<bool>::serialize(OB, BSE.HasError))
595
return false;
596
if (BSE.HasError)
597
if (!SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg))
598
return false;
599
return true;
600
}
601
602
static bool deserialize(SPSInputBuffer &IB,
603
detail::SPSSerializableError &BSE) {
604
if (!SPSArgList<bool>::deserialize(IB, BSE.HasError))
605
return false;
606
607
if (!BSE.HasError)
608
return true;
609
610
return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
611
}
612
};
613
614
/// Serialize to a SPSExpected<SPSTagT> from a
615
/// detail::SPSSerializableExpected<T>.
616
template <typename SPSTagT, typename T>
617
class SPSSerializationTraits<SPSExpected<SPSTagT>,
618
detail::SPSSerializableExpected<T>> {
619
public:
620
static size_t size(const detail::SPSSerializableExpected<T> &BSE) {
621
size_t Size = SPSArgList<bool>::size(BSE.HasValue);
622
if (BSE.HasValue)
623
Size += SPSArgList<SPSTagT>::size(BSE.Value);
624
else
625
Size += SPSArgList<SPSString>::size(BSE.ErrMsg);
626
return Size;
627
}
628
629
static bool serialize(SPSOutputBuffer &OB,
630
const detail::SPSSerializableExpected<T> &BSE) {
631
if (!SPSArgList<bool>::serialize(OB, BSE.HasValue))
632
return false;
633
634
if (BSE.HasValue)
635
return SPSArgList<SPSTagT>::serialize(OB, BSE.Value);
636
637
return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
638
}
639
640
static bool deserialize(SPSInputBuffer &IB,
641
detail::SPSSerializableExpected<T> &BSE) {
642
if (!SPSArgList<bool>::deserialize(IB, BSE.HasValue))
643
return false;
644
645
if (BSE.HasValue)
646
return SPSArgList<SPSTagT>::deserialize(IB, BSE.Value);
647
648
return SPSArgList<SPSString>::deserialize(IB, BSE.ErrMsg);
649
}
650
};
651
652
/// Serialize to a SPSExpected<SPSTagT> from a detail::SPSSerializableError.
653
template <typename SPSTagT>
654
class SPSSerializationTraits<SPSExpected<SPSTagT>,
655
detail::SPSSerializableError> {
656
public:
657
static size_t size(const detail::SPSSerializableError &BSE) {
658
assert(BSE.HasError && "Cannot serialize expected from a success value");
659
return SPSArgList<bool>::size(false) +
660
SPSArgList<SPSString>::size(BSE.ErrMsg);
661
}
662
663
static bool serialize(SPSOutputBuffer &OB,
664
const detail::SPSSerializableError &BSE) {
665
assert(BSE.HasError && "Cannot serialize expected from a success value");
666
if (!SPSArgList<bool>::serialize(OB, false))
667
return false;
668
return SPSArgList<SPSString>::serialize(OB, BSE.ErrMsg);
669
}
670
};
671
672
/// Serialize to a SPSExpected<SPSTagT> from a T.
673
template <typename SPSTagT, typename T>
674
class SPSSerializationTraits<SPSExpected<SPSTagT>, T> {
675
public:
676
static size_t size(const T &Value) {
677
return SPSArgList<bool>::size(true) + SPSArgList<SPSTagT>::size(Value);
678
}
679
680
static bool serialize(SPSOutputBuffer &OB, const T &Value) {
681
if (!SPSArgList<bool>::serialize(OB, true))
682
return false;
683
return SPSArgList<SPSTagT>::serialize(Value);
684
}
685
};
686
687
} // end namespace __orc_rt
688
689
#endif // ORC_RT_SIMPLE_PACKED_SERIALIZATION_H
690
691