// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace System.Linq
{
public static partial class AsyncEnumerable
{
///
/// Generates an async-enumerable sequence that repeats the given element the specified number of times.
///
/// The type of the element that will be repeated in the produced sequence.
/// Element to repeat.
/// Number of times to repeat the element.
/// An async-enumerable sequence that repeats the given element the specified number of times.
/// is less than zero.
public static IAsyncEnumerable Repeat(TResult element, int count)
{
if (count < 0)
throw Error.ArgumentOutOfRange(nameof(count));
return new RepeatAsyncIterator(element, count);
}
private sealed class RepeatAsyncIterator : AsyncIterator, IAsyncIListProvider
{
private readonly TResult _element;
private readonly int _count;
private int _remaining;
public RepeatAsyncIterator(TResult element, int count)
{
_element = element;
_count = count;
}
public override AsyncIteratorBase Clone() => new RepeatAsyncIterator(_element, _count);
public ValueTask GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) => new ValueTask(_count);
public ValueTask ToArrayAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var res = new TResult[_count];
for (var i = 0; i < _count; i++)
{
res[i] = _element;
}
return new ValueTask(res);
}
public ValueTask> ToListAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var res = new List(_count);
for (var i = 0; i < _count; i++)
{
res.Add(_element);
}
return new ValueTask>(res);
}
protected override async ValueTask MoveNextCore()
{
switch (_state)
{
case AsyncIteratorState.Allocated:
_remaining = _count;
if (_remaining > 0)
{
_current = _element;
}
_state = AsyncIteratorState.Iterating;
goto case AsyncIteratorState.Iterating;
case AsyncIteratorState.Iterating:
if (_remaining-- != 0)
{
return true;
}
break;
}
await DisposeAsync().ConfigureAwait(false);
return false;
}
}
}
}