From f4bd6144f232285dcd43c6f14579bca5b128e66d Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 26 Aug 2025 18:22:18 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20HexConverter?= =?UTF-8?q?=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataConverter/HexConverter.cs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs diff --git a/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs b/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs new file mode 100644 index 00000000..7c93bc2f --- /dev/null +++ b/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs @@ -0,0 +1,70 @@ +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using System.Text; + +namespace BootstrapBlazor.Components.DataConverter; + +/// +/// Byte 数组扩展方法 +/// +public static class HexConverter +{ + /// + /// 将 byte[] 转为 16 进制字符串 + /// Converts a byte array to its hexadecimal string representation. + /// + /// The byte array to convert. + /// + /// A string containing the hexadecimal representation of the byte array. + public static string ToString(byte[]? bytes, string? separator = "-") + { + if (bytes == null || bytes.Length == 0) + { + return string.Empty; + } + + if (separator == "-") + { + return BitConverter.ToString(bytes); + } + + var sb = new StringBuilder(bytes.Length * 3); + foreach (var b in bytes) + { + sb.Append(b.ToString("X2")); + sb.Append(separator); + } + return sb.ToString(0, sb.Length - 1); + } + + /// + /// 将字符串转换为字节数组 + /// + /// + /// + /// + /// + public static byte[] ToByte(string str, string? separator = null, StringSplitOptions options = StringSplitOptions.None) + { + // 把 str 内的 delimiter 符号替换掉 + if (!string.IsNullOrEmpty(separator)) + { + str = string.Join("", str.Split(separator, options)); + } + + // 把 Hex 形式的 str 转化为 byte[] + if (str.Length % 2 != 0) + { + throw new ArgumentException("The raw string cannot have an odd number of digits. 参数 str 位数不正确无法转化为 16 进制字节数组", nameof(str)); + } + + var bytes = new byte[str.Length / 2]; + for (var i = 0; i < bytes.Length; i++) + { + bytes[i] = Convert.ToByte(str.Substring(i * 2, 2), 16); + } + return bytes; + } +} From ef43651f140a76dc58b4327f54de013a6883d8a4 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 26 Aug 2025 18:22:27 +0800 Subject: [PATCH 2/7] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTestTcpSocket/ExtensionsTest.cs | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/UnitTestTcpSocket/ExtensionsTest.cs diff --git a/test/UnitTestTcpSocket/ExtensionsTest.cs b/test/UnitTestTcpSocket/ExtensionsTest.cs new file mode 100644 index 00000000..8584c9cd --- /dev/null +++ b/test/UnitTestTcpSocket/ExtensionsTest.cs @@ -0,0 +1,39 @@ +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using BootstrapBlazor.Components.DataConverter; + +namespace UnitTestTcpSocket; + +public class ExtensionsTest +{ + [Fact] + public void ToHexString_Ok() + { + var data = new byte[] { 0x1A, 0x02, 0x13, 0x04, 0xFE }; + var actual = HexConverter.ToString(data); + Assert.Equal("1A-02-13-04-FE", actual); + + actual = HexConverter.ToString(data, " "); + Assert.Equal("1A 02 13 04 FE", actual); + } + + [Fact] + public void ToByte_Ok() + { + var excepted = new byte[] { 0x1A, 0x02, 0x13, 0x04, 0xFE }; + + var data = "1A021304FE"; + var actual = HexConverter.ToByte(data); + Assert.Equal(excepted, actual); + + data = "1A-02-13-04-FE"; + actual = HexConverter.ToByte(data, "-"); + Assert.Equal(excepted, actual); + + data = "1A 02 13 04 FE"; + actual = HexConverter.ToByte(data, " "); + Assert.Equal(excepted, actual); + } +} From a3975ee78602dbc33a1a06564468bfc2423557d9 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 27 Aug 2025 09:11:49 +0800 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=20HexConvete?= =?UTF-8?q?r=20=E6=96=87=E6=A1=A3=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataConverter/HexConverter.cs | 4 ++-- .../{ExtensionsTest.cs => HexConverterTest.cs} | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) rename test/UnitTestTcpSocket/{ExtensionsTest.cs => HexConverterTest.cs} (75%) diff --git a/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs b/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs index 7c93bc2f..386027d4 100644 --- a/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs +++ b/src/extensions/BootstrapBlazor.Socket/DataConverter/HexConverter.cs @@ -7,7 +7,7 @@ namespace BootstrapBlazor.Components.DataConverter; /// -/// Byte 数组扩展方法 +/// 十六进制 与 Byte 数组转换方法 /// public static class HexConverter { @@ -46,7 +46,7 @@ public static string ToString(byte[]? bytes, string? separator = "-") /// /// /// - public static byte[] ToByte(string str, string? separator = null, StringSplitOptions options = StringSplitOptions.None) + public static byte[] ToBytes(string str, string? separator = null, StringSplitOptions options = StringSplitOptions.None) { // 把 str 内的 delimiter 符号替换掉 if (!string.IsNullOrEmpty(separator)) diff --git a/test/UnitTestTcpSocket/ExtensionsTest.cs b/test/UnitTestTcpSocket/HexConverterTest.cs similarity index 75% rename from test/UnitTestTcpSocket/ExtensionsTest.cs rename to test/UnitTestTcpSocket/HexConverterTest.cs index 8584c9cd..bb8eebbc 100644 --- a/test/UnitTestTcpSocket/ExtensionsTest.cs +++ b/test/UnitTestTcpSocket/HexConverterTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Website: https://www.blazor.zone or https://argozhang.github.io/ @@ -6,7 +6,7 @@ namespace UnitTestTcpSocket; -public class ExtensionsTest +public class HexConverterTest { [Fact] public void ToHexString_Ok() @@ -20,20 +20,20 @@ public void ToHexString_Ok() } [Fact] - public void ToByte_Ok() + public void ToBytes_Ok() { var excepted = new byte[] { 0x1A, 0x02, 0x13, 0x04, 0xFE }; var data = "1A021304FE"; - var actual = HexConverter.ToByte(data); + var actual = HexConverter.ToBytes(data); Assert.Equal(excepted, actual); data = "1A-02-13-04-FE"; - actual = HexConverter.ToByte(data, "-"); + actual = HexConverter.ToBytes(data, "-"); Assert.Equal(excepted, actual); data = "1A 02 13 04 FE"; - actual = HexConverter.ToByte(data, " "); + actual = HexConverter.ToBytes(data, " "); Assert.Equal(excepted, actual); } } From bb6a6516e2c099d1631ff74d044d0587d64b80fc Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 27 Aug 2025 09:12:07 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20BinConverter?= =?UTF-8?q?=20=E8=BD=AC=E6=8D=A2=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataConverter/BinConverter.cs | 59 +++++++++++++++++++ test/UnitTestTcpSocket/BinConverterTest.cs | 39 ++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs create mode 100644 test/UnitTestTcpSocket/BinConverterTest.cs diff --git a/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs b/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs new file mode 100644 index 00000000..239b8a4a --- /dev/null +++ b/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs @@ -0,0 +1,59 @@ +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using System.Text; + +namespace BootstrapBlazor.Components.DataConverter; + +/// +/// 二进制 与 Byte 数组转换方法 +/// +public static class BinConverter +{ + /// + /// 将 byte[] 转为 二进制字符串 + /// Converts a byte array to its hexadecimal string representation. + /// + /// The byte array to convert. + /// + /// A string containing the hexadecimal representation of the byte array. + public static string ToString(byte[]? bytes, string? separator = "-") + { + if (bytes == null || bytes.Length == 0) + { + return string.Empty; + } + + return string.Join(separator, bytes.Select(i => Convert.ToString(i, 2).PadLeft(8, '0'))); + } + + /// + /// 将字符串转换为字节数组 + /// + /// + /// + /// + /// + public static byte[] ToBytes(string str, string? separator = null, StringSplitOptions options = StringSplitOptions.None) + { + // 把 str 内的 delimiter 符号替换掉 + if (!string.IsNullOrEmpty(separator)) + { + str = string.Join("", str.Split(separator, options).Select(i => i.PadLeft(8, '0'))); + } + + // 把 Hex 形式的 str 转化为 byte[] + if (str.Length % 8 != 0) + { + throw new ArgumentException("The raw string cannot have an odd number of digits. 参数 str 位数不正确无法转化为 二进制字节数组", nameof(str)); + } + + var bytes = new byte[str.Length / 8]; + for (var i = 0; i < bytes.Length; i++) + { + bytes[i] = Convert.ToByte(str.Substring(i * 8, 8), 2); + } + return bytes; + } +} diff --git a/test/UnitTestTcpSocket/BinConverterTest.cs b/test/UnitTestTcpSocket/BinConverterTest.cs new file mode 100644 index 00000000..1bae1c61 --- /dev/null +++ b/test/UnitTestTcpSocket/BinConverterTest.cs @@ -0,0 +1,39 @@ +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using BootstrapBlazor.Components.DataConverter; + +namespace UnitTestTcpSocket; + +public class BinConverterTest +{ + [Fact] + public void ToBinString_Ok() + { + var data = new byte[] { 0x1A, 0x02 }; + var actual = BinConverter.ToString(data); + Assert.Equal("00011010-00000010", actual); + + actual = BinConverter.ToString(data, " "); + Assert.Equal("00011010 00000010", actual); + } + + [Fact] + public void ToBytes_Ok() + { + var excepted = new byte[] { 0x1A, 0x02 }; + + var data = "00011010-00000010"; + var actual = BinConverter.ToBytes(data, "-"); + Assert.Equal(excepted, actual); + + data = "00011010 00000010"; + actual = BinConverter.ToBytes(data, " "); + Assert.Equal(excepted, actual); + + data = "0001101000000010"; + actual = BinConverter.ToBytes(data); + Assert.Equal(excepted, actual); + } +} From 76f2b8623859bb13b89f86dda21ce1152e7388da Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 27 Aug 2025 09:21:41 +0800 Subject: [PATCH 5/7] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.Socket/DataConverter/BinConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs b/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs index 239b8a4a..58f6126a 100644 --- a/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs +++ b/src/extensions/BootstrapBlazor.Socket/DataConverter/BinConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Website: https://www.blazor.zone or https://argozhang.github.io/ @@ -37,7 +37,7 @@ public static string ToString(byte[]? bytes, string? separator = "-") /// public static byte[] ToBytes(string str, string? separator = null, StringSplitOptions options = StringSplitOptions.None) { - // 把 str 内的 delimiter 符号替换掉 + // 把 str 内的 separator 符号替换掉 if (!string.IsNullOrEmpty(separator)) { str = string.Join("", str.Split(separator, options).Select(i => i.PadLeft(8, '0'))); From e23d0959ca577ad174f7d2936481b184a8c0c20e Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 27 Aug 2025 09:21:49 +0800 Subject: [PATCH 6/7] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTestTcpSocket/BinConverterTest.cs | 18 ++++++++++++++++++ test/UnitTestTcpSocket/HexConverterTest.cs | 20 +++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/test/UnitTestTcpSocket/BinConverterTest.cs b/test/UnitTestTcpSocket/BinConverterTest.cs index 1bae1c61..e2fa6c0e 100644 --- a/test/UnitTestTcpSocket/BinConverterTest.cs +++ b/test/UnitTestTcpSocket/BinConverterTest.cs @@ -8,6 +8,16 @@ namespace UnitTestTcpSocket; public class BinConverterTest { + [Fact] + public void ToHexString_Null() + { + var actual = BinConverter.ToString(null); + Assert.Equal(string.Empty, actual); + + actual = BinConverter.ToString([]); + Assert.Equal(string.Empty, actual); + } + [Fact] public void ToBinString_Ok() { @@ -19,6 +29,14 @@ public void ToBinString_Ok() Assert.Equal("00011010 00000010", actual); } + [Fact] + public void ToHexString_Exception() + { + var data = "00011010-00000010"; + var ex = Assert.ThrowsAny(() => BinConverter.ToBytes(data)); + Assert.NotNull(ex); + } + [Fact] public void ToBytes_Ok() { diff --git a/test/UnitTestTcpSocket/HexConverterTest.cs b/test/UnitTestTcpSocket/HexConverterTest.cs index bb8eebbc..c7b528f7 100644 --- a/test/UnitTestTcpSocket/HexConverterTest.cs +++ b/test/UnitTestTcpSocket/HexConverterTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Website: https://www.blazor.zone or https://argozhang.github.io/ @@ -8,6 +8,24 @@ namespace UnitTestTcpSocket; public class HexConverterTest { + [Fact] + public void ToHexString_Null() + { + var actual = HexConverter.ToString(null); + Assert.Equal(string.Empty, actual); + + actual = HexConverter.ToString([]); + Assert.Equal(string.Empty, actual); + } + + [Fact] + public void ToHexString_Exception() + { + var data = "1A021304FE1"; + var ex = Assert.ThrowsAny(() => HexConverter.ToBytes(data)); + Assert.NotNull(ex); + } + [Fact] public void ToHexString_Ok() { From cefb93291ec02664e4673e1ffe4a312939740997 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 27 Aug 2025 09:22:55 +0800 Subject: [PATCH 7/7] chore: bump version 9.0.2 --- .../BootstrapBlazor.Socket/BootstrapBlazor.Socket.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/BootstrapBlazor.Socket/BootstrapBlazor.Socket.csproj b/src/extensions/BootstrapBlazor.Socket/BootstrapBlazor.Socket.csproj index cf6fc6cf..0c7d232b 100644 --- a/src/extensions/BootstrapBlazor.Socket/BootstrapBlazor.Socket.csproj +++ b/src/extensions/BootstrapBlazor.Socket/BootstrapBlazor.Socket.csproj @@ -1,7 +1,7 @@  - 9.0.1 + 9.0.2