Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/Nethermind/Nethermind.Core.Test/Int64Tests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using FluentAssertions;
using Nethermind.Core.Extensions;
using NUnit.Framework;
Expand All @@ -17,5 +18,56 @@ public void ToLongFromBytes()
long number = bytes.ToLongFromBigEndianByteArrayWithoutLeadingZeros();
number.Should().Be(long.MaxValue);
}

[TestCase("0000", 0L)]
[TestCase("0001234", 0x1234L)]
[TestCase("1234", 0x1234L)]
[TestCase("1", 1L)]
[TestCase("10", 16L)]
[TestCase("7fffffffffffffff", long.MaxValue)]
[TestCase("8000000000000000", long.MinValue)]
[TestCase("ffffffffffffffff", -1L)]
public void ToLongFromBytes_Vectors_match_for_array_and_span(string hexBytes, long expected)
{
byte[] bytes = Bytes.FromHexString(hexBytes);
long viaArray = bytes.ToLongFromBigEndianByteArrayWithoutLeadingZeros();
long viaSpan = bytes.AsSpan().ToLongFromBigEndianByteArrayWithoutLeadingZeros();
viaArray.Should().Be(expected);
viaSpan.Should().Be(expected);
}

[Test]
public void ToLongFromBytes_Exact_sequence_0102030405060708()
{
byte[] bytes = Bytes.FromHexString("0102030405060708");
long expected = unchecked((long)0x0102030405060708UL);
bytes.ToLongFromBigEndianByteArrayWithoutLeadingZeros().Should().Be(expected);
bytes.AsSpan().ToLongFromBigEndianByteArrayWithoutLeadingZeros().Should().Be(expected);
}

[TestCase("01ffffffffffffffff", -1L)]
[TestCase("010000000000000000", 0L)]
public void ToLongFromBytes_Oversized_inputs_keep_last_8_bytes(string hexBytes, long expected)
{
byte[] bytes = Bytes.FromHexString(hexBytes);
bytes.ToLongFromBigEndianByteArrayWithoutLeadingZeros().Should().Be(expected);
bytes.AsSpan().ToLongFromBigEndianByteArrayWithoutLeadingZeros().Should().Be(expected);
}

[Test]
public void ToLongFromBytes_Empty_span_is_zero()
{
ReadOnlySpan<byte> span = ReadOnlySpan<byte>.Empty;
long number = span.ToLongFromBigEndianByteArrayWithoutLeadingZeros();
number.Should().Be(0L);
}

[Test]
public void ToLongFromBytes_Null_array_is_zero()
{
byte[]? bytes = null;
long number = bytes.ToLongFromBigEndianByteArrayWithoutLeadingZeros();
number.Should().Be(0L);
}
}
}
17 changes: 10 additions & 7 deletions src/Nethermind/Nethermind.Core/Extensions/Int64Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,24 @@ public static string ToHexString(this in UInt256 value, bool skipLeadingZeros)
return bytes.ToHexString(true, skipLeadingZeros, false);
}

public static long ToLongFromBigEndianByteArrayWithoutLeadingZeros(this byte[]? bytes)
public static long ToLongFromBigEndianByteArrayWithoutLeadingZeros(this ReadOnlySpan<byte> bytes)
{
if (bytes is null)
if (bytes.IsEmpty)
{
return 0L;
}

long value = 0;
int length = bytes.Length;
ulong u = UInt64Extensions.ToULongFromBigEndianByteArrayWithoutLeadingZeros(bytes);
return unchecked((long)u);
}
Comment on lines +94 to +103
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new ReadOnlySpan overload lacks test coverage. Consider adding test cases similar to those in UInt64Tests.cs (which has comprehensive test cases for various edge cases like "7fffffffffffffff", "ffffffffffffffff", "0000", etc.) to ensure the span-based implementation handles all scenarios correctly, especially since it now delegates to UInt64Extensions and performs an unchecked cast.

Copilot uses AI. Check for mistakes.

for (int i = 0; i < length; i++)
public static long ToLongFromBigEndianByteArrayWithoutLeadingZeros(this byte[]? bytes)
{
if (bytes is null)
{
value += (long)bytes[length - 1 - i] << 8 * i;
return 0L;
}

return value;
return ToLongFromBigEndianByteArrayWithoutLeadingZeros(bytes.AsSpan());
}
}
Loading