Update NETStandard2.1 APIs (#17080)
[mono-project.git] / mcs / class / corlib / corefx / SequenceReaderExtensions.Binary.cs
blob81777fa747b4afb80de8c09a158abc8eacd40370
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Buffers.Binary;
6 using System.Diagnostics;
7 using System.Runtime.CompilerServices;
8 using System.Runtime.InteropServices;
9 using Internal.Runtime.CompilerServices;
11 namespace System.Buffers
13 #if !__MonoCS__
14 public static partial class SequenceReaderExtensions
16 /// <summary>
17 /// Try to read the given type out of the buffer if possible. Warning: this is dangerous to use with arbitrary
18 /// structs- see remarks for full details.
19 /// </summary>
20 /// <remarks>
21 /// IMPORTANT: The read is a straight copy of bits. If a struct depends on specific state of it's members to
22 /// behave correctly this can lead to exceptions, etc. If reading endian specific integers, use the explicit
23 /// overloads such as <see cref="TryReadLittleEndian(ref SequenceReader{byte}, out short)"/>
24 /// </remarks>
25 /// <returns>
26 /// True if successful. <paramref name="value"/> will be default if failed (due to lack of space).
27 /// </returns>
28 [MethodImpl(MethodImplOptions.AggressiveInlining)]
29 internal static unsafe bool TryRead<T>(ref this SequenceReader<byte> reader, out T value) where T : unmanaged
31 ReadOnlySpan<byte> span = reader.UnreadSpan;
32 if (span.Length < sizeof(T))
33 return TryReadMultisegment(ref reader, out value);
35 value = Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(span));
36 reader.Advance(sizeof(T));
37 return true;
40 private static unsafe bool TryReadMultisegment<T>(ref SequenceReader<byte> reader, out T value) where T : unmanaged
42 Debug.Assert(reader.UnreadSpan.Length < sizeof(T));
44 // Not enough data in the current segment, try to peek for the data we need.
45 T buffer = default;
46 Span<byte> tempSpan = new Span<byte>(&buffer, sizeof(T));
48 if (!reader.TryCopyTo(tempSpan))
50 value = default;
51 return false;
54 value = Unsafe.ReadUnaligned<T>(ref MemoryMarshal.GetReference(tempSpan));
55 reader.Advance(sizeof(T));
56 return true;
59 /// <summary>
60 /// Reads an <see cref="short"/> as little endian.
61 /// </summary>
62 /// <returns>False if there wasn't enough data for an <see cref="short"/>.</returns>
63 public static bool TryReadLittleEndian(ref this SequenceReader<byte> reader, out short value)
65 if (BitConverter.IsLittleEndian)
67 return reader.TryRead(out value);
70 return TryReadReverseEndianness(ref reader, out value);
73 /// <summary>
74 /// Reads an <see cref="short"/> as big endian.
75 /// </summary>
76 /// <returns>False if there wasn't enough data for an <see cref="short"/>.</returns>
77 public static bool TryReadBigEndian(ref this SequenceReader<byte> reader, out short value)
79 if (!BitConverter.IsLittleEndian)
81 return reader.TryRead(out value);
84 return TryReadReverseEndianness(ref reader, out value);
87 private static bool TryReadReverseEndianness(ref SequenceReader<byte> reader, out short value)
89 if (reader.TryRead(out value))
91 value = BinaryPrimitives.ReverseEndianness(value);
92 return true;
95 return false;
98 /// <summary>
99 /// Reads an <see cref="int"/> as little endian.
100 /// </summary>
101 /// <returns>False if there wasn't enough data for an <see cref="int"/>.</returns>
102 public static bool TryReadLittleEndian(ref this SequenceReader<byte> reader, out int value)
104 if (BitConverter.IsLittleEndian)
106 return reader.TryRead(out value);
109 return TryReadReverseEndianness(ref reader, out value);
112 /// <summary>
113 /// Reads an <see cref="int"/> as big endian.
114 /// </summary>
115 /// <returns>False if there wasn't enough data for an <see cref="int"/>.</returns>
116 public static bool TryReadBigEndian(ref this SequenceReader<byte> reader, out int value)
118 if (!BitConverter.IsLittleEndian)
120 return reader.TryRead(out value);
123 return TryReadReverseEndianness(ref reader, out value);
126 private static bool TryReadReverseEndianness(ref SequenceReader<byte> reader, out int value)
128 if (reader.TryRead(out value))
130 value = BinaryPrimitives.ReverseEndianness(value);
131 return true;
134 return false;
137 /// <summary>
138 /// Reads an <see cref="long"/> as little endian.
139 /// </summary>
140 /// <returns>False if there wasn't enough data for an <see cref="long"/>.</returns>
141 public static bool TryReadLittleEndian(ref this SequenceReader<byte> reader, out long value)
143 if (BitConverter.IsLittleEndian)
145 return reader.TryRead(out value);
148 return TryReadReverseEndianness(ref reader, out value);
151 /// <summary>
152 /// Reads an <see cref="long"/> as big endian.
153 /// </summary>
154 /// <returns>False if there wasn't enough data for an <see cref="long"/>.</returns>
155 public static bool TryReadBigEndian(ref this SequenceReader<byte> reader, out long value)
157 if (!BitConverter.IsLittleEndian)
159 return reader.TryRead(out value);
162 return TryReadReverseEndianness(ref reader, out value);
165 private static bool TryReadReverseEndianness(ref SequenceReader<byte> reader, out long value)
167 if (reader.TryRead(out value))
169 value = BinaryPrimitives.ReverseEndianness(value);
170 return true;
173 return false;
176 #else
177 public static partial class SequenceReaderExtensions
179 public static bool TryReadBigEndian(this System.Buffers.SequenceReader<byte> reader, out short value) => throw new PlatformNotSupportedException();
180 public static bool TryReadBigEndian(this System.Buffers.SequenceReader<byte> reader, out int value) => throw new PlatformNotSupportedException();
181 public static bool TryReadBigEndian(this System.Buffers.SequenceReader<byte> reader, out long value) => throw new PlatformNotSupportedException();
182 public static bool TryReadLittleEndian(this System.Buffers.SequenceReader<byte> reader, out short value) => throw new PlatformNotSupportedException();
183 public static bool TryReadLittleEndian(this System.Buffers.SequenceReader<byte> reader, out int value) => throw new PlatformNotSupportedException();
184 public static bool TryReadLittleEndian(this System.Buffers.SequenceReader<byte> reader, out long value) => throw new PlatformNotSupportedException();
186 #endif