mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
97 lines
3.4 KiB
C#
97 lines
3.4 KiB
C#
// Defines the data protocol for reading and writing strings on our stream
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace GitHub.Runner.Common
|
|
{
|
|
public class StreamString
|
|
{
|
|
private Stream _ioStream;
|
|
private UnicodeEncoding streamEncoding;
|
|
|
|
public StreamString(Stream ioStream)
|
|
{
|
|
_ioStream = ioStream;
|
|
streamEncoding = new UnicodeEncoding();
|
|
}
|
|
|
|
public async Task<Int32> ReadInt32Async(CancellationToken cancellationToken)
|
|
{
|
|
byte[] readBytes = new byte[sizeof(Int32)];
|
|
int dataread = 0;
|
|
while (sizeof(Int32) - dataread > 0 && (!cancellationToken.IsCancellationRequested))
|
|
{
|
|
Task<int> op = _ioStream.ReadAsync(readBytes, dataread, sizeof(Int32) - dataread, cancellationToken);
|
|
int newData = 0;
|
|
newData = await op.WithCancellation(cancellationToken);
|
|
dataread += newData;
|
|
if (0 == newData)
|
|
{
|
|
await Task.Delay(100, cancellationToken);
|
|
}
|
|
}
|
|
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
return BitConverter.ToInt32(readBytes, 0);
|
|
}
|
|
|
|
public async Task WriteInt32Async(Int32 value, CancellationToken cancellationToken)
|
|
{
|
|
byte[] int32Bytes = BitConverter.GetBytes(value);
|
|
Task op = _ioStream.WriteAsync(int32Bytes, 0, sizeof(Int32), cancellationToken);
|
|
await op.WithCancellation(cancellationToken);
|
|
}
|
|
|
|
const int MaxStringSize = 50 * 1000000;
|
|
|
|
public async Task<string> ReadStringAsync(CancellationToken cancellationToken)
|
|
{
|
|
Int32 len = await ReadInt32Async(cancellationToken);
|
|
if (len == 0)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
if (len < 0 || len > MaxStringSize)
|
|
{
|
|
throw new InvalidDataException();
|
|
}
|
|
|
|
byte[] inBuffer = new byte[len];
|
|
int dataread = 0;
|
|
while (len - dataread > 0 && (!cancellationToken.IsCancellationRequested))
|
|
{
|
|
Task<int> op = _ioStream.ReadAsync(inBuffer, dataread, len - dataread, cancellationToken);
|
|
int newData = 0;
|
|
newData = await op.WithCancellation(cancellationToken);
|
|
dataread += newData;
|
|
if (0 == newData)
|
|
{
|
|
await Task.Delay(100, cancellationToken);
|
|
}
|
|
}
|
|
|
|
return streamEncoding.GetString(inBuffer);
|
|
}
|
|
|
|
public async Task WriteStringAsync(string outString, CancellationToken cancellationToken)
|
|
{
|
|
byte[] outBuffer = streamEncoding.GetBytes(outString);
|
|
Int32 len = outBuffer.Length;
|
|
if (len > MaxStringSize)
|
|
{
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
await WriteInt32Async(len, cancellationToken);
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
Task op = _ioStream.WriteAsync(outBuffer, 0, len, cancellationToken);
|
|
await op.WithCancellation(cancellationToken);
|
|
op = _ioStream.FlushAsync(cancellationToken);
|
|
await op.WithCancellation(cancellationToken);
|
|
}
|
|
}
|
|
}
|