/// <summary> /// Decoder step 1: get message header 10 bytes /// </summary> /// <param name="length"></param> /// <param name="need"></param> /// <returns>The decoder step to execute next.</returns> private int DecoderStep1GetMessageHeader(ref int length, out int need) { if (!StreamDecoder.CheckAvailable(length, 10, out need)) { return(1); } this.messageHeader = MessageHeader.Decode(new ReadOnlySpan <byte>(this.Buffer, this.decodeIndex, 10)); this.decodeIndex += 10; this.messageDataLength -= 10; length -= 10; if (this.messageDataLength == 0) { if (this.messageHeader.MessageType == MessageType.DataMessage) { this.dataMessageHandler(this.messageHeader, new SecsMessage(this.messageHeader.S, this.messageHeader.F, string.Empty, replyExpected: this.messageHeader.ReplyExpected)); } else { this.controlMessageHandler(this.messageHeader); } return(0); } if (length >= this.messageDataLength) { Trace.WriteLine("Get Complete Data Message with total data"); this.dataMessageHandler(this.messageHeader, new SecsMessage(this.messageHeader.S, this.messageHeader.F, string.Empty, StreamDecoder.BufferedDecodeItem(this.Buffer, ref this.decodeIndex), this.messageHeader.ReplyExpected)); length -= (int)this.messageDataLength; this.messageDataLength = 0; return(0); //completeWith message received } return(this.DecoderStep2GetItemHeader(ref length, out need)); }
/// <summary> /// Decoder step 2: get _format + lengthBits(2bit) 1 byte /// </summary> /// <param name="length"></param> /// <param name="need"></param> /// <returns>The decoder step to execute next.</returns> private int DecoderStep2GetItemHeader(ref int length, out int need) { if (!StreamDecoder.CheckAvailable(length, 1, out need)) { return(2); } this.format = (SecsFormat)(this.Buffer[this.decodeIndex] & 0xFC); this.lengthBits = (byte)(this.Buffer[this.decodeIndex] & 3); this.decodeIndex++; this.messageDataLength--; length--; return(this.DecoderStep3GetItemLength(ref length, out need)); }
/// <summary> /// Decoder step 0: get total message length 4 bytes /// </summary> /// <param name="length"></param> /// <param name="need"></param> /// <returns>The decoder step to execute next.</returns> private int DecoderStep0GetTotalMessageLength(ref int length, out int need) { if (!StreamDecoder.CheckAvailable(length, 4, out need)) { return(0); } Array.Reverse(this.Buffer, this.decodeIndex, 4); this.messageDataLength = BitConverter.ToUInt32(this.Buffer, this.decodeIndex); Trace.WriteLine($"Get Message Length: {this.messageDataLength}"); this.decodeIndex += 4; length -= 4; return(this.DecoderStep1GetMessageHeader(ref length, out need)); }
/// <summary> /// Decoder step 3: get _itemLength _lengthBits bytes, at most 3 byte /// </summary> /// <param name="length"></param> /// <param name="need"></param> /// <returns>The decoder step to execute next.</returns> private int DecoderStep3GetItemLength(ref int length, out int need) { if (!StreamDecoder.CheckAvailable(length, this.lengthBits, out need)) { return(3); } Array.Copy(this.Buffer, this.decodeIndex, this.itemLengthBytes, 0, this.lengthBits); Array.Reverse(this.itemLengthBytes, 0, this.lengthBits); this.itemLength = BitConverter.ToInt32(this.itemLengthBytes, 0); Array.Clear(this.itemLengthBytes, 0, 4); Trace.WriteLineIf(this.format != SecsFormat.List, $"Get format: {this.format}, length: {this.itemLength}"); this.decodeIndex += this.lengthBits; this.messageDataLength -= this.lengthBits; length -= this.lengthBits; return(this.DecoderStep4GetItem(ref length, out need)); }
/// <summary> /// Decoder step 4: get item value /// </summary> /// <param name="length"></param> /// <param name="need"></param> /// <returns>The decoder step to execute next.</returns> private int DecoderStep4GetItem(ref int length, out int need) { need = 0; Item item; if (this.format == SecsFormat.List) { if (this.itemLength == 0) { item = Item.L(); } else { this.stack.Push(new List <Item>(this.itemLength)); return(this.DecoderStep2GetItemHeader(ref length, out need)); } } else { if (!StreamDecoder.CheckAvailable(length, this.itemLength, out need)) { return(4); } item = Item.BytesDecode(this.format, this.Buffer, this.decodeIndex, this.itemLength); Trace.WriteLine($"Complete Item: {this.format}"); this.decodeIndex += this.itemLength; this.messageDataLength -= (uint)this.itemLength; length -= this.itemLength; } if (this.stack.Count == 0) { Trace.WriteLine("Get Complete Data Message by stream decoded"); this.dataMessageHandler(this.messageHeader, new SecsMessage(this.messageHeader.S, this.messageHeader.F, string.Empty, item, this.messageHeader.ReplyExpected)); return(0); } var list = this.stack.Peek(); list.Add(item); while (list.Count == list.Capacity) { item = Item.L(this.stack.Pop()); Trace.WriteLine($"Complete List: {item.Count}"); if (this.stack.Count > 0) { list = this.stack.Peek(); list.Add(item); } else { Trace.WriteLine("Get Complete Data Message by stream decoded"); this.dataMessageHandler(this.messageHeader, new SecsMessage(this.messageHeader.S, this.messageHeader.F, string.Empty, item, this.messageHeader.ReplyExpected)); return(0); } } return(this.DecoderStep2GetItemHeader(ref length, out need)); }