public static void Pipe(this IBufferOperation transformation, ReadOnlyBytes source, IOutput destination) { int afterMergeSlice = 0; // Assign 'remainder' to something formally stack-referring. // The default classification is "returnable, not referring to stack", we want the opposite in this case. ReadOnlySpan <byte> remainder = stackalloc byte[0]; Span <byte> stackSpan = stackalloc byte[stackLength]; var poisition = Position.First; while (source.TryGet(ref poisition, out var sourceBuffer, true)) { Span <byte> outputSpan = destination.Buffer; ReadOnlySpan <byte> sourceSpan = sourceBuffer.Span; if (!remainder.IsEmpty) { int leftOverBytes = remainder.Length; remainder.CopyTo(stackSpan); int amountToCopy = Math.Min(sourceSpan.Length, stackSpan.Length - leftOverBytes); sourceSpan.Slice(0, amountToCopy).CopyTo(stackSpan.Slice(leftOverBytes)); int amountOfData = leftOverBytes + amountToCopy; Span <byte> spanToTransform = stackSpan.Slice(0, amountOfData); TryTransformWithRemainder: OperationStatus status = transformation.Execute(spanToTransform, outputSpan, out int bytesConsumed, out int bytesWritten); if (status != OperationStatus.Done) { destination.Advance(bytesWritten); spanToTransform = spanToTransform.Slice(bytesConsumed); if (status == OperationStatus.DestinationTooSmall) { destination.Enlarge(); // output buffer is too small outputSpan = destination.Buffer; if (outputSpan.Length - bytesWritten < 3) { return; // no more output space, user decides what to do. } goto TryTransformWithRemainder; } else { if (status == OperationStatus.InvalidData) { continue; // source buffer contains invalid bytes, user decides what to do for fallback } // at this point, status = TransformationStatus.NeedMoreSourceData // left over bytes in stack span remainder = spanToTransform; } continue; } else // success { afterMergeSlice = bytesConsumed - remainder.Length; remainder = Span <byte> .Empty; destination.Advance(bytesWritten); outputSpan = destination.Buffer; } } TryTransform: OperationStatus result = transformation.Execute(sourceSpan.Slice(afterMergeSlice), outputSpan, out int consumed, out int written); afterMergeSlice = 0; destination.Advance(written); sourceSpan = sourceSpan.Slice(consumed); if (result == OperationStatus.Done) { continue; } // Not successful if (result == OperationStatus.DestinationTooSmall) { destination.Enlarge(); // output buffer is too small outputSpan = destination.Buffer; if (outputSpan.Length - written < 3) { return; // no more output space, user decides what to do. } goto TryTransform; } else { if (result == OperationStatus.InvalidData) { continue; // source buffer contains invalid bytes, user decides what to do for fallback } // at this point, result = TransformationStatus.NeedMoreSourceData // left over bytes in source span remainder = sourceSpan; } } return; }
public BytesReader(ReadOnlyBytes bytes) : this(bytes, SymbolTable.InvariantUtf8) { }
public BytesReader(ReadOnlyBytes bytes) : this(bytes, TextEncoder.Utf8) { }
public BytesReader(ReadOnlyBytes bytes) : this(bytes, EncodingData.InvariantUtf8) { }