/// <summary>
        ///   Deserializes a <see cref="SafetySharpRuntimeModel" /> from the <paramref name="reader" />.
        /// </summary>
        private unsafe SerializedRuntimeModel DeserializeModel(byte[] buffer, BinaryReader reader)
        {
            // Deserialize the object table
            var objectTable = DeserializeObjectTable(reader);

            // Deserialize the object identifiers of the model itself and the root formulas
            var model    = (ModelBase)objectTable.GetObject(reader.ReadUInt16());
            var formulas = new Formula[reader.ReadInt32()];

            for (var i = 0; i < formulas.Length; ++i)
            {
                formulas[i] = (Formula)objectTable.GetObject(reader.ReadUInt16());
            }

            // Copy the serialized initial state from the stream
            var stateVectorSize = reader.ReadInt32();
            var serializedState = stackalloc byte[stateVectorSize];

            for (var i = 0; i < stateVectorSize; ++i)
            {
                serializedState[i] = reader.ReadByte();
            }

            // Deserialize the model's initial state
            OpenSerializationDelegate deserializer;

            lock (_syncObject)
            {
                if (StateVector == null)
                {
                    StateVector = SerializationRegistry.Default.GetStateVectorLayout(model, objectTable, SerializationMode.Full);
                }

                if (_deserializer == null)
                {
                    _deserializer = StateVector.CreateDeserializer();
                }

                deserializer = _deserializer;
            }

            deserializer(objectTable, serializedState);

            // We instantiate the runtime type for each component and replace the original component
            // instance with the new runtime instance; we also replace all of the component's fault effects
            // with that instance and deserialize the initial state again. Afterwards, we have completely
            // replaced the original instance with its runtime instance, taking over all serialized data
            objectTable.SubstituteRuntimeInstances();
            deserializer(objectTable, serializedState);

            // We substitute the dummy delegate objects with the actual instances obtained from the DelegateMetadata instances
            objectTable.SubstituteDelegates();
            deserializer(objectTable, serializedState);

            // Return the serialized model data
            return(new SerializedRuntimeModel(model, buffer, objectTable, formulas));
        }
        /// <summary>
        ///   Serializes the <paramref name="model" />.
        /// </summary>
        private unsafe void SerializeModel(BinaryWriter writer, ModelBase model, Formula[] formulas)
        {
            // Collect all objects contained in the model
            var objectTable = CreateObjectTable(model, formulas);

            // Prepare the serialization of the model's initial state
            lock (_syncObject)
            {
                StateVector   = SerializationRegistry.Default.GetStateVectorLayout(model, objectTable, SerializationMode.Full);
                _deserializer = null;
            }

            var stateVectorSize = StateVector.SizeInBytes;
            var serializer      = StateVector.CreateSerializer(objectTable);

            // Serialize the object table
            SerializeObjectTable(objectTable, writer);

            // Serialize the object identifier of the model itself and the formulas
            writer.Write(objectTable.GetObjectIdentifier(model));
            writer.Write(formulas.Length);
            foreach (var formula in formulas)
            {
                writer.Write(objectTable.GetObjectIdentifier(formula));
            }

            // Serialize the initial state
            var serializedState = stackalloc byte[stateVectorSize];

            serializer(serializedState);

            // Copy the serialized state to the stream
            writer.Write(stateVectorSize);
            for (var i = 0; i < stateVectorSize; ++i)
            {
                writer.Write(serializedState[i]);
            }
        }
		/// <summary>
		///   Serializes the <paramref name="model" />.
		/// </summary>
		private unsafe void SerializeModel(BinaryWriter writer, ModelBase model, Formula[] formulas)
		{
			// Collect all objects contained in the model
			var objectTable = CreateObjectTable(model, formulas);

			// Prepare the serialization of the model's initial state
			lock (_syncObject)
			{
				_stateVector = SerializationRegistry.Default.GetStateVectorLayout(model, objectTable, SerializationMode.Full);
				_deserializer = null;
			}

			var stateVectorSize = _stateVector.SizeInBytes;
			var serializer = _stateVector.CreateSerializer(objectTable);

			// Serialize the object table
			SerializeObjectTable(objectTable, writer);

			// Serialize the object identifier of the model itself and the formulas
			writer.Write(objectTable.GetObjectIdentifier(model));
			writer.Write(formulas.Length);
			foreach (var formula in formulas)
				writer.Write(objectTable.GetObjectIdentifier(formula));

			// Serialize the initial state
			var serializedState = stackalloc byte[stateVectorSize];
			serializer(serializedState);

			// Copy the serialized state to the stream
			writer.Write(stateVectorSize);
			for (var i = 0; i < stateVectorSize; ++i)
				writer.Write(serializedState[i]);
		}
		/// <summary>
		///   Deserializes a <see cref="RuntimeModel" /> from the <paramref name="reader" />.
		/// </summary>
		private unsafe SerializedRuntimeModel DeserializeModel(byte[] buffer, BinaryReader reader)
		{
			// Deserialize the object table
			var objectTable = DeserializeObjectTable(reader);

			// Deserialize the object identifiers of the model itself and the root formulas
			var model = (ModelBase)objectTable.GetObject(reader.ReadUInt16());
			var formulas = new Formula[reader.ReadInt32()];
			for (var i = 0; i < formulas.Length; ++i)
				formulas[i] = (Formula)objectTable.GetObject(reader.ReadUInt16());

			// Copy the serialized initial state from the stream
			var stateVectorSize = reader.ReadInt32();
			var serializedState = stackalloc byte[stateVectorSize];

			for (var i = 0; i < stateVectorSize; ++i)
				serializedState[i] = reader.ReadByte();

			// Deserialize the model's initial state
			OpenSerializationDelegate deserializer;
			lock (_syncObject)
			{
				if (_stateVector == null)
					_stateVector = SerializationRegistry.Default.GetStateVectorLayout(model, objectTable, SerializationMode.Full);

				if (_deserializer == null)
					_deserializer = _stateVector.CreateDeserializer();

				deserializer = _deserializer;
			}

			deserializer(objectTable, serializedState);

			// We instantiate the runtime type for each component and replace the original component
			// instance with the new runtime instance; we also replace all of the component's fault effects
			// with that instance and deserialize the initial state again. Afterwards, we have completely
			// replaced the original instance with its runtime instance, taking over all serialized data
			objectTable.SubstituteRuntimeInstances();
			deserializer(objectTable, serializedState);

			// We substitute the dummy delegate objects with the actual instances obtained from the DelegateMetadata instances
			objectTable.SubstituteDelegates();
			deserializer(objectTable, serializedState);

			// Return the serialized model data
			return new SerializedRuntimeModel(model, buffer, objectTable, formulas);
		}