Skip to content

Commit

Permalink
Extract most I/O methods from Terminal{Reader,Writer} to TerminalIOEx…
Browse files Browse the repository at this point in the history
…tensions.

Part of #193.
  • Loading branch information
alexrp committed Aug 21, 2024
1 parent 5f1bd4a commit b6467ec
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 253 deletions.
206 changes: 206 additions & 0 deletions src/core/IO/TerminalIOExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// SPDX-License-Identifier: 0BSD

namespace Vezel.Cathode.IO;

public static class TerminalIOExtensions
{
public static int Read(this TerminalReader reader, scoped Span<byte> value)
{
Check.Null(reader);

var count = 0;

while (count < value.Length)
{
var ret = reader.ReadPartial(value[count..]);

// EOF?
if (ret == 0)
break;

count += ret;
}

return count;
}

public static ValueTask<int> ReadAsync(
this TerminalReader reader, Memory<byte> value, CancellationToken cancellationToken = default)
{
Check.Null(reader);

return ReadAsync();

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
async ValueTask<int> ReadAsync()
{
var count = 0;

while (count < value.Length)
{
var ret = await reader.ReadPartialAsync(value[count..], cancellationToken).ConfigureAwait(false);

// EOF?
if (ret == 0)
break;

count += ret;
}

return count;
}
}

public static string? ReadLine(this TerminalReader reader)
{
Check.Null(reader);

return reader.TextReader.ReadLine();
}

public static ValueTask<string?> ReadLineAsync(
this TerminalReader reader, CancellationToken cancellationToken = default)
{
Check.Null(reader);

return reader.TextReader.ReadLineAsync(cancellationToken);
}

public static void Write<T>(this TerminalWriter writer, T value)
{
writer.Write((value?.ToString()).AsSpan());
}

public static void Write(this TerminalWriter writer, scoped ReadOnlySpan<byte> value)
{
Check.Null(writer);

for (var count = 0; count < value.Length; count += writer.WritePartial(value[count..]))
{
}
}

public static void Write(this TerminalWriter writer, scoped ReadOnlySpan<char> value)
{
var encoding = Terminal.Encoding;
var len = encoding.GetByteCount(value);
var array = ArrayPool<byte>.Shared.Rent(len);

try
{
var span = array.AsSpan(..len);

_ = encoding.GetBytes(value, span);

writer.Write(span);
}
finally
{
ArrayPool<byte>.Shared.Return(array);
}
}

public static ValueTask WriteAsync<T>(
this TerminalWriter writer, T value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync((value?.ToString()).AsMemory(), cancellationToken);
}

public static ValueTask WriteAsync(
this TerminalWriter writer, ReadOnlyMemory<byte> value, CancellationToken cancellationToken = default)
{
Check.Null(writer);

return WriteAsync();

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))]
async ValueTask WriteAsync()
{
for (var count = 0;
count < value.Length;
count += await writer.WritePartialAsync(value[count..], cancellationToken).ConfigureAwait(false))
{
}
}
}

public static ValueTask WriteAsync(
this TerminalWriter writer, Memory<byte> value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync((ReadOnlyMemory<byte>)value, cancellationToken);
}

public static ValueTask WriteAsync(
this TerminalWriter writer, byte[]? value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync(value.AsMemory(), cancellationToken);
}

public static ValueTask WriteAsync(
this TerminalWriter writer, ReadOnlyMemory<char> value, CancellationToken cancellationToken = default)
{
Check.Null(writer);

return WriteAsync();

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))]
async ValueTask WriteAsync()
{
var encoding = Terminal.Encoding;
var len = encoding.GetByteCount(value.Span);
var array = ArrayPool<byte>.Shared.Rent(len);

try
{
var mem = array.AsMemory(..len);

_ = encoding.GetBytes(value.Span, mem.Span);

await writer.WriteAsync(mem, cancellationToken).ConfigureAwait(false);
}
finally
{
ArrayPool<byte>.Shared.Return(array);
}
}
}

public static ValueTask WriteAsync(
this TerminalWriter writer, Memory<char> value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync((ReadOnlyMemory<char>)value, cancellationToken);
}

public static ValueTask WriteAsync(
this TerminalWriter writer, char[]? value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync(value.AsMemory(), cancellationToken);
}

public static ValueTask WriteAsync(
this TerminalWriter writer, string? value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync(value.AsMemory(), cancellationToken);
}

public static void WriteLine(this TerminalWriter writer)
{
writer.WriteLine(string.Empty);
}

public static void WriteLine<T>(this TerminalWriter writer, T value)
{
writer.Write(value?.ToString() + Environment.NewLine);
}

