Skip to content

(io): allow creating serializer for data defined outside Sight

Description

The serialization API have been opened a bit: It is now possible to call from anywhere io::session::SessionWriter::setDefaultSerializer() and io::session::SessionReader::setDefaultDeserializer() to set the default serializers used fro a class name. If one is already defined, it will be overridden.

The serialization functions must just be compliant with types io::session::serializer_t and io::session::deserializer_t:

using serializer_t = std::function<void (
    zip::ArchiveWriter&,
    boost::property_tree::ptree&,
    data::Object::csptr,
    std::map<std::string, data::Object::csptr>&,
    const core::crypto::secure_string&
)>;

using deserializer_t = std::function<data::Object::sptr(
    zip::ArchiveReader&,
    const boost::property_tree::ptree&,
    const std::map<std::string, data::Object::sptr>&,
    data::Object::sptr,
    const core::crypto::secure_string&
)>;

A simple example for custom serializers (that may be defined in a plugin.cpp) for data::String object may be clearer:

static constexpr auto CUSTOM_KEY = "custom key";

// Serialization function
inline static void customSerialize(
    zip::ArchiveWriter&,
    boost::property_tree::ptree& tree,
    data::Object::csptr object,
    std::map<std::string, data::Object::csptr>&,
    const core::crypto::secure_string& password = ""
)
{
    // Cast to the right type (throws exception if type is incorrect)
    const auto string = Helper::safeCast<data::String>(object);

    // Add a version number. Not mandatory, but could help for future release
    Helper::writeVersion<data::String>(tree, 666);

    Helper::writeString(tree, CUSTOM_KEY, string->getValue(), password);
}

// Deserialization function
inline static data::String::sptr customDeserialize(
    zip::ArchiveReader&,
    const boost::property_tree::ptree& tree,
    const std::map<std::string, data::Object::sptr>&,
    data::Object::sptr object,
    const core::crypto::secure_string& password = ""
)
{
    // Create or reuse the object (throws exception if type is incorrect)
    auto string = Helper::safeCast<data::String>(object);

    // Check version number (throws exception if type is incorrect)
    Helper::readVersion<data::String>(tree, 0, 666);

    // Assign the value
    string->setValue(Helper::readString(tree, CUSTOM_KEY, password));

    return string;
}

void Plugin::start()
{ 
    // Register custom serializers (default one will be overridden if there are defaults for those classes)
    io::session::SessionWriter::setDefaultSerializer(data::String::classname(), customSerialize);
    io::session::SessionReader::setDefaultDeserializer(data::String::classname(), customDeserialize);
}

//------------------------------------------------------------------------------

void Plugin::stop() noexcept
{
    // Unregister custom serializers (default ones will be used back if there are defaults for those classes)
    io::session::SessionWriter::setDefaultSerializer(data::String::classname());
    io::session::SessionReader::setDefaultDeserializer(data::String::classname());
}

It is also possible to set a custom serializers only on a SessionWriter or SessionReader instance and to keep default behaviors unchanged for other instances, by using SessionWriter::setSerializer() and SessionWriter::setDeserializer(), but it require, of course to not rely on SReader and SWriter services which means write your own services to be able to directly call SessionWriter::setSerializer() and SessionWriter::setDeserializer() from within.

Closes #775 (closed)

How to test it?

  • Launch io_sessiontest
Edited by Didier WECKMANN

Merge request reports