diff --git a/Robust.Shared/Serialization/NetBitArraySerializer.cs b/Robust.Shared/Serialization/NetBitArraySerializer.cs new file mode 100644 index 000000000..223be3eeb --- /dev/null +++ b/Robust.Shared/Serialization/NetBitArraySerializer.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization; +using JetBrains.Annotations; +using NetSerializer; + +namespace Robust.Shared.Serialization; + +/// +/// Custom serializer implementation for . +/// +/// +/// +/// This type is necessary as, since .NET 10, the internal layout of was changed. +/// The type now (internally) implements for backwards compatibility with existing +/// BinaryFormatter code, but NetSerializer does not support . +/// +/// +/// This code is designed to be backportable & network compatible with the previous behavior on .NET 9. +/// +/// +internal sealed class NetBitArraySerializer : IStaticTypeSerializer +{ + // For reference, the layout of BitArray before .NET 10 was: + // private int[] m_array; + // private int m_length; + // private int _version; + // NetSerializer serialized these in the following order (sorted by name): + // _version, m_array, m_length + + public bool Handles(Type type) + { + return type == typeof(BitArray); + } + + public IEnumerable GetSubtypes(Type type) + { + return [typeof(int[]), typeof(int)]; + } + + public MethodInfo GetStaticWriter(Type type) + { + return typeof(NetBitArraySerializer).GetMethod("Write", BindingFlags.Static | BindingFlags.NonPublic)!; + } + + public MethodInfo GetStaticReader(Type type) + { + return typeof(NetBitArraySerializer).GetMethod("Read", BindingFlags.Static | BindingFlags.NonPublic)!; + } + + [UsedImplicitly] + private static void Write(Serializer serializer, Stream stream, BitArray value) + { + var intCount = (31 + value.Length) >> 5; + var ints = new int[intCount]; + value.CopyTo(ints, 0); + + serializer.SerializeDirect(stream, 0); // _version + serializer.SerializeDirect(stream, ints); // m_array + serializer.SerializeDirect(stream, value.Length); // m_length + } + + [UsedImplicitly] + private static void Read(Serializer serializer, Stream stream, out BitArray value) + { + serializer.DeserializeDirect(stream, out _); // _version + serializer.DeserializeDirect(stream, out var array); // m_array + serializer.DeserializeDirect(stream, out var length); // m_length + + value = new BitArray(array) + { + Length = length + }; + } +} diff --git a/Robust.Shared/Serialization/RobustSerializer.cs b/Robust.Shared/Serialization/RobustSerializer.cs index 860a9fb38..9a4793edb 100644 --- a/Robust.Shared/Serialization/RobustSerializer.cs +++ b/Robust.Shared/Serialization/RobustSerializer.cs @@ -91,6 +91,7 @@ namespace Robust.Shared.Serialization MappedStringSerializer.TypeSerializer, new Vector2Serializer(), new Matrix3x2Serializer(), + new NetBitArraySerializer() } }; _serializer = new Serializer(types, settings);