// 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; } } } } }