/// <summary>
        /// Inspect a type and deserialize its contents
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceExtendedType"></param>
        /// <param name="sourceBytes"></param>
        /// <param name="maxDepth"></param>
        /// <param name="options">The serialization options</param>
        /// <param name="ignoreAttributes"></param>
        /// <param name="typeRegistry">Custom type registry</param>
        /// <returns></returns>
        internal object InspectAndDeserialize(Type type, byte[] sourceBytes, uint maxDepth, SerializerOptions options, ICollection <object> ignoreAttributes, TypeRegistry typeRegistry = null, ICollection <string> ignorePropertiesOrPaths = null)
        {
            if (sourceBytes == null)
            {
                return(null);
            }

            using (var stream = new MemoryStream(sourceBytes))
            {
                using (var reader = new BinaryReader(stream))
                {
                    var obj = TypeReader.Read(reader, type.GetExtendedType(), maxDepth, options, ignoreAttributes, typeRegistry, ignorePropertiesOrPaths);
                    return(obj);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Validate a byte array for valid serialization data
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public bool Validate(byte[] bytes)
        {
            var isValid = false;

            try
            {
                TypeDescriptors typeDescriptors = null;
                using (var stream = new MemoryStream(bytes))
                {
                    using (var reader = new BinaryReader(stream))
                    {
                        /**
                         * [SettingsByte]           1 byte (SerializerDataSettings)
                         *
                         * Chunk Format
                         * [ChunkType]              1 byte (byte)
                         * [ChunkLength]            4 bytes (UInt32) or 2 bytes (UInt16)
                         * [ObjectReferenceId]      2 bytes (UInt16)
                         * [OptionalTypeDescriptor] 2 bytes (UInt16)
                         * [Data]           [ChunkLength-Int32] bytes
                         *
                         * Chunks may contain value types or Chunks, it's a recursive structure.
                         * By reading if you've read all of the data bytes, you know you've read
                         * the whole structure.
                         */
                        // read in byte 0, the data settings
                        var dataReader   = reader;
                        var dataSettings = (SerializerDataSettings)reader.ReadByte();

                        // if it's a compressed data stream, decompress it first
                        if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compress))
                        {
                            dataReader = TypeReader.Decompress(dataReader);
                        }

                        // read in all chunks
                        isValid = ReadChunk(dataReader, typeDescriptors, dataSettings);
                    }
                }
            }
            catch (Exception)
            {
                isValid = false;
            }

            return(isValid);
        }
Exemple #3
0
        /// <summary>
        /// Read the parent object, and recursively process it's children
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="typeSupport">The type of the root object</param>
        /// <param name="maxDepth">The max depth tree to process</param>
        /// <param name="options">The serialization options</param>
        /// <param name="objectTree">Tracks the tree that has been traversed</param>
        /// <param name="ignoreAttributes">Properties/Fields with these attributes will be ignored from processing</param>
        /// <param name="typeRegistry">A registry that contains custom type mappings</param>
        /// <returns></returns>
        internal static object Read(BinaryReader reader, ExtendedType typeSupport, uint maxDepth, SerializerOptions options, ICollection <object> ignoreAttributes, SerializationTypeRegistry typeRegistry = null, ICollection <string> ignorePropertiesOrPaths = null)
        {
            var  currentDepth = 0;
            uint dataLength   = 0;
            uint headerLength = 0;

            var dataReader = reader;
            // read in byte 0, the data settings
            var dataSettings = (SerializerDataSettings)reader.ReadByte();

            if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compress))
            {
                // decompress the stream
                dataReader = Decompress(reader);
            }

            var typeReader = new TypeReader(dataSettings, options, maxDepth, ignoreAttributes, typeRegistry, ignorePropertiesOrPaths);

            return(typeReader.ReadObject(dataReader, typeSupport, currentDepth, string.Empty, ref dataLength, ref headerLength));
        }
Exemple #4
0
        /// <summary>
        /// Read a single chunk of data, recursively.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        private bool ReadChunk(BinaryReader reader, TypeDescriptors typeDescriptors, SerializerDataSettings dataSettings)
        {
            var isChunkValid        = true;
            var objectTypeIdByte    = reader.ReadByte();
            var objectTypeId        = (TypeId)objectTypeIdByte;
            var isTypeMapped        = TypeUtil.IsTypeMapped(objectTypeId);
            var isTypeDescriptorMap = TypeUtil.IsTypeDescriptorMap(objectTypeId);

            uint length = 0;

            if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compact))
            {
                length = reader.ReadUInt16();
            }
            else
            {
                length = reader.ReadUInt32();
            }
            var    lengthStartPosition = reader.BaseStream.Position;
            ushort objectReferenceId   = 0;
            ushort typeDescriptorId    = 0;


            if (isTypeDescriptorMap)
            {
                uint dataLength = 0;
                if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compact))
                {
                    dataLength = length - sizeof(ushort);
                }
                else
                {
                    dataLength = length - sizeof(uint);
                }
                // read in the type descriptor map
                var typeDescriptorMap = TypeReader.GetTypeDescriptorMap(reader, dataLength);
                // continue reading the data
                return(ReadChunk(reader, typeDescriptorMap, dataSettings));
            }
            else
            {
                // read the object reference id
                objectReferenceId = reader.ReadUInt16();
            }

            // only interfaces can store type descriptors
            if (typeDescriptors != null && isTypeMapped)
            {
                typeDescriptorId = reader.ReadUInt16();
                if (!typeDescriptors.Contains(typeDescriptorId))
                {
                    return(false);
                }
            }

            // value type
            if (length > 0)
            {
                switch (objectTypeId)
                {
                // these types may contain additional chunks, only value types may not.
                case TypeId.Array:
                case TypeId.Tuple:
                case TypeId.IDictionary:
                case TypeId.IEnumerable:
                case TypeId.Struct:
                case TypeId.Enum:
                case TypeId.KeyValuePair:
                case TypeId.Object:
                    isChunkValid = ReadChunk(reader, typeDescriptors, dataSettings);
                    if (!isChunkValid)
                    {
                        return(false);
                    }
                    break;

                default:
                    // it's not a chunk type, it's a value type
                    isChunkValid = true;
                    break;
                }

                if (reader.BaseStream.Position - lengthStartPosition - sizeof(ushort) == 0)
                {
                    // it's a value type, read the full data
                    byte[] data = null;
                    if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compact))
                    {
                        data = reader.ReadBytes((int)(length - Constants.CompactLengthHeaderSize));
                    }
                    else
                    {
                        data = reader.ReadBytes((int)(length - Constants.LengthHeaderSize));
                    }
                }
                else if (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    // read another chunk
                    isChunkValid = ReadChunk(reader, typeDescriptors, dataSettings);
                    if (!isChunkValid)
                    {
                        return(false);
                    }
                }
            }
            return(isChunkValid);
        }