22using System . IO . Pipelines ;
33using CHttpServer . Http3 ;
44
5- // TODO buffer segments
6-
75internal sealed class Http3DeframingPipeReader : PipeReader
86{
97 private enum StreamReadingStatus
@@ -15,17 +13,17 @@ private enum StreamReadingStatus
1513
1614 private class Segment : ReadOnlySequenceSegment < byte >
1715 {
18- public Segment ( ReadOnlyMemory < byte > data , object ? source , int sourceOffset , long framePayloadRemaining )
16+ public void Initialize ( ReadOnlyMemory < byte > data , object ? source , int sourceOffset , long framePayloadRemaining )
1917 {
2018 base . Memory = data ;
2119 Source = source ;
2220 SourceOffset = sourceOffset ;
2321 FramePayloadRemaining = framePayloadRemaining ;
2422 }
2523
26- public object ? Source { get ; }
27- public int SourceOffset { get ; }
28- public long FramePayloadRemaining { get ; }
24+ public object ? Source { get ; private set ; }
25+ public int SourceOffset { get ; private set ; }
26+ public long FramePayloadRemaining { get ; private set ; }
2927
3028 public Segment SetNext ( Segment s )
3129 {
@@ -54,6 +52,15 @@ public Segment Slice(int start)
5452 throw new InvalidOperationException ( "Not a Segment" ) ;
5553 }
5654
55+ public void Reset ( )
56+ {
57+ Memory = ReadOnlyMemory < byte > . Empty ;
58+ Source = null ;
59+ SourceOffset = 0 ; FramePayloadRemaining = 0 ;
60+ RunningIndex = 0 ;
61+ Next = null ;
62+ }
63+
5764 public SequencePosition End => new SequencePosition ( this , Memory . Length ) ;
5865 }
5966
@@ -62,10 +69,12 @@ public Segment Slice(int start)
6269 private long _payloadRemainingLength = 0 ;
6370 private Segment ? _head ;
6471 private Segment ? _tail ;
72+ private Stack < Segment > _segmentsBuffer ;
6573
6674 public Http3DeframingPipeReader ( PipeReader pipeReader )
6775 {
6876 _pipeReader = pipeReader ;
77+ _segmentsBuffer = new Stack < Segment > ( capacity : 10 ) ;
6978 }
7079
7180 public void Reset ( PipeReader pipeReader )
@@ -77,7 +86,7 @@ public void Reset(PipeReader pipeReader)
7786 _streamReadingState = StreamReadingStatus . ReadingFrameHeader ;
7887 }
7988
80- private void AddSegment ( Segment s )
89+ private void AppendDataSegment ( Segment s )
8190 {
8291 if ( _tail == null )
8392 _head = _tail = s ;
@@ -110,6 +119,9 @@ public override void AdvanceTo(SequencePosition consumed, SequencePosition exami
110119 sourceObject = segmentExamined . Source ;
111120 examined = new SequencePosition ( sourceObject , sourceOffset ) ;
112121
122+ while ( _head != segmentConsumed && _head != null )
123+ _head = ReturnSegment ( _head ) ;
124+
113125 _payloadRemainingLength = segmentConsumed . FramePayloadRemaining - segmentOffset ;
114126 if ( _payloadRemainingLength == 0 )
115127 _streamReadingState = StreamReadingStatus . ReadingFrameHeader ;
@@ -155,6 +167,8 @@ public override async ValueTask<ReadResult> ReadAsync(CancellationToken token =
155167 // at the beginning of the segment.
156168 private bool ProcessReadResult ( ReadOnlySequence < byte > buffer , out ReadOnlySequence < byte > sequence )
157169 {
170+ while ( _head != null )
171+ _head = ReturnSegment ( _head ) ;
158172 _head = _tail = null ;
159173 sequence = ReadOnlySequence < byte > . Empty ;
160174 long bufferConsumed = 0 ;
@@ -173,9 +187,10 @@ private bool ProcessReadResult(ReadOnlySequence<byte> buffer, out ReadOnlySequen
173187 foreach ( var s in dataPayload )
174188 {
175189 var position = buffer . GetPosition ( currentPosition ) ;
176- var segment = new Segment ( s , position . GetObject ( ) , position . GetInteger ( ) , currentPayloadRemainingLength ) ;
190+ var segment = RentSegment ( ) ;
191+ segment . Initialize ( s , position . GetObject ( ) , position . GetInteger ( ) , currentPayloadRemainingLength ) ;
177192 currentPayloadRemainingLength -= s . Length ;
178- AddSegment ( segment ) ;
193+ AppendDataSegment ( segment ) ;
179194 currentPosition += s . Length ;
180195 }
181196 }
@@ -259,6 +274,21 @@ private static StreamReadingStatus NextRequestReadingState(ulong frameType)
259274 return streamReadingState ;
260275 }
261276
277+ private Segment RentSegment ( )
278+ {
279+ if ( ! _segmentsBuffer . TryPop ( out var segment ) )
280+ segment = new Segment ( ) ;
281+ return segment ;
282+ }
283+
284+ private Segment ? ReturnSegment ( Segment segment )
285+ {
286+ var next = segment . Next ;
287+ segment . Reset ( ) ;
288+ _segmentsBuffer . Push ( segment ) ;
289+ return next as Segment ;
290+ }
291+
262292 public override async Task CopyToAsync ( PipeWriter destination , CancellationToken cancellationToken = default )
263293 {
264294 StreamReadingStatus streamState = StreamReadingStatus . ReadingFrameHeader ;
0 commit comments