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