note
	description: "[
		Decoding of arbitrary objects graphs between sessions of programs
		containing the same types or potentially different types (which can
		be mapped to the new type system via a correction mechanism,). It
		also basically takes care of potential reordering of attributes
		from one system to the other.
	]"
	legal: "See notice at end of class."
	status: "See notice at end of class."
	date: "$Date: 2020-05-19 14:29:33 +0000 (Tue, 19 May 2020) $"
	revision: "$Revision: 104259 $"

class 
	SED_RECOVERABLE_DESERIALIZER

create 
	make

feature {NONE} -- Initialization

	default_create
			-- Process instances of classes with no creation clause.
			-- (Default: do nothing.)
			-- (from ANY)
		do
		end

	make (a_deserializer: SED_READER_WRITER)
			-- Initialize current instance
		require -- from SED_SESSION_DESERIALIZER
			a_deserializer_not_void: a_deserializer /= Void
			a_deserializer_ready: a_deserializer.is_ready_for_reading
		do
			Precursor (a_deserializer)
			create mismatches.make (0)
			create mismatched_object.make (0)
		ensure -- from SED_SESSION_DESERIALIZER
			deserializer_set: deserializer = a_deserializer
		end
	
feature -- Access

	deserializer: SED_READER_WRITER
			-- Serializer used to decode data
			-- (from SED_SESSION_DESERIALIZER)

	generating_type: TYPE [detachable SED_RECOVERABLE_DESERIALIZER]
			-- Type of current object
			-- (type of which it is a direct instance)
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			generating_type_not_void: Result /= Void
		end

	generator: STRING_8
			-- Name of current object's generating class
			-- (base class of the type of which it is a direct instance)
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			generator_not_void: Result /= Void
			generator_not_empty: not Result.is_empty
		end

	last_decoded_object: detachable ANY
			-- Object decoded during last call to decode
			-- (from SED_SESSION_DESERIALIZER)

	last_exception: detachable EXCEPTION
			-- Last exception
			-- (from EXCEPTION_MANAGER)
		do
			Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.last_exception
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
		end
	
feature -- Comparison

	frozen deep_equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void
			-- or attached to isomorphic object structures?
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.is_deep_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			shallow_implies_deep: standard_equal (a, b) implies Result
			both_or_none_void: (a = Void) implies (Result = (b = Void))
			same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b))
			symmetric: Result implies deep_equal (b, a)
		end

	frozen equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void or attached
			-- to objects considered equal?
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.is_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.is_equal (b))
		end

	frozen is_deep_equal alias "≡≡≡" (other: SED_RECOVERABLE_DESERIALIZER): BOOLEAN
			-- Are Current and other attached to isomorphic object structures?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			shallow_implies_deep: standard_is_equal (other) implies Result
			same_type: Result implies same_type (other)
			symmetric: Result implies other.is_deep_equal (Current)
		end

	is_equal (other: SED_RECOVERABLE_DESERIALIZER): BOOLEAN
			-- Is other attached to an object considered
			-- equal to current object?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			symmetric: Result implies other ~ Current
			consistent: standard_is_equal (other) implies Result
		end

	frozen standard_equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void or attached to
			-- field-by-field identical objects of the same type?
			-- Always uses default object comparison criterion.
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.standard_is_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.standard_is_equal (b))
		end

	frozen standard_is_equal alias "" (other: SED_RECOVERABLE_DESERIALIZER): BOOLEAN
			-- Is other attached to an object of the same type
			-- as current object, and field-by-field identical to it?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			same_type: Result implies same_type (other)
			symmetric: Result implies other.standard_is_equal (Current)
		end
	
feature {NONE} -- Status report

	is_attribute_removal_allowed: BOOLEAN
			-- Do we not trigger a mismatch when an attribute has been removed?

	is_checking_data_consistency: BOOLEAN
			-- After retrieving objects, should we check that all objects are consistent?

	is_conforming_mismatch_allowed: BOOLEAN
			-- Do we not trigger a mismatch when an attribute type in the stored system is
			-- different from the retrieving system but conforming?

	is_stopping_on_data_retrieval_error: BOOLEAN
			-- When retrieving objects, should we stop at the first occurrence of a mismatch?

	is_transient_retrieval_required: BOOLEAN
			-- Do we need to retrieve transient attribute with their default value?
			-- This is necessary for Session/Basic storing where we expect the same
			-- object layout.
		do
			Result := False
		end
	
