ReadOnlyMemoryStream
using System.Threading;
using System.Threading.Tasks;
namespace System.IO
{
internal sealed class ReadOnlyMemoryStream : Stream
{
private ReadOnlyMemory<byte> _content;
private int _position;
private bool _isOpen;
public override bool CanRead => _isOpen;
public override bool CanSeek => _isOpen;
public override bool CanWrite => false;
public override long Length {
get {
EnsureNotClosed();
return _content.Length;
}
}
public override long Position {
get {
EnsureNotClosed();
return _position;
}
set {
EnsureNotClosed();
if (value < 0 || value > 2147483647)
throw new ArgumentOutOfRangeException("value");
_position = (int)value;
}
}
public ReadOnlyMemoryStream(ReadOnlyMemory<byte> content)
{
_content = content;
_isOpen = true;
}
private void EnsureNotClosed()
{
if (!_isOpen)
throw new ObjectDisposedException(null, System.SR.ObjectDisposed_StreamClosed);
}
public override long Seek(long offset, SeekOrigin origin)
{
EnsureNotClosed();
long num;
switch (origin) {
default:
throw new ArgumentOutOfRangeException("origin");
case SeekOrigin.End:
num = _content.Length + offset;
break;
case SeekOrigin.Current:
num = _position + offset;
break;
case SeekOrigin.Begin:
num = offset;
break;
}
long num2 = num;
if (num2 > 2147483647)
throw new ArgumentOutOfRangeException("offset");
if (num2 < 0)
throw new IOException(System.SR.IO_SeekBeforeBegin);
_position = (int)num2;
return _position;
}
public override int ReadByte()
{
EnsureNotClosed();
ReadOnlySpan<byte> span = _content.Span;
if (_position >= span.Length)
return -1;
return span[_position++];
}
public override int Read(byte[] buffer, int offset, int count)
{
ValidateBufferArguments(buffer, offset, count);
return ReadBuffer(new Span<byte>(buffer, offset, count));
}
private int ReadBuffer(Span<byte> buffer)
{
EnsureNotClosed();
int num = _content.Length - _position;
if (num <= 0 || buffer.Length == 0)
return 0;
ReadOnlySpan<byte> readOnlySpan;
if (num <= buffer.Length) {
readOnlySpan = _content.Span.Slice(_position);
readOnlySpan.CopyTo(buffer);
_position = _content.Length;
return num;
}
readOnlySpan = _content.Span;
readOnlySpan.Slice(_position, buffer.Length).CopyTo(buffer);
_position += buffer.Length;
return buffer.Length;
}
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
ValidateBufferArguments(buffer, offset, count);
EnsureNotClosed();
if (!cancellationToken.IsCancellationRequested)
return Task.FromResult(ReadBuffer(new Span<byte>(buffer, offset, count)));
return Task.FromCanceled<int>(cancellationToken);
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return System.Threading.Tasks.TaskToAsyncResult.Begin(ReadAsync(buffer, offset, count), callback, state);
}
public override int EndRead(IAsyncResult asyncResult)
{
EnsureNotClosed();
return System.Threading.Tasks.TaskToAsyncResult.End<int>(asyncResult);
}
public override void Flush()
{
}
public override Task FlushAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
protected override void Dispose(bool disposing)
{
_isOpen = false;
_content = default(ReadOnlyMemory<byte>);
base.Dispose(disposing);
}
private new static void ValidateBufferArguments(byte[] buffer, int offset, int count)
{
ExceptionPolyfills.ThrowIfNull(buffer, "buffer");
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", System.SR.ArgumentOutOfRange_NeedNonNegNum);
if ((uint)count > buffer.Length - offset)
throw new ArgumentOutOfRangeException("count", System.SR.Argument_InvalidOffLen);
}
}
}