public static ValueTask WriteLineAsync(this TerminalWriter writer, CancellationToken cancellationToken = default)
{
return writer.WriteLineAsync(string.Empty, cancellationToken);
}

public static ValueTask WriteLineAsync<T>(
this TerminalWriter writer, T value, CancellationToken cancellationToken = default)
{
return writer.WriteAsync(value?.ToString() + Environment.NewLine, cancellationToken);
}
}
47 changes: 0 additions & 47 deletions src/core/IO/TerminalReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,51 +30,4 @@ public async ValueTask<int> ReadPartialAsync(Memory<byte> buffer, CancellationTo

return count;
}

public int Read(scoped Span<byte> value)
{
var count = 0;

while (count < value.Length)
{
var ret = ReadPartial(value[count..]);

// EOF?
if (ret == 0)
break;

count += ret;
}

return count;
}

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))]
public async ValueTask<int> ReadAsync(Memory<byte> value, CancellationToken cancellationToken = default)
{
var count = 0;

while (count < value.Length)
{
var ret = await ReadPartialAsync(value[count..], cancellationToken).ConfigureAwait(false);

// EOF?
if (ret == 0)
break;

count += ret;
}

return count;
}

public string? ReadLine()
{
return TextReader.ReadLine();
}

public ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken = default)
{
return TextReader.ReadLineAsync(cancellationToken);
}
}
113 changes: 0 additions & 113 deletions src/core/IO/TerminalWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,117 +32,4 @@ public async ValueTask<int> WritePartialAsync(

return count;
}

public void Write(scoped ReadOnlySpan<byte> value)
{
for (var count = 0; count < value.Length; count += WritePartial(value[count..]))
{
}
}

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))]
public async ValueTask WriteAsync(ReadOnlyMemory<byte> value, CancellationToken cancellationToken = default)
{
for (var count = 0;
count < value.Length;
count += await WritePartialAsync(value[count..], cancellationToken).ConfigureAwait(false))
{
}
}

public ValueTask WriteAsync(Memory<byte> value, CancellationToken cancellationToken = default)
{
return WriteAsync((ReadOnlyMemory<byte>)value, cancellationToken);
}

public ValueTask WriteAsync(byte[]? value, CancellationToken cancellationToken = default)
{
return WriteAsync(value.AsMemory(), cancellationToken);
}

public void Write(scoped ReadOnlySpan<char> value)
{
var encoding = Terminal.Encoding;
var len = encoding.GetByteCount(value);
var array = ArrayPool<byte>.Shared.Rent(len);

try
{
var span = array.AsSpan(..len);

_ = encoding.GetBytes(value, span);

Write(span);
}
finally
{
ArrayPool<byte>.Shared.Return(array);
}
}

[AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))]
public async ValueTask WriteAsync(ReadOnlyMemory<char> value, CancellationToken cancellationToken = default)
{
var encoding = Terminal.Encoding;
var len = encoding.GetByteCount(value.Span);
var array = ArrayPool<byte>.Shared.Rent(len);

try
{
var mem = array.AsMemory(..len);

_ = encoding.GetBytes(value.Span, mem.Span);

await WriteAsync(mem, cancellationToken).ConfigureAwait(false);
}
finally
{
ArrayPool<byte>.Shared.Return(array);
}
}

public ValueTask WriteAsync(Memory<char> value, CancellationToken cancellationToken = default)
{
return WriteAsync((ReadOnlyMemory<char>)value, cancellationToken);
}

public ValueTask WriteAsync(char[]? value, CancellationToken cancellationToken = default)
{
return WriteAsync(value.AsMemory(), cancellationToken);
}

public ValueTask WriteAsync(string? value, CancellationToken cancellationToken = default)
{
return WriteAsync(value.AsMemory(), cancellationToken);
}

public void Write<T>(T value)
{
Write((value?.ToString()).AsSpan());
}

public ValueTask WriteAsync<T>(T value, CancellationToken cancellationToken = default)
{
return WriteAsync((value?.ToString()).AsMemory(), cancellationToken);
}

public void WriteLine()
{
WriteLine(string.Empty);
}

public ValueTask WriteLineAsync(CancellationToken cancellationToken = default)
{
return WriteLineAsync(string.Empty, cancellationToken);
}

public void WriteLine<T>(T value)
{
Write(value?.ToString() + Environment.NewLine);
}

public ValueTask WriteLineAsync<T>(T value, CancellationToken cancellationToken = default)
{
return WriteAsync(value?.ToString() + Environment.NewLine, cancellationToken);
}
}
Loading

0 comments on commit b6467ec

Please sign in to comment.