-
-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
136cd45
commit 9d5676b
Showing
7 changed files
with
125 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Riok.Mapperly.Helpers; | ||
|
||
internal class HashHelper | ||
{ | ||
public static int Combine(int h1, int h2) | ||
{ | ||
// RyuJIT optimizes this to use the ROL instruction | ||
// Related GitHub pull request: https://github.com/dotnet/coreclr/pull/1830 | ||
uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27); | ||
return ((int)rol5 + h1) ^ h2; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections; | ||
using Riok.Mapperly.Helpers; | ||
|
||
namespace Riok.Mapperly; | ||
|
||
/// <summary> | ||
/// Provides an immutable list implementation which implements sequence equality. | ||
/// </summary> | ||
public sealed class ImmutableEquatableArray<T> : IEquatable<ImmutableEquatableArray<T>>, IReadOnlyList<T> | ||
where T : IEquatable<T> | ||
{ | ||
public static ImmutableEquatableArray<T> Empty { get; } = new(Array.Empty<T>()); | ||
|
||
private readonly T[] _values; | ||
public T this[int index] => _values[index]; | ||
public int Count => _values.Length; | ||
|
||
public ImmutableEquatableArray(IEnumerable<T> values) => _values = values.ToArray(); | ||
|
||
public bool Equals(ImmutableEquatableArray<T>? other) => other != null && ((ReadOnlySpan<T>)_values).SequenceEqual(other._values); | ||
|
||
public override bool Equals(object? obj) => obj is ImmutableEquatableArray<T> other && Equals(other); | ||
|
||
public override int GetHashCode() | ||
{ | ||
var hash = 0; | ||
foreach (T value in _values) | ||
{ | ||
hash = HashHelper.Combine(hash, value.GetHashCode()); | ||
} | ||
|
||
return hash; | ||
} | ||
|
||
public Enumerator GetEnumerator() => new Enumerator(_values); | ||
|
||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => ((IEnumerable<T>)_values).GetEnumerator(); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator(); | ||
|
||
public struct Enumerator | ||
{ | ||
private readonly T[] _values; | ||
private int _index; | ||
|
||
internal Enumerator(T[] values) | ||
{ | ||
_values = values; | ||
_index = -1; | ||
} | ||
|
||
public bool MoveNext() | ||
{ | ||
var newIndex = _index + 1; | ||
|
||
if ((uint)newIndex < (uint)_values.Length) | ||
{ | ||
_index = newIndex; | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public readonly T Current => _values[_index]; | ||
} | ||
} | ||
|
||
public static class ImmutableEquatableArray | ||
{ | ||
public static ImmutableEquatableArray<T> Empty<T>() | ||
where T : IEquatable<T> => ImmutableEquatableArray<T>.Empty; | ||
|
||
public static ImmutableEquatableArray<T> ToImmutableEquatableArray<T>(this IEnumerable<T> values) | ||
where T : IEquatable<T> => new(values); | ||
|
||
public static ImmutableEquatableArray<T> Create<T>(params T[] values) | ||
where T : IEquatable<T> => values is { Length: > 0 } ? new(values) : ImmutableEquatableArray<T>.Empty; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,8 @@ | ||
using System.Collections.Immutable; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis; | ||
|
||
namespace Riok.Mapperly; | ||
|
||
public readonly struct MapperResults : IEquatable<MapperResults> | ||
public readonly record struct MapperResults(ImmutableEquatableArray<MapperNode> Mappers, ImmutableEquatableArray<Diagnostic> Diagnostics) | ||
{ | ||
public static readonly MapperResults Empty = new(ImmutableArray<MapperNode>.Empty, ImmutableArray<Diagnostic>.Empty); | ||
|
||
public MapperResults(ImmutableArray<MapperNode> mappers, ImmutableArray<Diagnostic> diagnostics) | ||
{ | ||
Mappers = mappers; | ||
Diagnostics = diagnostics; | ||
} | ||
|
||
public ImmutableArray<MapperNode> Mappers { get; } | ||
public ImmutableArray<Diagnostic> Diagnostics { get; } | ||
|
||
public bool Equals(MapperResults other) | ||
{ | ||
return Mappers.SequenceEqual(other.Mappers) && Diagnostics.SequenceEqual(other.Diagnostics); | ||
} | ||
|
||
public override bool Equals(object? obj) => obj is MapperResults other && Equals(other); | ||
|
||
public override int GetHashCode() | ||
{ | ||
unchecked | ||
{ | ||
var hash = 0; | ||
foreach (var mapper in Mappers) | ||
{ | ||
hash = Combine(hash, mapper.GetHashCode()); | ||
} | ||
foreach (var diagnostic in Diagnostics) | ||
{ | ||
hash = Combine(hash, diagnostic.GetHashCode()); | ||
} | ||
return hash; | ||
} | ||
|
||
static int Combine(int h1, int h2) | ||
{ | ||
// RyuJIT optimizes this to use the ROL instruction | ||
// Related GitHub pull request: https://github.com/dotnet/coreclr/pull/1830 | ||
uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27); | ||
return ((int)rol5 + h1) ^ h2; | ||
} | ||
} | ||
public static readonly MapperResults Empty = new(ImmutableEquatableArray<MapperNode>.Empty, ImmutableEquatableArray<Diagnostic>.Empty); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters