diff --git a/NBitcoin.Bench/UInt256Bench.cs b/NBitcoin.Bench/UInt256Bench.cs index 546a435324..6eac93befb 100644 --- a/NBitcoin.Bench/UInt256Bench.cs +++ b/NBitcoin.Bench/UInt256Bench.cs @@ -25,6 +25,25 @@ public void WriteToString() { Value.ToString(); } + +#if HAS_SPAN + [Benchmark] + [Arguments(new char[] { + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0', + '0','0','0','0','0','0','0','0' + })] + public void WriteToSpanString(Span destinationSpan) + { + Value.ToSpanString(destinationSpan); + } +#endif + [Benchmark] public void Read() { diff --git a/NBitcoin.Tests/NBitcoin.Tests.csproj b/NBitcoin.Tests/NBitcoin.Tests.csproj index 06a46c31ad..45f99e2aa5 100644 --- a/NBitcoin.Tests/NBitcoin.Tests.csproj +++ b/NBitcoin.Tests/NBitcoin.Tests.csproj @@ -41,8 +41,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/NBitcoin.Tests/uint256_tests.cs b/NBitcoin.Tests/uint256_tests.cs index b6c2647fa3..4e7998feaa 100644 --- a/NBitcoin.Tests/uint256_tests.cs +++ b/NBitcoin.Tests/uint256_tests.cs @@ -1,11 +1,7 @@ -using NBitcoin.Protocol; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; using Xunit; namespace NBitcoin.Tests @@ -147,7 +143,7 @@ public void uitnSerializationTests2() [Fact] [Trait("UnitTest", "UnitTest")] - public void uitnSerializationTests() + public void uintSerializationTests() { MemoryStream ms = new MemoryStream(); BitcoinStream stream = new BitcoinStream(ms, true); @@ -193,6 +189,18 @@ public void uitnSerializationTests() Assert.True(vs2.SequenceEqual(vs)); } +#if HAS_SPAN + [Fact] + [Trait("UnitTest", "UnitTest")] + public void uintSpanSerializationTests() + { + var v1 = new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + + Assert.Equal("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", v1.ToString()); + Assert.Equal("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff".AsSpan(), v1.ToSpanString()); + } +#endif + private void AssertEquals(uint256 a, uint256 b) { Assert.Equal(a, b); diff --git a/NBitcoin/UInt256.cs b/NBitcoin/UInt256.cs index 1ad6eb37de..26d1a4bf88 100644 --- a/NBitcoin/UInt256.cs +++ b/NBitcoin/UInt256.cs @@ -1,9 +1,8 @@ +using NBitcoin.DataEncoders; using System; -using System.Collections; using System.Linq; using System.Runtime.InteropServices; -using NBitcoin.DataEncoders; namespace NBitcoin { @@ -161,6 +160,43 @@ public override string ToString() return Encoder.EncodeData(bytes); } +#if HAS_SPAN + /// The method allocates a new 64 char array. + public Span ToSpanString() + { + Span result = new char[64]; + + ToSpanString(result); + return result; + } + + /// The method does not allocate. + public void ToSpanString(Span destination) + { + Span ulongs = stackalloc ulong[4]; + ulongs[0] = pn0; + ulongs[1] = pn1; + ulongs[2] = pn2; + ulongs[3] = pn3; + Span bytes = MemoryMarshal.Cast(ulongs); + + if (BitConverter.IsLittleEndian) + { + for (int i = 31, j = 0; i >= 0; i--, j += 2) + { + HexEncoder.ToCharsBuffer(bytes[i], destination, startingIndex: j); + } + } + else + { + for (int i = 0; i < 32; i++) + { + HexEncoder.ToCharsBuffer(bytes[i], destination, startingIndex: i); + } + } + } +#endif + public uint256(ulong b) { pn0 = (uint)b;