Skip to content

Commit 612dd9a

Browse files
committed
process multiple blocks
1 parent bee8654 commit 612dd9a

File tree

1 file changed

+63
-57
lines changed

1 file changed

+63
-57
lines changed

src/Microsoft.DotNet.XHarness.TestRunners.Xunit/WasmXmlResultWriter.cs

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Microsoft.DotNet.XHarness.TestRunners.Xunit;
1515

1616
internal class WasmXmlResultWriter
1717
{
18-
#if !NET || DEBUG
18+
#if DEBUG
1919
public static void WriteOnSingleLine(XElement assembliesElement)
2020
{
2121
using var ms = new MemoryStream();
@@ -29,6 +29,7 @@ public static void WriteOnSingleLine(XElement assembliesElement)
2929
private class ToBase64CharTransform : ICryptoTransform
3030
{
3131
private readonly ToBase64Transform _base64Transform = new ToBase64Transform();
32+
private byte[] _intermediate = new byte[2];
3233

3334
public int InputBlockSize => _base64Transform.InputBlockSize; // 3 bytes of input
3435
public int OutputBlockSize => _base64Transform.OutputBlockSize * 2; // 4 bytes of base64 output * 2 for UTF-16 encoding
@@ -45,66 +46,71 @@ public int TransformBlock(
4546
byte[] inputBuffer, int inputOffset, int inputCount,
4647
byte[] outputBuffer, int outputOffset)
4748
{
48-
int totalBytesWritten = 0;
49-
int inputProcessed = 0;
49+
int inputBlocks = Math.DivRem(inputCount, InputBlockSize, out int inputRemainder);
5050

51-
while (inputProcessed < inputCount)
51+
if (inputRemainder != 0)
5252
{
53-
int bytesToProcess = Math.Min(InputBlockSize, inputCount - inputProcessed);
54-
55-
/*
56-
Input Buffer ("hi mom"):
57-
+-----+-----+-----+-----+-----+-----+
58-
| 'h' | 'i' | ' ' | 'm' | 'o' | 'm' |
59-
+-----+-----+-----+-----+-----+-----+
60-
|104 |105 | 32 |109 |111 |109 |
61-
+-----+-----+-----+-----+-----+-----+
62-
63-
Base64 Encoding Process:
64-
- 'hi ' -> 'aGkg'
65-
- 'mom' -> 'bW9t'
66-
67-
Base64 Encoded Output:
68-
| |base64Written | | base64Written |
69-
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
70-
| \0 | \0 | \0 | \0 |'a' |'G' |'k' |'g' | \0 | \0 | \0 | \0 |'b' |'W' |'9' |'t' |
71-
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
72-
| 0 | 0 | 0 | 0 | 97 | 71 |107 |103 | 0 | 0 | 0 | 0 | 98 | 87 | 57 |116 |
73-
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
74-
75-
Expanded Output Buffer (UTF-16 Encoding):
76-
| outputChars | outputChars |
77-
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
78-
| \0 |'a' | \0 |'G' | \0 |'k' | \0 |'g' | \0 |'b' | \0 |'W' | \0 |'9' | \0 |'t' |
79-
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
80-
| 0 | 97 | 0 | 71 | 0 |107 | 0 |103 | 0 | 98 | 0 | 87 | 0 | 57 | 0 |116 |
81-
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
82-
83-
*/
84-
85-
// Calculate positions in the output buffer
86-
int outputStart = outputOffset + totalBytesWritten;
87-
int base64OutputStart = outputStart + OutputBlockSize / 2;
88-
89-
// write Base64 transformation directly to the second half of the output buffer
90-
int base64BytesWritten = _base64Transform.TransformBlock(
91-
inputBuffer, inputOffset + inputProcessed, bytesToProcess,
92-
outputBuffer, base64OutputStart);
93-
94-
var base64Written = outputBuffer.AsSpan(base64OutputStart, base64BytesWritten);
95-
var outputChars = outputBuffer.AsSpan(outputStart, OutputBlockSize);
96-
for (int i = 0; i < base64BytesWritten; i++)
53+
throw new ArgumentException($"Input count must be a multiple of {InputBlockSize}.", nameof(inputCount));
54+
}
55+
56+
if (inputCount == 0)
57+
{
58+
throw new ArgumentException("Input count must be greater than 0.", nameof(inputCount));
59+
}
60+
61+
/*
62+
Input Buffer ("hi mom"):
63+
+-----+-----+-----+-----+-----+-----+
64+
| 'h' | 'i' | ' ' | 'm' | 'o' | 'm' |
65+
+-----+-----+-----+-----+-----+-----+
66+
|104 |105 | 32 |109 |111 |109 |
67+
+-----+-----+-----+-----+-----+-----+
68+
69+
Base64 Encoding Process:
70+
- 'hi ' -> 'aGkg'
71+
- 'mom' -> 'bW9t'
72+
73+
Base64 Encoded Output:
74+
| |base64Written | | base64Written |
75+
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
76+
| \0 | \0 | \0 | \0 |'a' |'G' |'k' |'g' | \0 | \0 | \0 | \0 |'b' |'W' |'9' |'t' |
77+
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
78+
| 0 | 0 | 0 | 0 | 97 | 71 |107 |103 | 0 | 0 | 0 | 0 | 98 | 87 | 57 |116 |
79+
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
80+
81+
Expanded Output Buffer (UTF-16 Encoding):
82+
| outputChars | outputChars |
83+
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
84+
| \0 |'a' | \0 |'G' | \0 |'k' | \0 |'g' | \0 |'b' | \0 |'W' | \0 |'9' | \0 |'t' |
85+
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
86+
| 0 | 97 | 0 | 71 | 0 |107 | 0 |103 | 0 | 98 | 0 | 87 | 0 | 57 | 0 |116 |
87+
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
88+
89+
*/
90+
91+
// Calculate positions in the output buffer
92+
int base64OutputStart = outputOffset + OutputBlockSize / 2;
93+
94+
// write Base64 transformation directly to the second half of the output buffer
95+
int base64BytesWritten = _base64Transform.TransformBlock(
96+
inputBuffer, inputOffset, inputCount,
97+
outputBuffer, base64OutputStart);
98+
99+
var base64Written = outputBuffer.AsSpan(base64OutputStart, base64BytesWritten);
100+
var outputChars = outputBuffer.AsSpan(outputOffset, OutputBlockSize);
101+
102+
for (int i = 0; i < base64BytesWritten; i++)
103+
{
104+
// Expand each ascii byte to a char write it in the same logical position
105+
// as a char in outputChars eventually filling the output buffer
106+
if (!BitConverter.TryWriteBytes(outputChars.Slice(i * 2), (char)base64Written[i]))
97107
{
98-
// Expand each ascii byte to a char write it in the same logical position
99-
// as a char in outputChars eventually filling the output buffer
100-
BitConverter.TryWriteBytes(outputChars.Slice(i * 2), (char)base64Written[i]);
108+
BitConverter.TryWriteBytes(_intermediate, (char)base64Written[i]);
109+
_intermediate.CopyTo(outputChars.Slice(i * 2, 2));
101110
}
102-
103-
inputProcessed += bytesToProcess;
104-
totalBytesWritten += base64BytesWritten * 2;
105111
}
106112

107-
return totalBytesWritten;
113+
return base64BytesWritten * 2;
108114
}
109115

110116
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
@@ -144,9 +150,9 @@ public static void WriteOnSingleLine(XElement assembliesElement)
144150
// we went to a lot of trouble to put characters in the final buffer
145151
// so that we can avoid a copy here and pass the span directly to the
146152
// string interpolation logic.
147-
Span<char> charData = MemoryMarshal.Cast<byte,char>(bytes);
153+
Span<char> charData = MemoryMarshal.Cast<byte, char>(bytes.AsSpan());
148154

149-
// Output the result
155+
// Output the result and the the ascii length of the data
150156
Console.WriteLine($"STARTRESULTXML {charData.Length} {charData} ENDRESULTXML");
151157
Console.WriteLine($"Finished writing {charData.Length} bytes of RESULTXML");
152158
}

0 commit comments

Comments
 (0)