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);