internal StreamDecoder(int streamBufferSize, Action <MessageHeader> controlMsgHandler, Action <MessageHeader, SecsMessage> dataMsgHandler) { _buffer = new byte[streamBufferSize]; _BufferOffset = 0; _decodeIndex = 0; _dataMsgHandler = dataMsgHandler; _controlMsgHandler = controlMsgHandler; _decoders = new Decoder[] { // 0: get total message length 4 bytes (ref int length, out int need) => { if (!CheckAvailable(ref length, 4, out need)) { return(0); } Array.Reverse(_buffer, _decodeIndex, 4); _messageDataLength = BitConverter.ToUInt32(_buffer, _decodeIndex); Trace.WriteLine($"Get Message Length: {_messageDataLength}"); _decodeIndex += 4; length -= 4; return(1); }, // 1: get message header 10 bytes (ref int length, out int need) => { if (!CheckAvailable(ref length, 10, out need)) { return(1); } _msgHeader = new MessageHeader(_buffer, _decodeIndex); _decodeIndex += 10; _messageDataLength -= 10; length -= 10; if (_messageDataLength == 0) { if (_msgHeader.MessageType == MessageType.DataMessage) { _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty)); } else { _controlMsgHandler(_msgHeader); } return(0); } if (length >= _messageDataLength) { Trace.WriteLine("Get Complete Data Message with total data"); _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, _buffer, ref _decodeIndex)); length -= (int)_messageDataLength; _messageDataLength = 0; return(0); //completeWith message received } return(2); }, // 2: get _format + lengthBits(2bit) 1 byte (ref int length, out int need) => { if (!CheckAvailable(ref length, 1, out need)) { return(2); } _format = (SecsFormat)(_buffer[_decodeIndex] & 0xFC); _lengthBits = (byte)(_buffer[_decodeIndex] & 3); _decodeIndex++; _messageDataLength--; length--; return(3); }, // 3: get _itemLength _lengthBits bytes, at most 3 byte (ref int length, out int need) => { if (!CheckAvailable(ref length, _lengthBits, out need)) { return(3); } Array.Copy(_buffer, _decodeIndex, _itemLengthBytes, 0, _lengthBits); Array.Reverse(_itemLengthBytes, 0, _lengthBits); _itemLength = BitConverter.ToInt32(_itemLengthBytes, 0); Array.Clear(_itemLengthBytes, 0, 4); Trace.WriteLineIf(_format != SecsFormat.List, $"Get format: {_format}, length: {_itemLength}"); _decodeIndex += _lengthBits; _messageDataLength -= _lengthBits; length -= _lengthBits; return(4); }, // 4: get item value (ref int length, out int need) => { need = 0; Item item; if (_format == SecsFormat.List) { if (_itemLength == 0) { item = Item.L(); } else { _stack.Push(new List <Item>(_itemLength)); return(2); } } else { if (!CheckAvailable(ref length, _itemLength, out need)) { return(4); } item = _itemLength == 0 ? _format.BytesDecode() : _format.BytesDecode(_buffer, ref _decodeIndex, ref _itemLength); Trace.WriteLine($"Complete Item: {_format}"); _decodeIndex += _itemLength; _messageDataLength -= (uint)_itemLength; length -= _itemLength; } if (_stack.Count == 0) { Trace.WriteLine("Get Complete Data Message by stream decoded"); _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item)); return(0); } var list = _stack.Peek(); list.Add(item); while (list.Count == list.Capacity) { item = Item.L(_stack.Pop()); Trace.WriteLine($"Complete List: {item.Count}"); if (_stack.Count > 0) { list = _stack.Peek(); list.Add(item); } else { Trace.WriteLine("Get Complete Data Message by stream decoded"); _dataMsgHandler(_msgHeader, new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item)); return(0); } } return(2); }, }; }
internal SecsDecoder(Action <Header> controlMsgHandler, Action <Header, SecsMessage> msgHandler) { DataMsgHandler = msgHandler; ControlMsgHandler = controlMsgHandler; decoders = new Decoder[] { #region decoders[0]: get total message length 4 bytes (byte[] data, int length, ref int index, out int need) => { if (!CheckAvailable(length, index, 4, out need)) { return(0); } Array.Reverse(data, index, 4); _messageLength = BitConverter.ToUInt32(data, index); Trace.WriteLine("Get Message Length =" + _messageLength); index += 4; return(1); }, #endregion #region decoders[1]: get message header 10 bytes (byte[] data, int length, ref int index, out int need) => { if (!CheckAvailable(length, index, 10, out need)) { return(1); } _msgHeader = new Header(new byte[10]); Array.Copy(data, index, _msgHeader.Bytes, 0, 10); index += 10; _messageLength -= 10; if (_messageLength == 0) { if (_msgHeader.MessageType == MessageType.Data_Message) { ProcessMessage(new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty)); } else { ControlMsgHandler(_msgHeader); _messageLength = 0; } return(0); } else if (length - index >= _messageLength) { ProcessMessage(new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, data, ref index)); return(0); //completeWith message received } return(2); }, #endregion #region decoders[2]: get _format + lengthBits(2bit) 1 byte (byte[] data, int length, ref int index, out int need) => { if (!CheckAvailable(length, index, 1, out need)) { return(2); } _format = (SecsFormat)(data[index] & 0xFC); _lengthBits = (byte)(data[index] & 3); index++; _messageLength--; return(3); }, #endregion #region decoders[3]: get _itemLength _lengthBits bytes (byte[] data, int length, ref int index, out int need) => { if (!CheckAvailable(length, index, _lengthBits, out need)) { return(3); } byte[] itemLengthBytes = new byte[4]; Array.Copy(data, index, itemLengthBytes, 0, _lengthBits); Array.Reverse(itemLengthBytes, 0, _lengthBits); _itemLength = BitConverter.ToInt32(itemLengthBytes, 0); Array.Clear(itemLengthBytes, 0, 4); index += _lengthBits; _messageLength -= _lengthBits; return(4); }, #endregion #region decoders[4]: get item value (byte[] data, int length, ref int index, out int need) => { need = 0; Item item = null; if (_format == SecsFormat.List) { if (_itemLength == 0) { item = Item.L(); } else { _stack.Push(new List <Item>(_itemLength)); return(2); } } else { if (!CheckAvailable(length, index, _itemLength, out need)) { return(4); } item = _itemLength == 0 ? _format.BytesDecode() : _format.BytesDecode(data, index, _itemLength); index += _itemLength; _messageLength -= (uint)_itemLength; } if (_stack.Count > 0) { var list = _stack.Peek(); list.Add(item); while (list.Count == list.Capacity) { item = Item.L(_stack.Pop()); if (_stack.Count > 0) { list = _stack.Peek(); list.Add(item); } else { ProcessMessage(new SecsMessage(_msgHeader.S, _msgHeader.F, _msgHeader.ReplyExpected, string.Empty, item)); return(0); } } } return(2); }, #endregion }; }