using System; using System.IO; using System.Runtime.InteropServices; using System.Threading; namespace Server { public static class NativeReader { private static readonly INativeReader m_NativeReader; static NativeReader() => m_NativeReader = Core.Unix ? new NativeReaderUnix() : new NativeReaderWin32(); public static unsafe int Read(FileStream source, void* buffer, int length) => Read(source, buffer, 0, length); public static unsafe int Read(FileStream source, void* buffer, int bufferIndex, int length) => m_NativeReader.Read(source, buffer, bufferIndex, length); } public interface INativeReader { unsafe int Read(FileStream source, void* buffer, int bufferIndex, int length); } public sealed class NativeReaderWin32 : INativeReader { internal class UnsafeNativeMethods { [DllImport("kernel32")] internal static extern unsafe bool ReadFile(IntPtr hFile, void* lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, NativeOverlapped* lpOverlapped); } public unsafe int Read(FileStream source, void* buffer, int bufferIndex, int length) => InternalRead(source, buffer, bufferIndex, length); internal static unsafe int InternalRead(FileStream source, void* buffer, int bufferIndex, int length) { var byteCount = 0U; if (UnsafeNativeMethods.ReadFile(source.SafeFileHandle!.DangerousGetHandle(), (byte*)buffer + bufferIndex, (uint)length, ref byteCount, null)) { return (int)byteCount; } return -1; } } public sealed class NativeReaderUnix : INativeReader { internal class UnsafeNativeMethods { [DllImport("libc")] internal static extern unsafe int read(IntPtr ptr, void* buffer, int length); } public unsafe int Read(FileStream source, void* buffer, int bufferIndex, int length) => InternalRead(source, buffer, bufferIndex, length); internal unsafe int InternalRead(FileStream source, void* buffer, int bufferIndex, int length) => UnsafeNativeMethods.read(source.SafeFileHandle!.DangerousGetHandle(), (byte*)buffer + bufferIndex, length); } }