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;
        }
Beispiel #2
0
 public BytesReader(ReadOnlyBytes bytes) : this(bytes, SymbolTable.InvariantUtf8)
 {
 }
Beispiel #3
0
 public BytesReader(ReadOnlyBytes bytes) : this(bytes, TextEncoder.Utf8)
 {
 }
Beispiel #4
0
 public BytesReader(ReadOnlyBytes bytes) : this(bytes, EncodingData.InvariantUtf8)
 {
 }