AsyncEnumerableAdapter
using NUnit.Framework.Internal.Extensions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace NUnit.Framework.Internal
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal static class AsyncEnumerableAdapter
{
[System.Runtime.CompilerServices.Nullable(0)]
private class AsyncEnumerableWrapper : IEnumerable<object>, IEnumerable
{
private readonly AsyncEnumerableShapeInfo _shape;
private readonly object _asyncEnumerable;
private readonly MethodInfo _getAsyncEnumeratorMethod;
private static readonly object[] EnumeratorArgs = new object[1] {
CancellationToken.None
};
public AsyncEnumerableWrapper(AsyncEnumerableShapeInfo shape, object asyncEnumerable)
{
_shape = shape;
_asyncEnumerable = asyncEnumerable;
_getAsyncEnumeratorMethod = shape.GetAsyncEnumeratorMethod;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
2
})]
public IEnumerator<object> GetEnumerator()
{
return new AsyncEnumeratorWrapper(_shape, _getAsyncEnumeratorMethod.Invoke(_asyncEnumerable, EnumeratorArgs));
}
IEnumerator IEnumerable.GetEnumerator()
{
return new AsyncEnumeratorWrapper(_shape, _getAsyncEnumeratorMethod.Invoke(_asyncEnumerable, EnumeratorArgs));
}
}
[System.Runtime.CompilerServices.NullableContext(0)]
private class AsyncEnumeratorWrapper : IEnumerator<object>, IDisposable, IEnumerator
{
[System.Runtime.CompilerServices.Nullable(1)]
private readonly object _asyncEnumerator;
[System.Runtime.CompilerServices.Nullable(1)]
private readonly MethodInfo _disposeAsyncMethod;
[System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0
})]
private readonly Func<ValueTask<bool>> _moveNextAsyncMethod;
[System.Runtime.CompilerServices.Nullable(new byte[] {
1,
2
})]
private readonly Func<object> _getCurrentMethod;
[System.Runtime.CompilerServices.Nullable(2)]
public object Current {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _getCurrentMethod();
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
public AsyncEnumeratorWrapper(AsyncEnumerableShapeInfo shape, object asyncEnumerator)
{
_asyncEnumerator = asyncEnumerator;
_disposeAsyncMethod = shape.DisposeAsyncMethod;
_moveNextAsyncMethod = MethodInfoExtensions.CreateDelegate<Func<ValueTask<bool>>>(shape.MoveNextAsyncMethod, asyncEnumerator);
_getCurrentMethod = MethodInfoExtensions.CreateDelegate<Func<object>>(shape.CurrentProperty.GetGetMethod(), asyncEnumerator);
}
public void Dispose()
{
AsyncToSyncAdapter.Await(() => _disposeAsyncMethod.Invoke(_asyncEnumerator, null));
}
public bool MoveNext()
{
return AsyncToSyncAdapter.Await<bool>(() => _moveNextAsyncMethod());
}
public void Reset()
{
throw new InvalidOperationException("Can not reset an async enumerable.");
}
}
[System.Runtime.CompilerServices.Nullable(0)]
private class AsyncEnumerableShapeInfo : IEquatable<AsyncEnumerableShapeInfo>
{
[CompilerGenerated]
protected virtual Type EqualityContract {
[CompilerGenerated]
get {
return typeof(AsyncEnumerableShapeInfo);
}
}
public MethodInfo GetAsyncEnumeratorMethod { get; set; }
public PropertyInfo CurrentProperty { get; set; }
public MethodInfo MoveNextAsyncMethod { get; set; }
public MethodInfo DisposeAsyncMethod { get; set; }
public AsyncEnumerableShapeInfo(MethodInfo GetAsyncEnumeratorMethod, PropertyInfo CurrentProperty, MethodInfo MoveNextAsyncMethod, MethodInfo DisposeAsyncMethod)
{
GetAsyncEnumeratorMethod = GetAsyncEnumeratorMethod;
CurrentProperty = CurrentProperty;
MoveNextAsyncMethod = MoveNextAsyncMethod;
DisposeAsyncMethod = DisposeAsyncMethod;
base..ctor();
}
[CompilerGenerated]
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("AsyncEnumerableShapeInfo");
stringBuilder.Append(" { ");
if (PrintMembers(stringBuilder))
stringBuilder.Append(' ');
stringBuilder.Append('}');
return stringBuilder.ToString();
}
[CompilerGenerated]
protected virtual bool PrintMembers(StringBuilder builder)
{
RuntimeHelpers.EnsureSufficientExecutionStack();
builder.Append("GetAsyncEnumeratorMethod = ");
builder.Append(GetAsyncEnumeratorMethod);
builder.Append(", CurrentProperty = ");
builder.Append(CurrentProperty);
builder.Append(", MoveNextAsyncMethod = ");
builder.Append(MoveNextAsyncMethod);
builder.Append(", DisposeAsyncMethod = ");
builder.Append(DisposeAsyncMethod);
return true;
}
public static bool operator !=(AsyncEnumerableShapeInfo left, AsyncEnumerableShapeInfo right)
{
return !(left == right);
}
public static bool operator ==(AsyncEnumerableShapeInfo left, AsyncEnumerableShapeInfo right)
{
if ((object)left != right)
return left?.Equals(right) ?? false;
return true;
}
[CompilerGenerated]
public override int GetHashCode()
{
return (((EqualityComparer<Type>.Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<MethodInfo>.Default.GetHashCode(GetAsyncEnumeratorMethod)) * -1521134295 + EqualityComparer<PropertyInfo>.Default.GetHashCode(CurrentProperty)) * -1521134295 + EqualityComparer<MethodInfo>.Default.GetHashCode(MoveNextAsyncMethod)) * -1521134295 + EqualityComparer<MethodInfo>.Default.GetHashCode(DisposeAsyncMethod);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[CompilerGenerated]
public override bool Equals(object obj)
{
return Equals(obj as AsyncEnumerableShapeInfo);
}
[System.Runtime.CompilerServices.NullableContext(2)]
[CompilerGenerated]
public virtual bool Equals(AsyncEnumerableShapeInfo other)
{
if ((object)this != other) {
if ((object)other != null && EqualityContract == other.EqualityContract && EqualityComparer<MethodInfo>.Default.Equals(GetAsyncEnumeratorMethod, other.GetAsyncEnumeratorMethod) && EqualityComparer<PropertyInfo>.Default.Equals(CurrentProperty, other.CurrentProperty) && EqualityComparer<MethodInfo>.Default.Equals(MoveNextAsyncMethod, other.MoveNextAsyncMethod))
return EqualityComparer<MethodInfo>.Default.Equals(DisposeAsyncMethod, other.DisposeAsyncMethod);
return false;
}
return true;
}
[CompilerGenerated]
protected AsyncEnumerableShapeInfo(AsyncEnumerableShapeInfo original)
{
GetAsyncEnumeratorMethod = original.GetAsyncEnumeratorMethod;
CurrentProperty = original.CurrentProperty;
MoveNextAsyncMethod = original.MoveNextAsyncMethod;
DisposeAsyncMethod = original.DisposeAsyncMethod;
}
[CompilerGenerated]
public void Deconstruct(out MethodInfo GetAsyncEnumeratorMethod, out PropertyInfo CurrentProperty, out MethodInfo MoveNextAsyncMethod, out MethodInfo DisposeAsyncMethod)
{
GetAsyncEnumeratorMethod = this.GetAsyncEnumeratorMethod;
CurrentProperty = this.CurrentProperty;
MoveNextAsyncMethod = this.MoveNextAsyncMethod;
DisposeAsyncMethod = this.DisposeAsyncMethod;
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
public static IEnumerable CoalesceToEnumerable(object enumerable)
{
if (enumerable == null)
return null;
IEnumerable enumerable2 = enumerable as IEnumerable;
if (enumerable2 != null)
return enumerable2;
if (TryGetAsyncBlockingEnumerable(enumerable, out IEnumerable<object> result))
return result;
throw new ArgumentException("Argument can not be converted to an IEnumerable.", "enumerable");
}
private static bool TryGetAsyncBlockingEnumerable(object enumerable, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out IEnumerable<object> result)
{
result = null;
Type interface = enumerable.GetType().GetInterface("System.Collections.Generic.IAsyncEnumerable`1");
if ((object)interface == null)
return false;
MethodInfo method = interface.GetMethod("GetAsyncEnumerator");
if ((object)method == null)
return false;
Type returnType = method.ReturnType;
PropertyInfo property = returnType.GetProperty("Current");
if ((object)property == null)
return false;
MethodInfo method2 = returnType.GetMethod("MoveNextAsync");
if ((object)method2 == null)
return false;
Type interface2 = returnType.GetInterface("System.IAsyncDisposable");
if ((object)interface2 == null)
return false;
MethodInfo method3 = interface2.GetMethod("DisposeAsync");
if ((object)method3 == null)
return false;
AsyncEnumerableShapeInfo shape = new AsyncEnumerableShapeInfo(method, property, method2, method3);
result = new AsyncEnumerableWrapper(shape, enumerable);
return true;
}
}
}