fix ReceivedBy and refactor contact serialization

This commit is contained in:
Green Sky 2024-04-23 15:42:16 +02:00
parent 1a3fcc6757
commit e574c4f779
No known key found for this signature in database
3 changed files with 110 additions and 63 deletions

View File

@ -18,24 +18,44 @@ static Contact3 findContactByID(Contact3Registry& cr, const std::vector<uint8_t>
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<Contact::Components::ID>(c)) {
// unlucky, this contact is purely ephemeral
std::cerr << "MSC warning: encountered contact without ID\n";
return nullptr;
}
return nlohmann::json::binary(cr.get<Contact::Components::ID>(c).data);
}
Contact3 MessageSerializerNJ::deserlContactByID(const nlohmann::json& j) {
std::vector<uint8_t> 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<Contact::Components::ID>(other_c, id);
}
return other_c;
}
template<>
bool MessageSerializerNJ::component_get_json<Message::Components::ContactFrom>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) {
const Contact3 c = h.get<Message::Components::ContactFrom>().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<Contact::Components::ID>(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<Contact::Components::ID>(c).data);
j = msc.serlContactByID(c);
return true;
}
@ -48,21 +68,7 @@ bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components:
return true;
}
std::vector<uint8_t> 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<Contact::Components::ID>(other_c, id);
}
h.emplace_or_replace<Message::Components::ContactFrom>(other_c);
h.emplace_or_replace<Message::Components::ContactFrom>(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<Message::Components:
template<>
bool MessageSerializerNJ::component_get_json<Message::Components::ContactTo>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) {
const Contact3 c = h.get<Message::Components::ContactTo>().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<Contact::Components::ID>(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<Contact::Components::ID>(c).data);
j = msc.serlContactByID(c);
return true;
}
@ -98,21 +90,65 @@ bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components:
return true;
}
std::vector<uint8_t> 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<Contact::Components::ID>(other_c, id);
}
h.emplace_or_replace<Message::Components::ContactTo>(other_c);
h.emplace_or_replace<Message::Components::ContactTo>(msc.deserlContactByID(j));
// TODO: should we return false if the contact is unknown??
return true;
}
template<>
bool MessageSerializerNJ::component_get_json<Message::Components::ReceivedBy>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) {
const auto& comp = h.get<Message::Components::ReceivedBy>();
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<Contact::Components::ID>(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<Message::Components::ReceivedBy>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j) {
if (j.is_null()) {
std::cerr << "MSC warning: encountered null ReceivedBy\n";
h.emplace_or_replace<Message::Components::ReceivedBy>();
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<Message::Components::ReceivedBy>();
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<decltype(comp.ts)::mapped_type>()
);
}
// TODO: should we return false if the contact is unknown??
return true;

View File

@ -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<Message::Components::ContactTo>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j);
template<>
bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components::ContactTo>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j);
template<>
bool MessageSerializerNJ::component_get_json<Message::Components::ReceivedBy>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j);
template<>
bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components::ReceivedBy>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j);

View File

@ -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