+template<typename T>
+struct Protocol::Traits
+{
+ static const std::uint16_t signature = 'C';
+ typedef CompoundSerializer<T> Serializer;
+};
+
+template<> struct Protocol::Traits<bool>: BasicTraits<bool, 'B'> { };
+template<> struct Protocol::Traits<std::int8_t>: BasicTraits<std::int8_t, 'I'> { };
+template<> struct Protocol::Traits<std::uint8_t>: BasicTraits<std::uint8_t, 'U'> { };
+template<> struct Protocol::Traits<std::int16_t>: BasicTraits<std::int16_t, 'I'> { };
+template<> struct Protocol::Traits<std::uint16_t>: BasicTraits<std::uint16_t, 'U'> { };
+template<> struct Protocol::Traits<std::int32_t>: BasicTraits<std::int32_t, 'I'> { };
+template<> struct Protocol::Traits<std::uint32_t>: BasicTraits<std::uint32_t, 'U'> { };
+template<> struct Protocol::Traits<std::int64_t>: BasicTraits<std::int64_t, 'I'> { };
+template<> struct Protocol::Traits<std::uint64_t>: BasicTraits<std::uint64_t, 'U'> { };
+template<> struct Protocol::Traits<float>: BasicTraits<float, 'F'> { };
+template<> struct Protocol::Traits<double>: BasicTraits<double, 'F'> { };
+
+template<> struct Protocol::Traits<std::string>
+{
+ static const std::uint16_t signature = 'S';
+ typedef StringSerializer Serializer;
+};
+
+template<typename T>
+struct Protocol::Traits<std::vector<T>>
+{
+ static const std::uint16_t signature = 'A';
+ typedef ArraySerializer<std::vector<T>> Serializer;
+};
+
+
+inline std::uint64_t Protocol::StringSerializer::get_hash() const
+{
+ return Traits<std::string>::signature;
+}
+
+
+template<typename A>
+Protocol::ArraySerializer<A>::ArraySerializer(const Protocol &proto):
+ length_serializer(proto),
+ element_serializer(proto)
+{ }
+
+template<typename A>
+std::uint64_t Protocol::ArraySerializer<A>::get_hash() const
+{
+ return hash_round<64>(element_serializer.get_hash(), 'A');
+}
+
+template<typename A>
+char *Protocol::ArraySerializer<A>::serialize(const A &array, char *buf, char *end) const
+{
+ buf = length_serializer.serialize(array.size(), buf, end);
+ for(const auto &e: array)
+ buf = element_serializer.serialize(e, buf, end);
+ return buf;
+}
+
+template<typename A>
+const char *Protocol::ArraySerializer<A>::deserialize(A &array, const char *buf, const char *end) const
+{
+ std::uint16_t length;
+ buf = length_serializer.deserialize(length, buf, end);
+ array.resize(length);
+ for(unsigned i=0; i<length; ++i)
+ buf = element_serializer.deserialize(array[i], buf, end);
+ return buf;
+}
+
+
+template<typename C>
+Protocol::CompoundSerializer<C>::CompoundSerializer(const Protocol &proto):
+ serializer(proto.get_packet_by_class<C>().get_serializer())
+{ }
+
+template<typename C>
+std::uint64_t Protocol::CompoundSerializer<C>::get_hash() const
+{
+ return hash_round<64>(serializer.get_hash(), 'C');
+}
+
+template<typename C>
+char *Protocol::CompoundSerializer<C>::serialize(const C &com, char *buf, char *end) const
+{
+ return serializer.serialize(com, buf, end);
+}
+
+template<typename C>
+const char *Protocol::CompoundSerializer<C>::deserialize(C &com, const char *buf, const char *end) const
+{
+ return serializer.deserialize(com, buf, end);
+}
+
+
+template<typename C, typename Head, typename T>
+Protocol::FieldSerializer<C, Head, T>::FieldSerializer(const Head &h, T C::*p, const Protocol &proto):
+ Head(h),
+ ptr(p),
+ ser(proto)
+{ }
+
+template<typename C, typename Head, typename T>
+std::uint64_t Protocol::FieldSerializer<C, Head, T>::get_hash() const
+{
+ return hash_update<64>(Head::get_hash(), ser.get_hash());
+}
+
+template<typename C, typename Head, typename T>
+char *Protocol::FieldSerializer<C, Head, T>::serialize(const C &com, char *buf, char *end) const
+{
+ buf = Head::serialize(com, buf, end);
+ return ser.serialize(com.*ptr, buf, end);
+}
+
+template<typename C, typename Head, typename T>
+const char *Protocol::FieldSerializer<C, Head, T>::deserialize(C &com, const char *buf, const char *end) const
+{
+ buf = Head::deserialize(com, buf, end);
+ return ser.deserialize(com.*ptr, buf, end);
+}
+
+
+template<typename P>
+Protocol::PacketTypeDef<P>::PacketTypeDef(unsigned i):
+ PacketDefBase(i),
+ serializer(std::make_unique<Serializer<P>>())
+{ }
+
+template<typename P>
+template<typename S>
+void Protocol::PacketTypeDef<P>::set_serializer(const S &ser)
+{
+ serializer = std::make_unique<S>(ser);
+}
+