Skip to content

Commit 3d27554

Browse files
authored
Add NonCryptographicHashAlgorithm Clone methods (#113087)
1 parent 12e0ad6 commit 3d27554

18 files changed

+164
-0
lines changed

src/libraries/System.IO.Hashing/ref/System.IO.Hashing.cs

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public sealed partial class Crc32 : System.IO.Hashing.NonCryptographicHashAlgori
1010
{
1111
public Crc32() : base (default(int)) { }
1212
public override void Append(System.ReadOnlySpan<byte> source) { }
13+
public System.IO.Hashing.Crc32 Clone() { throw null; }
1314
[System.CLSCompliantAttribute(false)]
1415
public uint GetCurrentHashAsUInt32() { throw null; }
1516
protected override void GetCurrentHashCore(System.Span<byte> destination) { }
@@ -25,6 +26,7 @@ public override void Reset() { }
2526
public sealed partial class Crc64 : System.IO.Hashing.NonCryptographicHashAlgorithm
2627
{
2728
public Crc64() : base (default(int)) { }
29+
public System.IO.Hashing.Crc64 Clone() { throw null; }
2830
public override void Append(System.ReadOnlySpan<byte> source) { }
2931
[System.CLSCompliantAttribute(false)]
3032
public ulong GetCurrentHashAsUInt64() { throw null; }
@@ -64,6 +66,7 @@ public sealed partial class XxHash128 : System.IO.Hashing.NonCryptographicHashAl
6466
public XxHash128() : base (default(int)) { }
6567
public XxHash128(long seed) : base (default(int)) { }
6668
public override void Append(System.ReadOnlySpan<byte> source) { }
69+
public System.IO.Hashing.XxHash128 Clone() { throw null; }
6770
protected override void GetCurrentHashCore(System.Span<byte> destination) { }
6871
public static byte[] Hash(byte[] source) { throw null; }
6972
public static byte[] Hash(byte[] source, long seed) { throw null; }
@@ -77,6 +80,7 @@ public sealed partial class XxHash3 : System.IO.Hashing.NonCryptographicHashAlgo
7780
public XxHash3() : base (default(int)) { }
7881
public XxHash3(long seed) : base (default(int)) { }
7982
public override void Append(System.ReadOnlySpan<byte> source) { }
83+
public System.IO.Hashing.XxHash3 Clone() { throw null; }
8084
[System.CLSCompliantAttribute(false)]
8185
public ulong GetCurrentHashAsUInt64() { throw null; }
8286
protected override void GetCurrentHashCore(System.Span<byte> destination) { }
@@ -94,6 +98,7 @@ public sealed partial class XxHash32 : System.IO.Hashing.NonCryptographicHashAlg
9498
public XxHash32() : base (default(int)) { }
9599
public XxHash32(int seed) : base (default(int)) { }
96100
public override void Append(System.ReadOnlySpan<byte> source) { }
101+
public System.IO.Hashing.XxHash32 Clone() { throw null; }
97102
[System.CLSCompliantAttribute(false)]
98103
public uint GetCurrentHashAsUInt32() { throw null; }
99104
protected override void GetCurrentHashCore(System.Span<byte> destination) { }
@@ -111,6 +116,7 @@ public sealed partial class XxHash64 : System.IO.Hashing.NonCryptographicHashAlg
111116
public XxHash64() : base (default(int)) { }
112117
public XxHash64(long seed) : base (default(int)) { }
113118
public override void Append(System.ReadOnlySpan<byte> source) { }
119+
public System.IO.Hashing.XxHash64 Clone() { throw null; }
114120
[System.CLSCompliantAttribute(false)]
115121
public ulong GetCurrentHashAsUInt64() { throw null; }
116122
protected override void GetCurrentHashCore(System.Span<byte> destination) { }

src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs

+10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ public Crc32()
3939
{
4040
}
4141

42+
/// <summary>Initializes a new instance of the <see cref="Crc32"/> class using the state from another instance.</summary>
43+
private Crc32(uint crc) : base(Size)
44+
{
45+
_crc = crc;
46+
}
47+
48+
/// <summary>Returns a clone of the current instance, with a copy of the current instance's internal state.</summary>
49+
/// <returns>A new instance that will produce the same sequence of values as the current instance.</returns>
50+
public Crc32 Clone() => new(_crc);
51+
4252
/// <summary>
4353
/// Appends the contents of <paramref name="source"/> to the data already
4454
/// processed for the current hash computation.

src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ public Crc64()
3838
{
3939
}
4040

41+
/// <summary>Initializes a new instance of the <see cref="Crc64"/> class using the state from another instance.</summary>
42+
private Crc64(ulong crc) : base(Size)
43+
{
44+
_crc = crc;
45+
}
46+
47+
/// <summary>Returns a clone of the current instance, with a copy of the current instance's internal state.</summary>
48+
/// <returns>A new instance that will produce the same sequence of values as the current instance.</returns>
49+
public Crc64 Clone() => new(_crc);
50+
4151
/// <summary>
4252
/// Appends the contents of <paramref name="source"/> to the data already
4353
/// processed for the current hash computation.

src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash128.cs

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ public XxHash128(long seed) : base(HashLengthInBytes)
3838
Initialize(ref _state, (ulong)seed);
3939
}
4040

41+
/// <summary>Initializes a new instance of the <see cref="XxHash128"/> class using the state from another instance.</summary>
42+
private XxHash128(State state) : base(HashLengthInBytes)
43+
{
44+
_state = state;
45+
}
46+
47+
/// <summary>Returns a clone of the current instance, with a copy of the current instance's internal state.</summary>
48+
/// <returns>A new instance that will produce the same sequence of values as the current instance.</returns>
49+
public XxHash128 Clone() => new(_state);
50+
4151
/// <summary>Computes the XXH128 hash of the provided <paramref name="source"/> data.</summary>
4252
/// <param name="source">The data to hash.</param>
4353
/// <returns>The XXH128 128-bit hash code of the provided data.</returns>

src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash3.cs

+10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ public XxHash3(long seed) : base(HashLengthInBytes)
3737
Initialize(ref _state, (ulong)seed);
3838
}
3939

40+
/// <summary>Initializes a new instance of the <see cref="XxHash3"/> class using the state from another instance.</summary>
41+
private XxHash3(State state) : base(HashLengthInBytes)
42+
{
43+
_state = state;
44+
}
45+
46+
/// <summary>Returns a clone of the current instance, with a copy of the current instance's internal state.</summary>
47+
/// <returns>A new instance that will produce the same sequence of values as the current instance.</returns>
48+
public XxHash3 Clone() => new(_state);
49+
4050
/// <summary>Computes the XXH3 hash of the provided <paramref name="source"/> data.</summary>
4151
/// <param name="source">The data to hash.</param>
4252
/// <returns>The XXH3 64-bit hash code of the provided data.</returns>

src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs

+17
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ public XxHash32(int seed)
5151
Reset();
5252
}
5353

