(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