Skip to content

Commit

Permalink
Merge pull request #25 from skbkontur/net50
Browse files Browse the repository at this point in the history
Add net5.0 support
  • Loading branch information
AndrewKostousov authored Mar 11, 2021
2 parents 3da6398 + 4881dee commit 4689827
Show file tree
Hide file tree
Showing 21 changed files with 152 additions and 63 deletions.
8 changes: 3 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
dist: xenial
sudo: false
language: csharp
dotnet: 3.1.300
dotnet: 5.0.103
mono: none
before_install:
- sudo apt-get install dotnet-sdk-2.1
script:
- git fetch --unshallow # in order to make Nerdbank.GitVersioning.Tasks.GetBuildVersion work
- dotnet restore ./GroBuf.sln --verbosity m
- dotnet build --configuration Release --framework netstandard2.0 ./GroBuf/GroBuf.csproj
- dotnet build --configuration Release --framework netcoreapp3.1 ./GroBuf.Tests/GroBuf.Tests.csproj
- dotnet test --no-build --configuration Release --framework netcoreapp3.1 --filter TestCategory!=LongRunning ./GroBuf.Tests/GroBuf.Tests.csproj
- dotnet build --configuration Release --framework net5.0 ./GroBuf.Tests/GroBuf.Tests.csproj
- dotnet test --no-build --configuration Release --framework net5.0 --filter TestCategory!=LongRunning ./GroBuf.Tests/GroBuf.Tests.csproj
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## v1.7.x - 2021.03.xx
- Fix GroBuf to work on .NET 5.0 (PR [#25](https://github.com/skbkontur/GroBuf/pull/25)).

## v1.6.1 - 2020.08.26
- Use original [Mono.Reflection](https://www.nuget.org/packages/Mono.Reflection/2.0.0) package instead of forked one.
- Use strongly-named [GrEmit](https://github.com/skbkontur/gremit) assembly.
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.2.31" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" />
</ItemGroup>

</Project>
Binary file added GroBuf.Tests/Files/set0.buf
Binary file not shown.
Binary file added GroBuf.Tests/Files/set1.buf
Binary file not shown.
Binary file added GroBuf.Tests/Files/set2.buf
Binary file not shown.
Binary file added GroBuf.Tests/Files/set3.buf
Binary file not shown.
Binary file added GroBuf.Tests/Files/set4.buf
Binary file not shown.
24 changes: 5 additions & 19 deletions GroBuf.Tests/GroBuf.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,23 @@

<PropertyGroup>
<IsPackable>false</IsPackable>
<TargetFrameworks>net48;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>net48;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
<PackageReference Include="NUnit" Version="3.13.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="protobuf-net" Version="3.0.29" />
<PackageReference Include="protobuf-net" Version="3.0.73" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\GroBuf\GroBuf.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="Files\dict0.buf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\dict1.buf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\dict2.buf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\dict3.buf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\dict4.buf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\*.buf" CopyToOutputDirectory="Always" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion GroBuf.Tests/TestDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void SetUp()
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
public void TestRandom(int i, bool generateFiles = false)
public void TestBackwardsCompatibility(int i, bool generateFiles = false)
{
var rnd = new Random(i);
var count = rnd.Next(1, 100);
Expand Down
64 changes: 64 additions & 0 deletions GroBuf.Tests/TestHashSet.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

using FluentAssertions;

using GroBuf.DataMembersExtracters;

using NUnit.Framework;
Expand Down Expand Up @@ -165,6 +168,38 @@ public void TestCompatibilityWithArrayOfPrimitives()
Assert.IsTrue(hashSet.Contains(3));
}

[TestCase(0)]
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
[TestCase(4)]
public void TestBackwardsCompatibility(int i, bool generateFiles = false)
{
var rnd = new Random(i);
var count = rnd.Next(1, 100);
var set = new HashSet<Zzz>();
for (int j = 0; j < count; j++)
set.Add(new Zzz
{
Id = $"{i}{j}{count}{rnd.Next(1000, 10000)}",
Properties = new Dictionary<string, byte[]>
{
{rnd.Next(1000, 10000).ToString(), new byte[] {5, 4}}
}
});

var buf = serializer.Serialize(set);

if (generateFiles)
File.WriteAllBytes($"{TestContext.CurrentContext.TestDirectory}/../../../Files/set{i}.buf", buf);

var expectedBuf = File.ReadAllBytes($"{TestContext.CurrentContext.TestDirectory}/Files/set{i}.buf");
buf.Should().BeEquivalentTo(expectedBuf);

var set2 = serializer.Deserialize<HashSet<Zzz>>(buf);
set2.Should().BeEquivalentTo(set);
}

[Test]
[Category("LongRunning")]
public void TestPerformance()
Expand Down Expand Up @@ -223,6 +258,35 @@ public void TestPerformanceGuid()

private Serializer serializer;

private class Zzz
{
public Zzz()
{
Properties = new Dictionary<string, byte[]>();
}

protected bool Equals(Zzz other)
{
return Id == other.Id;
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Zzz)obj);
}

public override int GetHashCode()
{
return Id.GetHashCode();
}

public string Id { get; set; }
public Dictionary<string, byte[]> Properties { get; set; }
}

private class TestWithHashSet
{
public HashSet<Guid> H { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion GroBuf/GroBuf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GrEmit" Version="3.3.7" />
<PackageReference Include="GrEmit" Version="3.4.1" />
<PackageReference Include="Mono.Reflection" Version="2.0.0" />
</ItemGroup>

Expand Down
25 changes: 22 additions & 3 deletions GroBuf/PlatformHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,29 @@ public static class PlatformHelpers
{
static PlatformHelpers()
{
IsMono = Type.GetType("Mono.Runtime") != null;
IsMono = HasSystemType("Mono.Runtime");
IsDotNetCore30OrGreater = HasSystemType("System.Range");
IsDotNet50OrGreater = HasSystemType("System.Half");
}

public static bool IsMono { get; }
public static bool IsDotNetCore30OrGreater { get; }
public static bool IsDotNet50OrGreater { get; }

public static string DelegateTargetFieldName => IsMono ? "m_target" : "_target";
public static string[] LazyValueFactoryFieldNames => new[] {"m_valueFactory", "_factory"};
public static string[] DateTimeOffsetDateTimeFieldNames => new[] {"m_dateTime", "_dateTime"};
public static string[] DateTimeOffsetOffsetMinutesFieldNames => new[] {"m_offsetMinutes", "_offsetMinutes"};
public static string[] HashtableCountFieldNames => new[] {"count", "_count"};
public static string[] HashtableBucketsFieldNames => new[] {"buckets", "_buckets"};
public static string[] HashSetSlotsFieldNames => new[] {"m_slots", "_slots"};
public static string[] HashSetLastIndexFieldNames => new[] {"m_lastIndex", "_lastIndex"};
public static string[] HashSetCountFieldNames => IsDotNet50OrGreater ? new[] {"_count"} : new[] {"m_lastIndex", "_lastIndex"};
public static string[] HashSetSlotsFieldNames => IsDotNet50OrGreater ? new[] {"_entries"} : new[] {"m_slots", "_slots"};
public static string[] DictionaryCountFieldNames => new[] {"count", "_count"};
public static string[] DictionaryEntriesFieldNames => new[] {"entries", "_entries"};

public static string HashSetSlotTypeName => IsDotNet50OrGreater ? "Entry" : "Slot";
public static string HashSetSlotValueFieldName => IsDotNet50OrGreater ? "Value" : "value";

public static FieldInfo GetPrivateInstanceField(this Type type, params string[] fieldNames)
{
foreach (var fieldName in fieldNames)
Expand All @@ -33,5 +40,17 @@ public static FieldInfo GetPrivateInstanceField(this Type type, params string[]
}
throw new InvalidOperationException($"Failed to get filedInfo for type {type} with name candidates: {string.Join(", ", fieldNames)}");
}

private static bool HasSystemType(string typeName)
{
try
{
return Type.GetType(typeName) != null;
}
catch
{
return false;
}
}
}
}
12 changes: 5 additions & 7 deletions GroBuf/SizeCounters/DictionarySizeCounterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext contex

context.LoadObj(); // stack: [size, obj]
var entryType = Type.GetNestedType("Entry", BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
var hashCodeType = entryType.GetField("hashCode", BindingFlags.Public | BindingFlags.Instance).FieldType;
var isNetCore3 = hashCodeType == typeof(uint);
var entries = il.DeclareLocal(entryType.MakeArrayType());
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.DictionaryEntriesFieldNames));
il.Stloc(entries);
Expand All @@ -75,15 +73,15 @@ protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext contex
il.Dup(); // stack: [size, &entries[i], &entries[i]]
var entry = il.DeclareLocal(entryType.MakeByRefType());
il.Stloc(entry); // entry = &entries[i]; stack: [size, entry]
if (!isNetCore3)
if (PlatformHelpers.IsDotNetCore30OrGreater)
{
il.Ldfld(entryType.GetField("hashCode")); // stack: [entry.hashCode]
il.Ldc_I4(0); // stack: [entry.hashCode, 0]
il.Ldfld(entryType.GetField("next")); // stack: [entry.next]
il.Ldc_I4(-1); // stack: [entry.next, -1]
}
else
{
il.Ldfld(entryType.GetField("next")); // stack: [entry.next]
il.Ldc_I4(-1); // stack: [entry.next, -1]
il.Ldfld(entryType.GetField("hashCode")); // stack: [entry.hashCode]
il.Ldc_I4(0); // stack: [entry.hashCode, 0]
}
var nextLabel = il.DefineLabel("next");
il.Blt(nextLabel, false); // if(entry.hashCode < 0) goto next; stack: [size]
Expand Down
18 changes: 13 additions & 5 deletions GroBuf/SizeCounters/HashSetSizeCounterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext contex

context.LoadObj(); // stack: [size, obj]
var count = il.DeclareLocal(typeof(int));
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetLastIndexFieldNames)); // stack: [size, obj.m_lastIndex]
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetCountFieldNames)); // stack: [size, obj.m_lastIndex]
il.Dup();
il.Stloc(count); // count = obj.m_lastIndex; stack: [size, count]
var doneLabel = il.DefineLabel("done");
il.Brfalse(doneLabel); // if(!count) goto done; stack: [size]

