using System;
using System.Collections;
using System.Collections.Generic;
namespace PKHeX.Core
{
///
/// Iterates a generic collection with the ability to peek into the collection to see if the next element exists.
///
/// Generic Collection Element Type
public class PeekEnumerator : IEnumerator
{
private readonly IEnumerator Enumerator;
private T peek;
private bool didPeek;
#region IEnumerator Implementation
///
/// Advances the enumerator to the next element in the collection.
///
/// Indication if there are more elements in the collection.
public bool MoveNext()
{
if (!didPeek)
return Enumerator.MoveNext();
didPeek = false;
return true;
}
///
/// Sets the enumerator to its initial position, which is before the first element in the collection.
///
public void Reset()
{
Enumerator.Reset();
didPeek = false;
}
object IEnumerator.Current => Current;
public void Dispose() => Enumerator.Dispose();
public T Current => didPeek ? peek : Enumerator.Current;
#endregion
public PeekEnumerator(IEnumerator enumerator) => Enumerator = enumerator ?? throw new ArgumentNullException(nameof(enumerator));
public PeekEnumerator(IEnumerable enumerable) => Enumerator = enumerable.GetEnumerator();
///
/// Fetch the next element, if not already performed.
///
/// True/False that a Next element exists
/// Advances the enumerator if Next has not been peeked already
private bool TryFetchPeek()
{
if (!didPeek && (didPeek = Enumerator.MoveNext()))
peek = Enumerator.Current;
return didPeek;
}
///
/// Peeks to the next element
///
/// Next element
/// Throws an exception if no element exists
public T Peek()
{
if (!TryFetchPeek())
throw new InvalidOperationException("Enumeration already finished.");
return peek;
}
public T PeekOrDefault() => !TryFetchPeek() ? default(T) : peek;
///
/// Checks if a Next element exists
///
/// True/False that a Next element exists
public bool PeekIsNext() => TryFetchPeek();
}
}