|
4 | 4 |
|
5 | 5 | namespace SharpCompress.IO; |
6 | 6 |
|
7 | | -internal partial class SharpCompressStream |
| 7 | +public partial class SharpCompressStream |
8 | 8 | { |
9 | 9 | /// <summary> |
10 | | - /// Creates a SharpCompressStream that acts as a passthrough wrapper. |
11 | | - /// No buffering is performed; CanSeek delegates to the underlying stream. |
12 | | - /// The underlying stream will not be disposed when this stream is disposed. |
| 10 | + /// Creates a <see cref="SharpCompressStream"/> that acts as a zero-overhead passthrough wrapper |
| 11 | + /// around <paramref name="stream"/> without taking ownership of it. |
13 | 12 | /// </summary> |
| 13 | + /// <remarks> |
| 14 | + /// <para> |
| 15 | + /// This is a thin wrapper: all reads, writes, and seeks are forwarded directly to the underlying |
| 16 | + /// stream with no ring-buffer overhead. <see cref="Stream.CanSeek"/> delegates to the underlying |
| 17 | + /// stream's own value. |
| 18 | + /// </para> |
| 19 | + /// <para> |
| 20 | + /// The resulting stream does <b>not</b> support <see cref="StartRecording"/>, <see cref="Rewind()"/>, |
| 21 | + /// or <see cref="StopRecording"/>. Call <see cref="Create"/> on the passthrough stream to obtain |
| 22 | + /// a recording-capable wrapper when needed. |
| 23 | + /// </para> |
| 24 | + /// <para> |
| 25 | + /// Because the stream does not take ownership, the underlying stream is <b>never</b> disposed when |
| 26 | + /// this wrapper is disposed. Use this when you need to satisfy an API that expects a |
| 27 | + /// <see cref="SharpCompressStream"/> without transferring lifetime responsibility. |
| 28 | + /// </para> |
| 29 | + /// </remarks> |
| 30 | + /// <param name="stream">The underlying stream to wrap. Must not be <see langword="null"/>.</param> |
| 31 | + /// <returns> |
| 32 | + /// A passthrough <see cref="SharpCompressStream"/> that does not dispose <paramref name="stream"/>. |
| 33 | + /// </returns> |
14 | 34 | public static SharpCompressStream CreateNonDisposing(Stream stream) => |
15 | 35 | new(stream, leaveStreamOpen: true, passthrough: true, bufferSize: null); |
16 | 36 |
|
| 37 | + /// <summary> |
| 38 | + /// Creates a <see cref="SharpCompressStream"/> that supports recording and rewinding over |
| 39 | + /// <paramref name="stream"/>, choosing the most efficient strategy based on the stream's |
| 40 | + /// capabilities. |
| 41 | + /// </summary> |
| 42 | + /// <remarks> |
| 43 | + /// <para><b>Seekable streams</b> — wraps in a thin delegate that calls the underlying |
| 44 | + /// stream's native <see cref="Stream.Seek"/> directly. No ring buffer is allocated. |
| 45 | + /// <see cref="StartRecording"/> stores the current position; <see cref="Rewind()"/> seeks |
| 46 | + /// back to it.</para> |
| 47 | + /// <para><b>Non-seekable streams</b> (network streams, compressed streams, pipes) — allocates |
| 48 | + /// a ring buffer of <paramref name="bufferSize"/> bytes. All bytes read from the underlying |
| 49 | + /// stream are kept in the ring buffer so that <see cref="Rewind()"/> can replay them without |
| 50 | + /// re-reading the underlying stream. If more bytes have been read than the ring buffer can hold, |
| 51 | + /// a subsequent rewind will throw <see cref="InvalidOperationException"/>; increase |
| 52 | + /// <paramref name="bufferSize"/> or <see cref="Common.Constants.RewindableBufferSize"/> to |
| 53 | + /// avoid this.</para> |
| 54 | + /// <para><b>Already-wrapped streams</b> — if <paramref name="stream"/> is already a |
| 55 | + /// <see cref="SharpCompressStream"/> (or a stack that contains one), it is returned as-is to |
| 56 | + /// prevent double-wrapping and double-buffering.</para> |
| 57 | + /// </remarks> |
| 58 | + /// <param name="stream">The underlying stream to wrap. Must not be <see langword="null"/>.</param> |
| 59 | + /// <param name="bufferSize"> |
| 60 | + /// Size in bytes of the ring buffer allocated for non-seekable streams. |
| 61 | + /// Defaults to <see cref="Common.Constants.RewindableBufferSize"/> (81 920 bytes) when |
| 62 | + /// <see langword="null"/>. Has no effect when <paramref name="stream"/> is seekable, because |
| 63 | + /// no ring buffer is needed in that case. |
| 64 | + /// </param> |
| 65 | + /// <returns> |
| 66 | + /// A <see cref="SharpCompressStream"/> wrapping <paramref name="stream"/>. The returned instance |
| 67 | + /// owns the stream and will dispose it unless the original source was a non-disposing passthrough |
| 68 | + /// wrapper. |
| 69 | + /// </returns> |
17 | 70 | public static SharpCompressStream Create(Stream stream, int? bufferSize = null) |
18 | 71 | { |
19 | 72 | var rewindableBufferSize = bufferSize ?? Constants.RewindableBufferSize; |
@@ -54,6 +107,6 @@ public static SharpCompressStream Create(Stream stream, int? bufferSize = null) |
54 | 107 |
|
55 | 108 | // For non-seekable streams, create a SharpCompressStream with rolling buffer |
56 | 109 | // to allow limited backward seeking (required by decompressors that over-read) |
57 | | - return new SharpCompressStream(stream, false, false, bufferSize); |
| 110 | + return new SharpCompressStream(stream, false, false, rewindableBufferSize); |
58 | 111 | } |
59 | 112 | } |
0 commit comments