Skip to content

Commit

Permalink
Add a reference to MessagePack implementation (#14)
Browse files Browse the repository at this point in the history
* Add MsgPackSerializer sample

It's very rough and limited. And it assumes #12 is addressed.

* Add msgpack benchmarks

* Perf improvements

* More perf improvements

* Use list instead of dictionary for writing properties

* Remove unnecessary code

* Fix thread-safety

* Generate `IMessagePackFormatter<T>` implementations

* Remove extra level of indirection

* Fix failing unit tests

* Handle more primitive types and defer missing construction complaint till deserialization

* Fix DelayedFormatter pattern

* Store primitive formatters in a static dictionary

* Add support for enums

* Got non-default constructors working

* Remove workaround that is no longer required

* Serialize enum as underlying type rather than string

* Add msgpack Theory

* Replace msgpack sample with a reference

---------

Co-authored-by: Eirik Tsarpalis <[email protected]>
  • Loading branch information
AArnott and eiriktsarpalis authored Nov 1, 2024
1 parent 945f63f commit 0b03b2a
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*.user
*.userosscache
*.sln.docstates
*.lutconfig

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
Expand Down Expand Up @@ -376,4 +377,4 @@ artifacts/

# docfx files
_site
docs/api
docs/api
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ Here's a [benchmark](https://github.com/eiriktsarpalis/typeshape-csharp/blob/mai

Even though both serializers target the same underlying reader and writer types, the TypeShape implementation is ~75% faster for serialization and ~100% faster for deserialization, when compared with System.Text.Json's metadata serializer. As expected, fast-path serialization is still fastest since its implementation is fully inlined.

## Known libraries based on TypeShape

The following codebases are based upon TypeShape and may be worth checking out.

- [Nerdbank.MessagePack](https://github.com/AArnott/Nerdbank.MessagePack) - a MessagePack library with performance to rival MessagePack-CSharp, and greater simplicity and additional features.

## Project structure

The repo consists of the following projects:
Expand Down
6 changes: 5 additions & 1 deletion src/TypeShape.Examples/Utilities/SpanDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public SpanDictionary(IEnumerable<KeyValuePair<TKey[], TValue>> input, ISpanEqua
var source = input.ToArray();
int size = source.Length;
_comparer = comparer;

_buckets = new int[Math.Max(size, 1)];
_entries = new Entry[size];

Expand Down Expand Up @@ -138,4 +138,8 @@ public static class SpanDictionary
/// <summary>Maps the specified enumerable using a dictionary using the provided transformers.</summary>
public static SpanDictionary<TKey, TSource> ToSpanDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey[]> keySelector, ISpanEqualityComparer<TKey> keyComparer)
=> new(source.Select(t => new KeyValuePair<TKey[], TSource>(keySelector(t), t)), keyComparer);

/// <summary>Maps the specified enumerable using a dictionary using the provided transformers.</summary>
public static SpanDictionary<TKey, TValue> ToSpanDictionary<TSource, TKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TKey[]> keySelector, Func<TSource, TValue> valueSelector, ISpanEqualityComparer<TKey> keyComparer)
=> new(source.Select(t => new KeyValuePair<TKey[], TValue>(keySelector(t), valueSelector(t))), keyComparer);
}
12 changes: 6 additions & 6 deletions tests/TypeShape.Benchmarks/TypeShape.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<ServerGarbageCollection>true</ServerGarbageCollection>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>

<ItemGroup>
Expand All @@ -17,7 +17,7 @@

<ItemGroup>
<ProjectReference Include="..\..\src\TypeShape\TypeShape.csproj" />
<ProjectReference Include="..\..\src\TypeShape.SourceGenerator\TypeShape.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\src\TypeShape.SourceGenerator\TypeShape.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\src\TypeShape.Examples\TypeShape.Examples.csproj" />
</ItemGroup>

Expand Down
18 changes: 15 additions & 3 deletions tests/TypeShape.Tests/TestTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ public partial class DerivedDictionary : Dictionary<string, string>;
public void Clear() => _dictionary.Clear();
public bool Contains(KeyValuePair<TKey, TValue> item) => _dictionary.Contains(item);
public bool ContainsKey(TKey key) => _dictionary.ContainsKey(key);
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => ((IDictionary<TKey,TValue>)_dictionary).CopyTo(array, arrayIndex);
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => ((IDictionary<TKey, TValue>)_dictionary).CopyTo(array, arrayIndex);
public bool Remove(TKey key) => _dictionary.Remove(key);
public bool Remove(KeyValuePair<TKey, TValue> item) => ((IDictionary<TKey, TValue>)_dictionary).Remove(item);
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) => _dictionary.TryGetValue(key, out value);
Expand Down Expand Up @@ -592,15 +592,27 @@ public StructWithDefaultCtor()
}

[GenerateShape]
public partial class BaseClass
public partial class BaseClass : IEquatable<BaseClass>
{
public int X { get; set; }

public bool Equals(BaseClass? other) => other is not null && X == other.X;

public override bool Equals(object? obj) => obj is BaseClass other && Equals(other);

public override int GetHashCode() => X;
}

[GenerateShape]
public partial class DerivedClass : BaseClass
public partial class DerivedClass : BaseClass, IEquatable<DerivedClass>
{
public int Y { get; set; }

public bool Equals(DerivedClass? other) => base.Equals(other) && Y == other.Y;

public override bool Equals(object? obj) => obj is DerivedClass other && Equals(other);

public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Y);
}

[GenerateShape]
Expand Down

0 comments on commit 0b03b2a

Please sign in to comment.