clean up lazy readonly collections and add tests

This commit is contained in:
Adam Hathcock
2026-01-13 16:39:55 +00:00
parent 4fa976b478
commit ca4cf25a1f
4 changed files with 783 additions and 43 deletions

View File

@@ -10,23 +10,23 @@ namespace SharpCompress;
internal sealed class LazyAsyncReadOnlyCollection<T>(IAsyncEnumerable<T> source)
: IAsyncEnumerable<T>
{
private readonly List<T> backing = new();
private readonly IAsyncEnumerator<T> source = source.GetAsyncEnumerator();
private bool fullyLoaded;
private readonly List<T> _backing = new();
private readonly IAsyncEnumerator<T> _source = source.GetAsyncEnumerator();
private bool _fullyLoaded;
private class LazyLoader(
LazyAsyncReadOnlyCollection<T> lazyReadOnlyCollection,
CancellationToken cancellationToken
) : IAsyncEnumerator<T>
{
private bool disposed;
private int index = -1;
private bool _disposed;
private int _index = -1;
public ValueTask DisposeAsync()
{
if (!disposed)
if (!_disposed)
{
disposed = true;
_disposed = true;
}
return default;
}
@@ -34,27 +34,27 @@ internal sealed class LazyAsyncReadOnlyCollection<T>(IAsyncEnumerable<T> source)
public async ValueTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (index + 1 < lazyReadOnlyCollection.backing.Count)
if (_index + 1 < lazyReadOnlyCollection._backing.Count)
{
index++;
_index++;
return true;
}
if (
!lazyReadOnlyCollection.fullyLoaded
&& await lazyReadOnlyCollection.source.MoveNextAsync()
!lazyReadOnlyCollection._fullyLoaded
&& await lazyReadOnlyCollection._source.MoveNextAsync()
)
{
lazyReadOnlyCollection.backing.Add(lazyReadOnlyCollection.source.Current);
index++;
lazyReadOnlyCollection._backing.Add(lazyReadOnlyCollection._source.Current);
_index++;
return true;
}
lazyReadOnlyCollection.fullyLoaded = true;
lazyReadOnlyCollection._fullyLoaded = true;
return false;
}
#region IEnumerator<T> Members
public T Current => lazyReadOnlyCollection.backing[index];
public T Current => lazyReadOnlyCollection._backing[_index];
#endregion
@@ -62,9 +62,9 @@ internal sealed class LazyAsyncReadOnlyCollection<T>(IAsyncEnumerable<T> source)
public void Dispose()
{
if (!disposed)
if (!_disposed)
{
disposed = true;
_disposed = true;
}
}
@@ -73,18 +73,18 @@ internal sealed class LazyAsyncReadOnlyCollection<T>(IAsyncEnumerable<T> source)
internal async ValueTask EnsureFullyLoaded()
{
if (!fullyLoaded)
if (!_fullyLoaded)
{
var loader = new LazyLoader(this, CancellationToken.None);
while (await loader.MoveNextAsync())
{
// Intentionally empty
}
fullyLoaded = true;
_fullyLoaded = true;
}
}
internal IEnumerable<T> GetLoaded() => backing;
internal IEnumerable<T> GetLoaded() => _backing;
#region ICollection<T> Members

View File

@@ -8,24 +8,24 @@ namespace SharpCompress;
internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
{
private readonly List<T> backing = new();
private readonly IEnumerator<T> source;
private bool fullyLoaded;
private readonly List<T> _backing = new();
private readonly IEnumerator<T> _source;
private bool _fullyLoaded;
public LazyReadOnlyCollection(IEnumerable<T> source) => this.source = source.GetEnumerator();
public LazyReadOnlyCollection(IEnumerable<T> source) => _source = source.GetEnumerator();
private class LazyLoader : IEnumerator<T>
{
private readonly LazyReadOnlyCollection<T> lazyReadOnlyCollection;
private bool disposed;
private int index = -1;
private readonly LazyReadOnlyCollection<T> _lazyReadOnlyCollection;
private bool _disposed;
private int _index = -1;
internal LazyLoader(LazyReadOnlyCollection<T> lazyReadOnlyCollection) =>
this.lazyReadOnlyCollection = lazyReadOnlyCollection;
_lazyReadOnlyCollection = lazyReadOnlyCollection;
#region IEnumerator<T> Members
public T Current => lazyReadOnlyCollection.backing[index];
public T Current => _lazyReadOnlyCollection._backing[_index];
#endregion
@@ -33,9 +33,9 @@ internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
public void Dispose()
{
if (!disposed)
if (!_disposed)
{
disposed = true;
_disposed = true;
}
}
@@ -47,18 +47,18 @@ internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
public bool MoveNext()
{
if (index + 1 < lazyReadOnlyCollection.backing.Count)
if (_index + 1 < _lazyReadOnlyCollection._backing.Count)
{
index++;
_index++;
return true;
}
if (!lazyReadOnlyCollection.fullyLoaded && lazyReadOnlyCollection.source.MoveNext())
if (!_lazyReadOnlyCollection._fullyLoaded && _lazyReadOnlyCollection._source.MoveNext())
{
lazyReadOnlyCollection.backing.Add(lazyReadOnlyCollection.source.Current);
index++;
_lazyReadOnlyCollection._backing.Add(_lazyReadOnlyCollection._source.Current);
_index++;
return true;
}
lazyReadOnlyCollection.fullyLoaded = true;
_lazyReadOnlyCollection._fullyLoaded = true;
return false;
}
@@ -69,14 +69,14 @@ internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
internal void EnsureFullyLoaded()
{
if (!fullyLoaded)
if (!_fullyLoaded)
{
this.ForEach(x => { });
fullyLoaded = true;
_fullyLoaded = true;
}
}
internal IEnumerable<T> GetLoaded() => backing;
internal IEnumerable<T> GetLoaded() => _backing;
#region ICollection<T> Members
@@ -87,13 +87,13 @@ internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
public bool Contains(T item)
{
EnsureFullyLoaded();
return backing.Contains(item);
return _backing.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
EnsureFullyLoaded();
backing.CopyTo(array, arrayIndex);
_backing.CopyTo(array, arrayIndex);
}
public int Count
@@ -101,7 +101,7 @@ internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
get
{
EnsureFullyLoaded();
return backing.Count;
return _backing.Count;
}
}