public void Serialize(ref byte[] buffer, ref int offset, T value) { if (EqualityComparer <T> .Default.Equals(value, default)) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias); return; } if (value is Type type) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, InlineType, Bias); _typeFormatter.Serialize(ref buffer, ref offset, type); return; } if (value is IExternalRootObject externalObj) { if (!object.ReferenceEquals(_serializer.InstanceData.CurrentRoot, value)) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, ExternalObject, Bias); var refId = externalObj.GetReferenceId(); SerializerBinary.WriteInt32(ref buffer, ref offset, refId); _serializer.Config.OnExternalObject?.Invoke(externalObj); return; } } if (_serializer.InstanceData.ObjectCache.TryGetExistingObjectId(value, out int id)) { // Existing value SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias); } else { // Important: Insert the ID for this value into our dictionary BEFORE calling SerializeFirstTime, as that might recursively call us again (maybe with the same value!) _serializer.InstanceData.ObjectCache.RegisterObject(value); var specificType = value.GetType(); if (typeof(T) == specificType) { // New value (same type) SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValueSameType, Bias); } else { // New value (type included) SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValue, Bias); _typeFormatter.Serialize(ref buffer, ref offset, specificType); } // Write the object normally GetSpecificSerializerDispatcher(specificType)(ref buffer, ref offset, value); } }
public void Serialize(ref byte[] buffer, ref int offset, TItem[] ar) { if (ar == null) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, -1, 1); return; } SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, ar.Length, 1); var f = _itemFormatter; // Cache into local to prevent ram fetches for (int i = 0; i < ar.Length; i++) f.Serialize(ref buffer, ref offset, ar[i]); }
public void Serialize(ref byte[] buffer, ref int offset, ImmutableArray <TItem> value) { if (value.IsDefault) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, -1, 1); return; } SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, value.Length, 1); var itemFormatter = _itemFormatter; // Cache into local to prevent ram fetches for (int i = 0; i < value.Length; i++) { itemFormatter.Serialize(ref buffer, ref offset, value[i]); } }
public void Serialize(ref byte[] buffer, ref int offset, TItem[] ar) { if (ar == null) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, -1, 1); return; } SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, ar.Length, 1); for (int i = 0; i < ar.Length; i++) { _itemFormatter.Serialize(ref buffer, ref offset, ar[i]); } }
public void Serialize(ref byte[] buffer, ref int offset, byte[] ar) { if (ar == null) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, -1, 1); return; } var len = ar.Length; // Ensure we have enough space for the worst-case VarInt plus the byte array itself SerializerBinary.EnsureCapacity(ref buffer, offset, 5 + len); // Write the length, no need to check the capacity (we did that here) SerializerBinary.WriteUInt32BiasNoCheck(ref buffer, ref offset, len, 1); // Blit the array System.Array.Copy(ar, 0, buffer, offset, len); offset += len; }
public void Serialize(ref byte[] buffer, ref int offset, Type type) { // Null if (type == null) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias); return; } var typeCache = _serializer.InstanceData.TypeCache; // Existing if (typeCache.TryGetExistingObjectId(type, out int id)) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias); return; } // Mode: New // Is it a composite type that we have to split into its parts? (aka any generic) bool isClosed = !type.ContainsGenericParameters; if (isClosed && type.IsGenericType) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewGeneric, Bias); // Split and write // Base var baseType = type.GetGenericTypeDefinition(); Serialize(ref buffer, ref offset, baseType); // Args var genericArgs = type.GetGenericArguments(); SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(genericArgs.Length)); // We need count. Ex: Action<T1> and Action<T1, T2> share the name for (int i = 0; i < genericArgs.Length; i++) { Serialize(ref buffer, ref offset, genericArgs[i]); } // Register composite type typeCache.RegisterObject(type); } else { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewSingle, Bias); // Open generic, something that can be serialized alone var typeName = _typeBinder.GetBaseName(type); // Name SerializerBinary.WriteString(ref buffer, ref offset, typeName); // Register single type typeCache.RegisterObject(type); } // todo: do we put this only in the if or else part? or is it ok here? it should be ok, since we want to embed the schema of every type if (_serializer.Config.VersionTolerance == VersionTolerance.AutomaticEmbedded) { if (!CerasSerializer.FrameworkAssemblies.Contains(type.Assembly)) { _serializer.WriteSchemaForType(ref buffer, ref offset, type); } } }
public void Serialize(ref byte[] buffer, ref int offset, T value) { if (ReferenceEquals(value, null)) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias); return; } var specificType = value.GetType(); var entry = GetOrCreateEntry(specificType); if (entry.IsType) // This is very rare, so we cache the check itself, and do the cast below { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, InlineType, Bias); _typeFormatter.Serialize(ref buffer, ref offset, (Type)(object)value); return; } if (entry.IsExternalRootObject) { var externalObj = (IExternalRootObject)value; if (!ReferenceEquals(_ceras.InstanceData.CurrentRoot, value)) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, ExternalObject, Bias); var refId = externalObj.GetReferenceId(); SerializerBinary.WriteInt32(ref buffer, ref offset, refId); _ceras.Config.OnExternalObject?.Invoke(externalObj); return; } } if (_allowReferences) { if (_ceras.InstanceData.ObjectCache.TryGetExistingObjectId(value, out int id)) { // Existing value SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias); } else { // Register new object _ceras.InstanceData.ObjectCache.RegisterObject(value); // Embedd type (if needed) if (ReferenceEquals(typeof(T), specificType)) { // New value (same type) SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValueSameType, Bias); } else { // New value (type included) SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValue, Bias); _typeFormatter.Serialize(ref buffer, ref offset, specificType); } // Write object entry.CurrentSerializeDispatcher(ref buffer, ref offset, value); } } else { // Embedd type (if needed) if (ReferenceEquals(typeof(T), specificType)) { // New value (same type) SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValueSameType, Bias); } else { // New value (type included) SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewValue, Bias); _typeFormatter.Serialize(ref buffer, ref offset, specificType); } // Write object entry.CurrentSerializeDispatcher(ref buffer, ref offset, value); } }
public void Serialize(ref byte[] buffer, ref int offset, Type type) { // Null if (type == null) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, Null, Bias); return; } var typeCache = _serializer.InstanceData.TypeCache; // Existing if (typeCache.TryGetExistingObjectId(type, out int id)) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, id, Bias); return; } // Mode: New // Is it a composite type that we have to split into its parts? (aka any generic) bool isClosed = !type.ContainsGenericParameters; if (isClosed && type.IsGenericType) { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewComposite, Bias); // Split and write // Base var baseType = type.GetGenericTypeDefinition(); Serialize(ref buffer, ref offset, baseType); // Args var genericArgs = type.GetGenericArguments(); SerializerBinary.WriteByte(ref buffer, ref offset, (byte)(genericArgs.Length)); // We need count. Ex: Action<T1> and Action<T1, T2> share the name. for (int i = 0; i < genericArgs.Length; i++) { Serialize(ref buffer, ref offset, genericArgs[i]); } // Register composite type typeCache.RegisterObject(type); } else { SerializerBinary.WriteUInt32Bias(ref buffer, ref offset, NewSingle, Bias); // Open generic, something that can be serialized alone var typeName = _typeBinder.GetBaseName(type); // Name SerializerBinary.WriteString(ref buffer, ref offset, typeName); // Register single type typeCache.RegisterObject(type); } }