Skip to content

Commit 2f52dac

Browse files
committed
handle sequential media types that doesn't require the sequence to strictly end with a delimiter character
1 parent 2fb8778 commit 2f52dac

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

src/OpenAPI.WebApiGenerator/CodeGeneration/SequentialJsonEnumeratorGenerator.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,18 @@ internal abstract class SequentialJsonEnumerator<T>(
4545
where T : struct, IJsonValue<T>
4646
{
4747
private PipeReader PipeReader { get; } = PipeReader.Create(stream);
48+
49+
/// <summary>
50+
/// Delimiter between each item
51+
/// </summary>
4852
protected abstract byte Delimiter { get; }
53+
54+
/// <summary>
55+
/// Does the sequence require ending with a delimiter?
56+
/// </summary>
57+
protected abstract bool RequiresDelimiterAfterLastItem { get; }
58+
59+
/// <inheritdoc/>
4960
public ValueTask DisposeAsync() => PipeReader.CompleteAsync();
5061
5162
private int _itemPosition = -1;
@@ -71,13 +82,19 @@ public async ValueTask<bool> MoveNextAsync()
7182
return true;
7283
}
7384
74-
if (result.IsCompleted)
85+
switch (result.IsCompleted)
7586
{
76-
PipeReader.AdvanceTo(buffer.End);
77-
return false;
87+
case true when buffer.IsEmpty:
88+
return false;
89+
case true when !RequiresDelimiterAfterLastItem:
90+
_itemPosition++;
91+
Current = ParseItem(buffer);
92+
PipeReader.AdvanceTo(buffer.End);
93+
return true;
94+
default:
95+
PipeReader.AdvanceTo(buffer.Start, buffer.End);
96+
break;
7897
}
79-
80-
PipeReader.AdvanceTo(buffer.Start, buffer.End);
8198
} while (true);
8299
}
83100
@@ -122,6 +139,7 @@ internal sealed class ApplicationJsonlEnumerator<T>(Stream stream, CancellationT
122139
where T : struct, IJsonValue<T>
123140
{
124141
protected override byte Delimiter => 0x0A;
142+
protected override bool RequiresDelimiterAfterLastItem => false;
125143
protected override T ParseItem(ReadOnlySequence<byte> data) => T.Parse(data);
126144
}
127145
@@ -134,6 +152,7 @@ internal sealed class ApplicationJsonSeqEnumerator<T>(Stream stream, Cancellatio
134152
{
135153
private const byte RecordSeparator = 0x1E;
136154
protected override byte Delimiter => 0x0A;
155+
protected override bool RequiresDelimiterAfterLastItem => true;
137156
138157
protected override T ParseItem(ReadOnlySequence<byte> data)
139158
{

tests/Example.OpenApi32.IntegrationTests/ImportFooEventsTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ public async Task ImportingFooEvents_ShouldReturnAccepted()
1818
Method = new HttpMethod("POST"),
1919
Content = CreateJsonContent(
2020
"""
21-
{
22-
"Name": "test"
23-
}
21+
{ "Name": "test" }
22+
{ "Name": "another test" }
2423
""", "application/jsonl")
2524
}, CancellationToken);
2625
result.StatusCode.Should().Be(HttpStatusCode.Accepted);

0 commit comments

Comments
 (0)