DotNext by Roman Sakno

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

 MemoryTemplate<T>

public struct MemoryTemplate<T> where T : IEquatable<T>
Represents generic template for buffer rendering.
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 MemoryTemplate<[System.Runtime.CompilerServices.Nullable(0)] T> where T : IEquatable<T> { [System.Runtime.CompilerServices.NullableContext(0)] private sealed class Placeholder { internal readonly int Offset; [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0 })] internal Placeholder Next; internal Placeholder(int offset) { Offset = offset; } } [StructLayout(LayoutKind.Auto)] [System.Runtime.CompilerServices.Nullable(0)] private readonly struct BufferConsumer<TWriter> : IReadOnlySpanConsumer<T>, ISupplier<ReadOnlyMemory<T>, CancellationToken, ValueTask>, IConsumer<int> where TWriter : class, IBufferWriter<T> { private readonly TWriter buffer; private readonly Action<int, TWriter> rewriter; internal BufferConsumer(TWriter buffer, Action<int, TWriter> rewriter) { this.buffer = buffer; this.rewriter = rewriter; } void IReadOnlySpanConsumer<T>.Invoke([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> input) { BuffersExtensions.Write<T>((IBufferWriter<T>)buffer, input); } void IConsumer<int>.Invoke(int index) { rewriter(index, buffer); } } [StructLayout(LayoutKind.Auto)] [System.Runtime.CompilerServices.Nullable(0)] private readonly struct DelegatingConsumer<[System.Runtime.CompilerServices.Nullable(2)] TArg> : IReadOnlySpanConsumer<T>, ISupplier<ReadOnlyMemory<T>, CancellationToken, ValueTask>, IConsumer<int> { private readonly ReadOnlySpanAction<T, TArg> output; private readonly Action<int, TArg> rewriter; private readonly TArg state; internal DelegatingConsumer(ReadOnlySpanAction<T, TArg> output, Action<int, TArg> rewriter, TArg state) { this.output = output; this.rewriter = rewriter; this.state = state; } void IReadOnlySpanConsumer<T>.Invoke([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> input) { output(input, state); } void IConsumer<int>.Invoke(int index) { rewriter(index, state); } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private readonly ReadOnlyMemory<T> template; [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0 })] private readonly Placeholder firstOccurence; private readonly int placeholderLength; [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public ReadOnlyMemory<T> Value { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] get { return template; } } public MemoryTemplate([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlyMemory<T> template, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> placeholder) { this.template = template; if (placeholder.IsEmpty || placeholder.Length > template.Length) { placeholderLength = 0; firstOccurence = null; } else { placeholderLength = placeholder.Length; firstOccurence = BuildPlaceholdersChain(template.Span, placeholder); } } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0 })] private static Placeholder BuildPlaceholdersChain([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> source, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> placeholder) { Placeholder head = null; Placeholder tail = null; int num = 0; while (num < source.Length - placeholder.Length + 1) { if (MemoryExtensions.SequenceEqual<T>(source.Slice(num, placeholder.Length), placeholder)) { CreateNode(ref head, ref tail, num); num += placeholder.Length; } else num++; } return head; } private static void CreateNode([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0 })] ref Placeholder head, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0 })] ref Placeholder tail, int offset) { if (head == null || tail == null) head = (tail = new Placeholder(offset)); else { Placeholder placeholder = tail; tail = (placeholder.Next = new Placeholder(offset)); } } public void Render<TConsumer>(TConsumer consumer) where TConsumer : IReadOnlySpanConsumer<T>, IConsumer<int> { ReadOnlySpan<T> span = this.template.Span; Placeholder placeholder = this.firstOccurence; int offset = 0; int num = 0; int num2 = 0; bool isPlaceholder; while (this.MoveNext(ref offset, ref placeholder, out isPlaceholder)) { if (isPlaceholder) ((IConsumer<int>)consumer).Invoke(num2++); else ((IReadOnlySpanConsumer<T>)consumer).Invoke(span.Slice(num, offset - num)); num = offset; } } public void Render<TWriter>(TWriter output, Action<int, TWriter> rewriter) where TWriter : class, IBufferWriter<T> { if (output == null) throw new ArgumentNullException("output"); if (rewriter == null) throw new ArgumentNullException("rewriter"); Render(new BufferConsumer<TWriter>(output, rewriter)); } public void Render<[System.Runtime.CompilerServices.Nullable(2)] TArg>(TArg arg, Action<int, TArg> rewriter, ReadOnlySpanAction<T, TArg> output) { Render(new DelegatingConsumer<TArg>(output, rewriter, arg)); } private bool MoveNext(ref int offset, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 0 })] ref Placeholder placeholder, out bool isPlaceholder) { if (offset >= template.Length) { isPlaceholder = false; return false; } if (placeholder == null) { isPlaceholder = false; offset = template.Length; } else if (placeholder.Offset == offset) { isPlaceholder = true; offset += placeholderLength; placeholder = placeholder.Next; } else { offset = placeholder.Offset; isPlaceholder = false; } return true; } } }