Skip to content

Commit 3df186b

Browse files
committed
Update HashAlgorithm
1 parent fe64848 commit 3df186b

File tree

2 files changed

+91
-5
lines changed

2 files changed

+91
-5
lines changed

src/Blake3.Tests/Blake3HashAlgorithmTests.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,71 @@
22
// Licensed under the BSD-Clause 2 license.
33
// See license.txt file in the project root for full license information.
44

5+
using System;
56
using NUnit.Framework;
67

78
namespace Blake3.Tests
89
{
910
/// <summary>
10-
/// Tests for <see cref="Hasher"/>
11+
/// Tests for <see cref="Blake3HashAlgorithm"/>
1112
/// </summary>
1213
public class Blake3HashAlgorithmTests : Blake3TestsBase
1314
{
1415
[Test]
1516
public void TestComputeHash()
1617
{
17-
var hashAlgorithm = new Blake3HashAlgorithm();
18+
using var hashAlgorithm = new Blake3HashAlgorithm();
1819
var result = hashAlgorithm.ComputeHash(HasherTests.BigData);
1920
var hash = Hash.FromBytes(result);
2021
AssertTextAreEqual(HasherTests.BigExpected, hash.ToString());
2122
}
23+
24+
[Test]
25+
public void TestComputeHash_Span_And_TryHashFinal()
26+
{
27+
using var hashAlgorithm = new Blake3HashAlgorithm();
28+
29+
var data = HasherTests.BigData;
30+
31+
Span<byte> destination = stackalloc byte[Hash.Size];
32+
Assert.True(hashAlgorithm.TryComputeHash(data, destination, out var written));
33+
Assert.AreEqual(Hash.Size, written);
34+
35+
var hash = Hash.FromBytes(destination);
36+
AssertTextAreEqual(HasherTests.BigExpected, hash.ToString());
37+
}
38+
39+
[Test]
40+
public void TestTryHashFinal_BufferTooSmall()
41+
{
42+
using var hashAlgorithm = new Blake3HashAlgorithm();
43+
44+
Span<byte> destination = stackalloc byte[Hash.Size - 1];
45+
Assert.False(hashAlgorithm.TryComputeHash(HasherTests.BigData, destination, out var written));
46+
Assert.AreEqual(0, written);
47+
}
48+
49+
[Test]
50+
public void TestChunking_And_InitializeReuse()
51+
{
52+
var data = HasherTests.BigData;
53+
54+
using var hashAlgorithm = new Blake3HashAlgorithm();
55+
56+
// Chunked updates
57+
hashAlgorithm.TransformBlock(data, 0, 7, null, 0);
58+
hashAlgorithm.TransformBlock(data, 7, 13, null, 0);
59+
hashAlgorithm.TransformBlock(data, 20, data.Length - 20, null, 0);
60+
hashAlgorithm.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
61+
62+
var hash1 = Hash.FromBytes(hashAlgorithm.Hash);
63+
AssertTextAreEqual(HasherTests.BigExpected, hash1.ToString());
64+
65+
// Reuse
66+
hashAlgorithm.Initialize();
67+
var result = hashAlgorithm.ComputeHash(data);
68+
var hash2 = Hash.FromBytes(result);
69+
AssertTextAreEqual(HasherTests.BigExpected, hash2.ToString());
70+
}
2271
}
2372
}

src/Blake3/Blake3HashAlgorithm.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,67 @@ namespace Blake3;
1313
public class Blake3HashAlgorithm : HashAlgorithm
1414
{
1515
private Hasher _hasher;
16+
private bool _disposed;
1617

1718
public Blake3HashAlgorithm()
1819
{
1920
_hasher = Hasher.New();
21+
HashSizeValue = Blake3.Hash.Size * 8;
2022
}
21-
23+
24+
public override int InputBlockSize => 1;
25+
26+
public override int OutputBlockSize => Blake3.Hash.Size;
27+
28+
public override bool CanTransformMultipleBlocks => true;
29+
30+
public override bool CanReuseTransform => true;
31+
2232
protected override void Dispose(bool disposing)
2333
{
34+
if (disposing && !_disposed)
35+
{
36+
_hasher.Dispose();
37+
_disposed = true;
38+
}
39+
2440
base.Dispose(disposing);
25-
_hasher.Dispose();
2641
}
27-
42+
2843
protected override void HashCore(byte[] array, int ibStart, int cbSize)
2944
{
45+
if (array is null) throw new ArgumentNullException(nameof(array));
46+
if ((uint)ibStart > (uint)array.Length) throw new ArgumentOutOfRangeException(nameof(ibStart));
47+
if ((uint)cbSize > (uint)(array.Length - ibStart)) throw new ArgumentOutOfRangeException(nameof(cbSize));
48+
3049
_hasher.Update(new ReadOnlySpan<byte>(array, ibStart, cbSize));
3150
}
3251

52+
protected override void HashCore(ReadOnlySpan<byte> source)
53+
{
54+
_hasher.Update(source);
55+
}
56+
3357
protected override byte[] HashFinal()
3458
{
3559
var hash = new byte[Blake3.Hash.Size];
3660
_hasher.Finalize(hash);
3761
return hash;
3862
}
3963

64+
protected override bool TryHashFinal(Span<byte> destination, out int bytesWritten)
65+
{
66+
if (destination.Length < Blake3.Hash.Size)
67+
{
68+
bytesWritten = 0;
69+
return false;
70+
}
71+
72+
_hasher.Finalize(destination.Slice(0, Blake3.Hash.Size));
73+
bytesWritten = Blake3.Hash.Size;
74+
return true;
75+
}
76+
4077
public override void Initialize()
4178
{
4279
_hasher.Reset();

0 commit comments

Comments
 (0)