Example #1
0
 public TypeReader(SerializerDataSettings dataSettings, SerializerOptions options, uint maxDepth, ICollection <object> ignoreAttributes, SerializationTypeRegistry typeRegistry, ICollection <string> ignorePropertiesOrPaths = null)
 {
     _dataSettings            = dataSettings;
     _options                 = options;
     _maxDepth                = maxDepth;
     _ignoreAttributes        = ignoreAttributes;
     _ignorePropertiesOrPaths = ignorePropertiesOrPaths;
     _typeRegistry            = ConvertToTypeRegistry(typeRegistry);
     _objectReferences        = new Dictionary <ushort, object>();
     _customSerializers       = new Dictionary <Type, Lazy <ICustomSerializer> >
     {
         { typeof(Point), new Lazy <ICustomSerializer>(() => new PointSerializer()) },
         { typeof(Enum), new Lazy <ICustomSerializer>(() => new EnumSerializer()) },
         { typeof(XDocument), new Lazy <ICustomSerializer>(() => new XDocumentSerializer()) },
     };
 }
Example #2
0
 public TypeWriter(uint maxDepth, SerializerDataSettings dataSettings, SerializerOptions options, ICollection <object> ignoreAttributes, TypeDescriptors typeDescriptors, ICollection <string> ignorePropertiesOrPaths = null)
 {
     _debugWriter             = new DebugReportWriter();
     _maxDepth                = maxDepth;
     _dataSettings            = dataSettings;
     _options                 = options;
     _ignoreAttributes        = ignoreAttributes;
     _ignorePropertiesOrPaths = ignorePropertiesOrPaths;
     _typeDescriptors         = typeDescriptors;
     _referenceTracker        = new ObjectReferenceTracker();
     _customSerializers       = new Dictionary <Type, Lazy <ICustomSerializer> >
     {
         { typeof(Point), new Lazy <ICustomSerializer>(() => new PointSerializer()) },
         { typeof(Enum), new Lazy <ICustomSerializer>(() => new EnumSerializer()) },
         { typeof(XDocument), new Lazy <ICustomSerializer>(() => new XDocumentSerializer()) },
     };
 }
Example #3
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);
        }