예제 #1
0
        public void Deserialize(byte[] buffer, ref int offset, ref TItem[] ar)
        {
            int length = SerializerBinary.ReadUInt32Bias(buffer, ref offset, 1);

            if (length == -1)
            {
                ar = null;
                return;
            }

            if (length > _maxCount)
            {
                throw new InvalidOperationException($"The data contains a '{typeof(TItem)}'-array of size '{length}', which exceeds the allowed limit of '{_maxCount}'");
            }

            if (ar == null || ar.Length != length)
            {
                ar = new TItem[length];
            }

            var f = _itemFormatter;             // Cache into local to prevent ram fetches

            for (int i = 0; i < length; i++)
            {
                f.Deserialize(buffer, ref offset, ref ar[i]);
            }
        }
예제 #2
0
        public void Deserialize(byte[] buffer, ref int offset, ref int[] ar)
        {
            int length = SerializerBinary.ReadUInt32Bias(buffer, ref offset, 1);

            if (length == -1)
            {
                ar = null;
                return;
            }

            if (length > _maxSize)
            {
                throw new InvalidOperationException($"The data contains a byte-array of size '{length}', which exceeds the allowed limit of '{_maxSize}'");
            }

            if (ar == null || ar.Length != length)
            {
                ar = new int[length];
            }

            int byteLen = length * 4;

            Buffer.BlockCopy(buffer, offset, ar, 0, byteLen);

            offset += byteLen;
        }
