#pragma once #include #include #include namespace sp { namespace details { template struct IdPrinter {}; template <> struct IdPrinter<> { static std::string PrintMessageId() { return ""; } }; template struct IdPrinter { static std::string PrintMessageId() { return IdPrinter::PrintMessageId(); } }; template struct IdPrinter, TOptions...> { static std::string PrintMessageId() { return "(Id: " + std::to_string(TId) + ")"; } }; } // namespace details template std::ostream& operator<<(std::ostream& a_Stream, const std::tuple& a_Fields); template struct FieldPrinter { static std::ostream& PrintField(std::ostream& a_Stream, const sp::Field& a_Field) { return a_Stream << sp::Reflector::GetClassName() << "=" << PrintableField(a_Field.GetValue()); } }; template struct FieldPrinter, IAlignment> { static std::ostream& PrintField( std::ostream& a_Stream, const sp::Field, IAlignment>& a_Field) { a_Stream << "BitField<" << sp::Reflector::GetClassName() << ">["; a_Stream << a_Field.GetValue().GetFields() << "]"; return a_Stream; } }; template std::ostream& operator<<(std::ostream& a_Stream, const std::tuple& a_Fields) { bool first = true; TupleForEach( [&a_Stream, &first](const auto& a_Field) { if (!first) a_Stream << ", "; using TField = typename std::decay::type; constexpr std::size_t alignment = TField::AlignmentValue; FieldPrinter::PrintField(a_Stream, a_Field); first = false; }, a_Fields); return a_Stream; } template std::ostream& operator<<(std::ostream& a_Stream, const sp::MessageBase& a_Message) { a_Stream << sp::GetBasicClassName(a_Message) << sp::details::IdPrinter::PrintMessageId() << "[" << a_Message.GetFields() << "]"; return a_Stream; } } // namespace sp