// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.ClearScript.Test
{
// ReSharper disable once PartialTypeWithSinglePart
public static partial class TestEnumerable
{
public interface IDisposableEnumeratorFactory
{
int DisposedEnumeratorCount { get; }
}
public static IEnumerable CreateGeneric(params T[] items)
{
return CreateInternal(items);
}
public static IEnumerable Create(params T[] items)
{
return CreateGeneric(items);
}
public static IAsyncEnumerable CreateAsync(params T[] items)
{
return CreateInternal(items);
}
private static TestEnumerableImpl CreateInternal(T[] items)
{
return new TestEnumerableImpl(items);
}
// ReSharper disable once PartialTypeWithSinglePart
private partial class TestEnumerableImpl : IEnumerable, IAsyncEnumerable, IDisposableEnumeratorFactory
{
private readonly T[] items;
private int disposedEnumeratorCount;
public TestEnumerableImpl(T[] items)
{
this.items = items;
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
// ReSharper disable once NotDisposedResourceIsReturned
return ((IEnumerable)this).GetEnumerator();
}
IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken)
{
return new Enumerator(this);
}
int IDisposableEnumeratorFactory.DisposedEnumeratorCount => disposedEnumeratorCount;
// ReSharper disable once PartialTypeWithSinglePart
private partial class Enumerator : IEnumerator, IAsyncEnumerator
{
private readonly TestEnumerableImpl enumerable;
private int index = -1;
public Enumerator(TestEnumerableImpl enumerable)
{
this.enumerable = enumerable;
}
T IEnumerator.Current => enumerable.items[index];
object IEnumerator.Current => ((IEnumerator)this).Current;
bool IEnumerator.MoveNext()
{
return ++index < enumerable.items.Length;
}
void IEnumerator.Reset()
{
throw new NotImplementedException();
}
void IDisposable.Dispose()
{
Interlocked.Increment(ref enumerable.disposedEnumeratorCount);
}
T IAsyncEnumerator.Current => ((IEnumerator)this).Current;
ValueTask IAsyncEnumerator.MoveNextAsync()
{
return new ValueTask(((IEnumerator)this).MoveNext());
}
ValueTask IAsyncDisposable.DisposeAsync()
{
((IDisposable)this).Dispose();
return default;
}
}
}
}
}