54+
/// <summary>Initializes a new instance of the <see cref="XxHash32"/> class using the state from another instance.</summary>
55+
private XxHash32(uint seed, State state, byte[]? holdback, int length) :
56+
base(HashSize)
57+
{
58+
_seed = seed;
59+
_state = state;
60+
if (((int)length & 0x0F) > 0)
61+
{
62+
_holdback = (byte[]?)holdback?.Clone();
63+
}
64+
_length = length;
65+
}
66+
67+
/// <summary>Returns a clone of the current instance, with a copy of the current instance's internal state.</summary>
68+
/// <returns>A new instance that will produce the same sequence of values as the current instance.</returns>
69+
public XxHash32 Clone() => new(_seed, _state, _holdback, _length);
70+
5471
/// <summary>
5572
/// Resets the hash computation to the initial state.
5673
/// </summary>

src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs

+17
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,23 @@ public XxHash64(long seed)
5151
Reset();
5252
}
5353

54+
/// <summary>Initializes a new instance of the <see cref="XxHash64"/> class using the state from another instance.</summary>
55+
private XxHash64(ulong seed, State state, byte[]? holdback, long length) :
56+
base(HashSize)
57+
{
58+
_seed = seed;
59+
_state = state;
60+
if (((int)length & 0x1F) > 0)
61+
{
62+
_holdback = (byte[]?)holdback?.Clone();
63+
}
64+
_length = length;
65+
}
66+
67+
/// <summary>Returns a clone of the current instance, with a copy of the current instance's internal state.</summary>
68+
/// <returns>A new instance that will produce the same sequence of values as the current instance.</returns>
69+
public XxHash64 Clone() => new(_seed, _state, _holdback, _length);
70+
5471
/// <summary>
5572
/// Resets the hash computation to the initial state.
5673
/// </summary>

