Skip to content

Commit

Permalink
Pad: ICollection<> implementation (#458)
Browse files Browse the repository at this point in the history
  • Loading branch information
viceroypenguin authored May 25, 2023
1 parent 479a773 commit 6064d42
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 203 deletions.
75 changes: 55 additions & 20 deletions Source/SuperLinq/Pad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,36 +94,71 @@ public static IEnumerable<TSource> Pad<TSource>(this IEnumerable<TSource> source
Guard.IsGreaterThanOrEqualTo(width, 0);

if (source is IList<TSource> list)
return new PadIterator<TSource>(list, width, paddingSelector);
return new PadListIterator<TSource>(list, width, paddingSelector);

return Core(source, width, paddingSelector);
if (source.TryGetCollectionCount() is int)
return new PadCollectionIterator<TSource>(source, width, paddingSelector);

static IEnumerable<TSource> Core(
IEnumerable<TSource> source, int width,
Func<int, TSource> paddingSelector)
return PadCore(source, width, paddingSelector);
}

private static IEnumerable<TSource> PadCore<TSource>(
IEnumerable<TSource> source, int width,
Func<int, TSource> paddingSelector)
{
var count = 0;
foreach (var item in source)
{
yield return item;
count++;
}

while (count < width)
{
yield return paddingSelector(count);
count++;
}
}

private sealed class PadCollectionIterator<T> : CollectionIterator<T>
{
private readonly IEnumerable<T> _source;
private readonly int _width;
private readonly Func<int, T> _paddingSelector;

public PadCollectionIterator(
IEnumerable<T> source, int width,
Func<int, T> paddingSelector)
{
var count = 0;
foreach (var item in source)
{
yield return item;
count++;
}

while (count < width)
{
yield return paddingSelector(count);
count++;
}
_source = source;
_width = width;
_paddingSelector = paddingSelector;
}

public override int Count => Math.Max(_source.GetCollectionCount(), _width);

protected override IEnumerable<T> GetEnumerable() =>
PadCore(_source, _width, _paddingSelector);

public override void CopyTo(T[] array, int arrayIndex)
{
Guard.IsNotNull(array);
Guard.IsBetweenOrEqualTo(arrayIndex, 0, array.Length - Count);

var cnt = _source.CopyTo(array, arrayIndex);

for (var i = cnt; i < _width; i++)
array[arrayIndex + i] = _paddingSelector(i);
}
}

private sealed class PadIterator<T> : ListIterator<T>
private sealed class PadListIterator<T> : ListIterator<T>
{
private readonly IList<T> _source;
private readonly int _width;
private readonly Func<int, T> _paddingSelector;

public PadIterator(IList<T> source, int width, Func<int, T> paddingSelector)
public PadListIterator(IList<T> source, int width, Func<int, T> paddingSelector)
{
_source = source;
_width = width;
Expand All @@ -146,7 +181,7 @@ protected override IEnumerable<T> GetEnumerable()
public override void CopyTo(T[] array, int arrayIndex)
{
Guard.IsNotNull(array);
Guard.IsGreaterThanOrEqualTo(arrayIndex, 0);
Guard.IsBetweenOrEqualTo(arrayIndex, 0, array.Length - Count);

_source.CopyTo(array, arrayIndex);

Expand Down
Loading

0 comments on commit 6064d42

Please sign in to comment.