/// <summary> /// Reads a <see cref="IBufferReader{T}"/> to completion, writing to a <see cref="IBufferWriterAsync{T}"/> /// </summary> /// <typeparam name="T">The type of element</typeparam> /// <param name="reader">The reader to read from</param> /// <param name="writer">The writer to write to</param> /// <param name="token">A cancellation token to abort the operation</param> /// <returns>A task representing the progress fo the write operation</returns> public static async ValueTask CopyToAsync <T>(this IBufferReader <T> reader, IBufferWriterAsync <T> writer, CancellationToken token = default) { while (reader.CanRead) { var InBuffer = reader.GetMemory(0); if (InBuffer.IsEmpty) { break; } InBuffer.Span.CopyTo(writer.GetSpan(InBuffer.Length)); await writer.AdvanceAsync(InBuffer.Length, token); reader.Advance(InBuffer.Length); } }
/// <summary> /// Reads a <see cref="IBufferReader{T}"/> to completion, writing to a <see cref="IBufferWriter{T}"/> /// </summary> /// <typeparam name="T">The type of element</typeparam> /// <param name="reader">The reader to read from</param> /// <param name="writer">The writer to write to</param> public static void CopyTo <T>(this IBufferReader <T> reader, IBufferWriter <T> writer) { while (reader.CanRead) { var InBuffer = reader.GetSpan(0); if (InBuffer.IsEmpty) { break; } var OutBuffer = writer.GetSpan(InBuffer.Length); InBuffer.CopyTo(OutBuffer); writer.Advance(InBuffer.Length); reader.Advance(InBuffer.Length); } }
int Read(Span <char> buffer) { //**************************************** var CharsWritten = 0; //**************************************** if (buffer.IsEmpty) { return(0); } // Empty the buffer if there's anything in it if (_BufferLength > 0) { var WriteLength = Math.Min(_BufferLength, buffer.Length); _Buffer.AsSpan(_BufferIndex, WriteLength).CopyTo(buffer); buffer = buffer.Slice(WriteLength); CharsWritten += WriteLength; _BufferIndex += WriteLength; _BufferLength -= WriteLength; if (buffer.IsEmpty) { return(CharsWritten); } } if (_CheckPreamble) { CheckPreamble(); } if (_DetectEncoding) { DetectEncoding(); } ReadOnlySpan <byte> InBuffer; var OutBuffer = _Buffer.AsSpan(0, _Buffer.Length); bool IsCompleted; // Keep trying to read until we fill the buffer, or the source reader runs out do { InBuffer = _Reader.GetSpan(0); // Decode the bytes into our char buffer _Decoder.Convert( InBuffer, OutBuffer, InBuffer.IsEmpty, out var BytesRead, out var WrittenChars, out IsCompleted ); var ReadLength = Math.Min(WrittenChars, buffer.Length); OutBuffer.Slice(0, ReadLength).CopyTo(buffer); buffer = buffer.Slice(ReadLength); CharsWritten += ReadLength; _Position += BytesRead; _Reader.Advance(BytesRead); if (buffer.IsEmpty) { // Buffer is filled. Save any data left over for the next read operation _BufferIndex = ReadLength; _BufferLength = WrittenChars - ReadLength; return(CharsWritten); } // Loop while there are more bytes unread, or there are no bytes left but there's still data to flush }while (!InBuffer.IsEmpty || !IsCompleted); _BufferLength = 0; return(CharsWritten); }
internal static void ReadBufferAsync(IForwarder forwarder, IBufferReader bufferReader) { var buffer = bufferReader.Read(); var packet = Deserialize(buffer, out var bytesConsumed); if (bytesConsumed == 0) { return; } switch (packet) { case Connect connect: forwarder.Dispatch(connect); break; case ConnAck connAck: forwarder.Dispatch(connAck); break; case Disconnect disconnect: forwarder.Dispatch(disconnect); break; case PubAck pubAck: forwarder.Dispatch(pubAck); break; case PubRel pubRel: forwarder.Dispatch(pubRel); break; case PubRec pubRec: forwarder.Dispatch(pubRec); break; case PubComp pubComp: forwarder.Dispatch(pubComp); break; case PingReq pingReq: forwarder.Dispatch(pingReq); break; case PingResp pingResp: forwarder.Dispatch(pingResp); break; case Subscribe subscribe: forwarder.Dispatch(subscribe); break; case SubAck subAck: forwarder.Dispatch(subAck); break; case Unsubscribe unsubscribe: forwarder.Dispatch(unsubscribe); break; case UnsubAck unsubAck: forwarder.Dispatch(unsubAck); break; } bufferReader.Advance(bytesConsumed); }
public static void Advance(this IBufferReader reader, long count) { VerifyCountParam(count); reader.Advance((int)count); }
public static void CopyTo(this IBufferReader <byte> source, Stream target) => source.CopyTo(target, 81920); // Same buffer size as Stream.CopyTo /// <summary> /// Synchronously reads the bytes from the current <see cref="IBufferReader{Byte}"/> and writes them to a Stream /// </summary> /// <param name="source">The current buffer reader to read from</param> /// <param name="target">The stream to write to</param> /// <param name="blockSize">The size of the blocks to read and write</param> public static void CopyTo(this IBufferReader <byte> source, Stream target, int blockSize) { if (blockSize < 0) { throw new ArgumentOutOfRangeException(nameof(blockSize)); } #if NETSTANDARD2_0 byte[]? InBuffer = null; try { for (; ;) { var Buffer = source.GetMemory(blockSize); if (Buffer.IsEmpty) { break; } if (MemoryMarshal.TryGetArray(Buffer, out var Segment)) { // Have the stream write directly from the source buffer target.Write(Segment.Array, Segment.Offset, Segment.Count); source.Advance(Segment.Count); } else { // Not a buffer we can pass to Stream.Write, so we have to copy if (InBuffer == null) { InBuffer = ArrayPool <byte> .Shared.Rent(Buffer.Length); } var Length = Math.Min(Buffer.Length, InBuffer.Length); Buffer.Slice(0, Length).CopyTo(InBuffer); target.Write(InBuffer, 0, Length); source.Advance(Length); } } } finally { if (InBuffer != null) { ArrayPool <byte> .Shared.Return(InBuffer); } } #else for (; ;) { var Buffer = source.GetSpan(blockSize); if (Buffer.IsEmpty) { break; } target.Write(Buffer); source.Advance(Buffer.Length); } #endif }