[Platform] Read and Advance once per parse loop (#2575)

* Advance Reader once per parse loop
This commit is contained in:
Ben Adams 2018-05-16 20:14:05 +01:00 committed by David Fowler
parent 8da5f55832
commit aaaff4475a
1 changed files with 32 additions and 22 deletions

View File

@ -50,64 +50,74 @@ namespace PlatformBenchmarks
} }
var result = await task; var result = await task;
if (!ParseHttpRequest(ref result)) var buffer = result.Buffer;
while (true)
{ {
if (!ParseHttpRequest(ref buffer, result.IsCompleted, out var examined))
{
return;
}
if (_state == State.Body)
{
await ProcessRequestAsync();
_state = State.StartLine;
if (!buffer.IsEmpty)
{
// More input data to parse
continue;
}
}
// No more input or incomplete data, Advance the Reader
Reader.AdvanceTo(buffer.Start, examined);
break; break;
} }
if (_state == State.Body)
{
await ProcessRequestAsync();
_state = State.StartLine;
}
} }
} }
// Should be `in` but ReadResult isn't readonly struct private bool ParseHttpRequest(ref ReadOnlySequence<byte> buffer, bool isCompleted, out SequencePosition examined)
private bool ParseHttpRequest(ref ReadResult result)
{ {
var buffer = result.Buffer; examined = buffer.End;
var consumed = buffer.Start; var consumed = buffer.Start;
var examined = buffer.End;
var state = _state; var state = _state;
if (!buffer.IsEmpty) if (!buffer.IsEmpty)
{ {
var parsingStartLine = state == State.StartLine; if (state == State.StartLine)
if (parsingStartLine)
{ {
if (Parser.ParseRequestLine(new ParsingAdapter(this), buffer, out consumed, out examined)) if (Parser.ParseRequestLine(new ParsingAdapter(this), buffer, out consumed, out examined))
{ {
state = State.Headers; state = State.Headers;
} }
buffer = buffer.Slice(consumed);
} }
if (state == State.Headers) if (state == State.Headers)
{ {
if (parsingStartLine)
{
buffer = buffer.Slice(consumed);
}
if (Parser.ParseHeaders(new ParsingAdapter(this), buffer, out consumed, out examined, out int consumedBytes)) if (Parser.ParseHeaders(new ParsingAdapter(this), buffer, out consumed, out examined, out int consumedBytes))
{ {
state = State.Body; state = State.Body;
} }
buffer = buffer.Slice(consumed);
} }
if (state != State.Body && result.IsCompleted) if (state != State.Body && isCompleted)
{ {
ThrowUnexpectedEndOfData(); ThrowUnexpectedEndOfData();
} }
} }
else if (result.IsCompleted) else if (isCompleted)
{ {
return false; return false;
} }
_state = state; _state = state;
Reader.AdvanceTo(consumed, examined);
return true; return true;
} }