From ae50ba3b9f089db94fe45996304d2e5ef622e25e Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Fri, 8 Aug 2025 16:33:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BANumber=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=9B=B4=E5=A4=9A=E5=A4=84=E7=90=86=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server.test/NumberTest.cs | 116 +++++++++++++++++++++----- server/src/Common/Number.cs | 162 ++++++++++++++++++++++++++++-------- 2 files changed, 221 insertions(+), 57 deletions(-) diff --git a/server.test/NumberTest.cs b/server.test/NumberTest.cs index ae8af7f..dbb316e 100644 --- a/server.test/NumberTest.cs +++ b/server.test/NumberTest.cs @@ -35,57 +35,133 @@ public class NumberTest } /// - /// 测试 BytesToUInt64 的正常与异常情况 + /// 测试 BytesToUInt64 的正常与异常情况,覆盖不同参数组合 /// [Fact] public void Test_BytesToUInt64() { - // 正常大端 + // 正常大端(isLowNumHigh=false) var bytes = new byte[] { 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0x01 }; - var result = Number.BytesToUInt64((byte[])bytes.Clone(), false); + var result = Number.BytesToUInt64((byte[])bytes.Clone()); Assert.True(result.IsSuccessful); Assert.Equal(0x12345678ABCDEF01UL, result.Value); - // 正常小端 + // 正常小端(isLowNumHigh=true) var bytes2 = new byte[] { 0x01, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12 }; var result2 = Number.BytesToUInt64((byte[])bytes2.Clone(), true); Assert.True(result2.IsSuccessful); Assert.Equal(0x12345678ABCDEF01UL, result2.Value); - // 异常:长度超限 - var result3 = Number.BytesToUInt64(new byte[9], false); - Assert.False(result3.IsSuccessful); + // 长度不足8字节(numLength=4),大端 + var bytes3 = new byte[] { 0x12, 0x34, 0x56, 0x78 }; + var result3 = Number.BytesToUInt64((byte[])bytes3.Clone(), 0, 4, false); + Assert.True(result3.IsSuccessful); + Assert.Equal(0x1234567800000000UL, result3.Value); - // 异常:不足8字节 - var result4 = Number.BytesToUInt64(new byte[] { 0x01, 0x02 }, false); - Assert.False(result4.IsSuccessful); // BitConverter.ToUInt64 需要8字节 + // 长度不足8字节(numLength=4),小端 + var bytes4 = new byte[] { 0x78, 0x56, 0x34, 0x12 }; + var result4 = Number.BytesToUInt64((byte[])bytes4.Clone(), 0, 4, true); + Assert.True(result4.IsSuccessful); + Assert.Equal(0x12345678UL, result4.Value); + + // numLength=0 + var bytes5 = new byte[] { 0x12, 0x34, 0x56, 0x78 }; + var result5 = Number.BytesToUInt64((byte[])bytes5.Clone(), 0, 0, false); + Assert.True(result5.IsSuccessful); + Assert.Equal(0UL, result5.Value); + + // offset测试 + var bytes6 = new byte[] { 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0x01 }; + var result6 = Number.BytesToUInt64(bytes6, 2, 8, false); + Assert.True(result6.IsSuccessful); + Assert.Equal(0x12345678ABCDEF01UL, result6.Value); + + // numLength超限(>8),应返回异常 + var bytes7 = new byte[9]; + var result7 = Number.BytesToUInt64(bytes7, 0, 9, false); + Assert.False(result7.IsSuccessful); + + // offset+numLength超限 + var bytes8 = new byte[] { 0x01, 0x02, 0x03, 0x04 }; + var result8 = Number.BytesToUInt64(bytes8, 2, 4, false); + Assert.True(result8.IsSuccessful); + Assert.Equal(0x0304000000000000UL, result8.Value); + + // bytes长度不足offset+numLength + var bytes9 = new byte[] { 0x01, 0x02 }; + var result9 = Number.BytesToUInt64(bytes9, 1, 2, true); + Assert.True(result9.IsSuccessful); + Assert.Equal(0x02UL, result9.Value); + + // 空数组 + var result10 = Number.BytesToUInt64(new byte[0], 0, 0, false); + Assert.True(result10.IsSuccessful); + Assert.Equal(0UL, result10.Value); } /// - /// 测试 BytesToUInt32 的正常与异常情况 + /// 测试 BytesToUInt32 的正常与异常情况,覆盖不同参数组合 /// [Fact] public void Test_BytesToUInt32() { - // 正常大端 + // 正常大端(isLowNumHigh=false) var bytes = new byte[] { 0x12, 0x34, 0x56, 0x78 }; - var result = Number.BytesToUInt32((byte[])bytes.Clone(), false); + var result = Number.BytesToUInt32((byte[])bytes.Clone()); Assert.True(result.IsSuccessful); Assert.Equal(0x12345678U, result.Value); - // 正常小端 + // 正常小端(isLowNumHigh=true) var bytes2 = new byte[] { 0x78, 0x56, 0x34, 0x12 }; var result2 = Number.BytesToUInt32((byte[])bytes2.Clone(), true); Assert.True(result2.IsSuccessful); Assert.Equal(0x12345678U, result2.Value); - // 异常:长度超限 - var result3 = Number.BytesToUInt32(new byte[5], false); - Assert.False(result3.IsSuccessful); + // 长度不足4字节(numLength=2),大端 + var bytes3 = new byte[] { 0x12, 0x34 }; + var result3 = Number.BytesToUInt32((byte[])bytes3.Clone(), 0, 2, false); + Assert.True(result3.IsSuccessful); + Assert.Equal(0x12340000U, result3.Value); - // 异常:不足4字节 - var result4 = Number.BytesToUInt32(new byte[] { 0x01, 0x02 }, false); - Assert.False(result4.IsSuccessful); // BitConverter.ToUInt32 需要4字节 + // 长度不足4字节(numLength=2),小端 + var bytes4 = new byte[] { 0x34, 0x12 }; + var result4 = Number.BytesToUInt32((byte[])bytes4.Clone(), 0, 2, true); + Assert.True(result4.IsSuccessful); + Assert.Equal(0x1234U, result4.Value); + + // numLength=0 + var bytes5 = new byte[] { 0x12, 0x34, 0x56, 0x78 }; + var result5 = Number.BytesToUInt32((byte[])bytes5.Clone(), 0, 0, false); + Assert.True(result5.IsSuccessful); + Assert.Equal(0U, result5.Value); + + // offset测试 + var bytes6 = new byte[] { 0x00, 0x00, 0x12, 0x34, 0x56, 0x78 }; + var result6 = Number.BytesToUInt32(bytes6, 2, 4, false); + Assert.True(result6.IsSuccessful); + Assert.Equal(0x12345678U, result6.Value); + + // numLength超限(>4),应返回异常 + var bytes7 = new byte[5]; + var result7 = Number.BytesToUInt32(bytes7, 0, 5, false); + Assert.False(result7.IsSuccessful); + + // offset+numLength超限 + var bytes8 = new byte[] { 0x01, 0x02, 0x03, 0x04 }; + var result8 = Number.BytesToUInt32(bytes8, 2, 2, false); + Assert.True(result8.IsSuccessful); + Assert.Equal(0x03040000U, result8.Value); + + // bytes长度不足offset+numLength + var bytes9 = new byte[] { 0x01, 0x02 }; + var result9 = Number.BytesToUInt32(bytes9, 1, 1, true); + Assert.True(result9.IsSuccessful); + Assert.Equal(0x02U, result9.Value); + + // 空数组 + var result10 = Number.BytesToUInt32(new byte[0], 0, 0, false); + Assert.True(result10.IsSuccessful); + Assert.Equal(0U, result10.Value); } /// diff --git a/server/src/Common/Number.cs b/server/src/Common/Number.cs index 56a2266..d8ab922 100644 --- a/server/src/Common/Number.cs +++ b/server/src/Common/Number.cs @@ -78,6 +78,56 @@ public class Number return arr; } + /// + /// 二进制字节数组转成64bits整数 + /// + /// 二进制字节数组 + /// 字节数组偏移量 + /// 字节数组长度 + /// 是否高位在数组索引低 + /// 整数 + public static Result BytesToUInt64(byte[] bytes, int offset = 0, int numLength = 8, bool isLowNumHigh = false) + { + if (bytes.Length < offset) + { + return new(new ArgumentException($"The Length of bytes is less than offset")); + } + + if (numLength > 8) + { + return new(new ArgumentException($"The Length of bytes is greater than 8")); + } + + if (numLength <= 0) return 0; + + try + { + byte[] numBytes = new byte[8]; // 8字节 + int copyLen = Math.Min(numLength, bytes.Length - offset); + + if (isLowNumHigh) + { + // 小端:拷贝到低位 + Buffer.BlockCopy(bytes, offset, numBytes, 0, copyLen); + } + else + { + // 大端:拷贝到高位 + byte[] temp = new byte[copyLen]; + Buffer.BlockCopy(bytes, offset, temp, 0, copyLen); + Array.Reverse(temp); + Buffer.BlockCopy(temp, 0, numBytes, 8 - copyLen, copyLen); + } + + UInt64 num = BitConverter.ToUInt64(numBytes, 0); + return num; + } + catch (Exception error) + { + return new(error); + } + } + /// /// 二进制字节数组转成64bits整数 /// @@ -86,25 +136,78 @@ public class Number /// 整数 public static Result BytesToUInt64(byte[] bytes, bool isLowNumHigh = false) { - if (bytes.Length > 8) + return BytesToUInt64(bytes, 0, 8, isLowNumHigh); + } + + /// + /// 二进制字节数组转成64bits整数 + /// + /// 二进制字节数组 + /// 整数 + public static Result BytesToUInt64(byte[] bytes) + { + return BytesToUInt64(bytes, 0, 8, false); + } + + /// + /// 二进制字节数组转成32bits整数 + /// + /// 二进制字节数组 + /// 字节数组偏移量 + /// 整形所占字节数组长度 + /// 是否高位在数组索引低 + /// 整数 + public static Result BytesToUInt32(byte[] bytes, int offset = 0, int numLength = 4, bool isLowNumHigh = false) + { + if (bytes.Length < offset) { - return new(new ArgumentException( - "Unsigned long number can't over 8 bytes(64 bits).", - nameof(bytes) - )); + return new(new ArgumentException($"The Length of bytes is less than offset")); } - UInt64 num = 0; - int len = bytes.Length; + if (numLength > 4) + { + return new(new ArgumentException($"The Length of bytes is greater than 4")); + } + + if (bytes.Length < offset) + { + return new(new ArgumentException($"The Length of bytes is less than offset")); + } + + if (numLength > 4) + { + return new(new ArgumentException($"The Length of bytes is greater than 4")); + } + + if (numLength <= 0) return 0; try { - if (!isLowNumHigh) - { - Array.Reverse(bytes); - } - num = BitConverter.ToUInt64(bytes, 0); + byte[] numBytes = new byte[4]; // 4字节 + int copyLen = Math.Min(numLength, bytes.Length - offset); + if (copyLen < 0) copyLen = 0; + if (isLowNumHigh) + { + // 小端:拷贝到低位 + if (copyLen > 0) + { + Buffer.BlockCopy(bytes, offset, numBytes, 0, copyLen); + } + } + else + { + // 大端:拷贝到高位 + if (copyLen > 0) + { + byte[] temp = new byte[copyLen]; + Buffer.BlockCopy(bytes, offset, temp, 0, copyLen); + Array.Reverse(temp); + Buffer.BlockCopy(temp, 0, numBytes, 4 - copyLen, copyLen); + } + } + + UInt32 num = BitConverter.ToUInt32(numBytes, 0); return num; } catch (Exception error) @@ -121,32 +224,17 @@ public class Number /// 整数 public static Result BytesToUInt32(byte[] bytes, bool isLowNumHigh = false) { - if (bytes.Length > 4) - { - return new(new ArgumentException( - "Unsigned long number can't over 4 bytes(32 bits).", - nameof(bytes) - )); - } - - UInt32 num = 0; - int len = bytes.Length; - - try - { - if (!isLowNumHigh) - { - Array.Reverse(bytes); - } - num = BitConverter.ToUInt32(bytes, 0); - - return num; - } - catch (Exception error) - { - return new(error); - } + return BytesToUInt32(bytes, 0, 4, isLowNumHigh); + } + /// + /// 二进制字节数组转成32bits整数 + /// + /// 二进制字节数组 + /// 整数 + public static Result BytesToUInt32(byte[] bytes) + { + return BytesToUInt32(bytes, 0, 4, false); } ///