public static async Task <ReadOnlyMemory <byte> > ComputeHashAsync(
            this IAsyncEnumerable <byte> enumerable,
            IHashAlgorithm hashAlgorithm,
            CancellationToken cancellationToken
            )
        {
            // Validate parameters.
            if (enumerable == null)
            {
                throw new ArgumentNullException(nameof(enumerable));
            }
            if (hashAlgorithm == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithm));
            }

            // Memory
            var buffer = new Memory <byte>(new byte[1]);

            // Cycle through the items.
            await foreach (byte b in enumerable.WithCancellation(cancellationToken).ConfigureAwait(false))
            {
                // Copy the byte.
                var copy = b;

                // Write the byte to the span
                MemoryMarshal.Write(buffer.Span, ref copy);

                // Transform.
                hashAlgorithm.TransformBlock(buffer.Span);
            }

            // Return the hash.
            return(hashAlgorithm.Hash);
        }
Example #2
0
        public static ref readonly ReadOnlyMemory <byte> ComputeHash(
            this Stream stream,
            IHashAlgorithm hashAlgorithm,
            ArrayPool <byte> arrayPool,
            int bufferSize
            )
        {
            // Validate parameters.
            if (hashAlgorithm == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithm));
            }
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (arrayPool == null)
            {
                throw new ArgumentNullException(nameof(arrayPool));
            }
            if (bufferSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferSize), bufferSize,
                                                      $"The { nameof(bufferSize) } parameter must be a positive value.");
            }

            // The buffer.
            byte[]? buffer = null;

            // Wrap in a try/finally.
            try
            {
                // Rent.
                buffer = arrayPool.Rent(bufferSize);

                // Cycle through the stream.
                while (stream.Read(buffer, 0, bufferSize) != 0)
                {
                    // Run through the hash.
                    hashAlgorithm.TransformBlock(buffer);
                }

                // Return.
                return(ref hashAlgorithm.Hash);
            }
            finally
            {
                // Release.
                arrayPool.Return(buffer);
            }
        }
        public static ref readonly ReadOnlyMemory <byte> ComputeHash(this IHashAlgorithm hashAlgorithm, ReadOnlySpan <byte> bytes)
        {
            // Validate parameters.
            if (hashAlgorithm == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithm));
            }
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }

            // Transform the block.
            hashAlgorithm.TransformBlock(bytes);

            // Return the hash.
            return(ref hashAlgorithm.Hash);
        }
        public static int GetHashCode(this IHashAlgorithm hashAlgorithm, IEnumerable <int> hashCodes)
        {
            // Validate parameters.
            if (hashAlgorithm == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithm));
            }
            if (hashCodes == null)
            {
                throw new ArgumentNullException(nameof(hashCodes));
            }

            // Unsafe.
            unsafe
            {
                // Cycle through
                // the hashcodes, transforming each block that's returned.
                foreach (int hashCode in hashCodes)
                {
                    // Copy.
                    var hashCodeCopy = hashCode;

                    // Get the pointer.
                    int *p = &hashCodeCopy;

                    // Get the bytes.
                    var bytes = new ReadOnlySpan <byte>(p, sizeof(int));

                    // Transform the block.
                    hashAlgorithm.TransformBlock(bytes);
                }
            }

            // Return the hash.
            return(MemoryMarshal.Read <int>(hashAlgorithm.Hash.Span));
        }
Example #5
0
 public virtual int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
 {
     return(_hashAlgorithm.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset));
 }
Example #6
0
        public static async Task <ReadOnlyMemory <byte> > ComputeHashAsync(
            this Stream stream,
            IHashAlgorithm hashAlgorithm,
            ArrayPool <byte> arrayPool,
            int bufferSize,
            CancellationToken cancellationToken
            )
        {
            // Validate parameters.
            if (hashAlgorithm == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithm));
            }
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (arrayPool == null)
            {
                throw new ArgumentNullException(nameof(arrayPool));
            }
            if (bufferSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferSize), bufferSize, $"The { nameof(bufferSize) } parameter must be a positive value.");
            }

            // The declarations for the buffer and the copy.
            byte[]? buffer = null;
            byte[]? copy   = null;

            // Wrap in a try/finally.
            try
            {
                // Allocate.
                buffer = arrayPool.Rent(bufferSize);
                copy   = arrayPool.Rent(bufferSize);

                // The bytes read task.
                Task <int> bytesRead = stream.ReadAsync(buffer, 0, bufferSize, cancellationToken);

                // No bytes read, get out.
                if ((await bytesRead.ConfigureAwait(false)) == 0)
                {
                    return(hashAlgorithm.Hash);
                }

                // While there are items to process.
                do
                {
                    // Copy the buffer.
                    // NOTE: Need to do this because it's a shared resource.
                    // If tests show there's a sweet spot between the copy time and hash time < next ReadAsync time,
                    // move buffer size accordingly.
                    Array.Copy(buffer, copy, bufferSize);

                    // Read the next task.
                    bytesRead = stream.ReadAsync(buffer, 0, bufferSize, cancellationToken);

                    // Hash.
                    hashAlgorithm.TransformBlock(copy);

                    // Get the next stream immediately.
                } while (await bytesRead.ConfigureAwait(false) > 0);

                // Return.
                return(hashAlgorithm.Hash);
            }
            finally
            {
                // Release.
                arrayPool.Return(buffer);
                arrayPool.Return(copy);
            }
        }