private static bool HasReadPayload(ArraySegmentHolder <byte> previousPayloads, Packet packet, ProtocolErrorBehavior protocolErrorBehavior, out ValueTask <ArraySegment <byte> > result) { if (previousPayloads.Count == 0 && packet.Contents.Count < MaxPacketSize) { result = new ValueTask <ArraySegment <byte> >(packet.Contents); return(true); } var previousPayloadsArray = previousPayloads.Array; if (previousPayloadsArray == null) { previousPayloadsArray = new byte[ProtocolUtility.MaxPacketSize + 1]; } else if (previousPayloads.Offset + previousPayloads.Count + packet.Contents.Count > previousPayloadsArray.Length) { Array.Resize(ref previousPayloadsArray, previousPayloadsArray.Length * 2); } Buffer.BlockCopy(packet.Contents.Array, packet.Contents.Offset, previousPayloadsArray, previousPayloads.Offset + previousPayloads.Count, packet.Contents.Count); previousPayloads.ArraySegment = new ArraySegment <byte>(previousPayloadsArray, previousPayloads.Offset, previousPayloads.Count + packet.Contents.Count); if (packet.Contents.Count < ProtocolUtility.MaxPacketSize) { result = new ValueTask <ArraySegment <byte> >(previousPayloads.ArraySegment); return(true); } result = default(ValueTask <ArraySegment <byte> >); return(false); }
private static ValueTask <ArraySegment <byte> > DoReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegmentHolder <byte> previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { var readPacketTask = ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior); while (readPacketTask.IsCompleted) { if (HasReadPayload(previousPayloads, readPacketTask.Result, protocolErrorBehavior, out var result)) { return(result); } readPacketTask = ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior); } return(AddContinuation(readPacketTask, bufferedByteReader, byteHandler, getNextSequenceNumber, previousPayloads, protocolErrorBehavior, ioBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <ArraySegment <byte> > AddContinuation(ValueTask <Packet> readPacketTask_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ArraySegmentHolder <byte> previousPayloads_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) { return(readPacketTask_.ContinueWith(packet => HasReadPayload(previousPayloads_, packet, protocolErrorBehavior_, out var result_) ? result_ : DoReadPayloadAsync(bufferedByteReader_, byteHandler_, getNextSequenceNumber_, previousPayloads_, protocolErrorBehavior_, ioBehavior_))); } }
public static ValueTask <ArraySegment <byte> > ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegmentHolder <byte> cache, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { cache.Clear(); return(DoReadPayloadAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, cache, protocolErrorBehavior, ioBehavior)); }