From b400a7215aa4726a756bac125f638c88231cab01 Mon Sep 17 00:00:00 2001 From: Peter Butzhammer Date: Thu, 25 Apr 2024 12:16:49 +0200 Subject: [PATCH] Switch ReadFromBuffer to span --- .../ValueConverterTests/ConverterTestBase.cs | 15 +++++++---- Sharp7.Rx/ValueConverter.cs | 26 +++++++++---------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Sharp7.Rx.Tests/ValueConverterTests/ConverterTestBase.cs b/Sharp7.Rx.Tests/ValueConverterTests/ConverterTestBase.cs index d09c3ed..41fe7ac 100644 --- a/Sharp7.Rx.Tests/ValueConverterTests/ConverterTestBase.cs +++ b/Sharp7.Rx.Tests/ValueConverterTests/ConverterTestBase.cs @@ -9,7 +9,7 @@ internal abstract class ConverterTestBase public static MethodInfo CreateReadMethod(ConverterTestCase tc) { - var convertMi = typeof(ValueConverter).GetMethod(nameof(ValueConverter.ReadFromBuffer)); + var convertMi = typeof(ConverterTestBase).GetMethod(nameof(ReadFromBuffer)); var convert = convertMi!.MakeGenericMethod(tc.Value.GetType()); return convert; } @@ -67,12 +67,17 @@ internal abstract class ConverterTestBase /// /// This helper method exists, since I could not manage to invoke a generic method - /// accepring a Span<T> as parameter. + /// with a Span<T> parameter. /// - public static void WriteToBuffer(byte[] buffer, TValue value, VariableAddress address) - { + public static void WriteToBuffer(byte[] buffer, TValue value, VariableAddress address) => ValueConverter.WriteToBuffer(buffer, value, address); - } + + /// + /// This helper method exists, since I could not manage to invoke a generic method + /// with a Span<T> parameter. + /// + public static TValue ReadFromBuffer(byte[] buffer, VariableAddress address) => + ValueConverter.ReadFromBuffer(buffer, address); public record ConverterTestCase(object Value, string Address, byte[] Data) { diff --git a/Sharp7.Rx/ValueConverter.cs b/Sharp7.Rx/ValueConverter.cs index 83078c2..42c65b5 100644 --- a/Sharp7.Rx/ValueConverter.cs +++ b/Sharp7.Rx/ValueConverter.cs @@ -143,42 +143,40 @@ internal static class ValueConverter { return address.Type switch { - DbType.String => ParseString(), - DbType.WString => ParseWString(), - DbType.Byte => Encoding.ASCII.GetString(buffer.ToArray()), + DbType.String => ParseString(buffer), + DbType.WString => ParseWString(buffer), + DbType.Byte => Encoding.ASCII.GetString(buffer), _ => throw new DataTypeMissmatchException($"Cannot read string from {address.Type}", typeof(string), address) }; - string ParseString() + string ParseString(Span data) { // First byte is maximal length // Second byte is actual length // https://support.industry.siemens.com/cs/mdm/109747174?c=94063831435&lc=de-DE - var length = Math.Min(address.Length, buffer[1]); + var length = Math.Min(address.Length, data[1]); - return Encoding.ASCII.GetString(buffer, 2, length); + return Encoding.ASCII.GetString(data.Slice(2, length)); } - string ParseWString() + string ParseWString(Span data) { // First 2 bytes are maximal length // Second 2 bytes are actual length // https://support.industry.siemens.com/cs/mdm/109747174?c=94063855243&lc=de-DE - // the length of the string is two bytes per - var length = Math.Min(address.Length, BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(2, 2))) * 2; + // the length of the string is two bytes per character + var length = Math.Min(address.Length, BinaryPrimitives.ReadUInt16BigEndian(data.Slice(2, 2))) * 2; - return Encoding.BigEndianUnicode.GetString(buffer, 4, length); + return Encoding.BigEndianUnicode.GetString(data.Slice(4, length)); } } }, }; - public static TValue ReadFromBuffer(byte[] buffer, VariableAddress address) + public static TValue ReadFromBuffer(Span buffer, VariableAddress address) { - // Todo: Change to Span when switched to newer .net - if (buffer.Length < address.BufferLength) throw new ArgumentException($"Buffer must be at least {address.BufferLength} bytes long for {address}", nameof(buffer)); @@ -204,7 +202,7 @@ internal static class ValueConverter writeFunc(buffer, address, value); } - delegate object ReadFunc(byte[] data, VariableAddress address); + delegate object ReadFunc(Span data, VariableAddress address); [StructLayout(LayoutKind.Explicit)] private struct UInt32SingleMap