Skip to content

Commit

Permalink
Change the base class of PrimitiveSerializers to SerializerWithString…
Browse files Browse the repository at this point in the history
…Manifest (akkadotnet#4989)

* Change the base class of PrimitiveSerializers to SerializerWithStringManifest

* Add backward compatibility to the wire format

* Update API Approver list
  • Loading branch information
Arkatufus authored Apr 29, 2021
1 parent 46d4707 commit 25246ac
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,11 @@ namespace Akka.Remote.Serialization
public override string Manifest(object obj) { }
public override byte[] ToBinary(object obj) { }
}
public sealed class PrimitiveSerializers : Akka.Serialization.Serializer
public sealed class PrimitiveSerializers : Akka.Serialization.SerializerWithStringManifest
{
public PrimitiveSerializers(Akka.Actor.ExtendedActorSystem system) { }
public override bool IncludeManifest { get; }
public override object FromBinary(byte[] bytes, System.Type type) { }
public override object FromBinary(byte[] bytes, string manifest) { }
public override string Manifest(object obj) { }
public override byte[] ToBinary(object obj) { }
}
public class ProtobufSerializer : Akka.Serialization.Serializer
Expand Down
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()}]");
}
}
}
}

0 comments on commit 25246ac

Please sign in to comment.