/// <summary>
 ///   Initializes a new instance.
 /// </summary>
 /// <param name="counterExampleMetadata">The state vector layout expected by the counter example.</param>
 /// <param name="modelMetadata">The state vector layout expected by the model.</param>
 internal StateVectorMismatchException(StateVectorLayout counterExampleMetadata, StateVectorLayout modelMetadata)
     : base("Mismatch detected between the layout of the state vector as expected by the counter example and the " +
            "actual layout of the state vector used by the instantiated model.")
 {
     CounterExampleMetadata = counterExampleMetadata;
     ModelMetadata          = modelMetadata;
 }
        /// <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>
        ///   Generates the <see cref="StateVectorLayout" /> for the <paramref name="objects" />.
        /// </summary>
        /// <param name="model">The model the state vector should be layouted for.</param>
        /// <param name="objects">The objects consisting of state values the state vector layout should be generated for.</param>
        /// <param name="mode">The serialization mode that should be used to generate the state vector layout.</param>
        internal StateVectorLayout GetStateVectorLayout(ModelBase model, ObjectTable objects, SerializationMode mode)
        {
            Requires.NotNull(model, nameof(model));
            Requires.NotNull(objects, nameof(objects));
            Requires.InRange(mode, nameof(mode));

            var layout = new StateVectorLayout();

            foreach (var slot in objects.SelectMany(obj => GetSerializer(obj).GetStateSlotMetadata(obj, objects.GetObjectIdentifier(obj), mode)))
            {
                layout.Add(slot);
            }

            layout.Compact(model, mode);
            return(layout);
        }
        /// <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]);
            }
        }