DotNext by Roman Sakno

<PackageReference Include="DotNext" Version="3.2.0" />

 DelegatingReadOnlySpanConsumer<T, TArg>

Represents implementation of IReadOnlySpanConsumer<T> that delegates invocation to the delegate of type ReadOnlySpanAction<T, U>.
using System; using System.Buffers; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace DotNext.Buffers { [StructLayout(LayoutKind.Auto)] [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public readonly struct DelegatingReadOnlySpanConsumer<[System.Runtime.CompilerServices.Nullable(2)] T, [System.Runtime.CompilerServices.Nullable(2)] TArg> : IReadOnlySpanConsumer<T>, ISupplier<ReadOnlyMemory<T>, CancellationToken, ValueTask> { private readonly ReadOnlySpanAction<T, TArg> action; private readonly TArg arg; public bool IsEmpty => action == null; public DelegatingReadOnlySpanConsumer(ReadOnlySpanAction<T, TArg> action, TArg arg) { if (action == null) throw new ArgumentNullException("action"); this.action = action; this.arg = arg; } void IReadOnlySpanConsumer<T>.Invoke([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> span) { action(span, arg); } ValueTask ISupplier<ReadOnlyMemory<T>, CancellationToken, ValueTask>.Invoke([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlyMemory<T> input, CancellationToken token) { if (!token.IsCancellationRequested) { ValueTask result = default(ValueTask); try { action(input.Span, arg); return result; } catch (Exception exception) { return new ValueTask(Task.FromException(exception)); } } return new ValueTask(Task.FromCanceled(token)); } } }