fix: Fixes BitArray serialization (#2170)
Fixes serialization/deserialization edge cases with BitArray. If you use BitArray, you will need to migrate.
1. Change the type in the migration JSON file (if there is one) from `BitArray` to `byte[]` for all the versions you need to migrate.
2. Then in the `MigrateFrom`, use the following function to convert the field from a byte[] back to the BitArray.
Example Migration JSON:
```json
{
"name": "RestrictedSpells",
"type": "byte[]",
"rule": "ArrayMigrationRule",
"ruleArguments": [
"byte",
"PrimitiveTypeMigrationRule",
""
]
},
```
Migration function to use in MigrateFrom:
```cs
public static BitArray MigrateBitArray(byte[] data, int bitLength) => new(data) { Length = bitLength };
```
Example use:
```cs
private void MigrateFrom(V0Content content)
{
// ... deserialize
_restrictedSpells = content.RestrictedSpells.MigrateBitArray(SpellRegistry.Types.Length);
_restrictedSkills = content.RestrictedSkills.MigrateBitArray(SkillInfo.Table.Length);
// ... rest of deserialize
}
```
This commit is contained in:
parent
1eeeabb729
commit
5cb97cc6de
2 changed files with 27 additions and 14 deletions
|
|
@ -14,6 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
|
@ -51,7 +52,7 @@ public interface IGenericReader
|
|||
var delta => new DateTime(delta + DateTime.UtcNow.Ticks, DateTimeKind.Utc)
|
||||
};
|
||||
}
|
||||
decimal ReadDecimal() => new(stackalloc int[4] { ReadInt(), ReadInt(), ReadInt(), ReadInt() });
|
||||
decimal ReadDecimal() => new([ReadInt(), ReadInt(), ReadInt(), ReadInt()]);
|
||||
int ReadEncodedInt()
|
||||
{
|
||||
int v = 0, shift = 0;
|
||||
|
|
@ -119,14 +120,19 @@ public interface IGenericReader
|
|||
|
||||
public BitArray ReadBitArray()
|
||||
{
|
||||
var byteArrayLength = ReadEncodedInt();
|
||||
int bitLength = ReadEncodedInt();
|
||||
int byteLength = (bitLength + 7) / 8;
|
||||
|
||||
// We need an exact array size since the ctor doesn't allow for offset/length, not much we can do at this point.
|
||||
var byteArray = new byte[byteArrayLength];
|
||||
|
||||
Read(byteArray);
|
||||
|
||||
return new BitArray(byteArray);
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(byteLength);
|
||||
try
|
||||
{
|
||||
Read(buffer.AsSpan(0, byteLength));
|
||||
return new BitArray(buffer) { Length = bitLength };
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
TextDefinition ReadTextDefinition()
|
||||
|
|
|
|||
|
|
@ -163,14 +163,21 @@ public interface IGenericWriter
|
|||
|
||||
public void Write(BitArray bitArray)
|
||||
{
|
||||
var bytesLength = (bitArray.Length - 1 + (1 << 3)) >>> 3;
|
||||
var arrayBuffer = ArrayPool<byte>.Shared.Rent(bytesLength);
|
||||
int bitLength = bitArray.Length;
|
||||
int byteLength = (bitLength + 7) / 8;
|
||||
|
||||
WriteEncodedInt(bytesLength);
|
||||
bitArray.CopyTo(arrayBuffer, 0);
|
||||
WriteEncodedInt(bitLength);
|
||||
|
||||
Write(arrayBuffer.AsSpan(0, bytesLength));
|
||||
ArrayPool<byte>.Shared.Return(arrayBuffer);
|
||||
var arrayBuffer = ArrayPool<byte>.Shared.Rent(byteLength);
|
||||
try
|
||||
{
|
||||
bitArray.CopyTo(arrayBuffer, 0);
|
||||
Write(arrayBuffer.AsSpan(0, byteLength));
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(arrayBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Write(TextDefinition def)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue