├── logo.png
├── global.json
├── .github
├── dependabot.yaml
└── workflows
│ ├── pr_validation.yaml
│ └── publish_nuget.yml
├── Akka.Serialization.MessagePack
├── Internal
│ ├── TypeDict.cs
│ ├── TypeDictCtr.cs
│ └── IntIndexedMessagePackFormatterDict.cs
├── Resolvers
│ ├── SurrogateResolvable.cs
│ ├── SerializableResolver.cs
│ ├── BackwardsCompatibleSurrogatedFormatterResolver.cs
│ ├── ExceptionAsSerializableResolver.cs
│ ├── SurrogatedFormatterResolver.cs
│ └── PolymorphicFormatterResolver.cs
├── Akka.Serialization.MessagePack.csproj
├── Sample.hocon
├── Formatters
│ ├── PolymorphicFormatter.cs
│ ├── SerializableFormatter.cs
│ ├── SurrogatedFormatter.cs
│ └── BackwardsCompatibleSurrogatedFormatter.cs
├── MessagePackTypeFilteringOptions.cs
├── MsgPackSerializerSettings.cs
└── MsgPackSerializer.cs
├── Akka.Serialization.Testkit
├── Akka.Serialization.Testkit.csproj
├── Util
│ └── ConfigFactory.cs
├── AkkaMessagesTests.cs
├── IncapsulationTests.cs
├── CustomMessagesTests.cs
├── CollectionsTests.cs
├── PrimitiveSerializerTests.cs
├── ExceptionsTests.cs
├── PolymorphismTests.cs
└── ImmutableMessagesTests.cs
├── NuGet.Config
├── Akka.Serialization.MessagePack.Benchmarks
├── Akka.Serialization.MessagePack.Benchmarks.csproj
├── Program.cs
└── SerializationBenchmarks.cs
├── Akka.Serialization.MessagePack.Tests
├── Akka.Serialization.MessagePack.Tests.csproj
├── MsgPackSerializersTests.cs
└── MsgPackVersionToleranceTests.cs
├── scripts
├── bumpVersion.ps1
└── getReleaseNotes.ps1
├── Directory.Packages.props
├── Directory.Build.props
├── RELEASE_NOTES.md
├── Akka.Serialization.MessagePack.sln
├── README.md
├── .gitignore
└── LICENSE
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akkadotnet/Akka.Serialization.MessagePack/HEAD/logo.png
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "rollForward": "latestMinor",
4 | "version": "8.0.100"
5 | }
6 | }
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | updates:
4 | - package-ecosystem: github-actions
5 | directory: "/"
6 | schedule:
7 | interval: daily
8 | time: "11:00"
9 |
10 | - package-ecosystem: nuget
11 | directory: "/"
12 | schedule:
13 | interval: daily
14 | time: "11:00"
15 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Internal/TypeDict.cs:
--------------------------------------------------------------------------------
1 | namespace Akka.Serialization.MessagePack.Resolvers;
2 |
3 | ///
4 | /// Used to provide indexes into a fast array lookup for resolvers.
5 | ///
6 | internal static class TypeDict
7 | {
8 | public static readonly int TypeVal = TypeDictCtr.doNotCallExternally();
9 | }
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Internal/TypeDictCtr.cs:
--------------------------------------------------------------------------------
1 | namespace Akka.Serialization.MessagePack.Resolvers;
2 |
3 | ///
4 | /// Used as a Counter for calls.
5 | ///
6 | internal static class TypeDictCtr
7 | {
8 | private static int _typeCtr = -1;
9 |
10 | internal static int doNotCallExternally()
11 | {
12 | return Interlocked.Increment(ref _typeCtr);
13 | }
14 | }
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Resolvers/SurrogateResolvable.cs:
--------------------------------------------------------------------------------
1 | using Akka.Util;
2 |
3 | namespace Akka.Serialization.MessagePack.Resolvers
4 | {
5 | static class SurrogateResolvable
6 | {
7 | public static readonly bool IsSurrogated = (typeof(ISurrogated).IsAssignableFrom(typeof(T)));
8 | public static readonly bool IsSurrogate =
9 | typeof(ISurrogate).IsAssignableFrom(typeof(T));
10 | }
11 | }
--------------------------------------------------------------------------------
/Akka.Serialization.Testkit/Akka.Serialization.Testkit.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack.Benchmarks/Akka.Serialization.MessagePack.Benchmarks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | true
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack.Benchmarks/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BenchmarkDotNet.Configs;
3 | using BenchmarkDotNet.Environments;
4 | using BenchmarkDotNet.Jobs;
5 | using BenchmarkDotNet.Running;
6 | using BenchmarkDotNet.Toolchains.CsProj;
7 |
8 | namespace Akka.Serialization.MessagePack.Benchmarks
9 | {
10 | public class MyConfig : ManualConfig
11 | {
12 | public MyConfig()
13 | {
14 | Add(Job.Default.With(CsProjCoreToolchain.NetCoreApp31).With(Platform.X64).WithGcServer(true));
15 | this.Options =
16 | Options | ConfigOptions.DisableOptimizationsValidator;
17 | }
18 | }
19 |
20 | class Program
21 | {
22 | static void Main(string[] args)
23 | {
24 | BenchmarkRunner.Run();
25 |
26 | Console.ReadLine();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Akka.Serialization.MessagePack.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Akka.Serialization.MessagePack
5 | MessagePack serializer for Akka.NET
6 | netstandard2.0;net6.0
7 | Akka.Serialization.MessagePack2
8 | true
9 | $(NoWarn);CS1591
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack.Tests/Akka.Serialization.MessagePack.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.github/workflows/pr_validation.yaml:
--------------------------------------------------------------------------------
1 | name: pr_validation
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - dev
8 | - main
9 | pull_request:
10 | branches:
11 | - master
12 | - dev
13 | - main
14 |
15 | jobs:
16 | test:
17 | name: Test-${{matrix.os}}
18 | runs-on: ${{matrix.os}}
19 |
20 | strategy:
21 | matrix:
22 | os: [ubuntu-latest, windows-latest]
23 |
24 | steps:
25 | - name: "Checkout"
26 | uses: actions/checkout@v4.1.1
27 | with:
28 | lfs: true
29 | fetch-depth: 0
30 |
31 | - name: "Install .NET SDK"
32 | uses: actions/setup-dotnet@v4.0.0
33 | with:
34 | global-json-file: "./global.json"
35 |
36 | - name: "Update release notes"
37 | shell: pwsh
38 | run: |
39 | ./build.ps1
40 |
41 | - name: "dotnet build"
42 | run: dotnet build -c Release
43 |
44 | - name: "dotnet test"
45 | run: dotnet test -c Release
46 |
47 | - name: "dotnet pack"
48 | run: dotnet pack -c Release
--------------------------------------------------------------------------------
/Akka.Serialization.Testkit/Util/ConfigFactory.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (C) 2017 Akka.NET Contrib
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using System;
8 |
9 | namespace Akka.Serialization.Testkit.Util
10 | {
11 | public class ConfigFactory
12 | {
13 | public static string GetConfig(Type serializerType)
14 | {
15 | return @"
16 | akka.actor {
17 | serializers.msgpack = """ + serializerType.AssemblyQualifiedName + @"""
18 | serialization-bindings {
19 | ""System.Object"" = msgpack
20 | }
21 | serialization-settings {
22 | msgpack {
23 | enable-lz4-compression = false
24 | }
25 | }
26 | }";
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/scripts/bumpVersion.ps1:
--------------------------------------------------------------------------------
1 | function UpdateVersionAndReleaseNotes {
2 | param (
3 | [Parameter(Mandatory=$true)]
4 | [PSCustomObject]$ReleaseNotesResult,
5 |
6 | [Parameter(Mandatory=$true)]
7 | [string]$XmlFilePath
8 | )
9 |
10 | # Load XML
11 | $xmlContent = New-Object XML
12 | $xmlContent.Load($XmlFilePath)
13 |
14 | # Update VersionPrefix and PackageReleaseNotes
15 | $versionPrefixElement = $xmlContent.SelectSingleNode("//VersionPrefix")
16 | $versionPrefixElement.InnerText = $ReleaseNotesResult.Version
17 |
18 | $packageReleaseNotesElement = $xmlContent.SelectSingleNode("//PackageReleaseNotes")
19 | $packageReleaseNotesElement.InnerText = $ReleaseNotesResult.ReleaseNotes
20 |
21 | # Save the updated XML
22 | $xmlContent.Save($XmlFilePath)
23 | }
24 |
25 | # Usage example:
26 | # $notes = Get-ReleaseNotes -MarkdownFile "$PSScriptRoot\RELEASE_NOTES.md"
27 | # $propsPath = Join-Path -Path (Get-Item $PSScriptRoot).Parent.FullName -ChildPath "Directory.Build.props"
28 | # UpdateVersionAndReleaseNotes -ReleaseNotesResult $notes -XmlFilePath $propsPath
29 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Sample.hocon:
--------------------------------------------------------------------------------
1 |
2 | akka.actor {
3 | serializers.messagepack = "Akka.Serialization.MessagePack.MsgPackSerializer, Akka.Serialization.MessagePack"
4 | serialization-bindings {
5 | "System.Object" = messagepack
6 | }
7 | serialization-settings {
8 | messagepack {
9 |
10 | # Use "Lz4BlockArray" or "Lz4Block" to enable.
11 | # "Lz4BlockArray" is reccomended by MessagePack author.
12 | # Note that all sides must have this set!
13 | enable-lz4-compression = "none"
14 |
15 | # If False, Assembly version mismatches on typeless types may throw!
16 | allow-assembly-version-mismatch = true
17 |
18 | # If True, Assembly version is included in typeless serialized data.
19 | omit-assembly-version = true
20 |
21 | # A set of converters with FQCN (Including assembly) to use,
22 | # before falling back to the TypelessFormatter.
23 | # Note that Other converters like Akka surrogates are registered -before-
24 | # these. If you need to party on those types, use 'converters-override' instead
25 | converters = []
26 |
27 | # A set of 'Override' converters with FQCN (including assmebly) to use,
28 | # BEFORE All other converters.
29 | # This may break Akka Serialization if you are not careful!
30 | converters-override = []
31 |
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | Copyright © 2013-2024 Akka.NET Project
4 | $(NoWarn);CS1591;NU1701;CA1707;
5 | 1.1.0
6 |
7 | Akka.NET Team
8 | https://github.com/akkadotnet/Akka.Serialization.MessagePack
9 | * [Resolved `AK2001`: `if` statements not cleanly managed by Code Fix](https://github.com/akkadotnet/akka.analyzers/pull/46)
10 | akka;actors;actor model;Akka;concurrency;messagepack;serializer;serialization
11 | README.md
12 | Apache-2.0
13 | logo.png
14 |
15 | MsgPack serialization support for Akka.NET.
16 |
17 |
18 |
19 |
20 | latest
21 | enable
22 | enable
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/scripts/getReleaseNotes.ps1:
--------------------------------------------------------------------------------
1 | function Get-ReleaseNotes {
2 | param (
3 | [Parameter(Mandatory=$true)]
4 | [string]$MarkdownFile
5 | )
6 |
7 | # Read markdown file content
8 | $content = Get-Content -Path $MarkdownFile -Raw
9 |
10 | # Split content based on headers
11 | $sections = $content -split "####"
12 |
13 | # Output object to store result
14 | $outputObject = [PSCustomObject]@{
15 | Version = $null
16 | Date = $null
17 | ReleaseNotes = $null
18 | }
19 |
20 | # Check if we have at least 3 sections (1. Before the header, 2. Header, 3. Release notes)
21 | if ($sections.Count -ge 3) {
22 | $header = $sections[1].Trim()
23 | $releaseNotes = $sections[2].Trim()
24 |
25 | # Extract version and date from the header
26 | $headerParts = $header -split " ", 2
27 | if ($headerParts.Count -eq 2) {
28 | $outputObject.Version = $headerParts[0]
29 | $outputObject.Date = $headerParts[1]
30 | }
31 |
32 | $outputObject.ReleaseNotes = $releaseNotes
33 | }
34 |
35 | # Return the output object
36 | return $outputObject
37 | }
38 |
39 | # Call function example:
40 | #$result = Get-ReleaseNotes -MarkdownFile "$PSScriptRoot\RELEASE_NOTES.md"
41 | #Write-Output "Version: $($result.Version)"
42 | #Write-Output "Date: $($result.Date)"
43 | #Write-Output "Release Notes:"
44 | #Write-Output $result.ReleaseNotes
45 |
--------------------------------------------------------------------------------
/.github/workflows/publish_nuget.yml:
--------------------------------------------------------------------------------
1 | name: Publish NuGet
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | publish-nuget:
10 |
11 | name: publish-nuget
12 | runs-on: ${{ matrix.os }}
13 | strategy:
14 | matrix:
15 | os: [ubuntu-latest]
16 |
17 | steps:
18 | - uses: actions/checkout@v4
19 | - name: Setup .NET Core
20 | uses: actions/setup-dotnet@v4
21 | with:
22 | dotnet-version: ${{ env.DOTNET_VERSION }}
23 |
24 | - name: "Update release notes"
25 | shell: pwsh
26 | run: |
27 | ./build.ps1
28 |
29 | - name: Create Packages
30 | run: dotnet pack /p:PackageVersion=${{ github.ref_name }} -c Release -o ./output
31 |
32 | - name: Push Packages
33 | run: dotnet nuget push "output/*.nupkg" -k ${{ secrets.NUGET_KEY }} -s https://api.nuget.org/v3/index.json
34 |
35 | - name: release
36 | uses: actions/create-release@v1
37 | id: create_release
38 | with:
39 | draft: false
40 | prerelease: false
41 | release_name: 'Akka.Serialization.MessagePack ${{ github.ref_name }}'
42 | tag_name: ${{ github.ref }}
43 | body_path: RELEASE_NOTES.md
44 | env:
45 | GITHUB_TOKEN: ${{ github.token }}
46 |
47 | - name: Upload Release Asset
48 | uses: AButler/upload-release-assets@v3.0
49 | with:
50 | repo-token: ${{ github.token }}
51 | release-tag: ${{ github.ref_name }}
52 | files: 'output/*.nupkg'
53 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Resolvers/SerializableResolver.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (C) 2017 Akka.NET Contrib
4 | //
5 | //-----------------------------------------------------------------------
6 | using System;
7 | using MessagePack;
8 | using MessagePack.Formatters;
9 |
10 | namespace Akka.Serialization.MessagePack.Resolvers
11 | {
12 | public class SerializableResolver : IFormatterResolver
13 | {
14 | public static readonly IFormatterResolver Instance = new SerializableResolver();
15 | SerializableResolver() { }
16 |
17 | public IMessagePackFormatter GetFormatter() => FormatterCache.Formatter;
18 |
19 | static class FormatterCache
20 | {
21 | public static readonly IMessagePackFormatter Formatter;
22 | static FormatterCache() => Formatter = (IMessagePackFormatter)SerializableFormatterHelper.GetFormatter();
23 | }
24 | }
25 |
26 | internal static class SerializableFormatterHelper
27 | {
28 | internal static object GetFormatter()
29 | {
30 | return SerializableFormatterAssignable.IsAssignableFrom
31 | ? new SerializableFormatter()
32 | : null;
33 | }
34 | }
35 |
36 | internal static class SerializableFormatterAssignable
37 | {
38 | public static readonly bool IsAssignableFrom =
39 | typeof(Exception).IsAssignableFrom(typeof(T));
40 | }
41 | }
--------------------------------------------------------------------------------
/RELEASE_NOTES.md:
--------------------------------------------------------------------------------
1 | #### 1.5.31 November 26th 2024 ####
2 |
3 | This is the RTM release of Akka.Serialization.MessagePack
4 |
5 | * [Upgrade Akka.Net to 1.5.31](https://github.com/akkadotnet/akka.net/releases/tag/1.5.31)
6 | * [Bump MessagePack to 2.5.192](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/80)
7 | * [Bump CommunityToolkit.HighPerformance to 8.3.2](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/68)
8 |
9 | #### 1.5.31-beta1 November 18th 2024 ####
10 |
11 | * [Upgrade Akka.Net to 1.5.31](https://github.com/akkadotnet/akka.net/releases/tag/1.5.31)
12 | * [Bump MessagePack to 2.5.192](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/80)
13 | * [Bump CommunityToolkit.HighPerformance to 8.3.2](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/68)
14 |
15 | #### 1.5.16-beta1 February 14 2024 ####
16 |
17 | Akka.Serialization.MessagePack Beta release for Akka.NET v1.5
18 |
19 | * [Upgrade Akka.Net to 1.5.16](https://github.com/akkadotnet/akka.net/releases/tag/1.5.16)
20 | * [Better polymorphism handling](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/27)
21 | * [Use int array lookup for polymorphic resolver](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/42)
22 | * [Handle edge case for dictionary lookup](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/44)
23 | * [Fix off-by-one waste in IntIndexedDict](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/45)
24 | * [Bump MessagePack to 2.4](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/24)
25 | * [Bump CommunityToolkit.HighPerformance to 8.2.2](https://github.com/akkadotnet/Akka.Serialization.MessagePack/pull/36)
26 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Resolvers/BackwardsCompatibleSurrogatedFormatterResolver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using Akka.Actor;
4 | using MessagePack;
5 | using MessagePack.Formatters;
6 |
7 | namespace Akka.Serialization.MessagePack.Resolvers
8 | {
9 | public class BackwardsCompatibleSurrogatedFormatterResolver : IFormatterResolver, IDoNotUsePolymorphicFormatter
10 | {
11 |
12 | private readonly ConcurrentDictionary
13 | _formatterCache =
14 | new ConcurrentDictionary();
15 |
16 | private readonly Func _formatterCreateFunc;
17 | public BackwardsCompatibleSurrogatedFormatterResolver(ExtendedActorSystem system)
18 | {
19 | //Cast in the func since we'll have to cache anyway.
20 | //The alternative is making a 'nullable' func in another static class,
21 | //But that may result in too much garbage for other types.
22 | _formatterCreateFunc = t =>
23 | (IMessagePackFormatter)typeof(BackwardsCompatibleSurrogatedFormatter<>)
24 | .MakeGenericType(t)
25 | .GetConstructor(new[] { typeof(ActorSystem) })
26 | .Invoke(new[] { system });
27 |
28 | }
29 | public IMessagePackFormatter GetFormatter()
30 | {
31 | if (SurrogateResolvable.IsSurrogated)
32 | {
33 | return (IMessagePackFormatter)_formatterCache.GetOrAdd(
34 | typeof(T),
35 | _formatterCreateFunc);
36 | }
37 | else
38 | {
39 | return null;
40 | }
41 | }
42 |
43 | }
44 | }
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Resolvers/ExceptionAsSerializableResolver.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (C) 2017 Akka.NET Contrib
4 | //
5 | //-----------------------------------------------------------------------
6 | #if SERIALIZATION
7 | using System;
8 | using MessagePack;
9 | using MessagePack.Formatters;
10 |
11 | namespace Akka.Serialization.MessagePack.Resolvers
12 | {
13 | public class ExceptionAsSerializableResolver : IFormatterResolver
14 | {
15 | public static readonly IFormatterResolver Instance = new ExceptionAsSerializableResolver();
16 | ExceptionAsSerializableResolver() { }
17 |
18 | public IMessagePackFormatter GetFormatter() => FormatterCache.Formatter;
19 |
20 | static class FormatterCache
21 | {
22 | public static readonly IMessagePackFormatter Formatter;
23 | static FormatterCache() => Formatter = (IMessagePackFormatter)ExceptionAsSerializableFormatterHelper.GetFormatter();
24 | }
25 | }
26 |
27 | internal static class ExceptionAsSerializableFormatterHelper
28 | {
29 | internal static object GetFormatter()
30 | {
31 | return ExceptionAsSerializableFormatterAssignable
32 | .FormatterOrNull;
33 | }
34 | }
35 |
36 | ///
37 | /// A Generic-type cache to
38 | ///
39 | ///
40 | internal static class ExceptionAsSerializableFormatterAssignable
41 | {
42 | public static readonly object FormatterOrNull =
43 | typeof(Exception).IsAssignableFrom(typeof(T))
44 | ? new SerializableFormatter()
45 | : null;
46 | public static readonly bool IsAssignableFrom =
47 | FormatterOrNull != null;
48 | }
49 | }
50 | #endif
--------------------------------------------------------------------------------
/Akka.Serialization.Testkit/AkkaMessagesTests.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (C) 2017 Akka.NET Contrib
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using System;
8 | using Akka.Actor;
9 | using Akka.Serialization.Testkit.Util;
10 | using Akka.TestKit.TestActors;
11 | using Xunit;
12 |
13 | namespace Akka.Serialization.Testkit
14 | {
15 | public abstract class AkkaMessagesTests : TestKit.Xunit2.TestKit
16 | {
17 | protected AkkaMessagesTests(Type serializerType) : base(ConfigFactory.GetConfig(serializerType))
18 | {
19 | }
20 |
21 | [Fact]
22 | public void Can_serialize_ActorRef()
23 | {
24 | var actorRef = ActorOf();
25 | AssertEqual(actorRef);
26 | }
27 |
28 | [Fact]
29 | public void Can_serialize_RootActorPath()
30 | {
31 | var uri = "akka.tcp://sys@localhost:9000";
32 | var actorPath = ActorPath.Parse(uri);
33 | AssertEqual(actorPath);
34 | }
35 |
36 | [Fact]
37 | public void Can_serialize_ActorPath()
38 | {
39 | var uri = "akka.tcp://sys@localhost:9000/user/actor";
40 | var actorPath = ActorPath.Parse(uri);
41 | AssertEqual(actorPath);
42 | }
43 |
44 | protected T AssertAndReturn(T message)
45 | {
46 | var serializer = Sys.Serialization.FindSerializerFor(message);
47 | var serialized = serializer.ToBinary(message);
48 | var result = serializer.FromBinary(serialized, typeof(T));
49 | return (T)result;
50 | }
51 |
52 | protected void AssertEqual(T message)
53 | {
54 | var deserialized = AssertAndReturn(message);
55 | Assert.Equal(message, deserialized);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Resolvers/SurrogatedFormatterResolver.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (C) 2017 Akka.NET Contrib
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using System;
8 | using System.Collections.Concurrent;
9 | using System.Collections.Generic;
10 | using System.Runtime.CompilerServices;
11 | using Akka.Actor;
12 | using Akka.Util.Internal;
13 | using MessagePack;
14 | using MessagePack.Formatters;
15 |
16 | namespace Akka.Serialization.MessagePack.Resolvers
17 | {
18 | public class SurrogatedFormatterResolver : IFormatterResolver, IDoNotUsePolymorphicFormatter
19 | {
20 |
21 | private readonly ConcurrentDictionary
22 | _formatterCache =
23 | new ConcurrentDictionary();
24 |
25 | private readonly Func _formatterCreateFunc;
26 | public SurrogatedFormatterResolver(ExtendedActorSystem system)
27 | {
28 | //Cast in the func since we'll have to cache anyway.
29 | //The alternative is making a 'nullable' func in another static class,
30 | //But that may result in too much garbage for other types.
31 | _formatterCreateFunc = t =>
32 | (IMessagePackFormatter)typeof(SurrogatedFormatter<>)
33 | .MakeGenericType(t)
34 | .GetConstructor(new[] { typeof(ActorSystem) })
35 | .Invoke(new[] { system });
36 |
37 | }
38 | public IMessagePackFormatter GetFormatter()
39 | {
40 | if (SurrogateResolvable.IsSurrogated)
41 | {
42 | if (_formatterCache.TryGetValue(typeof(T),out var formatter))
43 | {
44 | return (IMessagePackFormatter)formatter;
45 | }
46 | else
47 | {
48 | return (IMessagePackFormatter)_formatterCache.GetOrAdd(typeof(T),
49 | _formatterCreateFunc);
50 | }
51 | }
52 | else
53 | {
54 | return null!;
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack.Tests/MsgPackSerializersTests.cs:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------
2 | //
3 | // Copyright (C) 2017 Akka.NET Contrib
4 | //
5 | //-----------------------------------------------------------------------
6 |
7 | using Akka.Serialization.Testkit;
8 | using Xunit;
9 |
10 | namespace Akka.Serialization.MessagePack.Tests
11 | {
12 | public class MsgPackAkkaMessagesTests : AkkaMessagesTests
13 | {
14 | public MsgPackAkkaMessagesTests() : base(typeof(MsgPackSerializer))
15 | {
16 | }
17 | }
18 |
19 | public class MsgPackCollectionsTests : CollectionsTests
20 | {
21 | public MsgPackCollectionsTests() : base(typeof(MsgPackSerializer))
22 | {
23 | }
24 | }
25 |
26 | public class MsgPackCustomMessagesTests : CustomMessagesTests
27 | {
28 | public MsgPackCustomMessagesTests() : base(typeof(MsgPackSerializer))
29 | {
30 | }
31 | }
32 |
33 | public class MsgPackExceptionsTests : ExceptionsTests
34 | {
35 | public MsgPackExceptionsTests() : base(typeof(MsgPackSerializer))
36 | {
37 | }
38 | }
39 |
40 | public class MsgPackImmutableMessagesTests : ImmutableMessagesTests
41 | {
42 | public MsgPackImmutableMessagesTests() : base(typeof(MsgPackSerializer))
43 | {
44 | }
45 | }
46 |
47 | public class MsgPackPolymorphismTests : PolymorphismTests
48 | {
49 | public MsgPackPolymorphismTests() : base(typeof(MsgPackSerializer))
50 | {
51 | }
52 | }
53 |
54 | public class MsgPackIncapsulationTests : IncapsulationTests
55 | {
56 | public MsgPackIncapsulationTests() : base(typeof(MsgPackSerializer))
57 | {
58 | }
59 |
60 | //[Fact(Skip = "Not supported yet")]
61 | //public override void Can_Serialize_a_class_with_internal_constructor()
62 | //{
63 | //}
64 |
65 | //[Fact(Skip = "Not supported yet")]
66 | //public override void Can_Serialize_a_class_with_private_constructor()
67 | //{
68 | //}
69 |
70 | //[Fact(Skip = "Not supported yet")]
71 | //public override void Can_Serialize_internal_class()
72 | //{
73 | //}
74 | }
75 |
76 | public class MsgPackPrimiviteSerializerTests : PrimitiveSerializerTests
77 | {
78 | public MsgPackPrimiviteSerializerTests() : base(typeof(MsgPackSerializer))
79 | {
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Formatters/PolymorphicFormatter.cs:
--------------------------------------------------------------------------------
1 | using MessagePack;
2 | using MessagePack.Formatters;
3 |
4 | namespace Akka.Serialization.MessagePack.Resolvers
5 | {
6 | public class PolymorphicFormatter : IMessagePackFormatter
7 | {
8 | //private static readonly ForceTypelessFormatter _typelessFormatter =
9 | // new ForceTypelessFormatter();
10 |
11 | private readonly IMessagePackFormatter _normalFormatter;
12 |
13 | public PolymorphicFormatter(IMessagePackFormatter normalFormatter)
14 | {
15 | _normalFormatter = normalFormatter;
16 | }
17 | public void Serialize(ref MessagePackWriter writer, T value,
18 | MessagePackSerializerOptions options)
19 | {
20 | if (value == null)
21 | {
22 | writer.WriteNil();
23 | }
24 | else if (value.GetType() == typeof(T))
25 | {
26 | _normalFormatter.Serialize(ref writer, value, options);
27 | }
28 | else
29 | {
30 | TypelessFormatter.Instance.Serialize(ref writer, value,
31 | options);
32 | }
33 | }
34 |
35 | public T Deserialize(ref MessagePackReader reader,
36 | MessagePackSerializerOptions options)
37 | {
38 | // It's a trap!
39 | // TryReadExtensionFormatHeader will throw if Code is not Ext!!!
40 | // So we -must- first peek at NextCode and make sure it is one of
41 | // The correct types for Ext Data.
42 | switch (reader.NextCode)
43 | {
44 | case MessagePackCode.Ext8:
45 | case MessagePackCode.Ext16:
46 | case MessagePackCode.Ext32:
47 | case MessagePackCode.FixExt1:
48 | case MessagePackCode.FixExt2:
49 | case MessagePackCode.FixExt4:
50 | case MessagePackCode.FixExt8:
51 | case MessagePackCode.FixExt16:
52 | {
53 | if (reader.CreatePeekReader().TryReadExtensionFormatHeader(out var header) &&
54 | header.TypeCode == 100)
55 | return (T)TypelessFormatter.Instance.Deserialize(ref reader,
56 | options);
57 | break;
58 | }
59 | case MessagePackCode.Nil:
60 | {
61 | reader.ReadNil();
62 | return default!;
63 | }
64 | }
65 |
66 | return _normalFormatter.Deserialize(ref reader, options);
67 | }
68 | }
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/Akka.Serialization.MessagePack/Formatters/SerializableFormatter.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.Serialization;
3 | using System.Text;
4 | using Akka.Util.Internal;
5 | using MessagePack;
6 | using MessagePack.Formatters;
7 |
8 | namespace Akka.Serialization.MessagePack.Resolvers
9 | {
10 | public class SerializableFormatter : IMessagePackFormatter
11 | {
12 | private static readonly IMessagePackFormatter