/// <summary>
 /// Implement an AxCryptReader based on a Stream.
 /// </summary>
 /// <param name="inputStream">The stream. Will be disposed when this instance is disposed.</param>
 public AxCryptStreamReader(Stream inputStream)
 {
     if (inputStream == null)
     {
         throw new ArgumentNullException("inputStream");
     }
     LookAheadStream lookAheadStream = inputStream as LookAheadStream;
     if (lookAheadStream == null)
     {
         lookAheadStream = new LookAheadStream(inputStream);
     }
     SetInputStream(lookAheadStream);
 }
 private void Dispose(bool disposing)
 {
     if (_disposed)
     {
         return;
     }
     if (disposing)
     {
         if (_inputStream != null)
         {
             _inputStream.Dispose();
             _inputStream = null;
         }
         if (_hmacBufferStream != null)
         {
             _hmacBufferStream.Dispose();
             _hmacBufferStream = null;
         }
         if (_hmacStream != null)
         {
             _hmacStream.Dispose();
             _hmacStream = null;
         }
         _disposed = true;
     }
 }
 protected void SetInputStream(LookAheadStream inputStream)
 {
     _inputStream = inputStream;
 }
        public static void TestLookAheadStream()
        {
            Assert.Throws<ArgumentNullException>(() =>
            {
                using (Stream stream = new LookAheadStream(null)) { }
            }, "Input stream cannot be null.");

            Assert.Throws<ArgumentException>(() =>
            {
                using (Stream writeOnlyStream = new DeflateStream(new MemoryStream(), CompressionMode.Compress))
                {
                    using (Stream stream = new LookAheadStream(writeOnlyStream)) { }
                }
            }, "The input stream must support reading.");

            using (Stream inputStream = new MemoryStream())
            {
                byte[] inData = Encoding.UTF8.GetBytes("0123456789");
                inputStream.Write(inData, 0, inData.Length);
                inputStream.Position = 0;
                using (LookAheadStream lookAheadStream = new LookAheadStream(inputStream))
                {
                    Assert.That(lookAheadStream.CanRead, Is.True, "The stream always supports reading.");
                    Assert.That(lookAheadStream.CanSeek, Is.False, "The stream does not support seeking.");
                    Assert.That(lookAheadStream.CanWrite, Is.False, "The stream does not support writing.");
                    Assert.Throws<NotSupportedException>(() =>
                    {
                        long length = lookAheadStream.Length;

                        // Make FxCop not complain
                        Object.Equals(length, null);
                    });
                    Assert.Throws<NotSupportedException>(() =>
                    {
                        long position = lookAheadStream.Position;

                        // Make FxCop not complain
                        Object.Equals(position, null);
                    });
                    Assert.Throws<NotSupportedException>(() =>
                    {
                        lookAheadStream.Position = 0;
                    });
                    Assert.Throws<NotSupportedException>(() =>
                    {
                        lookAheadStream.Seek(0, SeekOrigin.Begin);
                    });
                    Assert.Throws<NotSupportedException>(() =>
                    {
                        lookAheadStream.SetLength(0);
                    });
                    Assert.Throws<NotSupportedException>(() =>
                    {
                        lookAheadStream.Write(new byte[1], 0, 1);
                    });

                    int count;
                    byte[] buffer;

                    lookAheadStream.Pushback(new byte[] { 0x99 }, 0, 1);
                    buffer = new byte[1];
                    count = lookAheadStream.Read(buffer, 0, 1);
                    Assert.That(count, Is.EqualTo(1), "One byte was read.");
                    Assert.That(buffer[0], Is.EqualTo(0x99), "A byte with value 0x99 was pushed back.");

                    buffer = new byte[5];
                    count = lookAheadStream.Read(buffer, 0, buffer.Length);
                    Assert.That(count, Is.EqualTo(5), "Five bytes were read.");
                    Assert.That(buffer, Is.EquivalentTo(new byte[] { 48, 49, 50, 51, 52 }), "The string '01234' was read.");

                    lookAheadStream.Pushback(new byte[] { 52 }, 0, 1);
                    lookAheadStream.Pushback(new byte[] { 51 }, 0, 1);
                    lookAheadStream.Pushback(new byte[] { 48, 49, 50 }, 0, 3);

                    // Nothing should happen, this is a pure dummy call.
                    lookAheadStream.Flush();

                    buffer = new byte[10];
                    bool exactWasRead = lookAheadStream.ReadExact(buffer);
                    Assert.That(exactWasRead, Is.True, "Ten bytes were read.");
                    Assert.That(buffer, Is.EquivalentTo(new byte[] { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 }), "The string '0123456789' was read.");

                    // This also implicitly tests double-dispose since we're in a using block
                    lookAheadStream.Dispose();
                    Assert.Throws<ObjectDisposedException>(() =>
                    {
                        buffer = new byte[3];
                        lookAheadStream.Read(buffer, 0, 3);
                    });

                    Assert.Throws<ObjectDisposedException>(() =>
                    {
                        buffer = new byte[5];
                        lookAheadStream.ReadExact(buffer);
                    });

                    Assert.Throws<ObjectDisposedException>(() =>
                    {
                        buffer = new byte[5];
                        lookAheadStream.Pushback(buffer, 0, buffer.Length);
                    });
                }
            }
        }