private static BlobIdentifier ComputeIdentifierBasedOnBlocks(IEnumerable <BlobBlockHash> blocks) { var rollingId = new VsoHash.RollingBlobIdentifier(); // ReSharper disable once GenericEnumeratorNotDisposed IEnumerator <BlobBlockHash> enumerator = blocks.GetEnumerator(); bool isLast = !enumerator.MoveNext(); if (isLast) { throw new InvalidDataException("Blob must have at least one block."); } BlobBlockHash current = enumerator.Current; isLast = !enumerator.MoveNext(); while (!isLast) { rollingId.Update(current); current = enumerator.Current; isLast = !enumerator.MoveNext(); } return(rollingId.Finalize(current)); }
/// <inheritdoc /> protected override byte[] HashFinal() { Contract.AssertDebug(_buffer != null); // Here, either the buffer has data, or there were no blocks. // Flush out buffer if (_currentOffset != 0) { var blockHash = HashBlock(_buffer, _currentOffset); return(_rollingId.Finalize(blockHash).Bytes); } // if there are no blocks add an empty block var emptyBlockHash = HashBlock(new byte[] { }, 0); return(_rollingId.Finalize(emptyBlockHash).Bytes); }
private byte[]? TryHashAllBytesWithNoCopy(ReadOnlySpan <byte> source) { int startIndex = 0; byte[]? finalizedBytes = null; // If we know the size of the input upfront, we can hash all the data // without copying them into a temporary buffer. if (source.Length == _expectedInputLength && _currentOffset == 0) { // The span still maybe bigger than 2Mb buffer the hash algorithm uses to compute hash blocks. // Need to split the input source into the 2Mb pieces. int remaining = source.Length; int blockSize = GlobalObjectPools.TwoMbByteArrayPool.ArraySize; while (remaining > 0) { int bytesToCopy = Math.Min(blockSize, source.Length - startIndex); var currentBatch = source.Slice(startIndex, bytesToCopy); startIndex += bytesToCopy; remaining -= bytesToCopy; var blockHash = HashBlock(currentBatch); if (remaining == 0) { // Finalizing the hash. We're done. finalizedBytes = _rollingId.Finalize(blockHash).Bytes; } else { // Not done yet. _rollingId.Update(blockHash); } } } return(finalizedBytes); }
/// <inheritdoc /> protected override byte[] HashFinal() { var rollingId = new VsoHash.RollingBlobIdentifier(); // Flush out buffer if (_currentOffset != 0) { _blockHashes.Add(VsoHash.HashBlock(_buffer, _currentOffset)); } // if there are no blocks add an empty block if (_blockHashes.Count == 0) { _blockHashes.Add(VsoHash.HashBlock(new byte[] { }, 0)); } for (int i = 0; i < _blockHashes.Count - 1; i++) { rollingId.Update(_blockHashes[i]); } return(rollingId.Finalize(_blockHashes[_blockHashes.Count - 1]).Bytes); }