/// <summary> /// Parses the next <see cref="BString"/> from the reader. /// </summary> /// <param name="reader">The reader to parse from.</param> /// <param name="cancellationToken"></param> /// <returns>The parsed <see cref="BString"/>.</returns> /// <exception cref="InvalidBencodeException{BString}">Invalid bencode.</exception> /// <exception cref="UnsupportedBencodeException{BString}">The bencode is unsupported by this library.</exception> public override async ValueTask <BString> ParseAsync(PipeBencodeReader reader, CancellationToken cancellationToken = default) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var startPosition = reader.Position; using (var memoryOwner = MemoryPool <char> .Shared.Rent(BString.LengthMaxDigits)) { var lengthString = memoryOwner.Memory; var lengthStringCount = 0; for (var c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false); c != default && c.IsDigit(); c = await reader.ReadCharAsync(cancellationToken).ConfigureAwait(false)) { EnsureLengthStringBelowMaxLength(lengthStringCount, startPosition); lengthString.Span[lengthStringCount++] = c; } EnsurePreviousCharIsColon(reader.PreviousChar, reader.Position); var stringLength = ParseStringLength(lengthString.Span, lengthStringCount, startPosition); var bytes = new byte[stringLength]; var bytesRead = await reader.ReadAsync(bytes, cancellationToken).ConfigureAwait(false); EnsureExpectedBytesRead(bytesRead, stringLength, startPosition); return(new BString(bytes, Encoding)); } }
public async Task CanReadLessThanRequested() { var bytes = Encoding.UTF8.GetBytes("abc").AsMemory(); var(reader, writer) = new Pipe(); var bencodeReader = new PipeBencodeReader(reader); await writer.WriteAsync(bytes.Slice(0, 1)); var buffer = new byte[bytes.Length]; var readTask = bencodeReader.ReadAsync(buffer); await writer.WriteAsync(bytes.Slice(1, 1)); writer.Complete(); var bytesRead = await readTask; bytesRead.Should().Be(2); buffer[0].Should().Be((byte)'a'); buffer[1].Should().Be((byte)'b'); buffer[2].Should().Be(default);
internal static Task SkipBytesAsync(this PipeBencodeReader reader, int length) { return(reader.ReadAsync(new byte[length]).AsTask()); }