using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace BlittableStructure {
static class Program {
delegate uint SizeOfType(Type type);
static SizeOfType SizeOf = typeof(Marshal).GetMethod("SizeOfType", BindingFlags.NonPublic | BindingFlags.Static).CreateDelegate(typeof(SizeOfType)) as SizeOfType;
static class Blittable<T> where T : struct {
public static readonly int Size = (int)SizeOf(typeof(T));
public static readonly unsafe void* Handle = typeof(T).TypeHandle.Value.ToPointer();
}
[FixedAddressValueType]
static readonly unsafe void* handle = typeof(Array).TypeHandle.Value.ToPointer(),
type = typeof(byte[]).TypeHandle.Value.ToPointer();
[MethodImpl(MethodImplOptions.AggressiveInlining, MethodCodeType = MethodCodeType.IL)]
static unsafe T Read<T>(this Stream input) where T : struct {
var size = Blittable<T>.Size;
var tref = stackalloc byte[IntPtr.Size * 5 + size];
var inst = (void**)tref + 3;
inst[1] = (void*)size;
inst[0] = handle;
inst[-2] = type;
inst[-3] = &inst;
if(input.Read( __refvalue(*(TypedReference*)tref, byte[]), 0, size) < size) throw new EndOfStreamException();
inst[-3] = inst + 2;
inst[-2] = Blittable<T>.Handle;
return __refvalue( *(TypedReference*)tref,T);
}
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static unsafe void Main(string[] args) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
try {
var i = 100000;
var stack = stackalloc int[i];
stack[1] = 1;
stack[2] = 2;
stack[3] = 3;
stack[4] = 4;
using(var mem = new UnmanagedMemoryStream((byte*)stack, sizeof(int) * i))
using(var bin = new BinaryReader(mem, Encoding.ASCII, true)) {
var sw = Stopwatch.StartNew();
mem.Read<int>();
Console.WriteLine(mem.Read<Rectangle>());
mem.Seek(0L, SeekOrigin.Begin);
sw.Restart();
while(--i >= 0) mem.Read<int>();
Console.WriteLine(sw.ElapsedTicks);
i = 100000;
mem.Seek(0L, SeekOrigin.Begin);
sw.Restart();
while(--i >= 0) bin.ReadInt32();
Console.WriteLine(sw.ElapsedTicks);
}
} catch(Exception e) {
Console.WriteLine(e);
}
}
}
}