BinaryReaderExtensions
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace System.IO
{
internal static class BinaryReaderExtensions
{
[NullableContext(1)]
internal static DateTime ReadDateTime(this BinaryReader reader)
{
return CreateDateTimeFromData(reader.ReadInt64());
}
internal static DateTime CreateDateTimeFromData(long data)
{
try {
new DateTime(data & 4611686018427387903);
} catch (ArgumentException ex) {
throw new SerializationException(ex.Message, ex);
}
return Unsafe.As<long, DateTime>(ref data);
}
[NullableContext(1)]
internal static long Remaining(this BinaryReader reader)
{
Stream baseStream = reader.BaseStream;
return baseStream.Length - baseStream.Position;
}
[return: Nullable(new byte[] {
1,
0
})]
internal unsafe static T[] ReadPrimitiveArray<[IsUnmanaged] T>([Nullable(1)] this BinaryReader reader, int count) where T : struct
{
ArgumentOutOfRangeException.ThrowIfNegative(count, "count");
checked {
if (typeof(T) == typeof(decimal) || typeof(T) == typeof(DateTime) || typeof(T) == typeof(TimeSpan)) {
if (count == 0)
return Array.Empty<T>();
if (count > 0 && reader.Remaining() < count * ((typeof(T) == typeof(decimal)) ? 2 : sizeof(T)))
throw new SerializationException("Not enough data to fill array.");
return <ReadPrimitiveArray>g__ReadNonBlittableTypes|3_0<T>(reader, count);
}
if (typeof(T) != typeof(bool) && typeof(T) != typeof(byte) && typeof(T) != typeof(sbyte) && typeof(T) != typeof(char) && typeof(T) != typeof(short) && typeof(T) != typeof(ushort) && typeof(T) != typeof(int) && typeof(T) != typeof(uint) && typeof(T) != typeof(long) && typeof(T) != typeof(ulong) && typeof(T) != typeof(float) && typeof(T) != typeof(double))
throw new ArgumentException("Cannot read primitives of " + typeof(T).Name + ".", "T");
if (count > 0 && reader.Remaining() < count * ((typeof(T) == typeof(char)) ? 1 : sizeof(T)))
throw new SerializationException("Not enough data to fill array.");
if (count == 0)
return Array.Empty<T>();
}
if (typeof(T) == typeof(char))
return (T[])reader.ReadChars(count);
T[] array = new T[count];
fixed (T* pointer = array) {
Span<byte> span = new Span<byte>((void*)pointer, array.Length * sizeof(T));
if (reader.Read(span) != span.Length)
throw new SerializationException("Not enough data to fill array.");
if (sizeof(T) != 1 && !BitConverter.IsLittleEndian) {
if (sizeof(T) == 2) {
Span<ushort> span2 = MemoryMarshal.Cast<byte, ushort>(span);
BinaryPrimitives.ReverseEndianness(span2, span2);
} else if (sizeof(T) == 4) {
Span<int> span3 = MemoryMarshal.Cast<byte, int>(span);
BinaryPrimitives.ReverseEndianness(span3, span3);
} else {
if (sizeof(T) != 8)
throw new InvalidOperationException("Cannot read primitives of " + typeof(T).Name + ".");
Span<long> span4 = MemoryMarshal.Cast<byte, long>(span);
BinaryPrimitives.ReverseEndianness(span4, span4);
}
}
}
return array;
}
internal unsafe static void WritePrimitives<[IsUnmanaged] T>([Nullable(1)] this BinaryWriter writer, [Nullable(new byte[] {
1,
0
})] IReadOnlyList<T> values) where T : struct
{
if (((IReadOnlyCollection<T>)values).Count != 0) {
if (typeof(T) == typeof(DateTime) || typeof(T) == typeof(decimal) || typeof(T) == typeof(TimeSpan))
<WritePrimitives>g__WritePrimitiveCollection|4_0(writer, values);
else {
if (typeof(T) != typeof(bool) && typeof(T) != typeof(byte) && typeof(T) != typeof(sbyte) && typeof(T) != typeof(char) && typeof(T) != typeof(short) && typeof(T) != typeof(ushort) && typeof(T) != typeof(int) && typeof(T) != typeof(uint) && typeof(T) != typeof(long) && typeof(T) != typeof(ulong) && typeof(T) != typeof(float) && typeof(T) != typeof(double))
throw new ArgumentException("Cannot write primitives of " + typeof(T).Name + ".", "T");
T[] array = values as T[];
ReadOnlySpan<T> span;
if (array != null)
span = array;
else if (values is ArraySegment<T>) {
ArraySegment<T> segment = (ArraySegment<T>)values;
span = segment;
} else {
List<T> list = values as List<T>;
if (list == null) {
<WritePrimitives>g__WritePrimitiveCollection|4_0(writer, values);
return;
}
span = CollectionsMarshal.AsSpan(list);
}
if (typeof(T) == typeof(char))
writer.Write(MemoryMarshal.Cast<T, char>(span));
else if (sizeof(T) == 1 || BitConverter.IsLittleEndian) {
writer.Write(MemoryMarshal.Cast<T, byte>(span));
} else {
<WritePrimitives>g__WritePrimitiveCollection|4_0(writer, values);
}
}
}
}
}
}