using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames; namespace InnovEnergy.Lib.Protocols.Modbus.Tcp; internal static class ModbusTcpFrameExtensions { internal static ModbusTcpFrame ToModbusTcpFrame(this ModbusFrame frame, UInt16 transactionId) { var hdr = new MbapHeader(transactionId, frame.Data.Count); return new ModbusTcpFrame(hdr, frame); } } internal readonly struct ModbusTcpFrame { public MbapHeader Header => new MbapHeader(new ArraySegment(_Data, 0, MbapHeader.Size)); public ModbusFrame Frame => new ModbusFrame(new ArraySegment(_Data, MbapHeader.Size, _Data.Length - MbapHeader.Size)); public IReadOnlyList Data => _Data; private readonly Byte[] _Data; public ModbusTcpFrame(MbapHeader header, ModbusFrame frame) { if (frame.Data.Count != header.FrameLength /* - 1*/) // TODO throw new ArgumentException(nameof(header.FrameLength)); _Data = CreateData(header, frame); } public ModbusTcpFrame(Byte[] data) { _Data = data; if (Frame.Data.Count != Header.FrameLength - 1) throw new ArgumentException(nameof(Header.FrameLength)); } private static Byte[] CreateData(MbapHeader header, ModbusFrame frame) { var hdl = header.Data.Count; var fdl = frame.Data.Count; var data = new Byte[hdl + fdl]; // TODO: avoid Array copy using ArraySegments? Array.Copy(sourceArray: header.Data.Array!, sourceIndex: header.Data.Offset, destinationArray: data, destinationIndex: 0, length: hdl); Array.Copy(sourceArray: frame.Data.Array!, sourceIndex: frame.Data.Offset, destinationArray: data, destinationIndex: hdl, length: fdl); return data; } }