blob: 1e5f6ced597abe03d5c7fcd9012edc6fe17117eb [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
11#define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
12
13#include "OrcError.h"
14#include "llvm/Support/thread.h"
15#include <map>
16#include <mutex>
Andrew Scullcdfcccc2018-10-05 20:58:37 +010017#include <set>
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010018#include <sstream>
Andrew Scullcdfcccc2018-10-05 20:58:37 +010019#include <string>
20#include <vector>
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010021
22namespace llvm {
23namespace orc {
24namespace rpc {
25
26template <typename T>
27class RPCTypeName;
28
29/// TypeNameSequence is a utility for rendering sequences of types to a string
30/// by rendering each type, separated by ", ".
31template <typename... ArgTs> class RPCTypeNameSequence {};
32
33/// Render an empty TypeNameSequence to an ostream.
34template <typename OStream>
35OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
36 return OS;
37}
38
39/// Render a TypeNameSequence of a single type to an ostream.
40template <typename OStream, typename ArgT>
41OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
42 OS << RPCTypeName<ArgT>::getName();
43 return OS;
44}
45
46/// Render a TypeNameSequence of more than one type to an ostream.
47template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
48OStream&
49operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
50 OS << RPCTypeName<ArgT1>::getName() << ", "
51 << RPCTypeNameSequence<ArgT2, ArgTs...>();
52 return OS;
53}
54
55template <>
56class RPCTypeName<void> {
57public:
58 static const char* getName() { return "void"; }
59};
60
61template <>
62class RPCTypeName<int8_t> {
63public:
64 static const char* getName() { return "int8_t"; }
65};
66
67template <>
68class RPCTypeName<uint8_t> {
69public:
70 static const char* getName() { return "uint8_t"; }
71};
72
73template <>
74class RPCTypeName<int16_t> {
75public:
76 static const char* getName() { return "int16_t"; }
77};
78
79template <>
80class RPCTypeName<uint16_t> {
81public:
82 static const char* getName() { return "uint16_t"; }
83};
84
85template <>
86class RPCTypeName<int32_t> {
87public:
88 static const char* getName() { return "int32_t"; }
89};
90
91template <>
92class RPCTypeName<uint32_t> {
93public:
94 static const char* getName() { return "uint32_t"; }
95};
96
97template <>
98class RPCTypeName<int64_t> {
99public:
100 static const char* getName() { return "int64_t"; }
101};
102
103template <>
104class RPCTypeName<uint64_t> {
105public:
106 static const char* getName() { return "uint64_t"; }
107};
108
109template <>
110class RPCTypeName<bool> {
111public:
112 static const char* getName() { return "bool"; }
113};
114
115template <>
116class RPCTypeName<std::string> {
117public:
118 static const char* getName() { return "std::string"; }
119};
120
121template <>
122class RPCTypeName<Error> {
123public:
124 static const char* getName() { return "Error"; }
125};
126
127template <typename T>
128class RPCTypeName<Expected<T>> {
129public:
130 static const char* getName() {
131 std::lock_guard<std::mutex> Lock(NameMutex);
132 if (Name.empty())
133 raw_string_ostream(Name) << "Expected<"
134 << RPCTypeNameSequence<T>()
135 << ">";
136 return Name.data();
137 }
138
139private:
140 static std::mutex NameMutex;
141 static std::string Name;
142};
143
144template <typename T>
145std::mutex RPCTypeName<Expected<T>>::NameMutex;
146
147template <typename T>
148std::string RPCTypeName<Expected<T>>::Name;
149
150template <typename T1, typename T2>
151class RPCTypeName<std::pair<T1, T2>> {
152public:
153 static const char* getName() {
154 std::lock_guard<std::mutex> Lock(NameMutex);
155 if (Name.empty())
156 raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
157 << ">";
158 return Name.data();
159 }
160private:
161 static std::mutex NameMutex;
162 static std::string Name;
163};
164
165template <typename T1, typename T2>
166std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
167template <typename T1, typename T2>
168std::string RPCTypeName<std::pair<T1, T2>>::Name;
169
170template <typename... ArgTs>
171class RPCTypeName<std::tuple<ArgTs...>> {
172public:
173 static const char* getName() {
174 std::lock_guard<std::mutex> Lock(NameMutex);
175 if (Name.empty())
176 raw_string_ostream(Name) << "std::tuple<"
177 << RPCTypeNameSequence<ArgTs...>() << ">";
178 return Name.data();
179 }
180private:
181 static std::mutex NameMutex;
182 static std::string Name;
183};
184
185template <typename... ArgTs>
186std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
187template <typename... ArgTs>
188std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
189
190template <typename T>
191class RPCTypeName<std::vector<T>> {
192public:
193 static const char*getName() {
194 std::lock_guard<std::mutex> Lock(NameMutex);
195 if (Name.empty())
196 raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
197 << ">";
198 return Name.data();
199 }
200
201private:
202 static std::mutex NameMutex;
203 static std::string Name;
204};
205
206template <typename T>
207std::mutex RPCTypeName<std::vector<T>>::NameMutex;
208template <typename T>
209std::string RPCTypeName<std::vector<T>>::Name;
210
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100211template <typename T> class RPCTypeName<std::set<T>> {
212public:
213 static const char *getName() {
214 std::lock_guard<std::mutex> Lock(NameMutex);
215 if (Name.empty())
216 raw_string_ostream(Name)
217 << "std::set<" << RPCTypeName<T>::getName() << ">";
218 return Name.data();
219 }
220
221private:
222 static std::mutex NameMutex;
223 static std::string Name;
224};
225
226template <typename T> std::mutex RPCTypeName<std::set<T>>::NameMutex;
227template <typename T> std::string RPCTypeName<std::set<T>>::Name;
228
229template <typename K, typename V> class RPCTypeName<std::map<K, V>> {
230public:
231 static const char *getName() {
232 std::lock_guard<std::mutex> Lock(NameMutex);
233 if (Name.empty())
234 raw_string_ostream(Name)
235 << "std::map<" << RPCTypeNameSequence<K, V>() << ">";
236 return Name.data();
237 }
238
239private:
240 static std::mutex NameMutex;
241 static std::string Name;
242};
243
244template <typename K, typename V>
245std::mutex RPCTypeName<std::map<K, V>>::NameMutex;
246template <typename K, typename V> std::string RPCTypeName<std::map<K, V>>::Name;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100247
248/// The SerializationTraits<ChannelT, T> class describes how to serialize and
249/// deserialize an instance of type T to/from an abstract channel of type
250/// ChannelT. It also provides a representation of the type's name via the
251/// getName method.
252///
253/// Specializations of this class should provide the following functions:
254///
255/// @code{.cpp}
256///
257/// static const char* getName();
258/// static Error serialize(ChannelT&, const T&);
259/// static Error deserialize(ChannelT&, T&);
260///
261/// @endcode
262///
263/// The third argument of SerializationTraits is intended to support SFINAE.
264/// E.g.:
265///
266/// @code{.cpp}
267///
268/// class MyVirtualChannel { ... };
269///
270/// template <DerivedChannelT>
271/// class SerializationTraits<DerivedChannelT, bool,
272/// typename std::enable_if<
273/// std::is_base_of<VirtChannel, DerivedChannel>::value
274/// >::type> {
275/// public:
276/// static const char* getName() { ... };
277/// }
278///
279/// @endcode
280template <typename ChannelT, typename WireType,
281 typename ConcreteType = WireType, typename = void>
282class SerializationTraits;
283
284template <typename ChannelT>
285class SequenceTraits {
286public:
287 static Error emitSeparator(ChannelT &C) { return Error::success(); }
288 static Error consumeSeparator(ChannelT &C) { return Error::success(); }
289};
290
291/// Utility class for serializing sequences of values of varying types.
292/// Specializations of this class contain 'serialize' and 'deserialize' methods
293/// for the given channel. The ArgTs... list will determine the "over-the-wire"
294/// types to be serialized. The serialize and deserialize methods take a list
295/// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
296/// but may be different types from ArgTs, provided that for each CArgT there
297/// is a SerializationTraits specialization
298/// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
299/// caller argument to over-the-wire value.
300template <typename ChannelT, typename... ArgTs>
301class SequenceSerialization;
302
303template <typename ChannelT>
304class SequenceSerialization<ChannelT> {
305public:
306 static Error serialize(ChannelT &C) { return Error::success(); }
307 static Error deserialize(ChannelT &C) { return Error::success(); }
308};
309
310template <typename ChannelT, typename ArgT>
311class SequenceSerialization<ChannelT, ArgT> {
312public:
313
314 template <typename CArgT>
315 static Error serialize(ChannelT &C, CArgT &&CArg) {
316 return SerializationTraits<ChannelT, ArgT,
317 typename std::decay<CArgT>::type>::
318 serialize(C, std::forward<CArgT>(CArg));
319 }
320
321 template <typename CArgT>
322 static Error deserialize(ChannelT &C, CArgT &CArg) {
323 return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
324 }
325};
326
327template <typename ChannelT, typename ArgT, typename... ArgTs>
328class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
329public:
330
331 template <typename CArgT, typename... CArgTs>
332 static Error serialize(ChannelT &C, CArgT &&CArg,
333 CArgTs &&... CArgs) {
334 if (auto Err =
335 SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>::
336 serialize(C, std::forward<CArgT>(CArg)))
337 return Err;
338 if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
339 return Err;
340 return SequenceSerialization<ChannelT, ArgTs...>::
341 serialize(C, std::forward<CArgTs>(CArgs)...);
342 }
343
344 template <typename CArgT, typename... CArgTs>
345 static Error deserialize(ChannelT &C, CArgT &CArg,
346 CArgTs &... CArgs) {
347 if (auto Err =
348 SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
349 return Err;
350 if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
351 return Err;
352 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
353 }
354};
355
356template <typename ChannelT, typename... ArgTs>
357Error serializeSeq(ChannelT &C, ArgTs &&... Args) {
358 return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>::
359 serialize(C, std::forward<ArgTs>(Args)...);
360}
361
362template <typename ChannelT, typename... ArgTs>
363Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
364 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
365}
366
367template <typename ChannelT>
368class SerializationTraits<ChannelT, Error> {
369public:
370
371 using WrappedErrorSerializer =
372 std::function<Error(ChannelT &C, const ErrorInfoBase&)>;
373
374 using WrappedErrorDeserializer =
375 std::function<Error(ChannelT &C, Error &Err)>;
376
377 template <typename ErrorInfoT, typename SerializeFtor,
378 typename DeserializeFtor>
379 static void registerErrorType(std::string Name, SerializeFtor Serialize,
380 DeserializeFtor Deserialize) {
381 assert(!Name.empty() &&
382 "The empty string is reserved for the Success value");
383
384 const std::string *KeyName = nullptr;
385 {
386 // We're abusing the stability of std::map here: We take a reference to the
387 // key of the deserializers map to save us from duplicating the string in
388 // the serializer. This should be changed to use a stringpool if we switch
389 // to a map type that may move keys in memory.
390 std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
391 auto I =
392 Deserializers.insert(Deserializers.begin(),
393 std::make_pair(std::move(Name),
394 std::move(Deserialize)));
395 KeyName = &I->first;
396 }
397
398 {
399 assert(KeyName != nullptr && "No keyname pointer");
400 std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
401 // FIXME: Move capture Serialize once we have C++14.
402 Serializers[ErrorInfoT::classID()] =
403 [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
404 assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&
405 "Serializer called for wrong error type");
406 if (auto Err = serializeSeq(C, *KeyName))
407 return Err;
408 return Serialize(C, static_cast<const ErrorInfoT &>(EIB));
409 };
410 }
411 }
412
413 static Error serialize(ChannelT &C, Error &&Err) {
414 std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
415
416 if (!Err)
417 return serializeSeq(C, std::string());
418
419 return handleErrors(std::move(Err),
420 [&C](const ErrorInfoBase &EIB) {
421 auto SI = Serializers.find(EIB.dynamicClassID());
422 if (SI == Serializers.end())
423 return serializeAsStringError(C, EIB);
424 return (SI->second)(C, EIB);
425 });
426 }
427
428 static Error deserialize(ChannelT &C, Error &Err) {
429 std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
430
431 std::string Key;
432 if (auto Err = deserializeSeq(C, Key))
433 return Err;
434
435 if (Key.empty()) {
436 ErrorAsOutParameter EAO(&Err);
437 Err = Error::success();
438 return Error::success();
439 }
440
441 auto DI = Deserializers.find(Key);
442 assert(DI != Deserializers.end() && "No deserializer for error type");
443 return (DI->second)(C, Err);
444 }
445
446private:
447
448 static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) {
449 std::string ErrMsg;
450 {
451 raw_string_ostream ErrMsgStream(ErrMsg);
452 EIB.log(ErrMsgStream);
453 }
454 return serialize(C, make_error<StringError>(std::move(ErrMsg),
455 inconvertibleErrorCode()));
456 }
457
458 static std::recursive_mutex SerializersMutex;
459 static std::recursive_mutex DeserializersMutex;
460 static std::map<const void*, WrappedErrorSerializer> Serializers;
461 static std::map<std::string, WrappedErrorDeserializer> Deserializers;
462};
463
464template <typename ChannelT>
465std::recursive_mutex SerializationTraits<ChannelT, Error>::SerializersMutex;
466
467template <typename ChannelT>
468std::recursive_mutex SerializationTraits<ChannelT, Error>::DeserializersMutex;
469
470template <typename ChannelT>
471std::map<const void*,
472 typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer>
473SerializationTraits<ChannelT, Error>::Serializers;
474
475template <typename ChannelT>
476std::map<std::string,
477 typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer>
478SerializationTraits<ChannelT, Error>::Deserializers;
479
480/// Registers a serializer and deserializer for the given error type on the
481/// given channel type.
482template <typename ChannelT, typename ErrorInfoT, typename SerializeFtor,
483 typename DeserializeFtor>
484void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize,
485 DeserializeFtor &&Deserialize) {
486 SerializationTraits<ChannelT, Error>::template registerErrorType<ErrorInfoT>(
487 std::move(Name),
488 std::forward<SerializeFtor>(Serialize),
489 std::forward<DeserializeFtor>(Deserialize));
490}
491
492/// Registers serialization/deserialization for StringError.
493template <typename ChannelT>
494void registerStringError() {
495 static bool AlreadyRegistered = false;
496 if (!AlreadyRegistered) {
497 registerErrorSerialization<ChannelT, StringError>(
498 "StringError",
499 [](ChannelT &C, const StringError &SE) {
500 return serializeSeq(C, SE.getMessage());
501 },
502 [](ChannelT &C, Error &Err) -> Error {
503 ErrorAsOutParameter EAO(&Err);
504 std::string Msg;
505 if (auto E2 = deserializeSeq(C, Msg))
506 return E2;
507 Err =
508 make_error<StringError>(std::move(Msg),
509 orcError(
510 OrcErrorCode::UnknownErrorCodeFromRemote));
511 return Error::success();
512 });
513 AlreadyRegistered = true;
514 }
515}
516
517/// SerializationTraits for Expected<T1> from an Expected<T2>.
518template <typename ChannelT, typename T1, typename T2>
519class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> {
520public:
521
522 static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) {
523 if (ValOrErr) {
524 if (auto Err = serializeSeq(C, true))
525 return Err;
526 return SerializationTraits<ChannelT, T1, T2>::serialize(C, *ValOrErr);
527 }
528 if (auto Err = serializeSeq(C, false))
529 return Err;
530 return serializeSeq(C, ValOrErr.takeError());
531 }
532
533 static Error deserialize(ChannelT &C, Expected<T2> &ValOrErr) {
534 ExpectedAsOutParameter<T2> EAO(&ValOrErr);
535 bool HasValue;
536 if (auto Err = deserializeSeq(C, HasValue))
537 return Err;
538 if (HasValue)
539 return SerializationTraits<ChannelT, T1, T2>::deserialize(C, *ValOrErr);
540 Error Err = Error::success();
541 if (auto E2 = deserializeSeq(C, Err))
542 return E2;
543 ValOrErr = std::move(Err);
544 return Error::success();
545 }
546};
547
548/// SerializationTraits for Expected<T1> from a T2.
549template <typename ChannelT, typename T1, typename T2>
550class SerializationTraits<ChannelT, Expected<T1>, T2> {
551public:
552
553 static Error serialize(ChannelT &C, T2 &&Val) {
554 return serializeSeq(C, Expected<T2>(std::forward<T2>(Val)));
555 }
556};
557
558/// SerializationTraits for Expected<T1> from an Error.
559template <typename ChannelT, typename T>
560class SerializationTraits<ChannelT, Expected<T>, Error> {
561public:
562
563 static Error serialize(ChannelT &C, Error &&Err) {
564 return serializeSeq(C, Expected<T>(std::move(Err)));
565 }
566};
567
568/// SerializationTraits default specialization for std::pair.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100569template <typename ChannelT, typename T1, typename T2, typename T3, typename T4>
570class SerializationTraits<ChannelT, std::pair<T1, T2>, std::pair<T3, T4>> {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100571public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100572 static Error serialize(ChannelT &C, const std::pair<T3, T4> &V) {
573 if (auto Err = SerializationTraits<ChannelT, T1, T3>::serialize(C, V.first))
574 return Err;
575 return SerializationTraits<ChannelT, T2, T4>::serialize(C, V.second);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100576 }
577
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100578 static Error deserialize(ChannelT &C, std::pair<T3, T4> &V) {
579 if (auto Err =
580 SerializationTraits<ChannelT, T1, T3>::deserialize(C, V.first))
581 return Err;
582 return SerializationTraits<ChannelT, T2, T4>::deserialize(C, V.second);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100583 }
584};
585
586/// SerializationTraits default specialization for std::tuple.
587template <typename ChannelT, typename... ArgTs>
588class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
589public:
590
591 /// RPC channel serialization for std::tuple.
592 static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
593 return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
594 }
595
596 /// RPC channel deserialization for std::tuple.
597 static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
598 return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
599 }
600
601private:
602 // Serialization helper for std::tuple.
603 template <size_t... Is>
604 static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
605 llvm::index_sequence<Is...> _) {
606 return serializeSeq(C, std::get<Is>(V)...);
607 }
608
609 // Serialization helper for std::tuple.
610 template <size_t... Is>
611 static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
612 llvm::index_sequence<Is...> _) {
613 return deserializeSeq(C, std::get<Is>(V)...);
614 }
615};
616
617/// SerializationTraits default specialization for std::vector.
618template <typename ChannelT, typename T>
619class SerializationTraits<ChannelT, std::vector<T>> {
620public:
621
622 /// Serialize a std::vector<T> from std::vector<T>.
623 static Error serialize(ChannelT &C, const std::vector<T> &V) {
624 if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
625 return Err;
626
627 for (const auto &E : V)
628 if (auto Err = serializeSeq(C, E))
629 return Err;
630
631 return Error::success();
632 }
633
634 /// Deserialize a std::vector<T> to a std::vector<T>.
635 static Error deserialize(ChannelT &C, std::vector<T> &V) {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100636 assert(V.empty() &&
637 "Expected default-constructed vector to deserialize into");
638
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100639 uint64_t Count = 0;
640 if (auto Err = deserializeSeq(C, Count))
641 return Err;
642
643 V.resize(Count);
644 for (auto &E : V)
645 if (auto Err = deserializeSeq(C, E))
646 return Err;
647
648 return Error::success();
649 }
650};
651
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100652template <typename ChannelT, typename T, typename T2>
653class SerializationTraits<ChannelT, std::set<T>, std::set<T2>> {
654public:
655 /// Serialize a std::set<T> from std::set<T2>.
656 static Error serialize(ChannelT &C, const std::set<T2> &S) {
657 if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
658 return Err;
659
660 for (const auto &E : S)
661 if (auto Err = SerializationTraits<ChannelT, T, T2>::serialize(C, E))
662 return Err;
663
664 return Error::success();
665 }
666
667 /// Deserialize a std::set<T> to a std::set<T>.
668 static Error deserialize(ChannelT &C, std::set<T2> &S) {
669 assert(S.empty() && "Expected default-constructed set to deserialize into");
670
671 uint64_t Count = 0;
672 if (auto Err = deserializeSeq(C, Count))
673 return Err;
674
675 while (Count-- != 0) {
676 T2 Val;
677 if (auto Err = SerializationTraits<ChannelT, T, T2>::deserialize(C, Val))
678 return Err;
679
680 auto Added = S.insert(Val).second;
681 if (!Added)
682 return make_error<StringError>("Duplicate element in deserialized set",
683 orcError(OrcErrorCode::UnknownORCError));
684 }
685
686 return Error::success();
687 }
688};
689
690template <typename ChannelT, typename K, typename V, typename K2, typename V2>
691class SerializationTraits<ChannelT, std::map<K, V>, std::map<K2, V2>> {
692public:
693 /// Serialize a std::map<K, V> from std::map<K2, V2>.
694 static Error serialize(ChannelT &C, const std::map<K2, V2> &M) {
695 if (auto Err = serializeSeq(C, static_cast<uint64_t>(M.size())))
696 return Err;
697
698 for (const auto &E : M) {
699 if (auto Err =
700 SerializationTraits<ChannelT, K, K2>::serialize(C, E.first))
701 return Err;
702 if (auto Err =
703 SerializationTraits<ChannelT, V, V2>::serialize(C, E.second))
704 return Err;
705 }
706
707 return Error::success();
708 }
709
710 /// Deserialize a std::map<K, V> to a std::map<K, V>.
711 static Error deserialize(ChannelT &C, std::map<K2, V2> &M) {
712 assert(M.empty() && "Expected default-constructed map to deserialize into");
713
714 uint64_t Count = 0;
715 if (auto Err = deserializeSeq(C, Count))
716 return Err;
717
718 while (Count-- != 0) {
719 std::pair<K2, V2> Val;
720 if (auto Err =
721 SerializationTraits<ChannelT, K, K2>::deserialize(C, Val.first))
722 return Err;
723
724 if (auto Err =
725 SerializationTraits<ChannelT, V, V2>::deserialize(C, Val.second))
726 return Err;
727
728 auto Added = M.insert(Val).second;
729 if (!Added)
730 return make_error<StringError>("Duplicate element in deserialized map",
731 orcError(OrcErrorCode::UnknownORCError));
732 }
733
734 return Error::success();
735 }
736};
737
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100738} // end namespace rpc
739} // end namespace orc
740} // end namespace llvm
741
742#endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H