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