# MessagePack deserialization engine
class MsgPackSerializer
super CachingSerializer
super MsgPackEngine
# Target writing stream
var stream: Writer
# Write plain MessagePack without metadata for deserialization?
#
# If `false`, the default, serialize to support deserialization:
#
# * Each object is encapsulated in an array that contains metadata and
# the actual object attributes in a map. The metadata includes the type
# name and references to already serialized object. This information
# supports deserializing the message, including cycles.
# * Preserve the Nit `Char` and `Byte` types as an object.
# * The generated MessagePack is standard and can be read by non-Nit programs.
# However, it contains some complexity that may make it harder to use.
#
# If `true`, serialize only the real data or non-Nit programs:
#
# * Nit objects are serialized to pure and standard MessagePack so they can
# be easily read by non-Nit programs.
# * Nit objects are serialized at every reference, so they may be duplicated.
# It is easier to read but it creates a larger output and it does not support
# cycles. Cyclic references are replaced by `null`.
# * The serialized data can only be deserialized to their expected static
# types, losing the knowledge of their dynamic type.
var plain_msgpack = false is writable
# Should strings declaring the objects type and attributes name be cached?
#
# If `true` metadata strings are cached using `cache`.
# The first occurrence is written as an object declaration,
# successive occurrences are written as an object reference.
#
# If `false`, the default, metadata strings are written as pure MessagePack
# strings, without their own metadata.
#
# Using the cache may save some space by avoiding the repetition of
# names used by many types or attributes.
# However, it adds complexity to the generated message and may be less
# safe for versioning.
var cache_metadata_strings = false is writable
# List of the current open objects, the first is the main target of the serialization
#
# Used only when `plain_msgpack == true` to detect cycles in serialization.
private var open_objects = new Array[Object]
redef var current_object = null
redef fun serialize(object)
do
if object == null then
stream.write_msgpack_null
else
if plain_msgpack then
for o in open_objects do
if object.is_same_serialized(o) then
# Cycle, can't be managed in plain_msgpack mode
warn "Cycle detected in serialized object, replacing reference with 'null'."
stream.write_msgpack_null
return
end
end
open_objects.add object
end
var last_object = current_object
current_object = object
object.accept_msgpack_serializer self
current_object = last_object
if plain_msgpack then open_objects.pop
end
end
redef fun serialize_attribute(name, value)
do
serialize_meta_string name
super
end
redef fun serialize_reference(object)
do
if not plain_msgpack and cache.has_object(object) then
# if already serialized, add local reference
var id = cache.id_for(object)
stream.write_msgpack_ext(ext_typ_ref, id.to_bytes)
else
# serialize
serialize object
end
end
private fun serialize_meta_string(type_name: String)
do
if plain_msgpack or not cache_metadata_strings then
# String only version
stream.write_msgpack_str type_name
return
end
if cache.has_object(type_name) then
# if already serialized, add reference
var id = cache.id_for(type_name)
stream.write_msgpack_ext(ext_typ_ref, id.to_bytes)
else
# serialize
var id = cache.new_id_for(type_name)
stream.write_msgpack_array 2 # obj+id, type_name
stream.write_msgpack_ext(ext_typ_obj, id.to_bytes)
stream.write_msgpack_str type_name
end
end
end
lib/msgpack/serialization_write.nit:31,1--149,3