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]); } }
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; }
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; } }
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(); }
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]); } }
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]); } }
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); } } }
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; }
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); } } }
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; }
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; }
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; }