/// <summary>
        /// Creates an instance of <see cref="SdbSchemaData"/> using embedded streams for constraint data and simple types.
        /// </summary>
        /// <remarks>
        /// Constraint data are contained in a binary file that is defined as:
        ///
        /// <![CDATA[
        /// [SdbDataHead][SdbClassIdToSchemaTypeIndex][SdbSchemaType][SdbParticleConstraint][SdbParticleChildrenIndex][SdbAttributeConstraint]
        /// ]]>
        ///
        /// Since the size of the arrays are different for different <paramref name="fileFormat"/>, these are all marshalled separately, with the information
        /// of offsets contained in <see cref="SdbDataHead"/>. These items are deserialized in this method, while <see cref="SerializeSdbData(Stream)"/> provides
        /// the infrastructure to serialize them back to a binary file in the correct order
        /// </remarks>
        /// <param name="fileFormat">The version to load</param>
        private SdbSchemaData(FileFormatVersions fileFormat)
        {
            if (!fileFormat.Any())
            {
                throw new ArgumentOutOfRangeException(nameof(fileFormat));
            }

            _fileFormat = fileFormat;

            using (var schema = GetStream(fileFormat, Constraints))
            {
                var dataHead = SdbData.Deserialize <SdbDataHead>(schema);

                dataHead.Validate();

                var length = (int)schema.Length;

                if (dataHead.End != length)
                {
                    throw new InvalidDataException();
                }

                ClassIdMap      = SdbData.Deserialize <SdbClassIdToSchemaTypeIndex>(schema, dataHead.ClassIds);
                SchemaTypes     = SdbData.Deserialize <SdbSchemaType>(schema, dataHead.SchemaType);
                Particles       = SdbData.Deserialize <SdbParticleConstraint>(schema, dataHead.Particles);
                ParticleIndexes = SdbData.Deserialize <SdbParticleChildrenIndex>(schema, dataHead.ParticleChildren);
                Attributes      = SdbData.Deserialize <SdbAttributeConstraint>(schema, dataHead.Attributes);
            }
        }
 private static T[] Deserialize <T>(byte[] data)
     where T : struct
 {
     using (var ms = new MemoryStream(data))
     {
         return(SdbData.Deserialize <T>(ms, SdbSpan.Create <T>(0)));
     }
 }
Exemple #3
0
        /// <summary>
        /// Load the fields data from byte data.
        /// </summary>
        /// <param name="value">The byte data array.</param>
        /// <param name="startIndex">The offset the data begins at.</param>
        public override void LoadFromBytes(byte[] value, int startIndex)
        {
            Signature = new byte[SignatureSize];
            Array.Copy(value, startIndex, Signature, 0, SignatureSize);
            startIndex += SignatureSize;

            for (int i = 0; i < SignatureSize; i++)
            {
                if (Signature[i] != SignatureConst[i])
                {
                    // TODO: change to resource string
                    throw new InvalidDataException("Invalide schema constraint data.");
                }
            }

            // !!!!Caution: keep the order of the following code lines!!!!
            DataVersion   = SdbData.LoadInt(value, ref startIndex);
            DataByteCount = SdbData.LoadInt(value, ref startIndex);

            if (DataVersion != LatestDataVersion)
            {
                // TODO: change to resource string
                throw new InvalidDataException("Invalide schema constraint data.");
            }

            StartClassId = SdbData.LoadInt(value, ref startIndex);

            ClassIdsCount      = SdbData.LoadInt(value, ref startIndex);
            ClassIdsDataOffset = SdbData.LoadInt(value, ref startIndex);

            SchemaTypeCount      = SdbData.LoadInt(value, ref startIndex);
            SchemaTypeDataOffset = SdbData.LoadInt(value, ref startIndex);

            ParticleCount      = SdbData.LoadInt(value, ref startIndex);
            ParticleDataOffset = SdbData.LoadInt(value, ref startIndex);

            ParticleChildrenIndexCount      = SdbData.LoadInt(value, ref startIndex);
            ParticleChildrenIndexDataOffset = SdbData.LoadInt(value, ref startIndex);

            AttributeCount      = SdbData.LoadInt(value, ref startIndex);
            AttributeDataOffset = SdbData.LoadInt(value, ref startIndex);

            SimpleTypeCount      = SdbData.LoadInt(value, ref startIndex);
            SimpleTypeDataOffset = SdbData.LoadInt(value, ref startIndex);
        }
        private byte[] VerifyBytes <T>(T instance, byte[] expected)
            where T : struct
        {
            var structLayout = typeof(T).GetTypeInfo().StructLayoutAttribute;

            Assert.NotNull(structLayout);
            Assert.Equal(LayoutKind.Sequential, structLayout.Value);
            Assert.Equal(1, structLayout.Pack);

            var serialized = SdbData.Serialize(new[] { instance });

            var str = string.Join(", ", serialized.Select(t => "0x" + t.ToString("X2")));

            _output.WriteLine($"{{{str}}}");

            Assert.Equal(expected.Length, Marshal.SizeOf <T>());
            Assert.Equal(expected.Length, serialized.Length);
            Assert.Equal(expected, serialized);

            return(serialized);
        }
        public void SerializeSdbData(Stream stream)
        {
            var head = new SdbDataHead(
                _fileFormat,
                ClassIdMap,
                SchemaTypes,
                Particles,
                ParticleIndexes,
                Attributes);

            head.Validate();

            void ValidatePosition(int position)
            {
                if (position != stream.Position)
                {
                    throw new InvalidDataException();
                }
            }

            ValidatePosition(0);
            SdbData.Serialize(head, stream);

            ValidatePosition(head.ClassIds.Offset);
            SdbData.Serialize(ClassIdMap, stream);

            ValidatePosition(head.SchemaType.Offset);
            SdbData.Serialize(SchemaTypes, stream);

            ValidatePosition(head.Particles.Offset);
            SdbData.Serialize(Particles, stream);

            ValidatePosition(head.ParticleChildren.Offset);
            SdbData.Serialize(ParticleIndexes, stream);

            ValidatePosition(head.Attributes.Offset);
            SdbData.Serialize(Attributes, stream);
        }