diff --git a/System.IO.Streams/MemoryStream.cs b/System.IO.Streams/MemoryStream.cs index 3715c71..b64f45a 100644 --- a/System.IO.Streams/MemoryStream.cs +++ b/System.IO.Streams/MemoryStream.cs @@ -27,6 +27,8 @@ public class MemoryStream : Stream private readonly bool _expandable; // Is this stream open or closed? private bool _isOpen; + // Is the stream writable + private bool _isWritable; private const int MemStreamMaxLength = 0xFFFF; @@ -50,6 +52,7 @@ public MemoryStream() // Must be 0 for byte[]'s created by MemoryStream _origin = 0; _isOpen = true; + _isWritable = true; } /// @@ -61,11 +64,16 @@ public MemoryStream() /// /// The , , and properties are all set to . /// - /// - /// The capacity of the current stream automatically increases when you use the method to set the length to a value larger than the capacity of the current stream. - /// /// - public MemoryStream(byte[] buffer) + public MemoryStream(byte[] buffer) : this(buffer, true) { } + + /// + /// Initializes a new non-resizable instance of the class based on the specified byte array with the property set as specified. + /// + /// The array of unsigned bytes from which to create the current stream. + /// A bool indicating whether the stream should be writable + /// is . + public MemoryStream(byte[] buffer, bool isWritable) { _buffer = buffer ?? throw new ArgumentNullException(); @@ -73,6 +81,7 @@ public MemoryStream(byte[] buffer) _expandable = false; _origin = 0; _isOpen = true; + _isWritable = isWritable; } /// @@ -115,7 +124,7 @@ public MemoryStream(byte[] buffer) /// If the stream is closed, this property returns . /// /// - public override bool CanWrite => _isOpen; + public override bool CanWrite => _isWritable; /// protected override void Dispose(bool disposing) @@ -329,11 +338,13 @@ public override long Seek( /// /// - /// The stream buffer does not have the capacity to hold the data and is not expandable. + /// The stream buffer does not have the capacity to hold the + /// data and is not expandable, and/or the stream is not writable. /// The MemoryStream max size was exceeded public override void SetLength(long value) { EnsureOpen(); + EnsureWritable(); if (value > MemStreamMaxLength || value < 0) { @@ -368,7 +379,8 @@ public virtual byte[] ToArray() /// /// - /// The stream buffer does not have the capacity to hold the data and is not expandable. + /// The stream buffer does not have the capacity to hold the + /// data and is not expandable, and/or the stream is not writable. /// /// The MemoryStream max size was exceeded or /// or are less than 0 @@ -376,6 +388,7 @@ public virtual byte[] ToArray() public override void Write(byte[] buffer, int offset, int count) { EnsureOpen(); + EnsureWritable(); if (buffer == null) { @@ -411,11 +424,13 @@ public override void Write(byte[] buffer, int offset, int count) /// /// - /// The stream buffer does not have the capacity to hold the data and is not expandable. + /// The stream buffer does not have the capacity to hold the + /// data and is not expandable, and/or the stream is not writable. /// The MemoryStream max size was exceeded public override void WriteByte(byte value) { EnsureOpen(); + EnsureWritable(); if (_position >= _capacity) { @@ -459,6 +474,18 @@ private void EnsureOpen() } } + /// + /// Check that stream is writable. + /// + /// + private void EnsureWritable() + { + if (!CanWrite) + { + throw new NotSupportedException(); + } + } + /// /// Verifies that there is enough capacity in the stream. /// diff --git a/UnitTests/MemoryStreamUnitTests/CanWrite.cs b/UnitTests/MemoryStreamUnitTests/CanWrite.cs index 18add87..a26d29c 100644 --- a/UnitTests/MemoryStreamUnitTests/CanWrite.cs +++ b/UnitTests/MemoryStreamUnitTests/CanWrite.cs @@ -51,5 +51,24 @@ public void CanWrite_Byte_Ctor() OutputHelper.WriteLine($"Unexpected exception {ex}"); } } + + [TestMethod] + [DataRow(true)] + [DataRow(false)] + public void CanWrite_bool_isWritable_Ctor(bool isWritable) + { + // Arrange + byte[] buffer = new byte[1024]; + + // Act + using MemoryStream fs = new MemoryStream(buffer, isWritable); + + // Assert + Assert.AreEqual(isWritable, fs.CanWrite, $"Expected CanWrite == {isWritable}, but got CanWrite == {!isWritable}"); + if(!isWritable) + { + Assert.ThrowsException(typeof(NotSupportedException), () => fs.WriteByte(0), "Expected exception when attempt to write to a read only stream."); + } + } } }