feature -- Status report

	conforms_to (other: ANY): BOOLEAN
			-- Does type of current object conform to type
			-- of other (as per Eiffel: The Language, chapter 13)?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		end

	error: detachable SED_ERROR
		obsolete "Use `errors' directly to find out errors encountered during retrieval. [2017-05-31]"
			-- Last error encountered during retrieval
			-- (from SED_SESSION_DESERIALIZER)
		do
			if attached errors as l_errors and then not l_errors.is_empty then
				Result := l_errors.last
			end
		end

	errors: detachable ARRAYED_LIST [SED_ERROR]
			-- (from SED_SESSION_DESERIALIZER)

	has_error: BOOLEAN
			-- Did we encounter an error during retrieval?
			-- (from SED_SESSION_DESERIALIZER)
		do
			Result := attached errors as l_errors and then not l_errors.is_empty
		end

	is_caught (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN
			-- If set, type of a_exception is raised.
			-- (from EXCEPTION_MANAGER)
		do
			Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_caught (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
			not_is_ignored: Result = not is_ignored (a_exception)
		end

	is_ignorable (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN
			-- If set, type of a_exception is ignorable.
			-- (from EXCEPTION_MANAGER)
		do
			Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_ignorable (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
		end

	is_ignored (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN
			-- If set, type of a_exception is not raised.
			-- (from EXCEPTION_MANAGER)
		do
			Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_ignored (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
			not_is_caught: Result = not is_caught (a_exception)
		end

	is_raisable (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN
			-- If set, type of a_exception is raisable.
			-- (from EXCEPTION_MANAGER)
		do
			Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_raisable (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
		end

	same_type (other: ANY): BOOLEAN
			-- Is type of current object identical to type of other?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			definition: Result = (conforms_to (other) and other.conforms_to (Current))
		end
	
feature -- Status setting

	catch (a_exception: TYPE [detachable EXCEPTION])
			-- Set type of a_exception is_caught.
			-- (from EXCEPTION_MANAGER)
		require -- from EXCEPTION_MANAGER
			a_exception_not_void: a_exception /= Void
		do
			(create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.catch (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
			is_ignored: not is_ignored (a_exception)
		end

	ignore (a_exception: TYPE [detachable EXCEPTION])
			-- Ignore type of a_exception.
			-- (from EXCEPTION_MANAGER)
		require -- from EXCEPTION_MANAGER
			a_exception_not_void: a_exception /= Void
			is_ignorable: is_ignorable (a_exception)
		do
			(create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.ignore (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
			is_caught: is_ignored (a_exception)
		end

	set_is_ignored (a_exception: TYPE [detachable EXCEPTION]; a_ignored: BOOLEAN)
			-- Set type of a_exception to be a_ignored.
			-- (from EXCEPTION_MANAGER)
		require -- from EXCEPTION_MANAGER
			a_exception_not_void: a_exception /= Void
			a_ignored_implies_is_ignorable: a_ignored implies is_ignorable (a_exception)
		do
			(create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.set_is_ignored (a_exception, a_ignored)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
			is_ignored_set: is_ignored (a_exception) = a_ignored
		end
	
feature -- Duplication

	frozen clone (other: detachable ANY): like other
		obsolete "Use `twin' instead. [2017-05-31]"
			-- Void if other is void; otherwise new object
			-- equal to other
			--
			-- For non-void other, clone calls copy;
			-- to change copying/cloning semantics, redefine copy.
			-- (from ANY)
		do
			if other /= Void then
				Result := other.twin
			end
		ensure -- from ANY
			instance_free: class
			equal: Result ~ other
		end

	copy (other: SED_RECOVERABLE_DESERIALIZER)
			-- Update current object using fields of object attached
			-- to other, so as to yield equal objects.
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
			type_identity: same_type (other)
		external
			"built_in"
		ensure -- from ANY
			is_equal: Current ~ other
		end

	frozen deep_clone (other: detachable ANY): like other
		obsolete "Use `deep_twin' instead. [2017-05-31]"
			-- Void if other is void: otherwise, new object structure
			-- recursively duplicated from the one attached to other
			-- (from ANY)
		do
			if other /= Void then
				Result := other.deep_twin
			end
		ensure -- from ANY
			instance_free: class
			deep_equal: deep_equal (other, Result)
		end

	frozen deep_copy (other: SED_RECOVERABLE_DESERIALIZER)
			-- Effect equivalent to that of:
			--		copy (other . deep_twin)
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		do
			copy (other.deep_twin)
		ensure -- from ANY
			deep_equal: deep_equal (Current, other)
		end

	frozen deep_twin: SED_RECOVERABLE_DESERIALIZER
			-- New object structure recursively duplicated from Current.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			deep_twin_not_void: Result /= Void
			deep_equal: deep_equal (Current, Result)
		end

	frozen standard_clone (other: detachable ANY): like other
		obsolete "Use `standard_twin' instead. [2017-05-31]"
			-- Void if other is void; otherwise new object
			-- field-by-field identical to other.
			-- Always uses default copying semantics.
			-- (from ANY)
		do
			if other /= Void then
				Result := other.standard_twin
			end
		ensure -- from ANY
			instance_free: class
			equal: standard_equal (Result, other)
		end

	frozen standard_copy (other: SED_RECOVERABLE_DESERIALIZER)
			-- Copy every field of other onto corresponding field
			-- of current object.
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
			type_identity: same_type (other)
		external
			"built_in"
		ensure -- from ANY
			is_standard_equal: standard_is_equal (other)
		end

	frozen standard_twin: SED_RECOVERABLE_DESERIALIZER
			-- New object field-by-field identical to other.
			-- Always uses default copying semantics.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			standard_twin_not_void: Result /= Void
			equal: standard_equal (Result, Current)
		end

	frozen twin: SED_RECOVERABLE_DESERIALIZER
			-- New object equal to Current
			-- twin calls copy; to change copying/twinning semantics, redefine copy.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			twin_not_void: Result /= Void
			is_equal: Result ~ Current
		end
	
feature -- Basic operations

	frozen as_attached: attached SED_RECOVERABLE_DESERIALIZER
		obsolete "Remove calls to this feature. [2017-05-31]"
			-- Attached version of Current.
			-- (Can be used during transitional period to convert
			-- non-void-safe classes to void-safe ones.)
			-- (from ANY)
		do
			Result := Current
		end

	frozen decode (a_is_gc_enabled: BOOLEAN)
			-- Decode object graph stored in deserializer.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_count: NATURAL_32
			l_mem: detachable like Memory
			l_is_collecting: BOOLEAN
			retried: BOOLEAN
		do
			if not retried then
				reset_errors
				if not a_is_gc_enabled then
					l_mem := Memory
					l_is_collecting := l_mem.collecting;
					l_mem.collection_off
				end
				l_count := deserializer.read_compressed_natural_32
				create object_references.make_empty (l_count.to_integer_32 + 1)
				read_header (l_count)
				if not has_error then
					decode_objects (l_count)
				end
			else
				if attached last_exception as l_exception then
					add_error (Error_factory.new_exception_error (l_exception))
				else
					add_error (Error_factory.new_internal_error ("An Unknown exception occurred in `decode'."))
				end
				last_decoded_object := Void
			end
			if l_is_collecting and then l_mem /= Void then
				l_mem.collection_on
			end
			clear_internal_data
		rescue
			retried := True
			retry
		end

	frozen default: detachable SED_RECOVERABLE_DESERIALIZER
			-- Default value of object's type
			-- (from ANY)
		do
		end

	frozen default_pointer: POINTER
			-- Default value of type POINTER
			-- (Avoid the need to write p.default for
			-- some p of type POINTER.)
			-- (from ANY)
		do
		ensure -- from ANY
			instance_free: class
		end

	default_rescue
			-- Process exception for routines with no Rescue clause.
			-- (Default: do nothing.)
			-- (from ANY)
		do
		end

	frozen do_nothing
			-- Execute a null action.
			-- (from ANY)
		do
		ensure -- from ANY
			instance_free: class
		end
	
feature {NONE} -- Implementation

	abstract_type (a_type_id: INTEGER_32): INTEGER_32
			-- Abstract type of a_type_id.
			-- (from SED_UTILITIES)
		require -- from SED_UTILITIES
			a_type_id_non_negative: a_type_id >= 0
		local
			l_spec_mapping: like Special_type_mapping
		do
			l_spec_mapping := Special_type_mapping;
			l_spec_mapping.search (a_type_id)
			if l_spec_mapping.found then
				Result := l_spec_mapping.found_item
			else
				Result := {REFLECTOR_CONSTANTS}.reference_type
			end
		end

	associated_mismatch (a_dtype: INTEGER_32): SED_TYPE_MISMATCH
			-- Associated mismatch for a_dtype.
		require
			a_dtype_non_negative: a_dtype >= 0
		do
			if attached mismatches.item (a_dtype) as l_mis then
				check
					valid_mismatch: l_mis.type_id = a_dtype
				end
				Result := l_mis
			else
				create Result.make (a_dtype);
				mismatches.put (Result, a_dtype)
			end
		end

	attributes_map (a_dtype: INTEGER_32): HASH_TABLE [TUPLE [position: INTEGER_32; dtype: INTEGER_32], STRING_8]
			-- Attribute map for dynamic type a_dtype which records
			-- position and dynamic type for a given attribute name.
		require
			a_dtype_non_negative: a_dtype >= 0
		local
			l_reflector: like reflector
			i, nb: INTEGER_32
		do
			l_reflector := reflector
			from
				i := 1
				nb := l_reflector.field_count_of_type (a_dtype)
				create Result.make (nb)
				nb := nb + 1
			until
				i = nb
			loop
				Result.put ([i, l_reflector.field_static_type_of_type (i, a_dtype)], l_reflector.field_name_of_type (i, a_dtype))
				i := i + 1
			end
		ensure
			attributes_map_not_void: Result /= Void
		end

	decode_normal_object (a_reflected_object: REFLECTED_OBJECT)
			-- Decode an object represented by a_reflected_object.
		require -- from SED_SESSION_DESERIALIZER
			an_obj_not_void: a_reflected_object /= Void
		local
			l_deser: like deserializer
			i, nb: INTEGER_32
			l_dtype, l_exp_dtype, l_new_offset: INTEGER_32
			l_mismatch_info: SED_TYPE_MISMATCH
			l_info: detachable MISMATCH_INFORMATION
			l_check_for_non_void: BOOLEAN
			l_has_mismatch: BOOLEAN
			l_field_info: detachable TUPLE [old_name: STRING_8; new_name: STRING_8; old_attribute_type: INTEGER_32; new_attribute_type: INTEGER_32; old_position: INTEGER_32; new_position: INTEGER_32; is_changed: BOOLEAN; is_removed: BOOLEAN; is_attachment_check_required: BOOLEAN]
			l_exp: REFLECTED_REFERENCE_OBJECT
		do
			l_dtype := a_reflected_object.dynamic_type
			if not has_mismatch (l_dtype) then
				Precursor (a_reflected_object)
			else
				l_mismatch_info := associated_mismatch (l_dtype)
				if l_mismatch_info.has_version_mismatch then
					create l_info.make (l_mismatch_info.old_count);
					l_info.set_versions (l_mismatch_info.old_version, l_mismatch_info.new_version)
				end
				l_deser := deserializer
				from
					i := 1
					nb := read_persistent_field_count (a_reflected_object) + 1
				until
					i = nb
				loop
					l_field_info := l_mismatch_info.mismatches_by_stored_position.item (i)
					if l_field_info /= Void then
						l_check_for_non_void := l_field_info.is_attachment_check_required
						l_has_mismatch := l_field_info.is_changed or (not is_attribute_removal_allowed and then l_field_info.is_removed)
						if not l_has_mismatch then
							l_field_info := Void
						elseif l_info = Void then
							create l_info.make (l_mismatch_info.old_count)
						end
					else
						l_check_for_non_void := False
					end
					if l_field_info = Void then
						l_new_offset := new_attribute_offset (l_dtype, i)
						inspect a_reflected_object.field_type (l_new_offset)
						when {REFLECTOR_CONSTANTS}.boolean_type then
							a_reflected_object.set_boolean_field (l_new_offset, l_deser.read_boolean)
						when {REFLECTOR_CONSTANTS}.character_8_type then
							a_reflected_object.set_character_8_field (l_new_offset, l_deser.read_character_8)
						when {REFLECTOR_CONSTANTS}.character_32_type then
							a_reflected_object.set_character_32_field (l_new_offset, l_deser.read_character_32)
						when {REFLECTOR_CONSTANTS}.natural_8_type then
							a_reflected_object.set_natural_8_field (l_new_offset, l_deser.read_natural_8)
						when {REFLECTOR_CONSTANTS}.natural_16_type then
							a_reflected_object.set_natural_16_field (l_new_offset, l_deser.read_natural_16)
						when {REFLECTOR_CONSTANTS}.natural_32_type then
							a_reflected_object.set_natural_32_field (l_new_offset, l_deser.read_natural_32)
						when {REFLECTOR_CONSTANTS}.natural_64_type then
							a_reflected_object.set_natural_64_field (l_new_offset, l_deser.read_natural_64)
						when {REFLECTOR_CONSTANTS}.integer_8_type then
							a_reflected_object.set_integer_8_field (l_new_offset, l_deser.read_integer_8)
						when {REFLECTOR_CONSTANTS}.integer_16_type then
							a_reflected_object.set_integer_16_field (l_new_offset, l_deser.read_integer_16)
						when {REFLECTOR_CONSTANTS}.integer_32_type then
							a_reflected_object.set_integer_32_field (l_new_offset, l_deser.read_integer_32)
						when {REFLECTOR_CONSTANTS}.integer_64_type then
							a_reflected_object.set_integer_64_field (l_new_offset, l_deser.read_integer_64)
						when {REFLECTOR_CONSTANTS}.real_32_type then
							a_reflected_object.set_real_32_field (l_new_offset, l_deser.read_real_32)
						when {REFLECTOR_CONSTANTS}.real_64_type then
							a_reflected_object.set_real_64_field (l_new_offset, l_deser.read_real_64)
						when {REFLECTOR_CONSTANTS}.pointer_type then
							a_reflected_object.set_pointer_field (l_new_offset, l_deser.read_pointer)
						when {REFLECTOR_CONSTANTS}.reference_type then
							if has_reference_with_copy_semantics then
								if l_deser.read_boolean then
									l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32)
									if l_exp_dtype < 0 then
										raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!"))
									else
										create l_exp.make (reflector.new_instance_of (l_exp_dtype))
										decode_normal_object (l_exp);
										a_reflected_object.set_reference_field (l_new_offset, l_exp.object)
										if l_check_for_non_void then
											l_check_for_non_void := False
										end
									end
								else
									a_reflected_object.set_reference_field (l_new_offset, read_reference)
								end
							else
								a_reflected_object.set_reference_field (l_new_offset, read_reference)
							end
							if l_check_for_non_void and then a_reflected_object.reference_field (l_new_offset) = Void then
								if l_info = Void then
									create l_info.make (l_mismatch_info.old_count)
								end;
								l_info.put (Void, a_reflected_object.field_name (l_new_offset))
							end
						when {REFLECTOR_CONSTANTS}.expanded_type then
							l_deser.read_compressed_integer_32.do_nothing
							decode_normal_object (a_reflected_object.expanded_field (l_new_offset))
						else
							check
									False
							end
						end
					else
						if l_info = Void then
							create l_info.make (l_mismatch_info.old_count)
						end
						inspect abstract_type (l_field_info.old_attribute_type)
						when {REFLECTOR_CONSTANTS}.boolean_type then
							l_info.put (l_deser.read_boolean, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.character_8_type then
							l_info.put (l_deser.read_character_8, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.character_32_type then
							l_info.put (l_deser.read_character_32, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.natural_8_type then
							l_info.put (l_deser.read_natural_8, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.natural_16_type then
							l_info.put (l_deser.read_natural_16, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.natural_32_type then
							l_info.put (l_deser.read_natural_32, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.natural_64_type then
							l_info.put (l_deser.read_natural_64, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.integer_8_type then
							l_info.put (l_deser.read_integer_8, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.integer_16_type then
							l_info.put (l_deser.read_integer_16, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.integer_32_type then
							l_info.put (l_deser.read_integer_32, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.integer_64_type then
							l_info.put (l_deser.read_integer_64, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.real_32_type then
							l_info.put (l_deser.read_real_32, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.real_64_type then
							l_info.put (l_deser.read_real_64, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.pointer_type then
							l_info.put (l_deser.read_pointer, l_field_info.new_name)
						when {REFLECTOR_CONSTANTS}.reference_type then
							if has_reference_with_copy_semantics then
								if l_deser.read_boolean then
									l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32)
									if l_exp_dtype < 0 then
										raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!"))
									else
										create l_exp.make (reflector.new_instance_of (l_exp_dtype))
										decode_normal_object (l_exp);
										l_info.put (l_exp.object, l_field_info.new_name)
									end
								else
									l_info.put (read_reference, l_field_info.new_name)
								end
							else
								l_info.put (read_reference, l_field_info.new_name)
							end
						when {REFLECTOR_CONSTANTS}.expanded_type then
							l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32)
							if l_exp_dtype < 0 then
								raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!"))
							else
								create l_exp.make (reflector.new_instance_of (l_exp_dtype))
								decode_normal_object (l_exp);
								l_info.put (l_exp.object, l_field_info.new_name)
							end
						else
							check
									False
							end
						end
					end
					i := i + 1
				end
			end
			if l_info /= Void then
				mismatched_object.extend ([a_reflected_object.object, l_info])
			end
		end

	frozen decode_object (is_root: BOOLEAN)
			-- Decode one object and store it in last_decoded_object if is_root.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_deser: like deserializer
			l_reflected_object: like reflected_object
			l_obj: detachable ANY
			l_nat32: NATURAL_32
		do
			l_deser := deserializer
			l_reflected_object := reflected_object
			l_nat32 := l_deser.read_compressed_natural_32
			check
				l_nat32_valid: l_nat32 < {INTEGER_32}.max_value.as_natural_32
			end
			l_obj := object_references.item (l_nat32.to_integer_32);
			l_reflected_object.set_object (l_obj)
			if l_reflected_object.is_special then
				decode_special (l_obj, abstract_type (l_reflected_object.generic_dynamic_type (1)))
			elseif l_reflected_object.is_tuple then
				decode_tuple (l_obj)
			else
				decode_normal_object (l_reflected_object)
			end
			if is_root then
				last_decoded_object := l_obj
			end
		end

	decode_objects (a_count: NATURAL_32)
			-- Decode a_count object from deserializer and store root object in last_decoded_object.
		require -- from SED_SESSION_DESERIALIZER
			a_count_positive: a_count > 0
		local
			i, nb: INTEGER_32
		do
			Precursor (a_count)
			from
				mismatched_object.start
			until
				mismatched_object.after
			loop
				safe_mismatch_correction (mismatched_object.item.object, mismatched_object.item.info);
				mismatched_object.forth
			end
			if is_checking_data_consistency then
				from
					i := 0
					nb := object_references.upper
				until
					i > nb
				loop
					if attached object_references.item (i) as l_obj and then not is_object_valid (l_obj, True) then
						add_error (Error_factory.new_invalid_object_error (l_obj))
					end
					i := i + 1
				end
			end
		end

	frozen decode_special (an_obj: ANY; an_item_type: INTEGER_32)
			-- Decode SPECIAL object of element type an_item_type in an_obj.
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			an_obj_not_void: an_obj /= Void
			an_obj_is_special: attached {SPECIAL [detachable ANY]} an_obj
		local
			nb: INTEGER_32
		do
			nb := deserializer.read_compressed_integer_32
			inspect an_item_type
			when {REFLECTOR_CONSTANTS}.boolean_type then
				if attached {SPECIAL [BOOLEAN]} an_obj as l_spec_boolean then
					decode_special_boolean (l_spec_boolean, nb)
				else
					check
						l_spec_boolean_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.character_8_type then
				if attached {SPECIAL [CHARACTER_8]} an_obj as l_spec_character_8 then
					decode_special_character_8 (l_spec_character_8, nb)
				else
					check
						l_spec_character_8_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.character_32_type then
				if attached {SPECIAL [CHARACTER_32]} an_obj as l_spec_character_32 then
					decode_special_character_32 (l_spec_character_32, nb)
				else
					check
						l_spec_character_32_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.natural_8_type then
				if attached {SPECIAL [NATURAL_8]} an_obj as l_spec_natural_8 then
					decode_special_natural_8 (l_spec_natural_8, nb)
				else
					check
						l_spec_natural_8_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.natural_16_type then
				if attached {SPECIAL [NATURAL_16]} an_obj as l_spec_natural_16 then
					decode_special_natural_16 (l_spec_natural_16, nb)
				else
					check
						l_spec_natural_16_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.natural_32_type then
				if attached {SPECIAL [NATURAL_32]} an_obj as l_spec_natural_32 then
					decode_special_natural_32 (l_spec_natural_32, nb)
				else
					check
						l_spec_natural_32_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.natural_64_type then
				if attached {SPECIAL [NATURAL_64]} an_obj as l_spec_natural_64 then
					decode_special_natural_64 (l_spec_natural_64, nb)
				else
					check
						l_spec_natural_64_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.integer_8_type then
				if attached {SPECIAL [INTEGER_8]} an_obj as l_spec_integer_8 then
					decode_special_integer_8 (l_spec_integer_8, nb)
				else
					check
						l_spec_integer_8_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.integer_16_type then
				if attached {SPECIAL [INTEGER_16]} an_obj as l_spec_integer_16 then
					decode_special_integer_16 (l_spec_integer_16, nb)
				else
					check
						l_spec_integer_16_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.integer_32_type then
				if attached {SPECIAL [INTEGER_32]} an_obj as l_spec_integer_32 then
					decode_special_integer_32 (l_spec_integer_32, nb)
				else
					check
						l_spec_integer_32_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.integer_64_type then
				if attached {SPECIAL [INTEGER_64]} an_obj as l_spec_integer_64 then
					decode_special_integer_64 (l_spec_integer_64, nb)
				else
					check
						l_spec_integer_64_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.real_32_type then
				if attached {SPECIAL [REAL_32]} an_obj as l_spec_real_32 then
					decode_special_real_32 (l_spec_real_32, nb)
				else
					check
						l_spec_real_32_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.real_64_type then
				if attached {SPECIAL [REAL_64]} an_obj as l_spec_real_64 then
					decode_special_real_64 (l_spec_real_64, nb)
				else
					check
						l_spec_real_64_not_void: False
					end
				end
			when {REFLECTOR_CONSTANTS}.pointer_type then
				if attached {SPECIAL [POINTER]} an_obj as l_spec_pointer then
					decode_special_pointer (l_spec_pointer, nb)
				else
					check
						l_spec_pointer_not_void: False
					end
				end
			else
				check
					an_item_type_valid: an_item_type = {REFLECTOR_CONSTANTS}.reference_type
				end
				if attached {SPECIAL [detachable ANY]} an_obj as l_spec_any then
					decode_special_reference (l_spec_any, nb)
				else
					check
						l_spec_any_not_void: False
					end
				end
			end
		end

	frozen decode_special_boolean (a_spec: SPECIAL [BOOLEAN]; a_count: INTEGER_32)
			-- Decode SPECIAL [BOOLEAN].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_boolean)
				i := i + 1
			end
		end

	frozen decode_special_character_32 (a_spec: SPECIAL [CHARACTER_32]; a_count: INTEGER_32)
			-- Decode SPECIAL [CHARACTER_32].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_character_32)
				i := i + 1
			end
		end

	frozen decode_special_character_8 (a_spec: SPECIAL [CHARACTER_8]; a_count: INTEGER_32)
			-- Decode SPECIAL [CHARACTER_8].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_character_8)
				i := i + 1
			end
		end

	frozen decode_special_integer_16 (a_spec: SPECIAL [INTEGER_16]; a_count: INTEGER_32)
			-- Decode SPECIAL [INTEGER_16].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_integer_16)
				i := i + 1
			end
		end

	frozen decode_special_integer_32 (a_spec: SPECIAL [INTEGER_32]; a_count: INTEGER_32)
			-- Decode SPECIAL [INTEGER].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_integer_32)
				i := i + 1
			end
		end

	frozen decode_special_integer_64 (a_spec: SPECIAL [INTEGER_64]; a_count: INTEGER_32)
			-- Decode SPECIAL [INTEGER_64].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_integer_64)
				i := i + 1
			end
		end

	frozen decode_special_integer_8 (a_spec: SPECIAL [INTEGER_8]; a_count: INTEGER_32)
			-- Decode SPECIAL [INTEGER_8].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_integer_8)
				i := i + 1
			end
		end

	frozen decode_special_natural_16 (a_spec: SPECIAL [NATURAL_16]; a_count: INTEGER_32)
			-- Decode SPECIAL [NATURAL_16].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_natural_16)
				i := i + 1
			end
		end

	frozen decode_special_natural_32 (a_spec: SPECIAL [NATURAL_32]; a_count: INTEGER_32)
			-- Decode SPECIAL [NATURAL_32].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_natural_32)
				i := i + 1
			end
		end

	frozen decode_special_natural_64 (a_spec: SPECIAL [NATURAL_64]; a_count: INTEGER_32)
			-- Decode SPECIAL [NATURAL_64].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_natural_64)
				i := i + 1
			end
		end

	frozen decode_special_natural_8 (a_spec: SPECIAL [NATURAL_8]; a_count: INTEGER_32)
			-- Decode SPECIAL [NATURAL_8].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_natural_8)
				i := i + 1
			end
		end

	frozen decode_special_pointer (a_spec: SPECIAL [POINTER]; a_count: INTEGER_32)
			-- Decode SPECIAL [POINTER].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_pointer)
				i := i + 1
			end
		end

	frozen decode_special_real_32 (a_spec: SPECIAL [REAL_32]; a_count: INTEGER_32)
			-- Decode SPECIAL [REAL_32].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_real_32)
				i := i + 1
			end
		end

	frozen decode_special_real_64 (a_spec: SPECIAL [REAL_64]; a_count: INTEGER_32)
			-- Decode SPECIAL [REAL_64].
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_spec_not_void: a_spec /= Void
		local
			i: INTEGER_32
			l_deser: like deserializer
		do
			from
				l_deser := deserializer
			until
				i = a_count
			loop
				a_spec.extend (l_deser.read_real_64)
				i := i + 1
			end
		end

	frozen decode_special_reference (a_spec: SPECIAL [detachable ANY]; a_count: INTEGER_32)
			-- Decode SPECIAL of reference.
			-- (from SED_SESSION_DESERIALIZER)
		local
			i: INTEGER_32
			l_has_copy_semantics_item: BOOLEAN
			l_deser: like deserializer
			l_exp_dtype: INTEGER_32
			l_exp: REFLECTED_REFERENCE_OBJECT
		do
			l_deser := deserializer
			if version >= {SED_VERSIONS}.version_7_3 then
				l_has_copy_semantics_item := l_deser.read_boolean
			end
			if not l_has_copy_semantics_item then
				from
				until
					i = a_count
				loop
					a_spec.force (read_reference, i)
					i := i + 1
				end
			else
				from
				until
					i = a_count
				loop
					if l_deser.read_boolean then
						l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32)
						if l_exp_dtype < 0 then
							raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!"))
						else
							create l_exp.make (reflector.new_instance_of (l_exp_dtype))
							decode_normal_object (l_exp);
							a_spec.force (l_exp.object, i)
						end
					else
						a_spec.force (read_reference, i)
					end
					i := i + 1
				end
			end
		end

	frozen decode_tuple (an_obj: ANY)
			-- Decode TUPLE object.
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			an_obj_not_void: an_obj /= Void
			an_obj_is_tuple: attached {TUPLE} an_obj
		local
			l_deser: like deserializer
			i, nb: INTEGER_32
		do
			l_deser := deserializer
			if attached {TUPLE} an_obj as l_tuple then
				from
					i := 1
					nb := l_tuple.count + 1
				until
					i = nb
				loop
					inspect l_deser.read_natural_8
					when {TUPLE}.boolean_code then
						l_tuple.put_boolean (l_deser.read_boolean, i)
					when {TUPLE}.character_8_code then
						l_tuple.put_character_8 (l_deser.read_character_8, i)
					when {TUPLE}.character_32_code then
						l_tuple.put_character_32 (l_deser.read_character_32, i)
					when {TUPLE}.natural_8_code then
						l_tuple.put_natural_8 (l_deser.read_natural_8, i)
					when {TUPLE}.natural_16_code then
						l_tuple.put_natural_16 (l_deser.read_natural_16, i)
					when {TUPLE}.natural_32_code then
						l_tuple.put_natural_32 (l_deser.read_natural_32, i)
					when {TUPLE}.natural_64_code then
						l_tuple.put_natural_64 (l_deser.read_natural_64, i)
					when {TUPLE}.integer_8_code then
						l_tuple.put_integer_8 (l_deser.read_integer_8, i)
					when {TUPLE}.integer_16_code then
						l_tuple.put_integer_16 (l_deser.read_integer_16, i)
					when {TUPLE}.integer_32_code then
						l_tuple.put_integer_32 (l_deser.read_integer_32, i)
					when {TUPLE}.integer_64_code then
						l_tuple.put_integer_64 (l_deser.read_integer_64, i)
					when {TUPLE}.real_32_code then
						l_tuple.put_real_32 (l_deser.read_real_32, i)
					when {TUPLE}.real_64_code then
						l_tuple.put_real_64 (l_deser.read_real_64, i)
					when {TUPLE}.pointer_code then
						l_tuple.put_pointer (l_deser.read_pointer, i)
					when {TUPLE}.reference_code then
						l_tuple.put_reference (read_reference, i)
					else
						check
								False
						end
					end
					i := i + 1
				end
			end
		end

	has_mismatch (a_dtype: INTEGER_32): BOOLEAN
			-- Is there a mismatch triggered for a_dtype?
		require
			a_dtype_non_negative: a_dtype >= 0
		do
			Result := mismatches.has (a_dtype)
		end

	is_object_valid (an_obj: ANY; a_verify_invariant: BOOLEAN): BOOLEAN
			-- Is object content valid, i.e. are all attached attributes really attached?
		local
			l_reflected_object: like reflected_object
			l_reflector: like reflector
			i, nb: INTEGER_32
			retried: BOOLEAN
		do
			if not retried then
				from
					l_reflected_object := reflected_object
					l_reflector := reflector;
					l_reflected_object.set_object (an_obj)
					i := 1
					nb := l_reflected_object.field_count
					Result := True
				until
					i > nb or not Result
				loop
					if l_reflected_object.field_type (i) = {REFLECTOR_CONSTANTS}.reference_type then
						Result := not l_reflector.is_attached_type (l_reflected_object.field_static_type (i)) or else l_reflected_object.reference_field (i) /= Void
					end
					i := i + 1
				end
				if a_verify_invariant then
					an_obj.do_nothing
				end
			else
				Result := False
			end
		rescue
			retried := True
			retry
		end

	Is_special_flag: NATURAL_8 = 1
			-- (from SED_UTILITIES)

	Is_tuple_flag: NATURAL_8 = 2
			-- Various flags for storing objects
			-- (from SED_UTILITIES)

	Is_void_safe: BOOLEAN
			-- Is current system compiled in void-safe mode?
			-- (from SED_UTILITIES)
		once
			Result := {SPECIAL [ANY]} /= {SPECIAL [detachable ANY]}
		end

	Memory: MEMORY
			-- Access to MEMORY features without having to create a new instance each time.
			-- (from SED_SESSION_DESERIALIZER)
		once
			create Result
		ensure -- from SED_SESSION_DESERIALIZER
			memory_not_void: Result /= Void
		end

	frozen new_special_instance (a_dtype, a_item_type, a_count: INTEGER_32): SPECIAL [detachable ANY]
			-- Create new special instance of a special object whose dynamic
			-- type is a_dtype, whose element abstract type is a_item_type
			-- and of count a_count.
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_dtype_non_negative: a_dtype >= 0
			a_item_type_non_negative: a_item_type >= 0
			a_count_non_negative: a_count >= 0
		do
			inspect a_item_type
			when {REFLECTOR_CONSTANTS}.boolean_type then
				create {SPECIAL [BOOLEAN]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.character_8_type then
				create {SPECIAL [CHARACTER_8]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.character_32_type then
				create {SPECIAL [CHARACTER_32]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.natural_8_type then
				create {SPECIAL [NATURAL_8]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.natural_16_type then
				create {SPECIAL [NATURAL_16]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.natural_32_type then
				create {SPECIAL [NATURAL_32]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.natural_64_type then
				create {SPECIAL [NATURAL_64]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.integer_8_type then
				create {SPECIAL [INTEGER_8]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.integer_16_type then
				create {SPECIAL [INTEGER_16]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.integer_32_type then
				create {SPECIAL [INTEGER_32]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.integer_64_type then
				create {SPECIAL [INTEGER_64]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.real_32_type then
				create {SPECIAL [REAL_32]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.real_64_type then
				create {SPECIAL [REAL_64]} Result.make_empty (a_count)
			when {REFLECTOR_CONSTANTS}.pointer_type then
				create {SPECIAL [POINTER]} Result.make_empty (a_count)
			else
				Result := reflector.new_special_any_instance (a_dtype, a_count)
			end
		ensure -- from SED_SESSION_DESERIALIZER
			new_special_instance_not_void: Result /= Void
		end

	read_attributes (a_dtype: INTEGER_32)
			-- Read attribute description for a_dtype where a_dtype is a dynamic type
			-- from the current system.
		local
			l_deser: like deserializer
			l_reflector: like reflector
			l_map: like attributes_map
			l_mapping: SPECIAL [INTEGER_32]
			l_old_name, l_new_name: STRING_8
			l_old_dtype, l_dtype: INTEGER_32
			i, nb, l_not_founds: INTEGER_32
			l_old_count, l_new_count: INTEGER_32
			a: like attributes_mapping
			l_attribute_type: INTEGER_32
		do
			l_deser := deserializer
			l_reflector := reflector
			l_old_count := l_deser.read_compressed_natural_32.to_integer_32
			l_new_count := l_reflector.persistent_field_count_of_type (a_dtype)
			if l_old_count /= l_new_count then
				associated_mismatch (a_dtype).add_attribute_count_mismatch (l_old_count, l_new_count)
			end
			from
				i := 1
				l_map := attributes_map (a_dtype)
				nb := l_old_count + 1
				create l_mapping.make_empty (nb);
				l_mapping.extend (0)
			until
				i = nb
			loop
				l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32
				l_dtype := new_dynamic_type_id (l_old_dtype)
				l_old_name := l_deser.read_string_8
				l_new_name := if attached attribute_name_translator as translation then
					translation (l_old_name, a_dtype)
				else
					l_old_name
				end
				if l_dtype >= 0 then
					if attached l_map.item (l_new_name) as l_item then
						l_attribute_type := l_item.dtype
						if l_attribute_type /= l_dtype then
							if is_conforming_mismatch_allowed then
								if not l_reflector.type_conforms_to (l_dtype, l_attribute_type) then
									if l_reflector.is_attached_type (l_attribute_type) and then l_reflector.type_conforms_to (l_dtype, l_reflector.detachable_type (l_attribute_type)) then
										associated_mismatch (a_dtype).add_void_safe_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position)
									else
										associated_mismatch (a_dtype).add_attribute_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position)
									end
								end
							else
								if l_reflector.is_attached_type (l_attribute_type) then
									if l_reflector.detachable_type (l_attribute_type) = l_dtype then
										associated_mismatch (a_dtype).add_void_safe_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position)
									else
										associated_mismatch (a_dtype).add_attribute_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position)
									end
								else
									if l_reflector.is_attached_type (l_dtype) and then l_reflector.detachable_type (l_dtype) = l_attribute_type then
									else
										associated_mismatch (a_dtype).add_attribute_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position)
									end
								end
							end
						end;
						l_mapping.extend (l_item.position)
					else
						l_not_founds := l_not_founds + 1
						if not is_attribute_removal_allowed then
							associated_mismatch (a_dtype).add_removed_attribute (l_dtype, l_old_name, l_new_name, i)
						end;
						l_mapping.extend (-1)
					end
				else
					add_error (Error_factory.new_unknown_attribute_type_error (a_dtype, l_new_name))
				end
				i := i + 1
			end
			if l_old_count - l_not_founds < l_new_count then
				associated_mismatch (a_dtype).add_new_attribute_mismatch (l_new_count - (l_old_count - l_not_founds))
			end
			check
					attached attributes_mapping as l_a
			then
				if not l_a.valid_index (a_dtype) then
					a := l_a.aliased_resized_area_with_default (Void, (a_dtype + 1).max (l_a.count * 2))
					attributes_mapping := a
				else
					a := l_a
				end;
				a.put (l_mapping, a_dtype)
			end
		end

	frozen read_default_value (a_abstract_type: INTEGER_32)
			-- Read from the stream the default value that corresponds to a_abstract_type.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_deser: like deserializer
		do
			l_deser := deserializer
			inspect a_abstract_type
			when {REFLECTOR_CONSTANTS}.boolean_type then
				l_deser.read_boolean.do_nothing
			when {REFLECTOR_CONSTANTS}.character_8_type then
				l_deser.read_character_8.do_nothing
			when {REFLECTOR_CONSTANTS}.character_32_type then
				l_deser.read_character_32.do_nothing
			when {REFLECTOR_CONSTANTS}.natural_8_type then
				l_deser.read_natural_8.do_nothing
			when {REFLECTOR_CONSTANTS}.natural_16_type then
				l_deser.read_natural_16.do_nothing
			when {REFLECTOR_CONSTANTS}.natural_32_type then
				l_deser.read_natural_32.do_nothing
			when {REFLECTOR_CONSTANTS}.natural_64_type then
				l_deser.read_natural_64.do_nothing
			when {REFLECTOR_CONSTANTS}.integer_8_type then
				l_deser.read_integer_8.do_nothing
			when {REFLECTOR_CONSTANTS}.integer_16_type then
				l_deser.read_integer_16.do_nothing
			when {REFLECTOR_CONSTANTS}.integer_32_type then
				l_deser.read_integer_32.do_nothing
			when {REFLECTOR_CONSTANTS}.integer_64_type then
				l_deser.read_integer_64.do_nothing
			when {REFLECTOR_CONSTANTS}.real_32_type then
				l_deser.read_real_32.do_nothing
			when {REFLECTOR_CONSTANTS}.real_64_type then
				l_deser.read_real_64.do_nothing
			when {REFLECTOR_CONSTANTS}.pointer_type then
				l_deser.read_pointer.do_nothing
			when {REFLECTOR_CONSTANTS}.reference_type then
				l_deser.read_compressed_natural_32.do_nothing
			when {REFLECTOR_CONSTANTS}.expanded_type then
				l_deser.read_natural_8.do_nothing
			else
				check
						False
				end
			end
		end

	read_header (a_count: NATURAL_32)
			-- Read header which contains mapping between dynamic type and their
			-- string representation.
		require -- from  SED_SESSION_DESERIALIZER
			True
		local
			i, nb: INTEGER_32
			l_deser: like deserializer
			l_reflector: like reflector
			l_table: like dynamic_type_table
			l_old_dtype, l_new_dtype: INTEGER_32
			l_old_type_str, l_new_type_str: STRING_8
			l_old_version, l_new_version: detachable IMMUTABLE_STRING_8
		do
			l_reflector := reflector
			l_deser := deserializer
			read_settings
			if version < {SED_VERSIONS}.version_6_6 then
				raise_fatal_error (Error_factory.new_format_mismatch (version, {SED_VERSIONS}.version_6_6))
			end
			nb := l_deser.read_compressed_natural_32.to_integer_32
			create l_table.make_filled (0, nb)
			create attributes_mapping.make_filled (Void, nb)
			from
				i := 0
			until
				i = nb
			loop
				l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32
				l_old_type_str := l_deser.read_string_8
				l_new_type_str := if attached class_type_translator as translation then
					translation (l_old_type_str)
				else
					l_old_type_str
				end
				l_new_dtype := l_reflector.dynamic_type_from_string (l_new_type_str)
				if l_new_dtype >= 0 then
					if not l_table.valid_index (l_old_dtype) then
						l_table := l_table.aliased_resized_area_with_default (0, (l_old_dtype + 1).max (l_table.count * 2))
					end;
					l_table.put (l_new_dtype, l_old_dtype)
				else
					add_error (Error_factory.new_missing_type_error (l_old_type_str, l_new_type_str))
				end
				if l_deser.read_boolean then
					l_old_version := l_deser.read_immutable_string_8
				else
					l_old_version := Void
				end
				if l_new_dtype /= -1 then
					l_new_version := l_reflector.storable_version_of_type (l_new_dtype)
					if l_old_version /~ l_new_version then
						associated_mismatch (l_new_dtype).add_version_mismatch (l_old_version, l_new_version)
					end
				end
				i := i + 1
			end
			from
				i := 0
				nb := l_deser.read_compressed_natural_32.to_integer_32
			until
				i = nb
			loop
				l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32
				l_old_type_str := l_deser.read_string_8
				l_new_type_str := if attached class_type_translator as translation then
					translation (l_old_type_str)
				else
					l_old_type_str
				end
				l_new_dtype := l_reflector.dynamic_type_from_string (l_new_type_str)
				if l_new_dtype >= 0 then
					if not l_table.valid_index (l_old_dtype) then
						l_table := l_table.aliased_resized_area_with_default (0, (l_old_dtype + 1).max (l_table.count * 2))
					end;
					l_table.put (l_new_dtype, l_old_dtype)
				else
					add_error (Error_factory.new_missing_type_error (l_old_type_str, l_new_type_str))
				end
				i := i + 1
			end
			dynamic_type_table := l_table
			from
				i := 0
				nb := l_deser.read_compressed_natural_32.to_integer_32
			until
				i = nb
			loop
				l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32
				if l_table.valid_index (l_old_dtype) then
					read_attributes (l_table.item (l_old_dtype))
				else
					raise_fatal_error (Error_factory.new_internal_error ("Cannot read attributes data"))
				end
				i := i + 1
			end
			read_object_table (a_count)
		end

	frozen read_object_table (a_count: NATURAL_32)
			-- Read object table if any, which has a_count objects.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_objs: like object_references
			l_deser: like deserializer
			l_reflector: like reflector
			l_mem: like Memory
			l_is_collecting: BOOLEAN
			l_nat32: NATURAL_32
			l_dtype, l_old_dtype: INTEGER_32
			i, nb: INTEGER_32
			l_obj: ANY
		do
			if deserializer.read_boolean then
				l_mem := Memory
				l_is_collecting := l_mem.collecting
				l_deser := deserializer
				l_reflector := reflector
				l_objs := object_references;
				l_objs.extend (Current)
				from
					i := 0
					nb := a_count.to_integer_32
				until
					i = nb
				loop
					if l_is_collecting and then i // 2000 = 0 then
						l_mem.collection_off
					end
					l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32
					l_dtype := new_dynamic_type_id (l_old_dtype)
					if l_dtype >= 0 then
						l_nat32 := deserializer.read_compressed_natural_32
						check
							l_nat32_valid: l_nat32 > 0 and l_nat32 < {INTEGER_32}.max_value.as_natural_32
						end
						check
							valid_id: l_nat32.to_integer_32 = i + 1
						end
						if l_deser.read_natural_8 = Is_special_flag then
							l_obj := new_special_instance (l_dtype, l_deser.read_compressed_integer_32, l_deser.read_compressed_integer_32)
						else
							l_obj := l_reflector.new_instance_of (l_dtype)
						end;
						l_objs.extend (l_obj)
					else
						raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!"))
					end
					i := i + 1
				end
				if l_is_collecting then
					l_mem.collection_on
				end
			else
				raise_fatal_error (Error_factory.new_format_mismatch_66)
			end
		end

	read_persistent_field_count (a_reflected_object: REFLECTED_OBJECT): INTEGER_32
			-- Number of fields we are going to read from a_reflected_object in the the retrieved system.
		local
			l_dtype: INTEGER_32
		do
			l_dtype := a_reflected_object.dynamic_type
			if attached attributes_mapping as l_map and then l_map.valid_index (l_dtype) and then attached l_map.item (l_dtype) as l_entry then
				Result := l_entry.count - 1
			else
				raise_fatal_error (Error_factory.new_internal_error ("Cannot retrieve stored count"))
			end
		end

	frozen read_reference: detachable ANY
			-- Read reference from the stream.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_nat32: NATURAL_32
		do
			l_nat32 := deserializer.read_compressed_natural_32
			if l_nat32 /= 0 then
				check
					l_nat32_valid: l_nat32 < {INTEGER_32}.max_value.as_natural_32
				end
				Result := object_references.item (l_nat32.to_integer_32)
			end
		end

	frozen read_settings
			-- Read various settings of serialized data.
			-- (from SED_SESSION_DESERIALIZER)
		do
			if is_store_settings_enabled then
				version := deserializer.read_compressed_natural_32
				if version >= {SED_VERSIONS}.version_7_3 then
					has_reference_with_copy_semantics := deserializer.read_boolean
				else
					has_reference_with_copy_semantics := False
				end
			else
				version := {SED_VERSIONS}.version_5_6
				has_reference_with_copy_semantics := False
			end
		end

	safe_mismatch_correction (an_obj: ANY; a_mismatch_information: MISMATCH_INFORMATION)
			-- Try to apply {MISMATCH_CORRECTOR}.correct_mismatch to an_obj using a_mismatch_information
			-- to solve the mismatch.
		local
			retried: BOOLEAN
			l_check, l_mismatch_called: BOOLEAN
		do
			if not retried then
				if attached {MISMATCH_CORRECTOR} an_obj as l_corrector then
					l_mismatch_called := True
					l_check := {ISE_RUNTIME}.check_assert (False);
					a_mismatch_information.put (an_obj.generating_type.name, {MISMATCH_INFORMATION}.type_name_key);
					Mismatch_information.copy (a_mismatch_information);
					l_corrector.correct_mismatch
					l_check := {ISE_RUNTIME}.check_assert (l_check)
					if not is_object_valid (an_obj, False) then
						add_error (Error_factory.new_invalid_object_error (an_obj))
					end
				else
					add_error (Error_factory.new_object_mismatch_error (an_obj))
				end
			else
				if l_mismatch_called then
					l_check := {ISE_RUNTIME}.check_assert (l_check)
				end
				add_error (Error_factory.new_object_mismatch_error (an_obj))
			end
		rescue
			retried := True
			retry
		end

	Special_type_mapping: HASH_TABLE [INTEGER_32, INTEGER_32]
			-- Mapping betwwen dynamic type of SPECIAL instances
			-- to abstract element types.
			-- (from SED_UTILITIES)
		once
			create Result.make (10);
			Result.put ({REFLECTOR_CONSTANTS}.boolean_type, ({BOOLEAN}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.character_8_type, ({CHARACTER_8}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.character_32_type, ({CHARACTER_32}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.natural_8_type, ({NATURAL_8}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.natural_16_type, ({NATURAL_16}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.natural_32_type, ({NATURAL_32}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.natural_64_type, ({NATURAL_64}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.integer_8_type, ({INTEGER_8}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.integer_16_type, ({INTEGER_16}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.integer_32_type, ({INTEGER_32}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.integer_64_type, ({INTEGER_64}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.real_32_type, ({REAL_32}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.real_64_type, ({REAL_64}).type_id);
			Result.put ({REFLECTOR_CONSTANTS}.pointer_type, ({POINTER}).type_id)
		ensure -- from SED_UTILITIES
			special_type_mapping_not_void: Result /= Void
		end
	
feature {EXCEPTIONS} -- Backward compatibility support

	exception_from_code (a_code: INTEGER_32): detachable EXCEPTION
			-- Create exception object from a_code
			-- (from EXCEPTION_MANAGER)
		do
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
		end

	type_of_code (a_code: INTEGER_32): detachable TYPE [EXCEPTION]
			-- Exception type of a_code
			-- (from EXCEPTION_MANAGER)
		do
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
		end
	
feature {NONE} -- Cleaning

	clear_internal_data
			-- Clear all allocated data
		do
			Precursor {SED_BASIC_DESERIALIZER}
			attributes_mapping := Void;
			mismatches.wipe_out;
			mismatched_object.wipe_out
		end
	
feature -- Correction

	correct_mismatch
			-- Attempt to correct object mismatch using Mismatch_information.
			-- (from MISMATCH_CORRECTOR)
		local
			l_msg: STRING_32
			l_exc: EXCEPTIONS
		do
			create l_msg.make_from_string_general ("Mismatch: ")
			create l_exc;
			l_msg.append (generating_type.name_32);
			l_exc.raise_retrieval_exception (l_msg)
		end

	Mismatch_information: MISMATCH_INFORMATION
			-- Original attribute values of mismatched object
			-- (from MISMATCH_CORRECTOR)
		once
			create Result
		end
	
feature {NONE} -- Implementation: Access

	dynamic_type_table: detachable SPECIAL [INTEGER_32]
			-- Mapping between old dynamic types and new ones.
			-- (from SED_SESSION_DESERIALIZER)

	Error_factory: SED_ERROR_FACTORY
			-- Once access to the error factory.
			-- (from SED_SESSION_DESERIALIZER)
		once
			create Result
		ensure -- from SED_SESSION_DESERIALIZER
			result_not_void: Result /= Void
		end

	has_reference_with_copy_semantics: BOOLEAN
			-- Does retrieved data contain references with copy semantics?
			-- (from SED_SESSION_DESERIALIZER)

	is_store_settings_enabled: BOOLEAN
			-- Are settings stored?
			-- By default not for SED_INDEPENDENT_DESERIALIZER.
			-- (from SED_SESSION_DESERIALIZER)
		do
			Result := True
		end

	frozen new_dynamic_type_id (a_old_type_id: INTEGER_32): INTEGER_32
			-- Given a_old_type_id, dynamic type id in stored system, retrieve dynamic
			-- type id in current system. Return -1 if not found.
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_old_type_id_non_negative: a_old_type_id >= 0
		do
			if attached dynamic_type_table as t then
				if a_old_type_id < t.count then
					Result := t.item (a_old_type_id)
				else
					Result := -1
				end
			else
				Result := a_old_type_id
			end
		ensure -- from SED_SESSION_DESERIALIZER
			minus_one_of_non_negative: Result >= -1
		end

	object_references: SPECIAL [ANY]
			-- Mapping between reference ID and the associated object.
			-- (from SED_SESSION_DESERIALIZER)

	reflected_object: REFLECTED_REFERENCE_OBJECT
			-- Facilities to inspect objects.
			-- (from SED_SESSION_DESERIALIZER)

	reflector: REFLECTOR
			-- Facilities to inspect.
			-- (from SED_SESSION_DESERIALIZER)

	version: NATURAL_32
			-- Internal version of the storable being retrieved (See SED_VERSIONS for possible values).
			-- (from SED_SESSION_DESERIALIZER)
	
feature {NONE} -- Implementation: Settings

	add_error (a_error: SED_ERROR)
			-- Assign a_error to error.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_new_errors: like errors
		do
			if attached errors as l_errors then
				l_errors.extend (a_error)
			else
				create l_new_errors.make (10);
				l_new_errors.extend (a_error)
				errors := l_new_errors
			end
		ensure -- from SED_SESSION_DESERIALIZER
			error_set: attached errors as l_errors and then l_errors.has (a_error)
		end

	raise_fatal_error (a_error: SED_ERROR)
			-- Add a_error to errors and raise an exception to terminate retrieval
			-- because the error is beyond recovery.
			-- (from SED_SESSION_DESERIALIZER)
		local
			l_failure: SERIALIZATION_FAILURE
		do
			add_error (a_error)
			create l_failure;
			l_failure.set_description (a_error.message);
			l_failure.raise
		ensure -- from SED_SESSION_DESERIALIZER
			error_set: attached errors as l_errors and then l_errors.has (a_error)
		end

	reset_errors
			-- Remove all errors for a new retrieval
			-- (from SED_SESSION_DESERIALIZER)
		do
			errors := Void
		ensure -- from SED_SESSION_DESERIALIZER
			errors_reset: errors = Void
		end

	set_error (a_error: SED_ERROR)
		obsolete "Use `add_error' instead. [2017-05-31]"
			-- Assign a_error to error.
			-- (from SED_SESSION_DESERIALIZER)
		do
			add_error (a_error)
		ensure -- from SED_SESSION_DESERIALIZER
			error_set: error = a_error
		end
	
feature {NONE} -- Implementation: access

	attribute_name_translator: detachable FUNCTION [STRING_8, INTEGER_32, STRING_8]
			-- Provide a mapping for an attribute name for a give type ID.

	attributes_mapping: detachable SPECIAL [detachable SPECIAL [INTEGER_32]]
			-- Mapping for each dynamic type id between old attribute location
			-- and new attribute location.

	class_type_translator: detachable FUNCTION [STRING_8, STRING_8]
			-- Provide a mapping between a class type from the storable to a class type
			-- in the retrieving system.

	mismatched_object: ARRAYED_LIST [TUPLE [object: ANY; info: MISMATCH_INFORMATION]]
			-- List of all mismatched objects found during retrieval.

	mismatches: HASH_TABLE [SED_TYPE_MISMATCH, INTEGER_32]
			-- Set of mismatches recorded during retrieval indexed by dynamic types.

	new_attribute_offset (a_new_type_id, a_old_offset: INTEGER_32): INTEGER_32
			-- Given attribute offset a_old_offset in the stored object whose dynamic type id
			-- is now a_new_type_id, retrieve new offset in a_new_type_id.
		require -- from SED_SESSION_DESERIALIZER
			a_new_type_id_non_negative: a_new_type_id >= 0
			a_old_offset_positive: a_old_offset > 0
		do
			if attached attributes_mapping as l_map and then l_map.valid_index (a_new_type_id) and then attached l_map.item (a_new_type_id) as l_entry and then l_entry.valid_index (a_old_offset) then
				Result := l_entry.item (a_old_offset)
			end
		ensure -- from SED_SESSION_DESERIALIZER
			new_attribute_offset_non_negative: Result >= 0
		end
	
feature -- Output

	Io: STD_FILES
			-- Handle to standard file setup
			-- (from ANY)
		once
			create Result;
			Result.set_output_default
		ensure -- from ANY
			instance_free: class
			io_not_void: Result /= Void
		end

	out: STRING_8
			-- New string containing terse printable representation
			-- of current object
			-- (from ANY)
		do
			Result := tagged_out
		ensure -- from ANY
			out_not_void: Result /= Void
		end

	print (o: detachable ANY)
			-- Write terse external representation of o
			-- on standard output.
			-- (from ANY)
		local
			s: READABLE_STRING_8
		do
			if attached o then
				s := o.out
				if attached {READABLE_STRING_32} s as s32 then
					Io.put_string_32 (s32)
				elseif attached {READABLE_STRING_8} s as s8 then
					Io.put_string (s8)
				else
					Io.put_string_32 (s.as_string_32)
				end
			end
		ensure -- from ANY
			instance_free: class
		end

	frozen tagged_out: STRING_8
			-- New string containing terse printable representation
			-- of current object
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			tagged_out_not_void: Result /= Void
		end
	
feature -- Platform

	Operating_environment: OPERATING_ENVIRONMENT
			-- Objects available from the operating system
			-- (from ANY)
		once
			create Result
		ensure -- from ANY
			instance_free: class
			operating_environment_not_void: Result /= Void
		end
	
feature -- Raise

	raise (a_exception: EXCEPTION)
			-- Raise a_exception.
			-- (from EXCEPTION_MANAGER)
		require -- from EXCEPTION_MANAGER
			a_exception_not_void: a_exception /= Void
			a_exception_is_raisable: a_exception.is_raisable
		do
			(create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.raise (a_exception)
		ensure -- from EXCEPTION_MANAGER
			instance_free: class
		end
	
feature {NONE} -- Retrieval

	frozen internal_correct_mismatch
			-- Called from runtime to perform a proper dynamic dispatch on correct_mismatch
			-- from MISMATCH_CORRECTOR.
			-- (from ANY)
		local
			l_msg: STRING_32
			l_exc: EXCEPTIONS
		do
			if attached {MISMATCH_CORRECTOR} Current as l_corrector then
				l_corrector.correct_mismatch
			else
				create l_msg.make_from_string ("Mismatch: ".as_string_32)
				create l_exc;
				l_msg.append (generating_type.name_32);
				l_exc.raise_retrieval_exception (l_msg)
			end
		end
	
feature -- Settings

	allow_attribute_removal
			-- Set is_attribute_removal_allowed to True.
		do
			is_attribute_removal_allowed := True
		ensure
			is_attribute_removal_allowed_set: is_attribute_removal_allowed
		end

	allow_conforming_mismatches
			-- Set is_conforming_mismatch_allowed to True.
		do
			is_conforming_mismatch_allowed := True
		ensure
			is_conforming_mismatch_allowed_set: is_conforming_mismatch_allowed
		end

	continue_on_data_retrieval_error
			-- Set is_attribute_removal_allowed to False.
		do
			is_stopping_on_data_retrieval_error := False
		ensure
			is_stopping_on_data_retrieval_error_set: not is_stopping_on_data_retrieval_error
		end

	disallow_attribute_removal
			-- Set is_attribute_removal_allowed to False.
		do
			is_attribute_removal_allowed := False
		ensure
			is_attribute_removal_allowed_set: not is_attribute_removal_allowed
		end

	disallow_conforming_mismatches
			-- Set is_conforming_mismatch_allowed to False.
		do
			is_conforming_mismatch_allowed := False
		ensure
			is_conforming_mismatch_allowed_set: not is_conforming_mismatch_allowed
		end

	set_attribute_name_translator (a_translator: like attribute_name_translator)
			-- Set attribute_name_translator with a_translator.
		do
			attribute_name_translator := a_translator
		ensure
			attribute_name_translator_set: attribute_name_translator = a_translator
		end

	set_class_type_translator (a_translator: like class_type_translator)
			-- Set class_type_translator with a_translator.
		do
			class_type_translator := a_translator
		ensure
			class_type_translator_set: class_type_translator = a_translator
		end

	set_deserializer (a_deserializer: like deserializer)
			-- Set deserializer with a_deserializer.
			-- (from SED_SESSION_DESERIALIZER)
		require -- from SED_SESSION_DESERIALIZER
			a_deserializer_not_void: a_deserializer /= Void
			a_deserializer_ready: a_deserializer.is_ready_for_reading
		do
			deserializer := a_deserializer
		ensure -- from SED_SESSION_DESERIALIZER
			deserializer_set: deserializer = a_deserializer
		end

	set_is_checking_data_consistency (v: like is_checking_data_consistency)
			-- Set is_checking_data_consistency with v.
		do
			is_checking_data_consistency := v
		ensure
			is_checking_data_consistency_set: is_checking_data_consistency = v
		end

	stop_on_data_retrieval_error
			-- Set is_stopping_on_data_retrieval_error to False.
		do
			is_stopping_on_data_retrieval_error := True
		ensure
			is_stopping_on_data_retrieval_error_set: is_stopping_on_data_retrieval_error
		end
	
invariant
		-- from SED_SESSION_DESERIALIZER
	reflector_not_void: reflector /= Void
	reflected_object_not_void: reflected_object /= Void
	deserializer_not_void: deserializer /= Void
	object_references_not_void: object_references /= Void

		-- from ANY
	reflexive_equality: standard_is_equal (Current)
	reflexive_conformance: conforms_to (Current)

note
	library: "EiffelBase: Library of reusable components for Eiffel."
	copyright: "Copyright (c) 1984-2020, Eiffel Software and others"
	license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
	source: "[
		Eiffel Software
		5949 Hollister Ave., Goleta, CA 93117 USA
		Telephone 805-685-1006, Fax 805-685-6869
		Website http://www.eiffel.com
		Customer support http://support.eiffel.com
	]"

end -- class SED_RECOVERABLE_DESERIALIZER

Generated by ISE EiffelStudio