Property definitions

msgpack $ MsgPackSerializer :: defaultinit
# 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