Skip to content

Commit 4a4f6d0

Browse files
committed
Make PipeBencodeReader extendable
1 parent caec437 commit 4a4f6d0

1 file changed

Lines changed: 32 additions & 13 deletions

File tree

BencodeNET/IO/PipeBencodeReader.cs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,25 @@ namespace BencodeNET.IO
1111
/// </summary>
1212
public class PipeBencodeReader
1313
{
14-
private readonly PipeReader _reader;
14+
/// <summary>
15+
/// The <see cref="PipeReader"/> to read from.
16+
/// </summary>
17+
protected readonly PipeReader _reader;
1518

16-
private bool _endOfStream;
19+
/// <summary>
20+
/// Indicates if the <see cref="PipeReader"/> has been completed (i.e. "end of stream").
21+
/// </summary>
22+
protected bool _readerCompleted;
1723

1824
/// <summary>
1925
/// The position in the pipe (number of read bytes/characters) (does not included peeked char).
2026
/// </summary>
21-
public long Position { get; set; }
27+
public virtual long Position { get; protected set; }
2228

2329
/// <summary>
2430
/// The previously read/consumed char (does not include peeked char).
2531
/// </summary>
26-
public char PreviousChar { get; protected set; }
32+
public virtual char PreviousChar { get; protected set; }
2733

2834
/// <summary>
2935
/// Creates a <see cref="PipeBencodeReader"/> that reads from the specified <see cref="PipeReader"/>.
@@ -37,18 +43,18 @@ public PipeBencodeReader(PipeReader reader)
3743
/// <summary>
3844
/// Peek at the next char in the pipe, without advancing the reader.
3945
/// </summary>
40-
public ValueTask<char> PeekCharAsync(CancellationToken cancellationToken = default)
46+
public virtual ValueTask<char> PeekCharAsync(CancellationToken cancellationToken = default)
4147
=> ReadCharAsync(peek: true, cancellationToken);
4248

4349
/// <summary>
4450
/// Read the next char in the pipe and advance the reader.
4551
/// </summary>
46-
public ValueTask<char> ReadCharAsync(CancellationToken cancellationToken = default)
52+
public virtual ValueTask<char> ReadCharAsync(CancellationToken cancellationToken = default)
4753
=> ReadCharAsync(peek: false, cancellationToken);
4854

4955
private ValueTask<char> ReadCharAsync(bool peek = false, CancellationToken cancellationToken = default)
5056
{
51-
if (_endOfStream)
57+
if (_readerCompleted)
5258
return new ValueTask<char>(default(char));
5359

5460
if (_reader.TryRead(out var result))
@@ -67,12 +73,14 @@ private async ValueTask<char> ReadCharAsyncAwaited(bool peek, CancellationToken
6773
/// Reads the next char in the pipe and consumes it (advances the reader),
6874
/// unless <paramref name="peek"/> is <c>true</c>.
6975
/// </summary>
70-
private char ReadCharConsume(in ReadOnlySequence<byte> buffer, bool peek)
76+
/// <param name="buffer">The buffer to read from</param>
77+
/// <param name="peek">If true the char will not be consumed, i.e. the reader should not be advanced.</param>
78+
protected virtual char ReadCharConsume(in ReadOnlySequence<byte> buffer, bool peek)
7179
{
7280
if (buffer.IsEmpty)
7381
{
7482
// TODO: Add IsCompleted check?
75-
_endOfStream = true;
83+
_readerCompleted = true;
7684
return default;
7785
}
7886

@@ -98,9 +106,9 @@ private char ReadCharConsume(in ReadOnlySequence<byte> buffer, bool peek)
98106
/// </summary>
99107
/// <param name="bytes">The amount of bytes to read.</param>
100108
/// <param name="cancellationToken"></param>
101-
public ValueTask<long> ReadAsync(Memory<byte> bytes, CancellationToken cancellationToken = default)
109+
public virtual ValueTask<long> ReadAsync(Memory<byte> bytes, CancellationToken cancellationToken = default)
102110
{
103-
if (bytes.Length == 0 || _endOfStream)
111+
if (bytes.Length == 0 || _readerCompleted)
104112
return new ValueTask<long>(0);
105113

106114
if (_reader.TryRead(out var result) && TryReadConsume(result, bytes.Span, out var bytesRead))
@@ -123,7 +131,18 @@ private async ValueTask<long> ReadAsyncAwaited(Memory<byte> bytes, CancellationT
123131
}
124132
}
125133

126-
private bool TryReadConsume(ReadResult result, in Span<byte> bytes, out long bytesRead)
134+
/// <summary>
135+
/// Attempts to read the specified bytes from the reader and advances the reader if successful.
136+
/// If the end of the pipe is reached then the available bytes is read and returned, if any.
137+
/// <para>
138+
/// Returns <c>true</c> if any bytes was read or the reader was completed.
139+
/// </para>
140+
/// </summary>
141+
/// <param name="result">The read result from the pipe read operation.</param>
142+
/// <param name="bytes">The bytes to read.</param>
143+
/// <param name="bytesRead">The number of bytes read.</param>
144+
/// <returns></returns>
145+
protected virtual bool TryReadConsume(ReadResult result, in Span<byte> bytes, out long bytesRead)
127146
{
128147
if (result.IsCanceled) throw new InvalidOperationException("Read operation cancelled.");
129148

@@ -143,7 +162,7 @@ private bool TryReadConsume(ReadResult result, in Span<byte> bytes, out long byt
143162

144163
if (result.IsCompleted)
145164
{
146-
_endOfStream = true;
165+
_readerCompleted = true;
147166

148167
if (buffer.IsEmpty)
149168
{

0 commit comments

Comments
 (0)