internal Task?CreateReader(PipelineBuildDefinition pipeline, Stream stream) { throw new NotImplementedException(); }
internal async Task CreateReader(PipelineBuildDefinition def, ISegmenter segmenter) { var context = new { pipeline = def.Pipe.Reader, onError = def.OnReaderError ?? def.OnError, cancellationToken = def.CancellationTokenSource.Token, owner = segmenter, }; var completed = false; while (!context.cancellationToken.IsCancellationRequested) { var result = await context.pipeline.ReadAsync(context.cancellationToken); try { var buffer = result.Buffer; while (!context.cancellationToken.IsCancellationRequested) { var read = await segmenter.TryReadAsync(buffer); buffer = read.RemainingData; if (read.Status == SegmentationStatus.Incomplete) { break; } else if (read.Status == SegmentationStatus.Invalid) { throw new InvalidSegmentationException(); } } // Tell the PipeReader how much of the buffer we have consumed context.pipeline.AdvanceTo(buffer.Start, buffer.End); } catch (Exception ex) { var errorHandling = await context.onError.Handle(context.owner, ex); switch (errorHandling) { case ErrorHandling.Ignore: //Note: do nothing break; case ErrorHandling.Stop: completed = true; break; default: case ErrorHandling.Throw: context.pipeline.Complete(ex); return; } } // Stop reading if there's no more data coming if (result.IsCompleted || completed) { break; } } //Mark the PipeReader as complete context.pipeline.Complete(); }
//https://devblogs.microsoft.com/dotnet/system-io-pipelines-high-performance-io-in-net/ internal async Task CreateWriter(PipelineBuildDefinition def, Stream stream, int minimumBufferSize) { var context = new { pipeline = def.Pipe.Writer, onError = def.OnWriterError ?? def.OnError, cancellationToken = def.CancellationTokenSource.Token, owner = stream, }; var completed = false; while (!context.cancellationToken.IsCancellationRequested) { // Allocate at least 512 bytes from the PipeWriter var memory = context.pipeline.GetMemory(minimumBufferSize); try { var read = await context.owner.ReadAsync(memory, context.cancellationToken); if (read == 0) { break; } // Tell the PipeWriter how much was read from the Socket context.pipeline.Advance(read); } catch (Exception ex) { var errorHandling = await context.onError.Handle(context.owner, ex); switch (errorHandling) { case ErrorHandling.Ignore: //Note: do nothing break; case ErrorHandling.Stop: completed = true; break; default: case ErrorHandling.Throw: context.pipeline.Complete(ex); return; } } // Make the data available to the PipeReader var result = await context.pipeline.FlushAsync(); if (result.IsCompleted || completed) { break; } } // Tell the PipeReader that there's no more data coming context.pipeline.Complete(); }