mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Fix NetBitArraySerializer compatibility.
Apparently NetSerializer treats IDynamicTypeSerializer and IStaticTypeSerializer differently for sealed types??
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
using NetSerializer;
|
||||
@@ -22,8 +23,11 @@ namespace Robust.Shared.Serialization;
|
||||
/// This code is designed to be backportable & network compatible with the previous behavior on .NET 9.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal sealed class NetBitArraySerializer : IStaticTypeSerializer
|
||||
internal sealed class NetBitArraySerializer : IDynamicTypeSerializer
|
||||
{
|
||||
// NOTE: MUST be a IDynamicTypeSerializer for compatibility!
|
||||
// Can be changed in the future.
|
||||
|
||||
// For reference, the layout of BitArray before .NET 10 was:
|
||||
// private int[] m_array;
|
||||
// private int m_length;
|
||||
@@ -41,14 +45,32 @@ internal sealed class NetBitArraySerializer : IStaticTypeSerializer
|
||||
return [typeof(int[]), typeof(int)];
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticWriter(Type type)
|
||||
public void GenerateWriterMethod(Serializer serializer, Type type, ILGenerator il)
|
||||
{
|
||||
return typeof(NetBitArraySerializer).GetMethod("Write", BindingFlags.Static | BindingFlags.NonPublic)!;
|
||||
var method = typeof(NetBitArraySerializer).GetMethod("Write", BindingFlags.Static | BindingFlags.NonPublic)!;
|
||||
|
||||
// arg0: Serializer, arg1: Stream, arg2: value
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
|
||||
il.EmitCall(OpCodes.Call, method, null);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
public MethodInfo GetStaticReader(Type type)
|
||||
public void GenerateReaderMethod(Serializer serializer, Type type, ILGenerator il)
|
||||
{
|
||||
return typeof(NetBitArraySerializer).GetMethod("Read", BindingFlags.Static | BindingFlags.NonPublic)!;
|
||||
var method = typeof(NetBitArraySerializer).GetMethod("Read", BindingFlags.Static | BindingFlags.NonPublic)!;
|
||||
|
||||
// arg0: Serializer, arg1: stream, arg2: out value
|
||||
il.Emit(OpCodes.Ldarg_0);
|
||||
il.Emit(OpCodes.Ldarg_1);
|
||||
il.Emit(OpCodes.Ldarg_2);
|
||||
|
||||
il.EmitCall(OpCodes.Call, method, null);
|
||||
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using NetSerializer;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Serialization;
|
||||
|
||||
[Parallelizable(ParallelScope.All)]
|
||||
[TestFixture, TestOf(typeof(NetBitArraySerializer))]
|
||||
internal sealed class NetSerializerBitArrayTest
|
||||
{
|
||||
// Test that BitArray serialization matches the behavior before .NET 10
|
||||
// This test can be removed in future RT versions.
|
||||
|
||||
[Test]
|
||||
[TestCase("little creature, have you ever heard about gay people?",
|
||||
"AgAP2KWjxw7YlYOyDOSVi8YO6smrxgXAoIvmDsqByfcN6oGp5g7KyYOCDcqFk8cMwIST9g3q0YPyDMLlg4IOyr2Dxw3K/QHgBg==")]
|
||||
[TestCase("", "AgABAA==")]
|
||||
public void Test(string testData, string expected)
|
||||
{
|
||||
var bitData = Encoding.UTF8.GetBytes(testData);
|
||||
var bitArray = new BitArray(bitData);
|
||||
|
||||
var serializer = new Serializer([typeof(BitArray)],
|
||||
new Settings
|
||||
{
|
||||
CustomTypeSerializers = [new NetBitArraySerializer()]
|
||||
});
|
||||
|
||||
var stream = new MemoryStream();
|
||||
serializer.Serialize(stream, bitArray);
|
||||
|
||||
var base64 = Convert.ToBase64String(stream.ToArray());
|
||||
|
||||
TestContext.Out.WriteLine(base64);
|
||||
|
||||
Assert.That(base64, Is.EqualTo(expected));
|
||||
|
||||
stream.Position = 0;
|
||||
var newBitArray = (BitArray)serializer.Deserialize(stream);
|
||||
|
||||
Assert.That(newBitArray, Is.EquivalentTo(bitArray));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Unset()
|
||||
{
|
||||
var bitArray = new BitArray(16);
|
||||
|
||||
var serializer = new Serializer([typeof(BitArray)],
|
||||
new Settings
|
||||
{
|
||||
CustomTypeSerializers = [new NetBitArraySerializer()]
|
||||
});
|
||||
|
||||
var stream = new MemoryStream();
|
||||
serializer.Serialize(stream, bitArray);
|
||||
|
||||
var base64 = Convert.ToBase64String(stream.ToArray());
|
||||
|
||||
TestContext.Out.WriteLine(base64);
|
||||
|
||||
Assert.That(base64, Is.EqualTo("AgACACA="));
|
||||
|
||||
stream.Position = 0;
|
||||
var newBitArray = (BitArray)serializer.Deserialize(stream);
|
||||
|
||||
Assert.That(newBitArray, Is.EquivalentTo(bitArray));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClass()
|
||||
{
|
||||
var obj = new FooBar
|
||||
{
|
||||
Real = 0x3005,
|
||||
Heck = "omg",
|
||||
Wawa = new BitArray("I miss my wife"u8.ToArray())
|
||||
};
|
||||
|
||||
var serializer = new Serializer([typeof(BitArray), typeof(FooBar)],
|
||||
new Settings
|
||||
{
|
||||
CustomTypeSerializers = [new NetBitArraySerializer()]
|
||||
});
|
||||
|
||||
var stream = new MemoryStream();
|
||||
serializer.Serialize(stream, obj);
|
||||
|
||||
var base64 = Convert.ToBase64String(stream.ToArray());
|
||||
|
||||
TestContext.Out.WriteLine(base64);
|
||||
|
||||
Assert.That(base64, Is.EqualTo("AgQDb21nisABAwAFkoHplg3mzYPSDfKBuZcNzJUD4AE="));
|
||||
|
||||
stream.Position = 0;
|
||||
var newObject = (FooBar)serializer.Deserialize(stream);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(newObject.Real, Is.EqualTo(obj.Real));
|
||||
Assert.That(newObject.Heck, Is.EqualTo(obj.Heck));
|
||||
Assert.That(newObject.Wawa, Is.EquivalentTo(obj.Wawa));
|
||||
});
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class FooBar
|
||||
{
|
||||
public required int Real;
|
||||
public required string Heck;
|
||||
public required BitArray Wawa;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using NetSerializer;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -247,37 +245,5 @@ namespace Robust.UnitTesting.Shared.Serialization
|
||||
|
||||
Assert.That(read, NUnit.Framework.Is.EquivalentTo(x));
|
||||
}
|
||||
|
||||
[Test, TestOf(typeof(NetBitArraySerializer))]
|
||||
public void TestBitArray()
|
||||
{
|
||||
// Test that BitArray serialization matches the behavior before .NET 10
|
||||
// This test can be removed in future RT versions.
|
||||
|
||||
var bitData = "little creature, have you ever heard about gay people?"u8.ToArray();
|
||||
var bitArray = new BitArray(bitData);
|
||||
|
||||
var serializer = new Serializer([typeof(BitArray)],
|
||||
new Settings
|
||||
{
|
||||
CustomTypeSerializers = [new NetBitArraySerializer()]
|
||||
});
|
||||
|
||||
var stream = new MemoryStream();
|
||||
serializer.Serialize(stream, bitArray);
|
||||
|
||||
var base64 = Convert.ToBase64String(stream.ToArray());
|
||||
|
||||
TestContext.Out.WriteLine(base64);
|
||||
|
||||
Assert.That(base64,
|
||||
Is.EqualTo(
|
||||
"AgAP2KWjxw7YlYOyDOSVi8YO6smrxgXAoIvmDsqByfcN6oGp5g7KyYOCDcqFk8cMwIST9g3q0YPyDMLlg4IOyr2Dxw3K/QHgBg=="));
|
||||
|
||||
stream.Position = 0;
|
||||
var newBitArray = (BitArray)serializer.Deserialize(stream);
|
||||
|
||||
Assert.That(newBitArray, Is.EquivalentTo(bitArray));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user