Skip to content

Commit

Permalink
Fix array of user defined structs serialization failure (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkatufus authored Jul 8, 2021
1 parent 6f23f0a commit 97baf14
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 7 deletions.
84 changes: 83 additions & 1 deletion src/Hyperion.Tests/CollectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -616,5 +616,87 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
return os;
}
}
}

[Fact]
public void CanSerializeNullableIntArray()
{
SerializeAndAssert(new int?[]{1, 2, 3, 4, 5});
}

[Fact]
public void CanSerializeLongArray()
{
SerializeAndAssert(new []{1L, 2L, 3L, 4L, 5L});
}

[Fact]
public void CanSerializeNullableLongArray()
{
SerializeAndAssert(new long?[]{1L, 2L, 3L, 4L, 5L});
}

[Fact]
public void CanSerializeShortArray()
{
SerializeAndAssert(new short[]{1, 2, 3, 4, 5});
}

[Fact]
public void CanSerializeNullableShortArray()
{
SerializeAndAssert(new short?[]{1, 2, 3, 4, 5});
}

[Fact]
public void CanSerializeStringArray()
{
SerializeAndAssert(new []{"1", "2", "3", "4", "5"});
}

[Fact]
public void CanSerializeDateTimeOffsetArray()
{
SerializeAndAssert(new []
{
DateTimeOffset.Now,
DateTimeOffset.UtcNow,
});
}

[Fact]
public void CanSerializeStructArray()
{
SerializeAndAssert(new IStructInterface[]
{
new PrimitiveStruct {Int = 1, Long = 1, String = "1"},
new PrimitiveStruct {Int = 2, Long = 2, String = "2"},
new PrimitiveStruct {Int = 3, Long = 3, String = "3"},
new PrimitiveStruct {Int = 4, Long = 4, String = "4"},
new PrimitiveStruct {Int = 5, Long = 5, String = "5"},
});
}

private interface IStructInterface
{
int Int { get; set; }
long Long { get; set; }
string String { get; set; }
}

private struct PrimitiveStruct : IStructInterface
{
public int Int { get; set; }
public long Long { get; set; }
public string String { get; set; }
}

private void SerializeAndAssert<T>(T[] expected)
{
Serialize(expected);
Reset();
var res = Deserialize<T[]>();
Assert.Equal(expected, res);
AssertMemoryStreamConsumed();
}
}
}
16 changes: 10 additions & 6 deletions src/Hyperion/SerializerFactories/ArraySerializerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#endregion

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using Hyperion.Extensions;
using Hyperion.ValueSerializers;

Expand All @@ -21,7 +23,7 @@ internal sealed class ArraySerializerFactory : ValueSerializerFactory

public override bool CanDeserialize(Serializer serializer, Type type) => CanSerialize(serializer, type);

private static void WriteValues<T>(T[] array, Stream stream, Type elementType, ValueSerializer elementSerializer, SerializerSession session)
private static void WriteValues(Array array, Stream stream, Type elementType, ValueSerializer elementSerializer, SerializerSession session)
{
Int32Serializer.WriteValueImpl(stream, array.Length, session);
var preserveObjectReferences = session.Serializer.Options.PreserveObjectReferences;
Expand All @@ -30,12 +32,13 @@ private static void WriteValues<T>(T[] array, Stream stream, Type elementType, V
stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session);
}
}
private static void ReadValues<T>(int length, Stream stream, DeserializerSession session, T[] array)

private static void ReadValues(int length, Stream stream, DeserializerSession session, Array array)
{
for (var i = 0; i < length; i++)
{
var value = (T)stream.ReadObject(session);
array[i] = value;
var value = stream.ReadObject(session);
array.SetValue(value, i);
}
}

Expand All @@ -57,7 +60,7 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
session.TrackDeserializedObject(array);
}

ReadValues(length, stream, session, (dynamic)array);
ReadValues(length, stream, session, array);

return array;
};
Expand All @@ -68,7 +71,8 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
session.TrackSerializedObject(arr);
}

WriteValues((dynamic)arr, stream, elementType, elementSerializer, session);
// This janky way of converting array to Array is done to get around the problem of ValueType arrays
WriteValues(((IEnumerable)arr).Cast<object>().ToArray(), stream, elementType, elementSerializer, session);
};
arraySerializer.Initialize(reader, writer);

Expand Down

0 comments on commit 97baf14

Please sign in to comment.