Skip to content

Commit

Permalink
Refactor bindings (#334)
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmada committed Feb 26, 2021
1 parent 7bc4818 commit 4112aae
Show file tree
Hide file tree
Showing 22 changed files with 423 additions and 631 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using NetFabric.Assertive;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Generic
{
public class ListTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_List_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = source.ToList();

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<ArrayExtensions.ArraySegmentValueEnumerable<int>>()
.BeEnumerableOf<int>()
.BeEqualTo(source, testRefStructs: false);
_ = result.SequenceEqual(source).Must().BeTrue();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using NetFabric.Assertive;
using System.Collections.Immutable;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableArrayTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableArray_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = source.ToImmutableArray();

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<ReadOnlyListExtensions.ListValueEnumerable<int>>()
// .BeOfType<ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableArray<int>, ValueEnumerator<int>, ImmutableArray<int>.Enumerator, int, ImmutableArrayExtensions.GetEnumerator<int>, ImmutableArrayExtensions.GetEnumerator2<int>>>()
.BeEnumerableOf<int>()
.BeEqualTo(source);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using NetFabric.Assertive;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableDictionaryTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableDictionary_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = source.ToImmutableDictionary(item => item, default);
var expected = source.ToDictionary(item => item);

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableDictionary<int, int>, ImmutableDictionary<int, int>.Enumerator, ImmutableDictionary<int, int>.Enumerator, KeyValuePair<int, int>, ImmutableDictionaryExtensions.GetEnumerator<int, int>, ImmutableDictionaryExtensions.GetEnumerator<int, int>>>()
.BeEnumerableOf<KeyValuePair<int, int>>()
.BeEqualTo(expected);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using NetFabric.Assertive;
using System.Collections.Immutable;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableHashSetTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableHashSet_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = source.ToImmutableHashSet();

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableHashSet<int>, ImmutableHashSet<int>.Enumerator, ImmutableHashSet<int>.Enumerator, int, ImmutableHashSetExtensions.GetEnumerator<int>, ImmutableHashSetExtensions.GetEnumerator<int>>>()
.BeEnumerableOf<int>()
.BeEqualTo(source);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using NetFabric.Assertive;
using System.Collections.Immutable;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableListTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableList_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = source.ToImmutableList();

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableList<int>, ImmutableList<int>.Enumerator, ImmutableList<int>.Enumerator, int, ImmutableListExtensions.GetEnumerator<int>, ImmutableListExtensions.GetEnumerator<int>>>()
.BeEnumerableOf<int>()
.BeEqualTo(source);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using NetFabric.Assertive;
using System.Collections.Immutable;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableQueueTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableQueue_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = ImmutableQueue.Create(source);

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<EnumerableExtensions.ValueEnumerable<ImmutableQueue<int>, ValueEnumerator<int>, ImmutableQueue<int>.Enumerator, int, ImmutableQueueExtensions.GetEnumerator<int>, ImmutableQueueExtensions.GetEnumerator2<int>>>()
.BeEnumerableOf<int>()
.BeEqualTo(source);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using NetFabric.Assertive;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableSortedDictionaryTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableSortedDictionry_Must_ReturnWrapper(int[] source)
{
// Arrange
var dictionary = source.ToDictionary(item => item);
var wrapped = ImmutableSortedDictionary.CreateRange(default, dictionary);
var expected = new SortedDictionary<int, int>(dictionary);

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableSortedDictionary<int, int>, ImmutableSortedDictionary<int, int>.Enumerator, ImmutableSortedDictionary<int, int>.Enumerator, KeyValuePair<int, int>, ImmutableSortedDictionaryExtensions.GetEnumerator<int, int>, ImmutableSortedDictionaryExtensions.GetEnumerator<int, int>>>()
.BeEnumerableOf<KeyValuePair<int, int>>()
.BeEqualTo(expected);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using NetFabric.Assertive;
using System.Collections.Generic;
using System.Collections.Immutable;
using Xunit;

namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Bindings.System.Collections.Immutable
{
public class ImmutableStackTests
{
[Theory]
[MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Single), MemberType = typeof(TestData))]
[MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))]
public void AsValueEnumerable_With_ImmutableStack_Must_ReturnWrapper(int[] source)
{
// Arrange
var wrapped = ImmutableStack.Create(source);
var expected = new Stack<int>(source);

// Act
var result = wrapped.AsValueEnumerable();

// Assert
_ = result.Must()
.BeOfType<EnumerableExtensions.ValueEnumerable<ImmutableStack<int>, ValueEnumerator<int>, ImmutableStack<int>.Enumerator, int, ImmutableStackExtensions.GetEnumerator<int>, ImmutableStackExtensions.GetEnumerator2<int>>>()
.BeEnumerableOf<int>()
.BeEqualTo(expected);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net461' Or '$(TargetFramework)' == 'netcoreapp2.1'">
<Compile Remove="Conversion\AsValueEnumerable\Bindings\System\Collections\Immutable\*.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.0.3">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace NetFabric.Hyperlinq
{
public static class ListBindings
{
// List<TSource> is simply converted to ArraySegment<TSource> and share its IValueEnumerable<TSource> wrapper.
// It's not converted to ReadOnlySpan<TSource> because its enumerators cannot be casted to IEnumerable<TSource>, restricting its use.
// It's not converted to ReadOnlyMemory<TSource> because it's less efficient in enumerables (it has to call .Span on each iteration).

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ArrayExtensions.ArraySegmentValueEnumerable<TSource> AsValueEnumerable<TSource>(this List<TSource> source)
=> source.AsArraySegment().AsValueEnumerable();

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ArrayExtensions.ArraySegmentValueEnumerableRef<TSource> AsValueEnumerableRef<TSource>(this List<TSource> source)
=> source.AsArraySegment().AsValueEnumerableRef();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace NetFabric.Hyperlinq
{
public static class ImmutableArrayExtensions
{
// ImmutableArray<TSource> implements IReadOnlyList<TSource>
// No need for bindings
/*
// ImmutableArray<TSource> implements IReadOnlyCollection<TSource> and has two enumerators:
// One that is a value-type and doesn't implement interfaces.
// Another that is a reference-type and implements IEnumerator<TSource>.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableArray<TSource>, ValueEnumerator<TSource>, ImmutableArray<TSource>.Enumerator, TSource, GetEnumerator<TSource>, GetEnumerator2<TSource>> AsValueEnumerable<TSource>(this ImmutableArray<TSource> source)
=> ReadOnlyCollectionExtensions.AsValueEnumerable<ImmutableArray<TSource>, ValueEnumerator<TSource>, ImmutableArray<TSource>.Enumerator, TSource, GetEnumerator<TSource>, GetEnumerator2<TSource>>(source);
[StructLayout(LayoutKind.Auto)]
public readonly struct GetEnumerator<TSource>
: IFunction<ImmutableArray<TSource>, ValueEnumerator<TSource>>
{
public ValueEnumerator<TSource> Invoke(ImmutableArray<TSource> source)
=> new(((IEnumerable<TSource>)source).GetEnumerator());
}
[StructLayout(LayoutKind.Auto)]
public readonly struct GetEnumerator2<TSource>
: IFunction<ImmutableArray<TSource>, ImmutableArray<TSource>.Enumerator>
{
public ImmutableArray<TSource>.Enumerator Invoke(ImmutableArray<TSource> source)
=> source.GetEnumerator();
}
*/
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace NetFabric.Hyperlinq
{
public static class ImmutableDictionaryExtensions
{
// ImmutableDictionary<TKey, TValue> implements IReadOnlyCollection<KeyValuePair<TKey, TValue>> and has a value-type enumerator that implements IEnumerator<TKey, TValue>

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableDictionary<TKey, TValue>, ImmutableDictionary<TKey, TValue>.Enumerator, ImmutableDictionary<TKey, TValue>.Enumerator, KeyValuePair<TKey, TValue>, GetEnumerator<TKey, TValue>, GetEnumerator<TKey, TValue>> AsValueEnumerable<TKey, TValue>(this ImmutableDictionary<TKey, TValue> source)
where TKey: notnull
=> ReadOnlyCollectionExtensions.AsValueEnumerable<ImmutableDictionary<TKey, TValue>, ImmutableDictionary<TKey, TValue>.Enumerator, KeyValuePair<TKey, TValue>, GetEnumerator<TKey, TValue>>(source);

[StructLayout(LayoutKind.Auto)]
public readonly struct GetEnumerator<TKey, TValue>
: IFunction<ImmutableDictionary<TKey, TValue>, ImmutableDictionary<TKey, TValue>.Enumerator>
where TKey: notnull
{
public ImmutableDictionary<TKey, TValue>.Enumerator Invoke(ImmutableDictionary<TKey, TValue> source)
=> source.GetEnumerator();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

namespace NetFabric.Hyperlinq
{
[GeneratorIgnore]
public static class ImmutableHashSetExtensions
{
// ImmutableHashSet<TSource> has a value-type enumerator that implements IEnumerator<TSource>
// ImmutableHashSet<TSource> implements IReadOnlyCollection<TSource> and has a value-type enumerator that implements IEnumerator<TSource>

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableHashSet<TSource>, ImmutableHashSet<TSource>.Enumerator, ImmutableHashSet<TSource>.Enumerator, TSource, GetEnumerator<TSource>, GetEnumerator<TSource>> AsValueEnumerable<TSource>(this ImmutableHashSet<TSource> source)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

namespace NetFabric.Hyperlinq
{
[GeneratorIgnore]
public static class ImmutableListExtensions
{
// ImmutableList<TSource> has a value-type enumerator that implements IEnumerator<TSource>
// ImmutableList<TSource> implements IReadOnlyCollection<TSource> and has a value-type enumerator that implements IEnumerator<TSource>

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlyCollectionExtensions.ValueEnumerable<ImmutableList<TSource>, ImmutableList<TSource>.Enumerator, ImmutableList<TSource>.Enumerator, TSource, GetEnumerator<TSource>, GetEnumerator<TSource>> AsValueEnumerable<TSource>(this ImmutableList<TSource> source)
Expand Down
Loading

0 comments on commit 4112aae

Please sign in to comment.