Skip to content

Commit 9b4ed1a

Browse files
humheiDanthar
authored andcommitted
Array2D && Array3D support (#109)
1 parent 735c49e commit 9b4ed1a

File tree

3 files changed

+205
-0
lines changed

3 files changed

+205
-0
lines changed

src/Hyperion.Tests/CollectionTests.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,59 @@ public void CanSerializeStack()
316316
Assert.Equal(expected.ToList(), actual.ToList());
317317
}
318318

319+
[Fact]
320+
public void CanSerializeArray2DOfInt()
321+
{
322+
var expected = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // OK
323+
Serialize(expected);
324+
Reset();
325+
var actual = Deserialize<int[,]>();
326+
for (int i = expected.GetLowerBound(0); i < expected.GetUpperBound(0); i++)
327+
{
328+
for (int j = expected.GetLowerBound(1); j < expected.GetUpperBound(1); j++)
329+
{
330+
Assert.Equal(expected[i, j], actual[i, j]);
331+
}
332+
}
333+
}
334+
335+
[Fact]
336+
public void CanSerializeArray2DOfObj()
337+
{
338+
var expected = new object[,] { { "Header1", 2 }, { "Header2", 4 }}; // OK
339+
Serialize(expected);
340+
Reset();
341+
var actual = Deserialize<object[,]>();
342+
for (int i = expected.GetLowerBound(0); i < expected.GetUpperBound(0); i++)
343+
{
344+
for (int j = expected.GetLowerBound(1); j < expected.GetUpperBound(1); j++)
345+
{
346+
Assert.Equal(expected[i, j], actual[i, j]);
347+
}
348+
}
349+
}
350+
351+
[Fact]
352+
public void CanSerializeArray3DOfInt()
353+
{
354+
int[,,] expected = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
355+
{ { 7, 8, 9 }, { 10, 11, 12 } } };
356+
Serialize(expected);
357+
Reset();
358+
var actual = Deserialize<int[,,]>();
359+
for (int i = expected.GetLowerBound(0); i < expected.GetUpperBound(0); i++)
360+
{
361+
for (int j = expected.GetLowerBound(1); j < expected.GetUpperBound(1); j++)
362+
{
363+
for (int m = expected.GetLowerBound(2); j < expected.GetUpperBound(2); j++)
364+
{
365+
Assert.Equal(expected[i, j, m], actual[i, j, m]);
366+
}
367+
}
368+
}
369+
}
370+
371+
319372
[Fact]
320373
public void Issue18()
321374
{
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#region copyright
2+
// -----------------------------------------------------------------------
3+
// <copyright file="ArraySerializerFactory.cs" company="Akka.NET Team">
4+
// Copyright (C) 2015-2016 AsynkronIT <https://github.com/AsynkronIT>
5+
// Copyright (C) 2016-2016 Akka.NET Team <https://github.com/akkadotnet>
6+
// </copyright>
7+
// -----------------------------------------------------------------------
8+
#endregion
9+
10+
using System;
11+
using System.Collections.Concurrent;
12+
using System.IO;
13+
using System.Linq;
14+
using System.Reflection;
15+
using Hyperion.Extensions;
16+
using Hyperion.ValueSerializers;
17+
18+
namespace Hyperion.SerializerFactories
19+
{
20+
/// we don't support 4 dimensional array now
21+
internal sealed class MultipleDimensionalArraySerialzierFactory : ValueSerializerFactory
22+
{
23+
public override bool CanSerialize(Serializer serializer, Type type) =>
24+
/// wo don't support 4 dimensional array now
25+
type.IsArray && type.GetArrayRank() > 1 && type.GetArrayRank() < 4;
26+
27+
public override bool CanDeserialize(Serializer serializer, Type type) => CanSerialize(serializer, type);
28+
29+
private static void WriteValues(Array array, Stream stream, Type elementType, ValueSerializer elementSerializer, SerializerSession session)
30+
{
31+
for (var i = 0; i < array.Rank; i ++ )
32+
{
33+
Int32Serializer.WriteValueImpl(stream, array.GetLength(i), session);
34+
}
35+
var preserveObjectReferences = session.Serializer.Options.PreserveObjectReferences;
36+
foreach (var value in array)
37+
{
38+
stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session);
39+
}
40+
}
41+
42+
43+
private static Array ReadValues2D(Stream stream, DeserializerSession session, Array array)
44+
{
45+
for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
46+
{
47+
for (var j = array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
48+
{
49+
var value = stream.ReadObject(session);
50+
array.SetValue(value, i, j);
51+
}
52+
}
53+
return array;
54+
}
55+
56+
private static Array ReadValues3D(Stream stream, DeserializerSession session, Array array)
57+
{
58+
for (var i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
59+
{
60+
for (var j = array.GetLowerBound(1); j <= array.GetUpperBound(1); j++)
61+
{
62+
for (var m = array.GetLowerBound(2); m <= array.GetUpperBound(2); m++)
63+
{
64+
var value = stream.ReadObject(session);
65+
array.SetValue(value, i, j, m);
66+
}
67+
68+
}
69+
}
70+
return array;
71+
}
72+
73+
74+
private static ObjectReader CreateReader(bool preserveObjectReferences,int arrayRank, Type elementType)
75+
{
76+
if (arrayRank == 2)
77+
{
78+
ObjectReader reader = (stream, session) =>
79+
{
80+
var length1 = stream.ReadInt32(session);
81+
var length2 = stream.ReadInt32(session);
82+
var array = Array.CreateInstance(elementType, length1, length2);
83+
if (preserveObjectReferences)
84+
{
85+
session.TrackDeserializedObject(array);
86+
}
87+
return ReadValues2D(stream, session, array);
88+
};
89+
return reader;
90+
}
91+
if (arrayRank == 3)
92+
{
93+
ObjectReader reader = (stream, session) =>
94+
{
95+
var length1 = stream.ReadInt32(session);
96+
var length2 = stream.ReadInt32(session);
97+
var length3 = stream.ReadInt32(session);
98+
var array = Array.CreateInstance(elementType, length1, length2, length3);
99+
if (preserveObjectReferences)
100+
{
101+
session.TrackDeserializedObject(array);
102+
}
103+
return ReadValues3D(stream, session, array);
104+
};
105+
return reader;
106+
}
107+
108+
else
109+
{
110+
throw new UnsupportedTypeException(elementType, "we don't support 4 dimensional array now");
111+
}
112+
}
113+
114+
115+
public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
116+
ConcurrentDictionary<Type, ValueSerializer> typeMapping)
117+
{
118+
var arraySerializer = new ObjectSerializer(type);
119+
120+
var elementType =
121+
type.GetTypeInfo()
122+
.GetMethods()
123+
.Where(methodInfo => methodInfo.Name == "Get")
124+
.Select(methodInfo => methodInfo.ReturnType)
125+
.FirstOrDefault();
126+
127+
var elementSerializer = serializer.GetSerializerByType(elementType);
128+
var preserveObjectReferences = serializer.Options.PreserveObjectReferences;
129+
130+
var arrayRank = type.GetArrayRank();
131+
132+
//TODO: code gen this part
133+
ObjectReader reader = CreateReader(preserveObjectReferences, arrayRank, elementType);
134+
135+
ObjectWriter writer = (stream, arr, session) =>
136+
{
137+
if (preserveObjectReferences)
138+
{
139+
session.TrackSerializedObject(arr);
140+
}
141+
142+
WriteValues((Array)arr, stream, elementType, elementSerializer, session);
143+
};
144+
arraySerializer.Initialize(reader, writer);
145+
typeMapping.TryAdd(type, arraySerializer);
146+
return arraySerializer;
147+
}
148+
149+
150+
}
151+
}

src/Hyperion/SerializerOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class SerializerOptions
3838
new DefaultDictionarySerializerFactory(),
3939
new DictionarySerializerFactory(),
4040
new ArraySerializerFactory(),
41+
new MultipleDimensionalArraySerialzierFactory(),
4142
#if SERIALIZATION
4243
new ISerializableSerializerFactory(), //TODO: this will mess up the indexes in the serializer payload
4344
#endif

0 commit comments

Comments
 (0)