src/libraries/System.IO.Hashing/tests/Crc32Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public static IEnumerable<object[]> TestCases
8383
};
8484

8585
protected override NonCryptographicHashAlgorithm CreateInstance() => new Crc32();
86+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((Crc32)instance).Clone();
8687

8788
protected override byte[] StaticOneShot(byte[] source) => Crc32.Hash(source);
8889

src/libraries/System.IO.Hashing/tests/Crc64Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public static IEnumerable<object[]> TestCases
9292
};
9393

9494
protected override NonCryptographicHashAlgorithm CreateInstance() => new Crc64();
95+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((Crc64)instance).Clone();
9596

9697
protected override byte[] StaticOneShot(byte[] source) => Crc64.Hash(source);
9798

src/libraries/System.IO.Hashing/tests/NonCryptoHashTestDriver.cs

+26
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ protected NonCryptoHashTestDriver(byte[] emptyHash)
2121
}
2222

2323
protected abstract NonCryptographicHashAlgorithm CreateInstance();
24+
protected abstract NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance);
2425

2526
protected abstract byte[] StaticOneShot(byte[] source);
2627
protected abstract byte[] StaticOneShot(ReadOnlySpan<byte> source);
@@ -283,6 +284,31 @@ public void StaticVerifyTryOneShotSpanTooShortNoWrites()
283284
}
284285
}
285286

287+
[Fact]
288+
public void Clone_ProducesSameSequence()
289+
{
290+
NonCryptographicHashAlgorithm hash = CreateInstance();
291+
292+
for (int outer = 0; outer < 4; outer++)
293+
{
294+
NonCryptographicHashAlgorithm clone = Clone(hash);
295+
Assert.Equal(hash.HashLengthInBytes, clone.HashLengthInBytes);
296+
Assert.Equal(hash.GetCurrentHash(), clone.GetCurrentHash());
297+
298+
Random r = new Random(42);
299+
byte[] bytes = new byte[r.Next(1, 10)];
300+
301+
for (int inner = 0; inner < 4; inner++)
302+
{
303+
r.NextBytes(bytes);
304+
hash.Append(bytes);
305+
clone.Append(bytes);
306+
307+
Assert.Equal(hash.GetCurrentHash(), clone.GetCurrentHash());
308+
}
309+
}
310+
}
311+
286312
private void VerifyEmptyResult(ReadOnlySpan<byte> result)
287313
{
288314
if (!result.SequenceEqual(_emptyHash))

src/libraries/System.IO.Hashing/tests/XxHash128Tests.cs

+25
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,31 @@ public void Hash_Streaming_Expected()
131131
}
132132
}
133133

