Files
sharpcompress/src/SharpCompress/LazyAsyncReadOnlyCollection.cs

104 lines
2.7 KiB
C#
Raw Normal View History

2026-01-08 09:14:46 +00:00
#nullable disable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress;
2026-01-08 09:41:48 +00:00
internal sealed class LazyAsyncReadOnlyCollection<T>(IAsyncEnumerable<T> source)
: IAsyncEnumerable<T>
2026-01-08 09:14:46 +00:00
{
private readonly List<T> _backing = new();
private readonly IAsyncEnumerator<T> _source = source.GetAsyncEnumerator();
private bool _fullyLoaded;
2026-01-08 09:14:46 +00:00
2026-01-08 09:41:48 +00:00
private class LazyLoader(
LazyAsyncReadOnlyCollection<T> lazyReadOnlyCollection,
CancellationToken cancellationToken
) : IAsyncEnumerator<T>
2026-01-08 09:14:46 +00:00
{
private bool _disposed;
private int _index = -1;
2026-01-08 09:14:46 +00:00
public ValueTask DisposeAsync()
{
if (!_disposed)
2026-01-08 09:14:46 +00:00
{
_disposed = true;
2026-01-08 09:14:46 +00:00
}
return default;
}
public async ValueTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (_index + 1 < lazyReadOnlyCollection._backing.Count)
2026-01-08 09:14:46 +00:00
{
_index++;
2026-01-08 09:14:46 +00:00
return true;
}
2026-01-08 09:41:48 +00:00
if (
!lazyReadOnlyCollection._fullyLoaded
&& await lazyReadOnlyCollection._source.MoveNextAsync()
2026-01-08 09:41:48 +00:00
)
2026-01-08 09:14:46 +00:00
{
lazyReadOnlyCollection._backing.Add(lazyReadOnlyCollection._source.Current);
_index++;
2026-01-08 09:14:46 +00:00
return true;
}
lazyReadOnlyCollection._fullyLoaded = true;
2026-01-08 09:14:46 +00:00
return false;
}
#region IEnumerator<T> Members
public T Current => lazyReadOnlyCollection._backing[_index];
2026-01-08 09:14:46 +00:00
#endregion
#region IDisposable Members
public void Dispose()
{
if (!_disposed)
2026-01-08 09:14:46 +00:00
{
_disposed = true;
2026-01-08 09:14:46 +00:00
}
}
#endregion
}
internal async ValueTask EnsureFullyLoaded()
{
if (!_fullyLoaded)
2026-01-08 09:14:46 +00:00
{
var loader = new LazyLoader(this, CancellationToken.None);
while (await loader.MoveNextAsync())
{
// Intentionally empty
}
_fullyLoaded = true;
2026-01-08 09:14:46 +00:00
}
}
internal IEnumerable<T> GetLoaded() => _backing;
2026-01-08 09:14:46 +00:00
#region ICollection<T> Members
public void Add(T item) => throw new NotSupportedException();
public void Clear() => throw new NotSupportedException();
public bool IsReadOnly => true;
public bool Remove(T item) => throw new NotSupportedException();
#endregion
2026-01-08 09:41:48 +00:00
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default) =>
new LazyLoader(this, cancellationToken);
2026-01-08 09:14:46 +00:00
}