mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add BlitStruct<T> and BlitSpan<T>
This commit is contained in:
parent
bfaf95026a
commit
5b6ca9c160
3 changed files with 150 additions and 25 deletions
102
src/LibHac/Common/BlitSpan.cs
Normal file
102
src/LibHac/Common/BlitSpan.cs
Normal file
|
@ -0,0 +1,102 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a representation of a region of memory as if it were a series of blittable structs
|
||||
/// of type <typeparamref name="T"/>. Also allows viewing the memory as a <see cref="Span{T}"/> of bytes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The element type.</typeparam>
|
||||
public ref struct BlitSpan<T> where T : unmanaged
|
||||
{
|
||||
private readonly Span<T> _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The number of elements of type <typeparamref name="T"/> in the <see cref="BlitSpan{T}"/>.
|
||||
/// </summary>
|
||||
public int Length => _buffer.Length;
|
||||
|
||||
/// <summary>
|
||||
/// A reference to the first element in this collection.
|
||||
/// </summary>
|
||||
public ref T Value => ref _buffer[0];
|
||||
|
||||
/// <summary>
|
||||
/// A reference to the element at index <paramref name="index"/>.
|
||||
/// </summary>
|
||||
public ref T this[int index] => ref _buffer[index];
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BlitSpan{T}"/> using the provided <see cref="Span{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">The span from which to create the <see cref="BlitSpan{T}"/>.
|
||||
/// Must have a length of at least 1.</param>
|
||||
public BlitSpan(Span<T> data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
|
||||
_buffer = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BlitSpan{T}"/> using the provided <see cref="Span{T}"/> of bytes.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte span from which to create the <see cref="BlitSpan{T}"/>.
|
||||
/// Must be long enough to hold at least one struct of type <typeparamref name="T"/></param>
|
||||
public BlitSpan(Span<byte> data)
|
||||
{
|
||||
if (data.Length < Unsafe.SizeOf<T>())
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
|
||||
_buffer = MemoryMarshal.Cast<byte, T>(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BlitSpan{T}"/> over a struct of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="data">The struct from which to create the <see cref="BlitSpan{T}"/>.</param>
|
||||
public BlitSpan(ref T data)
|
||||
{
|
||||
_buffer = SpanHelpers.AsSpan(ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Span{T}"/> of the elements in the <see cref="BlitSpan{T}"/>.
|
||||
/// </summary>
|
||||
public Span<T> Span => _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a view of the <see cref="BlitSpan{T}"/> as a <see cref="Span{T}"/> of bytes.
|
||||
/// </summary>
|
||||
/// <returns>A byte span representation of the <see cref="BlitSpan{T}"/>.</returns>
|
||||
public Span<byte> GetByteSpan()
|
||||
{
|
||||
return MemoryMarshal.Cast<T, byte>(_buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a view of the element at index <see cref="elementIndex"/> as a <see cref="Span{T}"/> of bytes.
|
||||
/// </summary>
|
||||
/// <param name="elementIndex">The zero-based index of the element.</param>
|
||||
/// <returns>A byte span representation of the element.</returns>
|
||||
public Span<byte> GetByteSpan(int elementIndex)
|
||||
{
|
||||
Span<T> element = _buffer.Slice(elementIndex, 1);
|
||||
return MemoryMarshal.Cast<T, byte>(element);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the length of memory in bytes that would be needed to store <paramref name="elementCount"/>
|
||||
/// elements of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="elementCount">The number of elements.</param>
|
||||
/// <returns>The number of bytes required.</returns>
|
||||
public static int QueryByteLength(int elementCount)
|
||||
{
|
||||
return Unsafe.SizeOf<T>() * elementCount;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,45 +5,63 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
public ref struct BlitStruct<T> where T : unmanaged
|
||||
/// <summary>
|
||||
/// Handles storing a blittable struct or a series of blittable structs in a byte array.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The element type.</typeparam>
|
||||
public readonly struct BlitStruct<T> where T : unmanaged
|
||||
{
|
||||
private readonly Span<T> _buffer;
|
||||
private readonly byte[] _buffer;
|
||||
|
||||
public int Length => _buffer.Length;
|
||||
public int Length => _buffer.Length / Unsafe.SizeOf<T>();
|
||||
|
||||
public ref T Value => ref _buffer[0];
|
||||
public ref T this[int index] => ref _buffer[index];
|
||||
|
||||
public BlitStruct(Span<T> data)
|
||||
/// <summary>
|
||||
/// A reference to the first element in this collection.
|
||||
/// </summary>
|
||||
public ref T Value
|
||||
{
|
||||
_buffer = data;
|
||||
get
|
||||
{
|
||||
Debug.Assert(_buffer.Length >= Unsafe.SizeOf<T>());
|
||||
|
||||
Debug.Assert(_buffer.Length != 0);
|
||||
return ref Unsafe.As<byte, T>(ref _buffer[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public BlitStruct(Span<byte> data)
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="BlitStruct{T}"/> that can hold the specified number
|
||||
/// of elements of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="elementCount">The number of elements the <see cref="BlitStruct{T}"/> will be able to store.</param>
|
||||
public BlitStruct(int elementCount)
|
||||
{
|
||||
_buffer = MemoryMarshal.Cast<byte, T>(data);
|
||||
if (elementCount <= 0)
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
|
||||
Debug.Assert(_buffer.Length != 0);
|
||||
_buffer = new byte[QueryByteLength(elementCount)];
|
||||
}
|
||||
|
||||
public BlitStruct(ref T data)
|
||||
{
|
||||
_buffer = SpanHelpers.AsSpan(ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a <see cref="Span"/> view of the elements in the current <see cref="BlitStruct{T}"/> as type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
public Span<T> Span => MemoryMarshal.Cast<byte, T>(_buffer);
|
||||
|
||||
public Span<byte> GetByteSpan()
|
||||
{
|
||||
return MemoryMarshal.Cast<T, byte>(_buffer);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a <see cref="Span"/> view of the elements in the current <see cref="BlitStruct{T}"/> as <see cref="byte"/>s.
|
||||
/// </summary>
|
||||
public Span<byte> ByteSpan => _buffer;
|
||||
|
||||
public Span<byte> GetByteSpan(int elementIndex)
|
||||
{
|
||||
Span<T> element = _buffer.Slice(elementIndex, 1);
|
||||
return MemoryMarshal.Cast<T, byte>(element);
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a <see cref="BlitSpan{T}"/> from the current <see cref="BlitStruct{T}"/>.
|
||||
/// </summary>
|
||||
public BlitSpan<T> BlitSpan => new BlitSpan<T>(_buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the length of memory in bytes that would be needed to store <paramref name="elementCount"/>
|
||||
/// elements of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="elementCount">The number of elements.</param>
|
||||
/// <returns>The number of bytes required.</returns>
|
||||
public static int QueryByteLength(int elementCount)
|
||||
{
|
||||
return Unsafe.SizeOf<T>() * elementCount;
|
||||
|
|
|
@ -14,5 +14,10 @@ namespace LibHac
|
|||
|
||||
public static void ThrowResult(Result result, string message, Exception innerException) =>
|
||||
throw new HorizonResultException(result, message, innerException);
|
||||
|
||||
internal static void ThrowArgumentOutOfRangeException()
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue