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