context.LoadObj(); // stack: [size, obj]
var slotType = Type.GetNestedType("Slot", BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
var slotType = Type.GetNestedType(PlatformHelpers.HashSetSlotTypeName, BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
var slots = il.DeclareLocal(slotType.MakeArrayType());
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetSlotsFieldNames));
il.Stloc(slots);
Expand All @@ -70,13 +70,21 @@ protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext contex
il.Dup(); // stack: [size, &slots[i], &slots[i]]
var slot = il.DeclareLocal(slotType.MakeByRefType());
il.Stloc(slot); // slot = &slots[i]; stack: [size, slot]
il.Ldfld(slotType.GetField("hashCode", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [size, slot.hashCode]
il.Ldc_I4(0); // stack: [size, slot.hashCode, 0]
if (PlatformHelpers.IsDotNet50OrGreater)
{
il.Ldfld(slotType.GetField("Next")); // stack: [size, slot.Next]
il.Ldc_I4(-1); // stack: [size, slot.Next, -1]
}
else
{
il.Ldfld(slotType.GetField("hashCode", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [size, slot.hashCode]
il.Ldc_I4(0); // stack: [size, slot.hashCode, 0]
}
var nextLabel = il.DefineLabel("next");
il.Blt(nextLabel, false); // if(slot.hashCode < 0) goto next; stack: [size]

il.Ldloc(slot); // stack: [size, slot]
il.Ldfld(slotType.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [size, slot.value]
il.Ldfld(slotType.GetField(PlatformHelpers.HashSetSlotValueFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); // stack: [size, slot.value]
il.Ldc_I4(1); // stack: [size, slot.value, true]
context.LoadContext(); // stack: [size, slot.value, true, context]
context.CallSizeCounter(elementType); // stack: [size, writer(slot.value, true, context) = valueSize]
Expand Down
12 changes: 5 additions & 7 deletions GroBuf/Writers/DictionaryWriterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ protected override void WriteNotEmpty(WriterMethodBuilderContext context)

context.LoadObj(); // stack: [obj]
var entryType = Type.GetNestedType("Entry", BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
var hashCodeType = entryType.GetField("hashCode", BindingFlags.Public | BindingFlags.Instance).FieldType;
var isNetCore3 = hashCodeType == typeof(uint);
var entries = il.DeclareLocal(entryType.MakeArrayType());
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.DictionaryEntriesFieldNames)); // stack: [obj.entries]
il.Stloc(entries); // entries = obj.entries; stack: []
Expand All @@ -87,15 +85,15 @@ protected override void WriteNotEmpty(WriterMethodBuilderContext context)
il.Dup(); // stack: [&entries[i], &entries[i]]
var entry = il.DeclareLocal(entryType.MakeByRefType());
il.Stloc(entry); // entry = &entries[i]; stack: [entry]
if (!isNetCore3)
if (PlatformHelpers.IsDotNetCore30OrGreater)
{
il.Ldfld(entryType.GetField("hashCode")); // stack: [entry.hashCode]
il.Ldc_I4(0); // stack: [entry.hashCode, 0]
il.Ldfld(entryType.GetField("next")); // stack: [entry.next]
il.Ldc_I4(-1); // stack: [entry.next, -1]
}
else
{
il.Ldfld(entryType.GetField("next")); // stack: [entry.next]
il.Ldc_I4(-1); // stack: [entry.next, -1]
il.Ldfld(entryType.GetField("hashCode")); // stack: [entry.hashCode]
il.Ldc_I4(0); // stack: [entry.hashCode, 0]
}
var nextLabel = il.DefineLabel("next");
il.Blt(nextLabel, false); // if(entry.hashCode < 0) goto next; stack: []
Expand Down
19 changes: 13 additions & 6 deletions GroBuf/Writers/HashSetWriterBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ protected override void WriteNotEmpty(WriterMethodBuilderContext context)

context.LoadObj(); // stack: [obj]
var count = il.DeclareLocal(typeof(int));
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetLastIndexFieldNames)); // stack: [obj.m_lastIndex]
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetCountFieldNames)); // stack: [obj.m_lastIndex]
il.Dup();
il.Stloc(count); // count = obj.m_lastIndex; stack: []
var writeDataLengthLabel = il.DefineLabel("writeDataLength");
il.Brfalse(writeDataLengthLabel);

context.LoadObj(); // stack: [obj]
var slotType = Type.GetNestedType("Slot", BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
var slotType = Type.GetNestedType(PlatformHelpers.HashSetSlotTypeName, BindingFlags.NonPublic).MakeGenericType(Type.GetGenericArguments());
var slots = il.DeclareLocal(slotType.MakeArrayType());
il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashSetSlotsFieldNames));
il.Stloc(slots);
Expand All @@ -81,14 +81,21 @@ protected override void WriteNotEmpty(WriterMethodBuilderContext context)
il.Dup(); // stack: [&slots[i], &slots[i]]
var slot = il.DeclareLocal(slotType.MakeByRefType());
il.Stloc(slot); // slot = &slots[i]; stack: [slot]
il.Ldfld(slotType.GetField("hashCode", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [slot.hashCode]

il.Ldc_I4(0); // stack: [slot.hashCode, 0]
if (PlatformHelpers.IsDotNet50OrGreater)
{
il.Ldfld(slotType.GetField("Next")); // stack: [slot.Next]
il.Ldc_I4(-1); // stack: [slot.Next, -1]
}
else
{
il.Ldfld(slotType.GetField("hashCode", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [slot.hashCode]
il.Ldc_I4(0); // stack: [slot.hashCode, 0]
}
var nextLabel = il.DefineLabel("next");
il.Blt(nextLabel, false); // if(slot.hashCode < 0) goto next; stack: []

il.Ldloc(slot); // stack: [slot]
il.Ldfld(slotType.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [slot.value]
il.Ldfld(slotType.GetField(PlatformHelpers.HashSetSlotValueFieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); // stack: [slot.value]
il.Ldc_I4(1); // stack: [obj[i], true]
context.LoadResult(); // stack: [obj[i], true, result]
context.LoadIndexByRef(); // stack: [obj[i], true, result, ref index]
Expand Down
Loading

0 comments on commit 4689827

Please sign in to comment.