Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
df15fe0
Fixed `UInt160` and expanded class
cschuchardt88 Jul 18, 2024
acd1ef4
Cleaned up code for `TryParse`
cschuchardt88 Jul 18, 2024
47ac12e
Fixed `TryParse`
cschuchardt88 Jul 18, 2024
28c9af0
Fixed small bug with `TryParse`
cschuchardt88 Jul 18, 2024
4be0af1
Merge branch 'master' into fix/uint160-class
shargon Jul 22, 2024
950555b
Change `UInt160.Zero` to `static readonly`
cschuchardt88 Jul 23, 2024
3c3ff03
Merge branch 'fix/uint160-class' of https://github.com/cschuchardt88/…
cschuchardt88 Jul 23, 2024
d93f4fe
Merge branch 'master' into fix/uint160-class
cschuchardt88 Jul 23, 2024
20b97f2
Merge branch 'master' into fix/uint160-class
Jul 23, 2024
6303faa
Merge branch 'master' into fix/uint160-class
Jul 26, 2024
70b4ff9
Merge branch 'master' into fix/uint160-class
cschuchardt88 Jul 28, 2024
c8b1911
Merge branch 'master' into fix/uint160-class
Jul 29, 2024
c445f91
Merge branch 'master' into fix/uint160-class
Aug 1, 2024
8ccafb4
benchmark UInt160
Jim8y Aug 1, 2024
7bf3b0d
Merge branch 'master' into fix/uint160-class
cschuchardt88 Aug 1, 2024
c1b0fc7
Fix benchmark
cschuchardt88 Aug 1, 2024
b7209e2
Fixed bugs and added features for `UInt160` class
cschuchardt88 Aug 1, 2024
9bc5436
Revert and just keep bug fixes
cschuchardt88 Aug 1, 2024
bc65668
Made @shargon changes
cschuchardt88 Aug 2, 2024
6ac2adb
Set `InvariantCultureIgnoreCase` back for `0x` and `0X`
cschuchardt88 Aug 2, 2024
008f2cb
Merge branch 'master' into fix/uint160-class
cschuchardt88 Aug 10, 2024
9958d38
Merge branch 'master' into fix/uint160-class
cschuchardt88 Aug 23, 2024
d1ef56b
Merge branch 'master' into fix/uint160-class
cschuchardt88 Aug 26, 2024
2c4af0f
Merge branch 'master' into fix/uint160-class
cschuchardt88 Aug 27, 2024
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
123 changes: 72 additions & 51 deletions src/Neo/UInt160.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@

using Neo.IO;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Neo
Expand All @@ -31,68 +32,72 @@ public class UInt160 : IComparable<UInt160>, IEquatable<UInt160>, ISerializable
/// <summary>
/// Represents 0.
/// </summary>
public static readonly UInt160 Zero = new();
public static UInt160 Zero => new();

[FieldOffset(0)] private ulong value1;
[FieldOffset(8)] private ulong value2;
[FieldOffset(16)] private uint value3;
[FieldOffset(0)] private ulong _value1;
[FieldOffset(8)] private ulong _value2;
[FieldOffset(16)] private uint _value3;

public int Size => Length;

/// <summary>
/// Initializes a new instance of the <see cref="UInt160"/> class.
/// </summary>
public UInt160()
{
}
public UInt160() { }

/// <summary>
/// Initializes a new instance of the <see cref="UInt160"/> class.
/// </summary>
/// <param name="value">The value of the <see cref="UInt160"/>.</param>
public unsafe UInt160(ReadOnlySpan<byte> value)
public UInt160(ReadOnlySpan<byte> value)
{
if (value.Length != Length) throw new FormatException();
fixed (ulong* p = &value1)
{
Span<byte> dst = new(p, Length);
value[..Length].CopyTo(dst);
}
if (value.Length != Length)
throw new FormatException();

var bytes = value.ToArray();
_value1 = Unsafe.As<byte, ulong>(ref bytes[0]);
_value2 = Unsafe.As<byte, ulong>(ref bytes[8]);
_value3 = Unsafe.As<byte, uint>(ref bytes[16]);
}

public int CompareTo(UInt160 other)
{
int result = value3.CompareTo(other.value3);
var result = _value3.CompareTo(other._value3);
if (result != 0) return result;
result = value2.CompareTo(other.value2);
result = _value2.CompareTo(other._value2);
if (result != 0) return result;
return value1.CompareTo(other.value1);
return _value1.CompareTo(other._value1);
}

public void Deserialize(ref MemoryReader reader)
{
value1 = reader.ReadUInt64();
value2 = reader.ReadUInt64();
value3 = reader.ReadUInt32();
_value1 = reader.ReadUInt64();
_value2 = reader.ReadUInt64();
_value3 = reader.ReadUInt32();
}

public override bool Equals(object obj)
{
if (ReferenceEquals(obj, this)) return true;
return Equals(obj as UInt160);
if (obj == null)
return false;

var other = obj as UInt160;
if (other == null)
return false;
return Equals(other);
}

public bool Equals(UInt160 other)
{
if (other is null) return false;
return value1 == other.value1
&& value2 == other.value2
&& value3 == other.value3;
if (other == null) return false;
return _value1 == other._value1 &&
_value2 == other._value2 &&
_value3 == other._value3;
}

public override int GetHashCode()
{
return (int)value1;
return HashCode.Combine(_value1, _value2, _value3);
}

/// <summary>
Expand All @@ -109,9 +114,9 @@ public static UInt160 Parse(string value)

public void Serialize(BinaryWriter writer)
{
writer.Write(value1);
writer.Write(value2);
writer.Write(value3);
writer.Write(_value1);
writer.Write(_value2);
writer.Write(_value3);
}

public override string ToString()
Expand All @@ -122,44 +127,60 @@ public override string ToString()
/// <summary>
/// Parses an <see cref="UInt160"/> from the specified <see cref="string"/>.
/// </summary>
/// <param name="s">An <see cref="UInt160"/> represented by a <see cref="string"/>.</param>
/// <param name="str">An <see cref="UInt160"/> represented by a <see cref="string"/>.</param>
/// <param name="result">The parsed <see cref="UInt160"/>.</param>
/// <returns><see langword="true"/> if an <see cref="UInt160"/> is successfully parsed; otherwise, <see langword="false"/>.</returns>
public static bool TryParse(string s, out UInt160 result)
public static bool TryParse(string str, out UInt160 result)
{
if (s == null)
result = null;

if (string.IsNullOrWhiteSpace(str)) return false;

if (str.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
str = str[2..];

if (str.Length != Length * 2) return false;

try
{
result = null;
return false;
var data = Enumerable.Range(0, Length)
.Select(s => Convert.ToByte(str.Substring(s * 2, 2), 16))
.Reverse()
.ToArray();

result = new(data);
return true;
}
if (s.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
s = s[2..];
if (s.Length != Length * 2)
catch
{
result = null;
return false;
}
byte[] data = new byte[Length];
for (int i = 0; i < Length; i++)
if (!byte.TryParse(s.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, null, out data[Length - i - 1]))
{
result = null;
return false;
}
result = new UInt160(data);
return true;
}

public static implicit operator UInt160(string s)
{
return Parse(s);
}

public static implicit operator UInt160(byte[] b)
{
return new UInt160(b);
}

public static bool operator ==(UInt160 left, UInt160 right)
{
if (ReferenceEquals(left, right)) return true;
if (left is null || right is null) return false;
if (left is null || right is null)
return Equals(left, right);
return left.Equals(right);
}

public static bool operator !=(UInt160 left, UInt160 right)
{
return !(left == right);
if (ReferenceEquals(left, right)) return false;
if (left is null || right is null)
return !Equals(left, right);
return !left.Equals(right);
}

public static bool operator >(UInt160 left, UInt160 right)
Expand Down
27 changes: 21 additions & 6 deletions tests/Neo.UnitTests/UT_UInt160.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

#pragma warning disable CS1718

using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Security.Cryptography;

namespace Neo.UnitTests.IO
{
Expand All @@ -36,8 +35,16 @@ public void TestGernerator1()
[TestMethod]
public void TestGernerator2()
{
UInt160 uInt160 = new UInt160(new byte[20]);
UInt160 uInt160 = new byte[20];
Assert.IsNotNull(uInt160);
}

[TestMethod]
public void TestGernerator3()
{
UInt160 uInt160 = "0xff00000000000000000000000000000000000001";
Assert.IsNotNull(uInt160);
Assert.IsTrue(uInt160.ToString() == "0xff00000000000000000000000000000000000001");
}

[TestMethod]
Expand All @@ -57,9 +64,13 @@ public void TestEquals()
byte[] temp = new byte[20];
temp[19] = 0x01;
UInt160 result = new UInt160(temp);
Assert.AreEqual(true, UInt160.Zero.Equals(UInt160.Zero));
Assert.AreEqual(false, UInt160.Zero.Equals(result));
Assert.AreEqual(false, result.Equals(null));
Assert.IsTrue(UInt160.Zero.Equals(UInt160.Zero));
Assert.IsFalse(UInt160.Zero.Equals(result));
Assert.IsFalse(result.Equals(null));
Assert.IsTrue(UInt160.Zero == UInt160.Zero);
Assert.IsFalse(UInt160.Zero != UInt160.Zero);
Assert.IsTrue(UInt160.Zero == "0x0000000000000000000000000000000000000000");
Assert.IsFalse(UInt160.Zero == "0x0000000000000000000000000000000000000001");
}

[TestMethod]
Expand Down Expand Up @@ -92,24 +103,28 @@ public void TestTryParse()
public void TestOperatorLarger()
{
Assert.AreEqual(false, UInt160.Zero > UInt160.Zero);
Assert.IsFalse(UInt160.Zero > "0x0000000000000000000000000000000000000000");
}

[TestMethod]
public void TestOperatorLargerAndEqual()
{
Assert.AreEqual(true, UInt160.Zero >= UInt160.Zero);
Assert.IsTrue(UInt160.Zero >= "0x0000000000000000000000000000000000000000");
}

[TestMethod]
public void TestOperatorSmaller()
{
Assert.AreEqual(false, UInt160.Zero < UInt160.Zero);
Assert.IsFalse(UInt160.Zero < "0x0000000000000000000000000000000000000000");
}

[TestMethod]
public void TestOperatorSmallerAndEqual()
{
Assert.AreEqual(true, UInt160.Zero <= UInt160.Zero);
Assert.IsTrue(UInt160.Zero >= "0x0000000000000000000000000000000000000000");
}
}
}