diff --git a/src/solanaceae/message3/message_serializer.cpp b/src/solanaceae/message3/message_serializer.cpp index 253b62b..5d2baa7 100644 --- a/src/solanaceae/message3/message_serializer.cpp +++ b/src/solanaceae/message3/message_serializer.cpp @@ -18,24 +18,44 @@ static Contact3 findContactByID(Contact3Registry& cr, const std::vector return entt::null; } +nlohmann::json MessageSerializerNJ::serlContactByID(Contact3 c) const { + if (!cr.valid(c)) { + // while this is invalid registry state, it is valid serialization + std::cerr << "MSC warning: encountered invalid contact\n"; + return nullptr; + } + + if (!cr.all_of(c)) { + // unlucky, this contact is purely ephemeral + std::cerr << "MSC warning: encountered contact without ID\n"; + return nullptr; + } + + return nlohmann::json::binary(cr.get(c).data); +} + +Contact3 MessageSerializerNJ::deserlContactByID(const nlohmann::json& j) { + std::vector id; + if (j.is_binary()) { + id = j.get_binary(); + } else { + j["bytes"].get_to(id); + } + + Contact3 other_c = findContactByID(cr, id); + if (!cr.valid(other_c)) { + // create sparse contact with id only + other_c = cr.create(); + cr.emplace_or_replace(other_c, id); + } + + return other_c; +} + template<> bool MessageSerializerNJ::component_get_json(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) { const Contact3 c = h.get().c; - if (!msc.cr.valid(c)) { - // while this is invalid registry state, it is valid serialization - j = nullptr; - std::cerr << "MSC warning: encountered invalid contact\n"; - return true; - } - - if (!msc.cr.all_of(c)) { - // unlucky, this contact is purely ephemeral - j = nullptr; - std::cerr << "MSC warning: encountered contact without ID\n"; - return true; - } - - j = nlohmann::json::binary(msc.cr.get(c).data); + j = msc.serlContactByID(c); return true; } @@ -48,21 +68,7 @@ bool MessageSerializerNJ::component_emplace_or_replace_json id; - if (j.is_binary()) { - id = j.get_binary(); - } else { - j["bytes"].get_to(id); - } - - Contact3 other_c = findContactByID(msc.cr, id); - if (!msc.cr.valid(other_c)) { - // create sparse contact with id only - other_c = msc.cr.create(); - msc.cr.emplace_or_replace(other_c, id); - } - - h.emplace_or_replace(other_c); + h.emplace_or_replace(msc.deserlContactByID(j)); // TODO: should we return false if the contact is unknown?? return true; @@ -71,21 +77,7 @@ bool MessageSerializerNJ::component_emplace_or_replace_json bool MessageSerializerNJ::component_get_json(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) { const Contact3 c = h.get().c; - if (!msc.cr.valid(c)) { - // while this is invalid registry state, it is valid serialization - j = nullptr; - std::cerr << "MSC warning: encountered invalid contact\n"; - return true; - } - - if (!msc.cr.all_of(c)) { - // unlucky, this contact is purely ephemeral - j = nullptr; - std::cerr << "MSC warning: encountered contact without ID\n"; - return true; - } - - j = nlohmann::json::binary(msc.cr.get(c).data); + j = msc.serlContactByID(c); return true; } @@ -98,21 +90,65 @@ bool MessageSerializerNJ::component_emplace_or_replace_json id; - if (j.is_binary()) { - id = j.get_binary(); - } else { - j["bytes"].get_to(id); - } - - Contact3 other_c = findContactByID(msc.cr, id); - if (!msc.cr.valid(other_c)) { - // create sparse contact with id only - other_c = msc.cr.create(); - msc.cr.emplace_or_replace(other_c, id); - } - - h.emplace_or_replace(other_c); + h.emplace_or_replace(msc.deserlContactByID(j)); + + // TODO: should we return false if the contact is unknown?? + return true; +} + +template<> +bool MessageSerializerNJ::component_get_json(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) { + const auto& comp = h.get(); + if (comp.ts.empty()) { + // empty array + j = nlohmann::json::array(); + return true; + } + + for (const auto& [c, v] : comp.ts) { + if (!msc.cr.valid(c) || !msc.cr.all_of(c)) { + // while this is invalid registry state, it is valid serialization + // we just skip this contact entirely and drop the time + std::cerr << "MSC warning: encountered invalid contact / contact without ID\n"; + continue; + } + auto& new_entry = j.emplace_back(nlohmann::json::array()); + new_entry.emplace_back(msc.serlContactByID(c)); + new_entry.emplace_back(v); + } + + return true; +} + +template<> +bool MessageSerializerNJ::component_emplace_or_replace_json(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j) { + if (j.is_null()) { + std::cerr << "MSC warning: encountered null ReceivedBy\n"; + h.emplace_or_replace(); + return true; + } + + if (!j.is_array()) { + throw (nlohmann::detail::type_error::create(302, nlohmann::detail::concat("type must be array, but is ", j.type_name()), &j)); + } + + auto& comp = h.emplace_or_replace(); + + if (j.empty()) { + // empty comp + return true; + } + + for (const auto& p : j) { + if (!p.is_array()) { + throw (nlohmann::detail::type_error::create(302, nlohmann::detail::concat("type must be array, but is ", p.type_name()), &j)); + } + + comp.ts.emplace( + msc.deserlContactByID(p.at(0)), // TODO: error checking? + p.at(1).get() + ); + } // TODO: should we return false if the contact is unknown?? return true; diff --git a/src/solanaceae/message3/message_serializer.hpp b/src/solanaceae/message3/message_serializer.hpp index a3024e1..b9b80ac 100644 --- a/src/solanaceae/message3/message_serializer.hpp +++ b/src/solanaceae/message3/message_serializer.hpp @@ -70,12 +70,19 @@ struct MessageSerializerNJ { } // TODO: deregister + + + + // helper + nlohmann::json serlContactByID(Contact3 c) const; + Contact3 deserlContactByID(const nlohmann::json& j); }; // fwd namespace Message::Components { struct ContactFrom; struct ContactTo; +struct ReceivedBy; } // make specializations known @@ -87,3 +94,7 @@ template<> bool MessageSerializerNJ::component_get_json(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j); template<> bool MessageSerializerNJ::component_emplace_or_replace_json(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j); +template<> +bool MessageSerializerNJ::component_get_json(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j); +template<> +bool MessageSerializerNJ::component_emplace_or_replace_json(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j); diff --git a/src/solanaceae/message3/nj/message_components.hpp b/src/solanaceae/message3/nj/message_components.hpp index 451adfe..a9db939 100644 --- a/src/solanaceae/message3/nj/message_components.hpp +++ b/src/solanaceae/message3/nj/message_components.hpp @@ -11,12 +11,12 @@ namespace Message::Components { NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Timestamp, ts) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(TimestampProcessed, ts) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(TimestampWritten, ts) - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ContactFrom, c) - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ContactTo, c) + //NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ContactFrom, c) // ms special + //NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ContactTo, c) // ms special NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Read, ts) - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ReceivedBy, ts) + //NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ReceivedBy, ts) // ms special // ReadBy // SyncedBy