@@ -11,44 +11,53 @@ internal static class ProtocolUtility
11
11
{
12
12
public static ValueTask < Packet > ReadPacketAsync ( BufferedByteReader bufferedByteReader , IByteHandler byteHandler , Func < int ? > getNextSequenceNumber , ProtocolErrorBehavior protocolErrorBehavior , IOBehavior ioBehavior )
13
13
{
14
- return bufferedByteReader . ReadBytesAsync ( byteHandler , 4 , ioBehavior )
15
- . ContinueWith ( headerBytes =>
16
- {
17
- if ( headerBytes . Count < 4 )
18
- {
19
- return protocolErrorBehavior == ProtocolErrorBehavior . Throw ?
20
- ValueTaskExtensions . FromException < Packet > ( new EndOfStreamException ( ) ) :
21
- default ( ValueTask < Packet > ) ;
22
- }
23
-
24
- var payloadLength = ( int ) SerializationUtility . ReadUInt32 ( headerBytes . Array , headerBytes . Offset , 3 ) ;
25
- int packetSequenceNumber = headerBytes . Array [ headerBytes . Offset + 3 ] ;
26
-
27
- var expectedSequenceNumber = getNextSequenceNumber ( ) % 256 ;
28
- if ( expectedSequenceNumber . HasValue && packetSequenceNumber != expectedSequenceNumber . Value )
29
- {
30
- if ( protocolErrorBehavior == ProtocolErrorBehavior . Ignore )
31
- return default ( ValueTask < Packet > ) ;
32
-
33
- var exception = MySqlProtocolException . CreateForPacketOutOfOrder ( expectedSequenceNumber . Value , packetSequenceNumber ) ;
34
- return ValueTaskExtensions . FromException < Packet > ( exception ) ;
35
- }
36
-
37
- return bufferedByteReader . ReadBytesAsync ( byteHandler , payloadLength , ioBehavior )
38
- . ContinueWith ( payloadBytes =>
39
- {
40
- if ( payloadBytes . Count < payloadLength )
41
- {
42
- return protocolErrorBehavior == ProtocolErrorBehavior . Throw ?
43
- ValueTaskExtensions . FromException < Packet > ( new EndOfStreamException ( ) ) :
44
- default ( ValueTask < Packet > ) ;
45
- }
46
-
47
- return new ValueTask < Packet > ( new Packet ( packetSequenceNumber , payloadBytes ) ) ;
48
- } ) ;
49
- } ) ;
14
+ var headerBytesTask = bufferedByteReader . ReadBytesAsync ( byteHandler , 4 , ioBehavior ) ;
15
+ if ( headerBytesTask . IsCompleted )
16
+ return ReadPacketAfterHeader ( headerBytesTask . Result , bufferedByteReader , byteHandler , getNextSequenceNumber , protocolErrorBehavior , ioBehavior ) ;
17
+ return AddContinuation ( headerBytesTask , bufferedByteReader , byteHandler , getNextSequenceNumber , protocolErrorBehavior , ioBehavior ) ;
18
+
19
+ // NOTE: use a local function (with no captures) to defer creation of lambda objects
20
+ ValueTask < Packet > AddContinuation ( ValueTask < ArraySegment < byte > > headerBytes_ , BufferedByteReader bufferedByteReader_ , IByteHandler byteHandler_ , Func < int ? > getNextSequenceNumber_ , ProtocolErrorBehavior protocolErrorBehavior_ , IOBehavior ioBehavior_ ) =>
21
+ headerBytes_ . ContinueWith ( x => ReadPacketAfterHeader ( x , bufferedByteReader_ , byteHandler_ , getNextSequenceNumber_ , protocolErrorBehavior_ , ioBehavior_ ) ) ;
22
+ }
23
+
24
+ private static ValueTask < Packet > ReadPacketAfterHeader ( ArraySegment < byte > headerBytes , BufferedByteReader bufferedByteReader , IByteHandler byteHandler , Func < int ? > getNextSequenceNumber , ProtocolErrorBehavior protocolErrorBehavior , IOBehavior ioBehavior )
25
+ {
26
+ if ( headerBytes . Count < 4 )
27
+ {
28
+ return protocolErrorBehavior == ProtocolErrorBehavior . Throw ?
29
+ ValueTaskExtensions . FromException < Packet > ( new EndOfStreamException ( ) ) :
30
+ default ( ValueTask < Packet > ) ;
31
+ }
32
+
33
+ var payloadLength = ( int ) SerializationUtility . ReadUInt32 ( headerBytes . Array , headerBytes . Offset , 3 ) ;
34
+ int packetSequenceNumber = headerBytes . Array [ headerBytes . Offset + 3 ] ;
35
+
36
+ var expectedSequenceNumber = getNextSequenceNumber ( ) % 256 ;
37
+ if ( expectedSequenceNumber . HasValue && packetSequenceNumber != expectedSequenceNumber . Value )
38
+ {
39
+ if ( protocolErrorBehavior == ProtocolErrorBehavior . Ignore )
40
+ return default ( ValueTask < Packet > ) ;
41
+
42
+ var exception = MySqlProtocolException . CreateForPacketOutOfOrder ( expectedSequenceNumber . Value , packetSequenceNumber ) ;
43
+ return ValueTaskExtensions . FromException < Packet > ( exception ) ;
44
+ }
45
+
46
+ var payloadBytesTask = bufferedByteReader . ReadBytesAsync ( byteHandler , payloadLength , ioBehavior ) ;
47
+ if ( payloadBytesTask . IsCompleted )
48
+ return CreatePacketFromPayload ( payloadBytesTask . Result , payloadLength , packetSequenceNumber , protocolErrorBehavior ) ;
49
+ return AddContinuation ( payloadBytesTask , payloadLength , packetSequenceNumber , protocolErrorBehavior ) ;
50
+
51
+ // NOTE: use a local function (with no captures) to defer creation of lambda objects
52
+ ValueTask < Packet > AddContinuation ( ValueTask < ArraySegment < byte > > payloadBytesTask_ , int payloadLength_ , int packetSequenceNumber_ , ProtocolErrorBehavior protocolErrorBehavior_ )
53
+ => payloadBytesTask_ . ContinueWith ( x => CreatePacketFromPayload ( x , payloadLength_ , packetSequenceNumber_ , protocolErrorBehavior_ ) ) ;
50
54
}
51
55
56
+ private static ValueTask < Packet > CreatePacketFromPayload ( ArraySegment < byte > payloadBytes , int payloadLength , int packetSequenceNumber , ProtocolErrorBehavior protocolErrorBehavior ) =>
57
+ payloadBytes . Count >= payloadLength ? new ValueTask < Packet > ( new Packet ( packetSequenceNumber , payloadBytes ) ) :
58
+ protocolErrorBehavior == ProtocolErrorBehavior . Throw ? ValueTaskExtensions . FromException < Packet > ( new EndOfStreamException ( ) ) :
59
+ default ( ValueTask < Packet > ) ;
60
+
52
61
public static ValueTask < ArraySegment < byte > > ReadPayloadAsync ( BufferedByteReader bufferedByteReader , IByteHandler byteHandler , Func < int ? > getNextSequenceNumber , ArraySegment < byte > previousPayloads , ProtocolErrorBehavior protocolErrorBehavior , IOBehavior ioBehavior )
53
62
{
54
63
var readPacketTask = ReadPacketAsync ( bufferedByteReader , byteHandler , getNextSequenceNumber , protocolErrorBehavior , ioBehavior ) ;
0 commit comments