-
Notifications
You must be signed in to change notification settings - Fork 0
/
JsonParser.ParseSimpleAsync.cs
73 lines (64 loc) · 2.14 KB
/
JsonParser.ParseSimpleAsync.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace json_test
{
static partial class JsonParser
{
/// <remarks>
/// Parses via Span using a single growing buffer.
/// </remarks>
public static async Task<T> ParseSimpleAsync<T, TParser>(Stream stream, CancellationToken cancellationToken)
where TParser : IJsonParser<T>, new()
{
var buffer = new byte[4096];
int fill = 0, consumed = 0;
bool done = false;
var readerState = new JsonReaderState();
var parser = new TParser();
while(true)
{
if (!done)
{
if (fill == buffer.Length)
{
if (consumed != 0)
{
buffer.AsSpan(consumed).CopyTo(buffer);
fill -= consumed;
consumed = 0;
}
else
{
Array.Resize(ref buffer, buffer.Length * 3 / 2);
}
}
int read = await stream.ReadAsync(buffer.AsMemory(fill), cancellationToken).ConfigureAwait(false);
fill += read;
done = read == 0;
}
if (!DoReadSync())
{
if (done) throw new Exception("unexpected end of document.");
}
else
{
return parser.FinalValue;
}
}
bool DoReadSync()
{
var reader = new Utf8JsonReader(buffer.AsSpan(consumed, fill - consumed), done, readerState);
bool res = parser.TryContinueParse(ref reader);
consumed += (int)reader.BytesConsumed;
readerState = reader.CurrentState;
return res;
}
}
}
}