using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Ghost.Core.Utilities; public unsafe struct BufferWriter : IDisposable { private UnsafeList _buffer; private int _position; public int Position { readonly get => _position; set => _position = value; } public BufferWriter(int initialCapacity, AllocationHandle allocationHandle) { _buffer = new UnsafeList(initialCapacity, allocationHandle); _position = 0; } public void Write(T value) where T : unmanaged { Unsafe.WriteUnaligned(ref _buffer[_position], value); _position += sizeof(T); } public void WriteSpan(ReadOnlySpan data) where T : unmanaged { var size = sizeof(T) * data.Length; var byteSpan = MemoryMarshal.AsBytes(data); byteSpan.CopyTo(_buffer.AsSpan().Slice(_position, size)); _position += size; } public Span ReserveSpan(int length) { var span = _buffer.AsSpan().Slice(_position, length); _position += length; return span; } public readonly Span AsSpan() { return _buffer.AsSpan(); } public void Dispose() { _buffer.Dispose(); } } public unsafe ref struct SpanWriter { private Span _buffer; private int _position; public int Position { readonly get => _position; set => _position = value; } public SpanWriter(Span buffer) { _buffer = buffer; _position = 0; } public void Write(T value) where T : unmanaged { Unsafe.WriteUnaligned(ref _buffer[_position], value); _position += sizeof(T); } public void WriteSpan(ReadOnlySpan data) where T : unmanaged { var size = sizeof(T) * data.Length; var byteSpan = MemoryMarshal.AsBytes(data); byteSpan.CopyTo(_buffer.Slice(_position, size)); _position += size; } public readonly Span AsSpan() { return _buffer; } } public unsafe ref struct SpanReader { private readonly Span _buffer; private int _position; public int Position { readonly get => _position; set => _position = value; } public SpanReader(Span buffer) { _buffer = buffer; _position = 0; } public T Read() where T : unmanaged { var value = Unsafe.ReadUnaligned(ref _buffer[_position]); _position += Unsafe.SizeOf(); return value; } public ReadOnlySpan ReadSpan(int length) where T : unmanaged { var size = sizeof(T) * length; var span = MemoryMarshal.Cast(_buffer.Slice(_position, size)); _position += size; return span; } public ReadOnlySpan ReadToEnd() where T : unmanaged { var span = MemoryMarshal.Cast(_buffer.Slice(_position)); _position += span.Length; return span; } }