/// </summary>
public static partial class MemoryMarshal
{
+ /// <summary>
+ /// Casts a Span of one primitive type <typeparamref name="T"/> to Span of bytes.
+ /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <param name="span">The source slice, of type <typeparamref name="T"/>.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when <typeparamref name="T"/> contains pointers.
+ /// </exception>
+ /// <exception cref="System.OverflowException">
+ /// Thrown if the Length property of the new Span would exceed Int32.MaxValue.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<byte> AsBytes<T>(Span<T> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+
+ return new Span<byte>(
+ ref Unsafe.As<T, byte>(ref GetReference(span)),
+ checked(span.Length * Unsafe.SizeOf<T>()));
+ }
+
+ /// <summary>
+ /// Casts a ReadOnlySpan of one primitive type <typeparamref name="T"/> to ReadOnlySpan of bytes.
+ /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <param name="span">The source slice, of type <typeparamref name="T"/>.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when <typeparamref name="T"/> contains pointers.
+ /// </exception>
+ /// <exception cref="System.OverflowException">
+ /// Thrown if the Length property of the new Span would exceed Int32.MaxValue.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<byte> AsBytes<T>(ReadOnlySpan<T> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+
+ return new ReadOnlySpan<byte>(
+ ref Unsafe.As<T, byte>(ref GetReference(span)),
+ checked(span.Length * Unsafe.SizeOf<T>()));
+ }
+
/// <summary>Creates a <see cref="Memory{T}"/> from a <see cref="ReadOnlyMemory{T}"/>.</summary>
/// <param name="memory">The <see cref="ReadOnlyMemory{T}"/>.</param>
/// <returns>A <see cref="Memory{T}"/> representing the same memory as the <see cref="ReadOnlyMemory{T}"/>, but writable.</returns>
using System.Runtime.CompilerServices;
using System.Collections.Generic;
+#if !netstandard
+using Internal.Runtime.CompilerServices;
+#endif
+
namespace System.Runtime.InteropServices
{
/// <summary>
return false;
}
}
+
+ /// <summary>
+ /// Reads a structure of type T out of a read-only span of bytes.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ReadMachineEndian<T>(ReadOnlySpan<byte> source)
+ where T : struct
+ {
+#if netstandard
+ if (SpanHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#else
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#endif
+ if (Unsafe.SizeOf<T>() > source.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return Unsafe.ReadUnaligned<T>(ref GetReference(source));
+ }
+
+ /// <summary>
+ /// Reads a structure of type T out of a span of bytes.
+ /// <returns>If the span is too small to contain the type T, return false.</returns>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool TryReadMachineEndian<T>(ReadOnlySpan<byte> source, out T value)
+ where T : struct
+ {
+#if netstandard
+ if (SpanHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#else
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#endif
+ if (Unsafe.SizeOf<T>() > (uint)source.Length)
+ {
+ value = default;
+ return false;
+ }
+ value = Unsafe.ReadUnaligned<T>(ref GetReference(source));
+ return true;
+ }
+
+ /// <summary>
+ /// Writes a structure of type T into a span of bytes.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void WriteMachineEndian<T>(Span<byte> destination, ref T value)
+ where T : struct
+ {
+#if netstandard
+ if (SpanHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#else
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#endif
+ if ((uint)Unsafe.SizeOf<T>() > (uint)destination.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ Unsafe.WriteUnaligned<T>(ref GetReference(destination), value);
+ }
+
+ /// <summary>
+ /// Writes a structure of type T into a span of bytes.
+ /// <returns>If the span is too small to contain the type T, return false.</returns>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool TryWriteMachineEndian<T>(Span<byte> destination, ref T value)
+ where T : struct
+ {
+#if netstandard
+ if (SpanHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#else
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+#endif
+ if (Unsafe.SizeOf<T>() > (uint)destination.Length)
+ {
+ return false;
+ }
+ Unsafe.WriteUnaligned<T>(ref GetReference(destination), value);
+ return true;
+ }
}
}