diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4f7696cf6e..aa935fd2d3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -151,6 +151,18 @@ jobs: dotnet pack ./src/Neo \ --configuration Release \ --output ./out + - name : Pack (Neo.IO) + if: steps.check_tag.outputs.statusCode == '404' + run: | + dotnet pack ./src/Neo.IO \ + --configuration Release \ + --output ./out + - name : Pack (Neo.Extensions) + if: steps.check_tag.outputs.statusCode == '404' + run: | + dotnet pack ./src/Neo.Extensions \ + --configuration Release \ + --output ./out - name : Pack (Neo.Json) if: steps.check_tag.outputs.statusCode == '404' run: | diff --git a/neo.sln b/neo.sln index dc50d0f4d7..b62de06a6e 100644 --- a/neo.sln +++ b/neo.sln @@ -24,18 +24,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.VM", "src\Neo.VM\Neo.VM EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.VM.Tests", "tests\Neo.VM.Tests\Neo.VM.Tests.csproj", "{005F84EB-EA2E-449F-930A-7B4173DDC7EC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.ConsoleService", "src\Neo.ConsoleService\Neo.ConsoleService.csproj", "{9E886812-7243-48D8-BEAF-47AADC11C054}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.ConsoleService", "src\Neo.ConsoleService\Neo.ConsoleService.csproj", "{9E886812-7243-48D8-BEAF-47AADC11C054}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.GUI", "src\Neo.GUI\Neo.GUI.csproj", "{02ABDE42-9880-43B4-B6F7-8D618602A277}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.GUI", "src\Neo.GUI\Neo.GUI.csproj", "{02ABDE42-9880-43B4-B6F7-8D618602A277}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.CLI", "src\Neo.CLI\Neo.CLI.csproj", "{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.CLI", "src\Neo.CLI\Neo.CLI.csproj", "{BDFBE455-4C1F-4FC4-B5FC-1387B93A8687}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.ConsoleService.Tests", "tests\Neo.ConsoleService.Tests\Neo.ConsoleService.Tests.csproj", "{B40F8584-5AFB-452C-AEFA-009C80CC23A9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.ConsoleService.Tests", "tests\Neo.ConsoleService.Tests\Neo.ConsoleService.Tests.csproj", "{B40F8584-5AFB-452C-AEFA-009C80CC23A9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Cryptography.BLS12_381", "src\Neo.Cryptography.BLS12_381\Neo.Cryptography.BLS12_381.csproj", "{D48C1FAB-3471-4CA0-8688-25E6F43F2C25}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Cryptography.BLS12_381.Tests", "tests\Neo.Cryptography.BLS12_381.Tests\Neo.Cryptography.BLS12_381.Tests.csproj", "{387CCF6C-9A26-43F6-A639-0A82E91E10D8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.IO", "src\Neo.IO\Neo.IO.csproj", "{4CDAC1AA-45C6-4157-8D8E-199050433048}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Extensions", "src\Neo.Extensions\Neo.Extensions.csproj", "{9C5213D6-3833-4570-8AE2-47E9F9017A8F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -98,6 +102,14 @@ Global {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Debug|Any CPU.Build.0 = Debug|Any CPU {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|Any CPU.ActiveCfg = Release|Any CPU {387CCF6C-9A26-43F6-A639-0A82E91E10D8}.Release|Any CPU.Build.0 = Release|Any CPU + {4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CDAC1AA-45C6-4157-8D8E-199050433048}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CDAC1AA-45C6-4157-8D8E-199050433048}.Release|Any CPU.Build.0 = Release|Any CPU + {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -117,6 +129,8 @@ Global {B40F8584-5AFB-452C-AEFA-009C80CC23A9} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1} {D48C1FAB-3471-4CA0-8688-25E6F43F2C25} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} {387CCF6C-9A26-43F6-A639-0A82E91E10D8} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1} + {4CDAC1AA-45C6-4157-8D8E-199050433048} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} + {9C5213D6-3833-4570-8AE2-47E9F9017A8F} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC} diff --git a/src/Neo/LogLevel.cs b/src/Neo.Extensions/LogLevel.cs similarity index 100% rename from src/Neo/LogLevel.cs rename to src/Neo.Extensions/LogLevel.cs diff --git a/src/Neo.Extensions/Neo.Extensions.csproj b/src/Neo.Extensions/Neo.Extensions.csproj new file mode 100644 index 0000000000..7552a56311 --- /dev/null +++ b/src/Neo.Extensions/Neo.Extensions.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.1;net7.0 + enable + NEO;Blockchain;Extensions + + + + + + + + + + + + + diff --git a/src/Neo/Utility.cs b/src/Neo.Extensions/Utility.cs similarity index 97% rename from src/Neo/Utility.cs rename to src/Neo.Extensions/Utility.cs index 6883c69a26..fca164a4f2 100644 --- a/src/Neo/Utility.cs +++ b/src/Neo.Extensions/Utility.cs @@ -31,7 +31,7 @@ public Logger() } } - public static event LogEventHandler Logging; + public static event LogEventHandler? Logging; /// /// A strict UTF8 encoding used in NEO system. diff --git a/src/Neo/IO/ByteArrayComparer.cs b/src/Neo.IO/ByteArrayComparer.cs similarity index 62% rename from src/Neo/IO/ByteArrayComparer.cs rename to src/Neo.IO/ByteArrayComparer.cs index 872052095c..f9d44e24d6 100644 --- a/src/Neo/IO/ByteArrayComparer.cs +++ b/src/Neo.IO/ByteArrayComparer.cs @@ -20,27 +20,32 @@ internal class ByteArrayComparer : IComparer public static readonly ByteArrayComparer Default = new(1); public static readonly ByteArrayComparer Reverse = new(-1); - private readonly int direction; + private readonly int _direction; private ByteArrayComparer(int direction) { - this.direction = direction; + _direction = direction; } - public int Compare(byte[] x, byte[] y) + public int Compare(byte[]? x, byte[]? y) { - return direction > 0 - ? CompareInternal(x, y) - : -CompareInternal(x, y); + if (x == y) return 0; + if (x is null && y is not null) + return _direction > 0 ? -y.Length : y.Length; + if (y is null && x is not null) + return _direction > 0 ? x.Length : -x.Length; + return _direction > 0 ? + CompareInternal(x!, y!) : + -CompareInternal(x!, y!); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int CompareInternal(byte[] x, byte[] y) { - int length = Math.Min(x.Length, y.Length); - for (int i = 0; i < length; i++) + var length = Math.Min(x.Length, y.Length); + for (var i = 0; i < length; i++) { - int r = x[i].CompareTo(y[i]); + var r = x[i].CompareTo(y[i]); if (r != 0) return r; } return x.Length.CompareTo(y.Length); diff --git a/src/Neo/IO/ByteArrayEqualityComparer.cs b/src/Neo.IO/ByteArrayEqualityComparer.cs similarity index 90% rename from src/Neo/IO/ByteArrayEqualityComparer.cs rename to src/Neo.IO/ByteArrayEqualityComparer.cs index ffb5ad0e63..2b6f01491c 100644 --- a/src/Neo/IO/ByteArrayEqualityComparer.cs +++ b/src/Neo.IO/ByteArrayEqualityComparer.cs @@ -17,11 +17,11 @@ internal class ByteArrayEqualityComparer : IEqualityComparer { public static readonly ByteArrayEqualityComparer Default = new(); - public unsafe bool Equals(byte[] x, byte[] y) + public unsafe bool Equals(byte[]? x, byte[]? y) { if (ReferenceEquals(x, y)) return true; if (x is null || y is null) return false; - int len = x.Length; + var len = x.Length; if (len != y.Length) return false; if (len == 0) return true; fixed (byte* xp = x, yp = y) @@ -48,8 +48,8 @@ public int GetHashCode(byte[] obj) { unchecked { - int hash = 17; - foreach (byte element in obj) + var hash = 17; + foreach (var element in obj) hash = hash * 31 + element; return hash; } diff --git a/src/Neo/IO/ISerializable.cs b/src/Neo.IO/ISerializable.cs similarity index 100% rename from src/Neo/IO/ISerializable.cs rename to src/Neo.IO/ISerializable.cs diff --git a/src/Neo/IO/MemoryReader.cs b/src/Neo.IO/MemoryReader.cs similarity index 73% rename from src/Neo/IO/MemoryReader.cs rename to src/Neo.IO/MemoryReader.cs index ece7cb56be..df8afbb3d3 100644 --- a/src/Neo/IO/MemoryReader.cs +++ b/src/Neo.IO/MemoryReader.cs @@ -17,29 +17,29 @@ namespace Neo.IO { public ref struct MemoryReader { - private readonly ReadOnlyMemory memory; - private readonly ReadOnlySpan span; - private int pos = 0; + private readonly ReadOnlyMemory _memory; + private readonly ReadOnlySpan _span; + private int _pos = 0; - public readonly int Position => pos; + public readonly int Position => _pos; public MemoryReader(ReadOnlyMemory memory) { - this.memory = memory; - this.span = memory.Span; + _memory = memory; + _span = memory.Span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private readonly void EnsurePosition(int move) { - if (pos + move > span.Length) throw new FormatException(); + if (_pos + move > _span.Length) throw new FormatException(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly byte Peek() { EnsurePosition(1); - return span[pos]; + return _span[_pos]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -57,7 +57,7 @@ public bool ReadBoolean() public sbyte ReadSByte() { EnsurePosition(1); - byte b = span[pos++]; + var b = _span[_pos++]; return unchecked((sbyte)b); } @@ -65,15 +65,15 @@ public sbyte ReadSByte() public byte ReadByte() { EnsurePosition(1); - return span[pos++]; + return _span[_pos++]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public short ReadInt16() { EnsurePosition(sizeof(short)); - var result = BinaryPrimitives.ReadInt16LittleEndian(span[pos..]); - pos += sizeof(short); + var result = BinaryPrimitives.ReadInt16LittleEndian(_span[_pos..]); + _pos += sizeof(short); return result; } @@ -81,8 +81,8 @@ public short ReadInt16() public short ReadInt16BigEndian() { EnsurePosition(sizeof(short)); - var result = BinaryPrimitives.ReadInt16BigEndian(span[pos..]); - pos += sizeof(short); + var result = BinaryPrimitives.ReadInt16BigEndian(_span[_pos..]); + _pos += sizeof(short); return result; } @@ -90,8 +90,8 @@ public short ReadInt16BigEndian() public ushort ReadUInt16() { EnsurePosition(sizeof(ushort)); - var result = BinaryPrimitives.ReadUInt16LittleEndian(span[pos..]); - pos += sizeof(ushort); + var result = BinaryPrimitives.ReadUInt16LittleEndian(_span[_pos..]); + _pos += sizeof(ushort); return result; } @@ -99,8 +99,8 @@ public ushort ReadUInt16() public ushort ReadUInt16BigEndian() { EnsurePosition(sizeof(ushort)); - var result = BinaryPrimitives.ReadUInt16BigEndian(span[pos..]); - pos += sizeof(ushort); + var result = BinaryPrimitives.ReadUInt16BigEndian(_span[_pos..]); + _pos += sizeof(ushort); return result; } @@ -108,8 +108,8 @@ public ushort ReadUInt16BigEndian() public int ReadInt32() { EnsurePosition(sizeof(int)); - var result = BinaryPrimitives.ReadInt32LittleEndian(span[pos..]); - pos += sizeof(int); + var result = BinaryPrimitives.ReadInt32LittleEndian(_span[_pos..]); + _pos += sizeof(int); return result; } @@ -117,8 +117,8 @@ public int ReadInt32() public int ReadInt32BigEndian() { EnsurePosition(sizeof(int)); - var result = BinaryPrimitives.ReadInt32BigEndian(span[pos..]); - pos += sizeof(int); + var result = BinaryPrimitives.ReadInt32BigEndian(_span[_pos..]); + _pos += sizeof(int); return result; } @@ -126,8 +126,8 @@ public int ReadInt32BigEndian() public uint ReadUInt32() { EnsurePosition(sizeof(uint)); - var result = BinaryPrimitives.ReadUInt32LittleEndian(span[pos..]); - pos += sizeof(uint); + var result = BinaryPrimitives.ReadUInt32LittleEndian(_span[_pos..]); + _pos += sizeof(uint); return result; } @@ -135,8 +135,8 @@ public uint ReadUInt32() public uint ReadUInt32BigEndian() { EnsurePosition(sizeof(uint)); - var result = BinaryPrimitives.ReadUInt32BigEndian(span[pos..]); - pos += sizeof(uint); + var result = BinaryPrimitives.ReadUInt32BigEndian(_span[_pos..]); + _pos += sizeof(uint); return result; } @@ -144,8 +144,8 @@ public uint ReadUInt32BigEndian() public long ReadInt64() { EnsurePosition(sizeof(long)); - var result = BinaryPrimitives.ReadInt64LittleEndian(span[pos..]); - pos += sizeof(long); + var result = BinaryPrimitives.ReadInt64LittleEndian(_span[_pos..]); + _pos += sizeof(long); return result; } @@ -153,8 +153,8 @@ public long ReadInt64() public long ReadInt64BigEndian() { EnsurePosition(sizeof(long)); - var result = BinaryPrimitives.ReadInt64BigEndian(span[pos..]); - pos += sizeof(long); + var result = BinaryPrimitives.ReadInt64BigEndian(_span[_pos..]); + _pos += sizeof(long); return result; } @@ -162,8 +162,8 @@ public long ReadInt64BigEndian() public ulong ReadUInt64() { EnsurePosition(sizeof(ulong)); - var result = BinaryPrimitives.ReadUInt64LittleEndian(span[pos..]); - pos += sizeof(ulong); + var result = BinaryPrimitives.ReadUInt64LittleEndian(_span[_pos..]); + _pos += sizeof(ulong); return result; } @@ -171,16 +171,16 @@ public ulong ReadUInt64() public ulong ReadUInt64BigEndian() { EnsurePosition(sizeof(ulong)); - var result = BinaryPrimitives.ReadUInt64BigEndian(span[pos..]); - pos += sizeof(ulong); + var result = BinaryPrimitives.ReadUInt64BigEndian(_span[_pos..]); + _pos += sizeof(ulong); return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong ReadVarInt(ulong max = ulong.MaxValue) { - byte b = ReadByte(); - ulong value = b switch + var b = ReadByte(); + var value = b switch { 0xfd => ReadUInt16(), 0xfe => ReadUInt32(), @@ -195,24 +195,24 @@ public ulong ReadVarInt(ulong max = ulong.MaxValue) public string ReadFixedString(int length) { EnsurePosition(length); - int end = pos + length; - int i = pos; - while (i < end && span[i] != 0) i++; - ReadOnlySpan data = span[pos..i]; + var end = _pos + length; + var i = _pos; + while (i < end && _span[i] != 0) i++; + var data = _span[_pos..i]; for (; i < end; i++) - if (span[i] != 0) + if (_span[i] != 0) throw new FormatException(); - pos = end; + _pos = end; return Utility.StrictUTF8.GetString(data); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string ReadVarString(int max = 0x1000000) { - int length = (int)ReadVarInt((ulong)max); + var length = (int)ReadVarInt((ulong)max); EnsurePosition(length); - ReadOnlySpan data = span.Slice(pos, length); - pos += length; + var data = _span.Slice(_pos, length); + _pos += length; return Utility.StrictUTF8.GetString(data); } @@ -220,22 +220,20 @@ public string ReadVarString(int max = 0x1000000) public ReadOnlyMemory ReadMemory(int count) { EnsurePosition(count); - ReadOnlyMemory result = memory.Slice(pos, count); - pos += count; + var result = _memory.Slice(_pos, count); + _pos += count; return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory ReadVarMemory(int max = 0x1000000) - { - return ReadMemory((int)ReadVarInt((ulong)max)); - } + public ReadOnlyMemory ReadVarMemory(int max = 0x1000000) => + ReadMemory((int)ReadVarInt((ulong)max)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory ReadToEnd() { - ReadOnlyMemory result = memory[pos..]; - pos = memory.Length; + var result = _memory[_pos..]; + _pos = _memory.Length; return result; } } diff --git a/src/Neo.IO/Neo.IO.csproj b/src/Neo.IO/Neo.IO.csproj new file mode 100644 index 0000000000..05bc305a67 --- /dev/null +++ b/src/Neo.IO/Neo.IO.csproj @@ -0,0 +1,20 @@ + + + + netstandard2.1;net7.0 + true + enable + NEO;Blockchain;IO + + + + + + + + + + + + + diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 130ff2a570..75541f9091 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -18,6 +18,8 @@ + + diff --git a/tests/Neo.UnitTests/IO/UT_ByteArrayComparer.cs b/tests/Neo.UnitTests/IO/UT_ByteArrayComparer.cs index 5efba80cb3..19c3fafcd6 100644 --- a/tests/Neo.UnitTests/IO/UT_ByteArrayComparer.cs +++ b/tests/Neo.UnitTests/IO/UT_ByteArrayComparer.cs @@ -12,6 +12,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; +using System; namespace Neo.UnitTests.IO { @@ -22,10 +23,23 @@ public class UT_ByteArrayComparer public void TestCompare() { ByteArrayComparer comparer = ByteArrayComparer.Default; - byte[] x = new byte[0], y = new byte[0]; + byte[] x = null, y = null; comparer.Compare(x, y).Should().Be(0); + x = new byte[] { 1, 2, 3, 4, 5 }; + y = x; + comparer.Compare(x, y).Should().Be(0); + comparer.Compare(x, x).Should().Be(0); + + y = null; + comparer.Compare(x, y).Should().Be(5); + + y = x; + x = null; + comparer.Compare(x, y).Should().Be(-5); + x = new byte[] { 1 }; + y = Array.Empty(); comparer.Compare(x, y).Should().Be(1); y = x; comparer.Compare(x, y).Should().Be(0);