diff --git a/binding/csharp/IP2Region.Net.Test/XdbTest.cs b/binding/csharp/IP2Region.Net.Test/XdbTest.cs index b61c911..ff376a1 100644 --- a/binding/csharp/IP2Region.Net.Test/XdbTest.cs +++ b/binding/csharp/IP2Region.Net.Test/XdbTest.cs @@ -1,6 +1,4 @@ -using System.Buffers; -using System.Buffers.Binary; -using Xunit; +using Xunit; namespace IP2Region.Net.Test; @@ -10,67 +8,28 @@ public class XdbTest public async Task VersionIPV4_Ok() { var db = Path.Combine(AppContext.BaseDirectory, "TestData", $"ip2region_v4.xdb"); - using var reader = File.OpenRead(db); - using var owner = MemoryPool.Shared.Rent(256); - var length = await reader.ReadAsync(owner.Memory[0..256]); - Assert.Equal(256, length); - - var ver = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span[..2]); - Assert.Equal(3, ver); - - var indexPolicy = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span.Slice(2, 2)); - Assert.Equal(1, indexPolicy); - - var createdAt = BinaryPrimitives.ReadUInt32LittleEndian(owner.Memory.Span.Slice(4, 4)); - var dtm = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - dtm = dtm.AddSeconds(createdAt); - Assert.Equal("2025-09-06 02:24:16", dtm.ToString("yyyy-MM-dd HH:mm:ss")); - - var startIndexPtr = BinaryPrimitives.ReadUInt32LittleEndian(owner.Memory.Span.Slice(8, 4)); - Assert.Equal((uint)955933, startIndexPtr); - - var endIndexPtr = BinaryPrimitives.ReadUInt32LittleEndian(owner.Memory.Span.Slice(12, 4)); - Assert.Equal((uint)11042415, endIndexPtr); - - // since IPv6 supporting - var ipVersion = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span.Slice(16, 2)); - Assert.Equal(4, ipVersion); - - var runtimePtrBytes = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span.Slice(18, 2)); - Assert.Equal(4, runtimePtrBytes); + var version = await XDB.Util.GetVersionAsync(db); + Assert.Equal(3, version.Ver); + Assert.Equal(1, version.CachePolice); + Assert.Equal("2025-09-06 02:24:16", version.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss")); + Assert.Equal((uint)955933, version.StartIndex); + Assert.Equal((uint)11042415, version.EndIndex); + Assert.Equal(4, version.IPVer); + Assert.Equal(4, version.BytesCount); } [Fact] public async Task VersionIPV6_Ok() { var db = Path.Combine(AppContext.BaseDirectory, "TestData", $"ip2region_v6.xdb"); - using var reader = File.OpenRead(db); - - using var owner = MemoryPool.Shared.Rent(256); - var length = await reader.ReadAsync(owner.Memory[0..256]); - Assert.Equal(256, length); - - var ver = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span[..2]); - Assert.Equal(3, ver); - - var indexPolicy = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span.Slice(2, 2)); - var createdAt = BinaryPrimitives.ReadUInt32LittleEndian(owner.Memory.Span.Slice(4, 4)); - var dtm = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - dtm = dtm.AddSeconds(createdAt); - Assert.Equal("2025-10-17 04:41:04", dtm.ToString("yyyy-MM-dd HH:mm:ss")); - - var startIndexPtr = BinaryPrimitives.ReadUInt32LittleEndian(owner.Memory.Span.Slice(8, 4)); - Assert.Equal((uint)3094259, startIndexPtr); - - var endIndexPtr = BinaryPrimitives.ReadUInt32LittleEndian(owner.Memory.Span.Slice(12, 4)); - Assert.Equal((uint)36258303, endIndexPtr); - - // since IPv6 supporting - var ipVersion = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span.Slice(16, 2)); - Assert.Equal(6, ipVersion); - - var runtimePtrBytes = BinaryPrimitives.ReadUInt16LittleEndian(owner.Memory.Span.Slice(18, 2)); - Assert.Equal(4, runtimePtrBytes); + var version = await XDB.Util.GetVersionAsync(db); + Assert.Equal(3, version.Ver); + Assert.Equal(1, version.CachePolice); + Assert.Equal("2025-10-17 04:41:04", version.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss")); + Assert.Equal((uint)3094259, version.StartIndex); + Assert.Equal((uint)36258303, version.EndIndex); + Assert.Equal(6, version.IPVer); + Assert.Equal(4, version.BytesCount); } } diff --git a/binding/csharp/IP2Region.Net/XDB/Util.cs b/binding/csharp/IP2Region.Net/XDB/Util.cs index 1075377..d92a613 100644 --- a/binding/csharp/IP2Region.Net/XDB/Util.cs +++ b/binding/csharp/IP2Region.Net/XDB/Util.cs @@ -1,3 +1,5 @@ +using System.Buffers; +using System.Buffers.Binary; using System.Net; using System.Runtime.InteropServices; @@ -10,7 +12,7 @@ public static class Util var address = IPAddress.Parse(ipAddress); return IpAddressToUInt32(address); } - + public static uint IpAddressToUInt32(IPAddress ipAddress) { byte[] bytes = ipAddress.GetAddressBytes(); @@ -20,4 +22,55 @@ public static class Util public static uint GetMidIp(uint x, uint y) => (x & y) + ((x ^ y) >> 1); + + public static async Task GetVersionAsync(string dbPath, CancellationToken token = default) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException(nameof(dbPath)); + } + + if (!File.Exists(dbPath)) + { + throw new FileNotFoundException("xdb file not fould.", dbPath); + } + + XdbVersion ret = default; + using var reader = File.OpenRead(dbPath); + var buffer = ArrayPool.Shared.Rent(256); + + try + { + var length = await reader.ReadAsync(buffer, 0, 256, token); + if (length == 256) + { + ret = Parse(buffer); + } + } + finally + { + ArrayPool.Shared.Return(buffer); + } + + return ret; + } + + private static XdbVersion Parse(ReadOnlySpan buffer) + { + var ret = new XdbVersion + { + Ver = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(0, 2)), + CachePolice = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(2, 2)), + StartIndex = BinaryPrimitives.ReadUInt32LittleEndian(buffer.Slice(8, 4)), + EndIndex = BinaryPrimitives.ReadUInt32LittleEndian(buffer.Slice(12, 4)), + IPVer = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(16, 2)), + BytesCount = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(18, 2)) + }; + + var createdAt = BinaryPrimitives.ReadUInt32LittleEndian(buffer.Slice(4, 4)); + var dtm = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.FromHours(8)); + ret.CreatedTime = dtm.AddSeconds(createdAt); + + return ret; + } } \ No newline at end of file diff --git a/binding/csharp/IP2Region.Net/XDB/XdbVersion.cs b/binding/csharp/IP2Region.Net/XDB/XdbVersion.cs index 2ac7398..1fdb743 100644 --- a/binding/csharp/IP2Region.Net/XDB/XdbVersion.cs +++ b/binding/csharp/IP2Region.Net/XDB/XdbVersion.cs @@ -1,6 +1,6 @@ namespace IP2Region.Net.XDB; -public record struct XdbVersion +public struct XdbVersion { /// /// 获得/设置 版本号