<PackageReference Include="Azure.Storage.Blobs" Version="12.25.1" />

WindowStream

abstract class WindowStream : Stream
Exposes a predetermined slice of a larger stream using the same Stream interface. There should not be access to the base stream while this facade is in use.
using Azure.Core.Pipeline; using System; using System.IO; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace Azure.Storage.Shared { internal abstract class WindowStream : Stream { private class UnseekableWindowStream : WindowStream { private long _position; private long MaxLength { get; } public override bool CanSeek => false; public override long Length { get { throw new NotSupportedException(); } } public override long Position { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } public UnseekableWindowStream(Stream stream, long maxWindowLength) : base(stream) { MaxLength = maxWindowLength; } public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } public override void SetLength(long value) { throw new NotSupportedException(); } protected override int AdjustCount(int count) { return (int)Math.Min(count, MaxLength - _position); } protected override void ReportInnerStreamRead(int resultRead) { _position += resultRead; } } private class SeekableWindowStream : WindowStream { private readonly long _baseStreamStartingPosition; public override bool CanSeek => true; public override long Length { get; } public override long Position { get { return base.InnerStream.Position - _baseStreamStartingPosition; } set { base.InnerStream.Position = _baseStreamStartingPosition + value; } } public SeekableWindowStream(Stream stream, long maxWindowLength) : base(stream) { Length = Math.Min(stream.Length - stream.Position, maxWindowLength); _baseStreamStartingPosition = stream.Position; } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: base.InnerStream.Seek(_baseStreamStartingPosition + offset, SeekOrigin.Begin); break; case SeekOrigin.Current: base.InnerStream.Seek(base.InnerStream.Position + offset, SeekOrigin.Current); break; case SeekOrigin.End: base.InnerStream.Seek(_baseStreamStartingPosition + Length - base.InnerStream.Length + offset, SeekOrigin.End); break; } return Position; } public override void SetLength(long value) { throw new NotSupportedException(); } protected override int AdjustCount(int count) { return (int)Math.Min(count, Length - Position); } protected override void ReportInnerStreamRead(int resultRead) { } } private Stream InnerStream { get; } public override bool CanRead => true; public override bool CanWrite => false; private WindowStream(Stream stream) { InnerStream = stream; } public static Stream GetWindow(Stream stream, long maxWindowLength) { if (stream.CanSeek) return new SeekableWindowStream(stream, maxWindowLength); return new UnseekableWindowStream(stream, maxWindowLength); } public override void Flush() { throw new NotSupportedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } public override void WriteByte(byte value) { throw new NotSupportedException(); } public override int ReadByte() { if (AdjustCount(1) <= 0) return -1; int num = InnerStream.ReadByte(); if (num != -1) ReportInnerStreamRead(1); return num; } public override int Read(byte[] buffer, int offset, int count) { return ReadInternal(buffer, offset, count, false, default(CancellationToken)).EnsureCompleted(); } [AsyncStateMachine(typeof(<ReadAsync>d__14))] public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { <ReadAsync>d__14 stateMachine = default(<ReadAsync>d__14); stateMachine.<>t__builder = AsyncTaskMethodBuilder<int>.Create(); stateMachine.<>4__this = this; stateMachine.buffer = buffer; stateMachine.offset = offset; stateMachine.count = count; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(<ReadInternal>d__15))] private Task<int> ReadInternal(byte[] buffer, int offset, int count, bool async, CancellationToken cancellationToken) { <ReadInternal>d__15 stateMachine = default(<ReadInternal>d__15); stateMachine.<>t__builder = AsyncTaskMethodBuilder<int>.Create(); stateMachine.<>4__this = this; stateMachine.buffer = buffer; stateMachine.offset = offset; stateMachine.count = count; stateMachine.async = async; stateMachine.cancellationToken = cancellationToken; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } protected abstract int AdjustCount(int count); protected abstract void ReportInnerStreamRead(int resultRead); } }