Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the base class of PrimitiveSerializers to SerializerWithStringManifest #4989

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Akka.Configuration;
using Akka.Remote.Configuration;
using Akka.Remote.Serialization;
using Akka.Serialization;
using Akka.TestKit;
using FluentAssertions;
using Xunit;
Expand Down Expand Up @@ -57,16 +58,29 @@ public void Can_serialize_String(string value)

private T AssertAndReturn<T>(T message)
{
var serializer = Sys.Serialization.FindSerializerFor(message);
var serializer = (SerializerWithStringManifest)Sys.Serialization.FindSerializerFor(message);
serializer.Should().BeOfType<PrimitiveSerializers>();
var serializedBytes = serializer.ToBinary(message);
return (T)serializer.FromBinary(serializedBytes, typeof(T));
var manifest = serializer.Manifest(message);
return (T)serializer.FromBinary(serializedBytes, manifest);
}

private T AssertCrossPlatformAndReturn<T>(T message)
{
var serializer = (SerializerWithStringManifest)Sys.Serialization.FindSerializerFor(message);
serializer.Should().BeOfType<PrimitiveSerializers>();
var serializedBytes = serializer.ToBinary(message);
// GetType() will make sure that each namespace is compatible with the serializer
// as the test is run on each platform.
return (T)serializer.FromBinary(serializedBytes, message.GetType());
}

private void AssertEqual<T>(T message)
{
var deserialized = AssertAndReturn(message);
Assert.Equal(message, deserialized);
deserialized = AssertCrossPlatformAndReturn(message);
Assert.Equal(message, deserialized);
}
}
}
74 changes: 59 additions & 15 deletions src/core/Akka.Remote/Serialization/PrimitiveSerializers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,22 @@

namespace Akka.Remote.Serialization
{
public sealed class PrimitiveSerializers : Serializer
public sealed class PrimitiveSerializers : SerializerWithStringManifest
{
internal const string StringManifest = "S";
internal const string Int32Manifest = "I";
internal const string Int64Manifest = "L";

// .Net Core manifests
internal const string StringManifestNetCore = "System.String, System.Private.CoreLib";
internal const string Int32ManifestNetCore = "System.Int32, System.Private.CoreLib";
internal const string Int64ManifestNetCore = "System.Int64, System.Private.CoreLib";

// .Net Framework manifests
internal const string StringManifestNetFx = "System.String, mscorlib";
internal const string Int32ManifestNetFx = "System.Int32, mscorlib";
internal const string Int64ManifestNetFx = "System.Int64, mscorlib";

/// <summary>
/// Initializes a new instance of the <see cref="PrimitiveSerializers" /> class.
/// </summary>
Expand All @@ -23,28 +37,58 @@ public PrimitiveSerializers(ExtendedActorSystem system) : base(system)
{
}

/// <inheritdoc />
public override bool IncludeManifest { get; } = true;

/// <inheritdoc />
public override byte[] ToBinary(object obj)
{
var str = obj as string;
if (str != null) return Encoding.UTF8.GetBytes(str);
if (obj is int) return BitConverter.GetBytes((int)obj);
if (obj is long) return BitConverter.GetBytes((long)obj);

throw new ArgumentException($"Cannot serialize object of type [{obj.GetType().TypeQualifiedName()}]");
switch (obj)
{
case string s:
return Encoding.UTF8.GetBytes(s);
case int i:
return BitConverter.GetBytes(i);
case long l:
return BitConverter.GetBytes(l);
default:
throw new ArgumentException($"Cannot serialize object of type [{obj.GetType()}]");
}
}

/// <inheritdoc />
public override object FromBinary(byte[] bytes, Type type)
public override object FromBinary(byte[] bytes, string manifest)
{
if (type == typeof(string)) return Encoding.UTF8.GetString(bytes);
if (type == typeof(int)) return BitConverter.ToInt32(bytes, 0);
if (type == typeof(long)) return BitConverter.ToInt64(bytes, 0);
switch (manifest)
{
case StringManifest:
case StringManifestNetCore:
case StringManifestNetFx:
return Encoding.UTF8.GetString(bytes);
case Int32Manifest:
case Int32ManifestNetCore:
case Int32ManifestNetFx:
return BitConverter.ToInt32(bytes, 0);
case Int64Manifest:
case Int64ManifestNetCore:
case Int64ManifestNetFx:
return BitConverter.ToInt64(bytes, 0);
default:
throw new ArgumentException($"Unimplemented deserialization of message with manifest [{manifest}] in [${GetType()}]");
}
}

throw new ArgumentException($"Unimplemented deserialization of message with manifest [{type.TypeQualifiedName()}] in [${nameof(PrimitiveSerializers)}]");
/// <inheritdoc />
public override string Manifest(object obj)
{
switch (obj)
{
case string _:
return StringManifest;
case int _:
return Int32Manifest;
case long _:
return Int64Manifest;
default:
throw new ArgumentException($"Cannot serialize object of type [{obj.GetType()}] in [{GetType()}]");
}
}
}
}