Meum/Meum.Core/QuicStreamWrapper.cs
2025-05-08 21:48:57 +05:00

85 lines
2.6 KiB
C#

using System.Buffers;
using System.Net.Quic;
using System.Runtime.InteropServices;
using Meum.Core.Messages;
namespace Meum.Core;
public class QuicStreamWrapper : IAsyncDisposable
{
private QuicStream _stream;
public QuicStreamWrapper(QuicStream stream)
{
_stream = stream;
}
public async ValueTask<T> ReadStructAsync<T>(CancellationToken ct = default)
where T : struct
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(Marshal.SizeOf(typeof(T)));
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
await _stream.ReadExactlyAsync(buffer, ct);
return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T))!;
}
finally
{
handle.Free();
ArrayPool<byte>.Shared.Return(buffer);
}
}
public ValueTask WriteStructAsync<T>(T msg_struct, CancellationToken ct = default)
where T : struct
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(Marshal.SizeOf(typeof(T)));
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
Marshal.StructureToPtr(msg_struct, handle.AddrOfPinnedObject(), false);
return _stream.WriteAsync(buffer, ct);
}
finally
{
handle.Free();
ArrayPool<byte>.Shared.Return(buffer);
}
}
public ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken ct = default)
=> _stream.ReadAsync(buffer, ct);
public ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken ct = default)
=> _stream.WriteAsync(buffer, ct);
public ValueTask WriteCodeMessageAsync(MessageTypeCode messageTypeCode, CancellationToken ct = default)
{
CodeMessage m = new CodeMessage(messageTypeCode);
return WriteStructAsync(m, ct);
}
public async ValueTask<MessageTypeCode> ReadCodeMessageAsync(CancellationToken ct = default)
{
CodeMessage m = await ReadStructAsync<CodeMessage>(ct);
m.ThrowIfInvalid();
return m.type_code;
}
public async ValueTask<DataMessageHeader> ReadDataMessageHeaderAsync(CancellationToken ct = default)
{
var m = await ReadStructAsync<DataMessageHeader>(ct);
m.ThrowIfInvalid();
return m;
}
//TODO
// public async ValueTask<>
public async ValueTask DisposeAsync()
{
_stream.Close();
await _stream.DisposeAsync();
}
}