134+
[Fact]
135+
public void Clone_ProducesSameSequence()
136+
{
137+
XxHash128 hash = new(42);
138+
139+
for (int outer = 0; outer < 4; outer++)
140+
{
141+
XxHash128 clone = hash.Clone();
142+
Assert.Equal(hash.HashLengthInBytes, clone.HashLengthInBytes);
143+
Assert.Equal(hash.GetCurrentHash(), clone.GetCurrentHash());
144+
145+
Random r = new Random(42);
146+
byte[] bytes = new byte[r.Next(1, 10)];
147+
148+
for (int inner = 0; inner < 4; inner++)
149+
{
150+
r.NextBytes(bytes);
151+
hash.Append(bytes);
152+
clone.Append(bytes);
153+
154+
Assert.Equal(hash.GetCurrentHash(), clone.GetCurrentHash());
155+
}
156+
}
157+
}
158+
134159
private static Hash128 ReadHashBigEndian(ReadOnlySpan<byte> span)
135160
{
136161
var high = BinaryPrimitives.ReadUInt64BigEndian(span);

src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public static IEnumerable<object[]> LargeTestCases
118118
};
119119

120120
protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(Seed);
121+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((XxHash32)instance).Clone();
121122

122123
protected override byte[] StaticOneShot(byte[] source) => XxHash32.Hash(source, Seed);
123124

src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ public static IEnumerable<object[]> LargeTestCases
132132
};
133133

134134
protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32();
135+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((XxHash32)instance).Clone();
135136

136137
protected override byte[] StaticOneShot(byte[] source) => XxHash32.Hash(source);
137138

src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public static IEnumerable<object[]> LargeTestCases
118118
};
119119

120120
protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(Seed);
121+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((XxHash32)instance).Clone();
121122

122123
protected override byte[] StaticOneShot(byte[] source) => XxHash32.Hash(source, Seed);
123124

src/libraries/System.IO.Hashing/tests/XxHash3Tests.cs

+25
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,31 @@ public void Hash_Streaming_Expected()
122122
}
123123
}
124124

125+
[Fact]
126+
public void Clone_ProducesSameSequence()
127+
{
128+
XxHash3 hash = new(42);
129+
130+
for (int outer = 0; outer < 4; outer++)
131+
{
132+
XxHash3 clone = hash.Clone();
133+
Assert.Equal(hash.HashLengthInBytes, clone.HashLengthInBytes);
134+
Assert.Equal(hash.GetCurrentHash(), clone.GetCurrentHash());
135+
136+
Random r = new Random(42);
137+
byte[] bytes = new byte[r.Next(1, 10)];
138+
139+
for (int inner = 0; inner < 4; inner++)
140+
{
141+
r.NextBytes(bytes);
142+
hash.Append(bytes);
143+
clone.Append(bytes);
144+
145+
Assert.Equal(hash.GetCurrentHash(), clone.GetCurrentHash());
146+
}
147+
}
148+
}
149+
125150
private static IEnumerable<(ulong Hash, long Seed, string Ascii)> TestCases()
126151
{
127152
yield return (Hash: 0x2d06800538d394c2UL, Seed: 0x0000000000000000L, Ascii: "");

src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public static IEnumerable<object[]> TestCases
103103
};
104104

105105
protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(Seed);
106+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((XxHash64)instance).Clone();
106107

107108
protected override byte[] StaticOneShot(byte[] source) => XxHash64.Hash(source, Seed);
108109

src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ public static IEnumerable<object[]> LargeTestCases
145145
};
146146

147147
protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64();
148+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((XxHash64)instance).Clone();
148149

149150
protected override byte[] StaticOneShot(byte[] source) => XxHash64.Hash(source);
150151

src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public static IEnumerable<object[]> LargeTestCases
128128
};
129129

130130
protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(Seed);
131+
protected override NonCryptographicHashAlgorithm Clone(NonCryptographicHashAlgorithm instance) => ((XxHash64)instance).Clone();
131132

132133
protected override byte[] StaticOneShot(byte[] source) => XxHash64.Hash(source, Seed);
133134

0 commit comments

Comments
 (0)