diff --git a/src/Hyperion.Tests/CollectionTests.cs b/src/Hyperion.Tests/CollectionTests.cs index caf0b0c6..306028e0 100644 --- a/src/Hyperion.Tests/CollectionTests.cs +++ b/src/Hyperion.Tests/CollectionTests.cs @@ -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[] expected) + { + Serialize(expected); + Reset(); + var res = Deserialize(); + Assert.Equal(expected, res); + AssertMemoryStreamConsumed(); + } + } } \ No newline at end of file diff --git a/src/Hyperion/SerializerFactories/ArraySerializerFactory.cs b/src/Hyperion/SerializerFactories/ArraySerializerFactory.cs index 797d635b..8abef018 100644 --- a/src/Hyperion/SerializerFactories/ArraySerializerFactory.cs +++ b/src/Hyperion/SerializerFactories/ArraySerializerFactory.cs @@ -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; @@ -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[] 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; @@ -30,12 +32,13 @@ private static void WriteValues(T[] array, Stream stream, Type elementType, V stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session); } } - private static void ReadValues(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); } } @@ -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; }; @@ -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().ToArray(), stream, elementType, elementSerializer, session); }; arraySerializer.Initialize(reader, writer);