You've already forked linux-packaging-mono
Imported Upstream version 6.6.0.103
Former-commit-id: ed8637df0061cb6f128ae1d26d26db7734e0fa0d
This commit is contained in:
parent
53ae335b9c
commit
9b1ef54dc9
187
mcs/class/corlib/corefx/SequenceReaderExtensions.Binary.cs
Normal file
187
mcs/class/corlib/corefx/SequenceReaderExtensions.Binary.cs
Normal file
@ -0,0 +1,187 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Buffers.Binary;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Internal.Runtime.CompilerServices;
|
||||
|
||||
namespace System.Buffers
|
||||
{
|
||||
#if !__MonoCS__
|
||||
public static partial class SequenceReaderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Try to read the given type out of the buffer if possible. Warning: this is dangerous to use with arbitrary
|
||||
/// structs- see remarks for full details.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// IMPORTANT: The read is a straight copy of bits. If a struct depends on specific state of it's members to
|
||||
/// behave correctly this can lead to exceptions, etc. If reading endian specific integers, use the explicit
|
||||
/// overloads such as <see cref="TryReadLittleEndian(ref SequenceReader{byte}, out short)"/>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// True if successful. <paramref name="value"/> will be default if failed (due to lack of space).
|
||||
/// </returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static unsafe bool TryRead<T>(ref this SequenceReader<byte> reader, out T value) where T : unmanaged
|
||||
{
|
||||
ReadOnlySpan<byte> span = reader.UnreadSpan;
|
||||
if (span.Length < sizeof(T))
|
||||
return TryReadMultisegment(ref reader, out value);
|
||||
|
||||
value = Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(span));
|
||||
reader.Advance(sizeof(T));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static unsafe bool TryReadMultisegment<T>(ref SequenceReader<byte> reader, out T value) where T : unmanaged
|
||||
{
|
||||
Debug.Assert(reader.UnreadSpan.Length < sizeof(T));
|
||||
|
||||
// Not enough data in the current segment, try to peek for the data we need.
|
||||
T buffer = default;
|
||||
Span<byte> tempSpan = new Span<byte>(&buffer, sizeof(T));
|
||||
|
||||
if (!reader.TryCopyTo(tempSpan))
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
value = Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(tempSpan));
|
||||
reader.Advance(sizeof(T));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="short"/> as little endian.
|
||||
/// </summary>
|
||||
/// <returns>False if there wasn't enough data for an <see cref="short"/>.</returns>
|
||||
public static bool TryReadLittleEndian(ref this SequenceReader<byte> reader, out short value)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
return reader.TryRead(out value);
|
||||
}
|
||||
|
||||
return TryReadReverseEndianness(ref reader, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="short"/> as big endian.
|
||||
/// </summary>
|
||||
/// <returns>False if there wasn't enough data for an <see cref="short"/>.</returns>
|
||||
public static bool TryReadBigEndian(ref this SequenceReader<byte> reader, out short value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
return reader.TryRead(out value);
|
||||
}
|
||||
|
||||
return TryReadReverseEndianness(ref reader, out value);
|
||||
}
|
||||
|
||||
private static bool TryReadReverseEndianness(ref SequenceReader<byte> reader, out short value)
|
||||
{
|
||||
if (reader.TryRead(out value))
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="int"/> as little endian.
|
||||
/// </summary>
|
||||
/// <returns>False if there wasn't enough data for an <see cref="int"/>.</returns>
|
||||
public static bool TryReadLittleEndian(ref this SequenceReader<byte> reader, out int value)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
return reader.TryRead(out value);
|
||||
}
|
||||
|
||||
return TryReadReverseEndianness(ref reader, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="int"/> as big endian.
|
||||
/// </summary>
|
||||
/// <returns>False if there wasn't enough data for an <see cref="int"/>.</returns>
|
||||
public static bool TryReadBigEndian(ref this SequenceReader<byte> reader, out int value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
return reader.TryRead(out value);
|
||||
}
|
||||
|
||||
return TryReadReverseEndianness(ref reader, out value);
|
||||
}
|
||||
|
||||
private static bool TryReadReverseEndianness(ref SequenceReader<byte> reader, out int value)
|
||||
{
|
||||
if (reader.TryRead(out value))
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="long"/> as little endian.
|
||||
/// </summary>
|
||||
/// <returns>False if there wasn't enough data for an <see cref="long"/>.</returns>
|
||||
public static bool TryReadLittleEndian(ref this SequenceReader<byte> reader, out long value)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
return reader.TryRead(out value);
|
||||
}
|
||||
|
||||
return TryReadReverseEndianness(ref reader, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an <see cref="long"/> as big endian.
|
||||
/// </summary>
|
||||
/// <returns>False if there wasn't enough data for an <see cref="long"/>.</returns>
|
||||
public static bool TryReadBigEndian(ref this SequenceReader<byte> reader, out long value)
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
return reader.TryRead(out value);
|
||||
}
|
||||
|
||||
return TryReadReverseEndianness(ref reader, out value);
|
||||
}
|
||||
|
||||
private static bool TryReadReverseEndianness(ref SequenceReader<byte> reader, out long value)
|
||||
{
|
||||
if (reader.TryRead(out value))
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
public static partial class SequenceReaderExtensions
|
||||
{
|
||||
public static bool TryReadBigEndian(this System.Buffers.SequenceReader<byte> reader, out short value) => throw new PlatformNotSupportedException();
|
||||
public static bool TryReadBigEndian(this System.Buffers.SequenceReader<byte> reader, out int value) => throw new PlatformNotSupportedException();
|
||||
public static bool TryReadBigEndian(this System.Buffers.SequenceReader<byte> reader, out long value) => throw new PlatformNotSupportedException();
|
||||
public static bool TryReadLittleEndian(this System.Buffers.SequenceReader<byte> reader, out short value) => throw new PlatformNotSupportedException();
|
||||
public static bool TryReadLittleEndian(this System.Buffers.SequenceReader<byte> reader, out int value) => throw new PlatformNotSupportedException();
|
||||
public static bool TryReadLittleEndian(this System.Buffers.SequenceReader<byte> reader, out long value) => throw new PlatformNotSupportedException();
|
||||
}
|
||||
#endif
|
||||
}
|
Reference in New Issue
Block a user