예제 #3
0
        public void Deserialize(byte[] buffer, ref int offset, ref Type value)
        {
            int mode = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            // Null
            if (mode == Null)
            {
                value = null;
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (mode >= 0)
            {
                var id = mode;
                value = typeCache.GetExistingObject <Type>(id);
                return;
            }


            bool isComposite = mode == NewComposite;

            if (isComposite)             // composite aka "closed generic"
            {
                // Read main type
                var compositeProxy = typeCache.CreateDeserializationProxy <Type>();

                Type baseType = value;
                Deserialize(buffer, ref offset, ref baseType);


                // Read count
                var    argCount    = SerializerBinary.ReadByte(buffer, ref offset);
                Type[] genericArgs = new Type[argCount];
                for (int i = 0; i < argCount; i++)
                {
                    var genericArgProxy = typeCache.CreateDeserializationProxy <Type>();

                    Deserialize(buffer, ref offset, ref genericArgProxy.Value);

                    genericArgs[i] = genericArgProxy.Value;
                }

                value = _typeBinder.GetTypeFromBaseAndAgruments(baseType.FullName, genericArgs);
                compositeProxy.Value = value;                 // make it available for future deserializations
            }
            else
            {
                var proxy = typeCache.CreateDeserializationProxy <Type>();

                string baseTypeName = SerializerBinary.ReadString(buffer, ref offset);
                value = _typeBinder.GetTypeFromBase(baseTypeName);

                proxy.Value = value;
            }
        }
예제 #4
0
        public void Deserialize(byte[] buffer, ref int offset, ref byte[] ar)
        {
            int length = SerializerBinary.ReadUInt32Bias(buffer, ref offset, 1);

            if (length == -1)
            {
                ar = null;
                return;
            }

            if (ar == null || ar.Length != length)
            {
                ar = new byte[length];
            }

            System.Array.Copy(buffer, offset, ar, 0, length);
        }
        public void Deserialize(byte[] buffer, ref int offset, ref ImmutableArray <TItem> value)
        {
            int length = SerializerBinary.ReadUInt32Bias(buffer, ref offset, 1);

            if (length == -1)
            {
                value = default;
                return;
            }
            var builder       = ImmutableArray.CreateBuilder <TItem>(length);
            var itemFormatter = _itemFormatter;             // Cache into local to prevent ram fetches

            for (int i = 0; i < length; i++)
            {
                TItem item = default;
                itemFormatter.Deserialize(buffer, ref offset, ref item);
                builder.Add(item);
            }
            value = builder.MoveToImmutable();
        }
예제 #6
0
        public void Deserialize(byte[] buffer, ref int offset, ref TItem[] ar)
        {
            int length = SerializerBinary.ReadUInt32Bias(buffer, ref offset, 1);

            if (length == -1)
            {
                ar = null;
                return;
            }

            if (ar == null || ar.Length != length)
            {
                ar = new TItem[length];
            }

            for (int i = 0; i < length; i++)
            {
                _itemFormatter.Deserialize(buffer, ref offset, ref ar[i]);
            }
        }
예제 #7
0
        public void Deserialize(byte[] buffer, ref int offset, ref TItem[] ar)
        {
            int length = SerializerBinary.ReadUInt32Bias(buffer, ref offset, 1);

            if (length == -1)
            {
                ar = null;
                return;
            }

            if (ar == null || ar.Length != length)
            {
                ar = new TItem[length];
            }

            var f = _itemFormatter;             // Cache into local to prevent ram fetches

            for (int i = 0; i < length; i++)
            {
                f.Deserialize(buffer, ref offset, ref ar[i]);
            }
        }
예제 #8
0
        public void Deserialize(byte[] buffer, ref int offset, ref Type value)
        {
            int mode = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            // Null
            if (mode == Null)
            {
                value = null;
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (mode >= 0)
            {
                var id = mode;
                value = typeCache.GetExistingObject <Type>(id);
                return;
            }


            bool isComposite = mode == NewGeneric;

            if (isComposite)             // composite aka "closed generic"
            {
                // Read base type first (example: Dictionary<T1, T2>)
                Type baseType = value;
                Deserialize(buffer, ref offset, ref baseType);


                // Read count (example: 2)
                var    argCount    = SerializerBinary.ReadByte(buffer, ref offset);
                Type[] genericArgs = new Type[argCount];

                // Read all inner type definitions (in our example: 'string' and 'object)
                for (int i = 0; i < argCount; i++)
                {
                    Deserialize(buffer, ref offset, ref genericArgs[i]);
                }


                // Read construct full composite (example: Dictionary<string, object>)
                var compositeProxy = typeCache.CreateDeserializationProxy <Type>();

                value = _typeBinder.GetTypeFromBaseAndAgruments(baseType.FullName, genericArgs);
                compositeProxy.Value = value;                 // make it available for future deserializations
            }
            else
            {
                var proxy = typeCache.CreateDeserializationProxy <Type>();

                string baseTypeName = SerializerBinary.ReadString(buffer, ref offset);
                value = _typeBinder.GetTypeFromBase(baseTypeName);

                proxy.Value = value;
            }

            // todo: what to do when the type is not written because it is the same already?
            // a) force writing the type when embedding version info
            // b) just write schema, assuming the type

            if (_serializer.Config.VersionTolerance == VersionTolerance.AutomaticEmbedded)
            {
                if (!CerasSerializer.FrameworkAssemblies.Contains(value.Assembly))
                {
                    _serializer.ReadSchemaForType(buffer, ref offset, value);
                }
            }
        }
예제 #9
0
        public void Deserialize(byte[] buffer, ref int offset, ref T value)
        {
            var objId = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            if (objId == Null)
            {
                // Null

                // Ok the data tells us that value should be null.
                // But maybe we're recycling an object and it still contains an instance.
                // Lets return it to the user
                if (value != null)
                {
                    _ceras.DiscardObjectMethod?.Invoke(value);
                }

                value = default;
                return;
            }

            if (objId == InlineType)
            {
                Type type = null;
                _typeFormatter.Deserialize(buffer, ref offset, ref type);
                value = (T)(object)type;                 // This is ugly, but there's no way to prevent it, right?
                return;
            }

            if (objId >= 0)
            {
                // Something we already know
                value = _ceras.InstanceData.ObjectCache.GetExistingObject <T>(objId);
                return;
            }

            if (objId == ExternalObject)
            {
                // External object, let the user resolve!
                int externalId = SerializerBinary.ReadInt32(buffer, ref offset);

                // Let the user resolve
                _ceras.Config.ExternalObjectResolver.Resolve(externalId, out value);
                return;
            }


            // New object, see Note#1
            Type specificType = null;

            if (objId == NewValue)
            {
                // == NewValue (EmbeddedType)
                _typeFormatter.Deserialize(buffer, ref offset, ref specificType);
            }
            else
            {
                // == NewValueSameType
                specificType = typeof(T);
            }


            var entry = GetOrCreateEntry(specificType);

            // At this point we know that the 'value' will not be 'null', so if 'value' (the variable) is null we need to create an instance
            if (!entry.IsValueType)             // still possible that we're dealing with a boxed value;
            {
                // Do we already have an object?
                if (value != null)
                {
                    // Yes, then maybe we can overwrite its values (works for objects and collections)
                    // But only if it's the right type!

                    if (value.GetType() != specificType)
                    {
                        // Discard the old value
                        _ceras.DiscardObjectMethod?.Invoke(value);

                        // Create instance of the right type
                        value = (T)entry.Constructor();
                    }
                    else
                    {
                        // Existing object is the right type
                    }
                }
                else
                {
                    // Instance is null, create one
                    value = (T)entry.Constructor();
                }
            }
            else
            {
                // Not a reference type. So it doesn't matter anyway.
            }


            if (!_allowReferences)
            {
                entry.CurrentDeserializeDispatcher(buffer, ref offset, ref value);
                return;
            }

            //
            // Deserialize the object
            // 1. First generate a proxy so we can do lookups
            var objectProxy = _ceras.InstanceData.ObjectCache.CreateDeserializationProxy <T>();

            // 2. Make sure that the deserializer can make use of an already existing object (if there is one)
            objectProxy.Value = value;

            // 3. Actually read the object
            entry.CurrentDeserializeDispatcher(buffer, ref offset, ref objectProxy.Value);

            // 4. Write back the actual value, which instantly resolves all references
            value = objectProxy.Value;
        }
예제 #10
0
        public void Deserialize(byte[] buffer, ref int offset, ref Type type)
        {
            int mode = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            // Null
            if (mode == Null)
            {
                type = null;
                return;
            }

            var typeCache = _serializer.InstanceData.TypeCache;

            // Existing
            if (mode >= 0)
            {
                var id = mode;
                type = typeCache.GetExistingObject(id);
                return;
            }


            bool isComposite = mode == NewGeneric;

            if (isComposite)             // composite aka "closed generic"
            {
                // Read base type first (example: Dictionary<T1, T2>)
                Type baseType = type;
                Deserialize(buffer, ref offset, ref baseType);


                // Read count (example: 2)
                var    argCount    = SerializerBinary.ReadByte(buffer, ref offset);
                Type[] genericArgs = new Type[argCount];

                // Read all inner type definitions (in our example: 'string' and 'object)
                for (int i = 0; i < argCount; i++)
                {
                    Deserialize(buffer, ref offset, ref genericArgs[i]);
                }


                // Read construct full composite (example: Dictionary<string, object>)
                var compositeProxy = typeCache.CreateDeserializationProxy();

                type = _typeBinder.GetTypeFromBaseAndAgruments(baseType.FullName, genericArgs);
                compositeProxy.Type = type;                 // make it available for future deserializations

                if (_isSealed)
                {
                    ThrowSealed(type, false);
                }
            }
            else
            {
                var proxy = typeCache.CreateDeserializationProxy();

                string baseTypeName = SerializerBinary.ReadString(buffer, ref offset);
                type = _typeBinder.GetTypeFromBase(baseTypeName);

                proxy.Type = type;

                if (_isSealed)
                {
                    ThrowSealed(type, false);
                }
            }
        }
예제 #11
0
        public void Deserialize(byte[] buffer, ref int offset, ref T value)
        {
            var objId = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            if (objId == Null)
            {
                // Null

                // Ok the data tells us that value should be null.
                // But maybe we're recycling an object and it still contains an instance.
                // Lets return it to the user
                if (value != null)
                {
                    _serializer.Config.DiscardObjectMethod?.Invoke(value);
                }

                value = default(T);
                return;
            }

            if (objId >= 0)
            {
                // Something we already know
                value = _serializer.InstanceData.ObjectCache.GetExistingObject <T>(objId);
                return;
            }

            if (objId == ExternalObject)
            {
                // External object, let the user resolve!
                int externalId = SerializerBinary.ReadInt32(buffer, ref offset);

                // Let the user resolve
                _serializer.Config.ExternalObjectResolver.Resolve(externalId, out value);
                return;
            }


            // New object, see Note#1
            Type specificType = null;

            if (objId == NewValue)
            {
                _typeFormatter.Deserialize(buffer, ref offset, ref specificType);
            }
            else             // if (objId == NewValueSameType) commented out, its the only possible remaining case
            {
                specificType = typeof(T);
            }

            // At this point we know that the 'value' will have value, so if 'value' (the variable) is null we need to create an instance
            // todo: investigate if there is a way to do this better,
            // todo: is the generic code optimized in the jit? is this check is never even done in the ASM?
            // todo: have the recent fixes made these checks obsolete? What if someone forces serialization of private fields in a type that cannot be directly instantiated?
            // todo: enforce all types to have a parameterless constructor
            if (value == null &&
                (typeof(T) != typeof(string) && typeof(T) != typeof(Type)))
            {
                var factory = _serializer.Config.ObjectFactoryMethod;
                if (factory != null)
                {
                    value = (T)_serializer.Config.ObjectFactoryMethod(specificType);
                }

                if (value == null)
                {
                    try
                    {
                        // todo: can we optimize this? The specific type might be different, we cannot use "CreateInstance<T>" or "new T()"
                        //		 so is there a way we can quickly instantiate a new object given just the type? (sure there are lots of ways but any FAST ones??)
                        value = (T)Activator.CreateInstance(specificType);
                    }
                    catch (MissingMethodException e)
                    {
                        throw new Exception($"Cannot create an instance of type '{specificType.FullName}'", e);
                    }
                }
            }


            var objectProxy = _serializer.InstanceData.ObjectCache.CreateDeserializationProxy <T>();

            // Make sure that the deserializer can make use of an already existing object (if there is one)
            objectProxy.Value = value;


            // Read the object
            GetSpecificDeserializerCall(specificType)(buffer, ref offset, ref objectProxy.Value);

            // Write back the actual value
            value = objectProxy.Value;
        }
예제 #12
0
        public void Deserialize(byte[] buffer, ref int offset, ref T value)
        {
            var objId = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            if (objId == Null)
            {
                // Null

                // Ok the data tells us that value should be null.
                // But maybe we're recycling an object and it still contains an instance.
                // Lets return it to the user
                if (value != null)
                {
                    _serializer.Config.DiscardObjectMethod?.Invoke(value);
                }

                value = default(T);
                return;
            }

            if (objId >= 0)
            {
                // Something we already know
                value = _serializer.InstanceData.ObjectCache.GetExistingObject <T>(objId);
                return;
            }

            if (objId == ExternalObject)
            {
                // External object, let the user resolve!
                int externalId = SerializerBinary.ReadInt32(buffer, ref offset);

                // Let the user resolve
                _serializer.Config.ExternalObjectResolver.Resolve(externalId, out value);
                return;
            }


            // New object, see Note#1
            Type specificType = null;

            if (objId == NewValue)
            {
                _typeFormatter.Deserialize(buffer, ref offset, ref specificType);
            }
            else             // if (objId == NewValueSameType) commented out, its the only possible remaining case
            {
                specificType = typeof(T);
            }

            // At this point we know that the 'value' will have value, so if 'value' (the variable) is null we need to create an instance
            // todo: investigate if there is a way to do this better,
            // todo: is the generic code optimized in the jit? is this check is never even done in the ASM?
            // todo: have the recent fixes made these checks obsolete? What if someone forces serialization of private fields in a type that cannot be directly instantiated?
            // todo: enforce all types to have a parameterless constructor
            bool isRefType      = !specificType.IsValueType;
            bool isStringOrType = typeof(T) == typeof(string) || typeof(T) == typeof(Type);


            if (value == null)
            {
                if (!isStringOrType &&             // we can't create instances of String or Type, they are special cases
                    isRefType)                     // only ref types have a ctor
                {
                    value = CreateInstance(specificType);
                }
            }
            else
            {
                // There is a value already, but is it the right type?
                // Maybe the field is 'ICollection<int>' and the data says we should have a List<int>, but there's already a LinkedList<int> present!
                // What we need to do is throw out the
                if (isRefType)
                {
                    if (value.GetType() != specificType)                     // todo: types using a SerializationCtor (in the future) are handled in a different ReferenceFormatter
                    {
                        // Discard the old value
                        _serializer.Config.DiscardObjectMethod?.Invoke(value);

                        // Create instance of the right type
                        value = CreateInstance(specificType);
                    }
                }
            }


            var objectProxy = _serializer.InstanceData.ObjectCache.CreateDeserializationProxy <T>();

            // Make sure that the deserializer can make use of an already existing object (if there is one)
            objectProxy.Value = value;


            // Read the object
            GetSpecificDeserializerDispatcher(specificType)(buffer, ref offset, ref objectProxy.Value);

            // Write back the actual value
            value = objectProxy.Value;
        }
예제 #13
0
        public void Deserialize(byte[] buffer, ref int offset, ref T value)
        {
            var objId = SerializerBinary.ReadUInt32Bias(buffer, ref offset, Bias);

            if (objId == Null)
            {
                // Null

                // Ok the data tells us that value should be null.
                // But maybe we're recycling an object and it still contains an instance.
                // Lets return it to the user
                if (value != null)
                {
                    _serializer.Config.DiscardObjectMethod?.Invoke(value);
                }

                value = default;
                return;
            }

            if (objId == InlineType)
            {
                Type type = null;
                _typeFormatter.Deserialize(buffer, ref offset, ref type);
                value = (T)(object)type;                 // This is ugly, but there's no way to prevent it, right?
                return;
            }

            if (objId >= 0)
            {
                // Something we already know
                value = _serializer.InstanceData.ObjectCache.GetExistingObject <T>(objId);
                return;
            }

            if (objId == ExternalObject)
            {
                // External object, let the user resolve!
                int externalId = SerializerBinary.ReadInt32(buffer, ref offset);

                // Let the user resolve
                _serializer.Config.ExternalObjectResolver.Resolve(externalId, out value);
                return;
            }


            // New object, see Note#1
            Type specificType = null;

            if (objId == NewValue)
            {
                _typeFormatter.Deserialize(buffer, ref offset, ref specificType);
            }
            else             // if (objId == NewValueSameType) commented out, its the only possible remaining case
            {
                specificType = typeof(T);
            }


            // At this point we know that the 'value' will not be 'null', so if 'value' (the variable) is null we need to create an instance
            bool isRefType = !specificType.IsValueType;

            if (isRefType)
            {
                // Do we already have an object?
                if (value != null)
                {
                    // Yes, then maybe we can overwrite its values (works for objects and collections)
                    // But only if it's the right type!

                    // todo: types using a SerializationCtor (in the future) are handled in a different ReferenceFormatter
                    //		 where we first read all members into local variables, then create the object (passing some of them into the constructor), and then writing the remaining as usual
                    if (value.GetType() != specificType)
                    {
                        // Discard the old value
                        _serializer.Config.DiscardObjectMethod?.Invoke(value);

                        // Create instance of the right type
                        value = CreateInstance(specificType);
                    }
                    else
                    {
                        // Existing object is the right type
                    }
                }
                else
                {
                    // Instance is null, create one
                    // Note: that we *could* check if the type is one of the types that we cannot instantiate (String, Type, MemberInfo, ...) and then
                    //       just not call CreateInstance, but the check itself would be expensive as well (HashSet look up?), so what's the point of complicating the code more?
                    //       CreateInstance will do a dictionary lookup for us and simply return null for those types.
                    value = CreateInstance(specificType);
                }
            }
            else
            {
                // Not a reference type. So it doesn't matter.
            }



            //
            // Deserialize the object
            // 1. First generate a proxy so we can do lookups
            var objectProxy = _serializer.InstanceData.ObjectCache.CreateDeserializationProxy <T>();

            // 2. Make sure that the deserializer can make use of an already existing object (if there is one)
            objectProxy.Value = value;

            // 3. Actually read the object
            GetSpecificDeserializerDispatcher(specificType)(buffer, ref offset, ref objectProxy.Value);

            // 4. Write back the actual value, which instantly resolves all references
            value = objectProxy.Value;
        }