Skip to content

Instantly share code, notes, and snippets.

@juliusfriedman
Last active December 3, 2021 20:50
Show Gist options
  • Save juliusfriedman/6f2cb28056c4b97ecffe59a435f068c7 to your computer and use it in GitHub Desktop.
Save juliusfriedman/6f2cb28056c4b97ecffe59a435f068c7 to your computer and use it in GitHub Desktop.
Type System
/// <summary>
/// Of 8 bytes.
/// A structure which represents an:
/// <see cref="System.Object"/>, <see cref="System.Array"/> or <see cref="System.String"/>.
/// </summary>
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit, Size = 8)]
public struct Invariant
{
[System.Runtime.InteropServices.FieldOffset(0)]
public System.Array Array;
[System.Runtime.InteropServices.FieldOffset(0)]
public object Object;
[System.Runtime.InteropServices.FieldOffset(0)]
public string String;
/// <summary>
/// Used to interpret the address/memory of object which can be thought of as IntPtr*
/// Remember to deference the type 1 time to inspect the memory where ref object points to.
/// </summary>
/// <typeparam name="TType"></typeparam>
/// <param name="index"></param>
/// <param name="length"></param>
/// <returns></returns>
public System.Span<TType> GetSpan<TType>(int index, int length) => System.Runtime.InteropServices.MemoryMarshal.CreateSpan(ref System.Runtime.CompilerServices.Unsafe.Add(ref System.Runtime.CompilerServices.Unsafe.As<object, TType>(ref Object), index), length);
/// <summary>
/// Get a <see cref="System.IntPtr"/> which points to the address of <see cref="Object"/>
/// </summary>
/// <returns></returns>
public System.IntPtr ToPointer() => GetSpan<System.IntPtr>(0, 1)[0] + System.IntPtr.Size + System.IntPtr.Size; //Syncbloc, Rtti
/// <summary>
/// Allowing one to set the <see cref="System.Type"/> of <see cref="Object"/>
/// </summary>
public System.Type Type
{
set
{
System.Runtime.InteropServices.Marshal.WriteIntPtr(GetSpan<System.IntPtr>(0, 1)[0], value.TypeHandle.Value);
//System.Runtime.CompilerServices.Unsafe.AsRef(GetSpan<System.IntPtr>(0, 1)[0]) = value.TypeHandle.Value;
}
}
//Requires unsafe
//[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
//public unsafe static System.IntPtr AddressOf<T>(ref T t)
//{
// System.TypedReference reference = __makeref(t);
// return **(System.IntPtr**)(&reference);
//}
}
/// <summary>
/// A single value
/// Will implicitly convert to <see cref="Invariant"/>
/// </summary>
/// <typeparam name="T"></typeparam>
public ref struct Invariant<T>
{
/// <summary>
/// The value
/// </summary>
public T Value;
/// <summary>
/// Implicit create <see cref="Invariant"/>
/// </summary>
/// <param name="src"></param>
public static implicit operator Invariant(Invariant<T> src) => new Invariant() { Object = src.Value };
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static T Alloc(Invariant invariant) => Alloc(invariant.ToPointer());
/// <summary>
/// Allocate the value initializing the Object header and TypeHandle.
/// </summary>
/// <param name="bufferPtr"></param>
/// <returns></returns>
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static T Alloc(System.IntPtr bufferPtr)
{
var dataPointer = bufferPtr + 1;
//New way
//System.Runtime.CompilerServices.Unsafe.AsRef(bufferPtr) = System.IntPtr.Zero;
//System.Runtime.CompilerServices.Unsafe.AsRef(dataPointer) = typeof(T).TypeHandle.Value;
//Old way
System.Runtime.InteropServices.Marshal.WriteIntPtr(bufferPtr, System.IntPtr.Zero); //Object Header
System.Runtime.InteropServices.Marshal.WriteIntPtr(dataPointer, typeof(T).TypeHandle.Value);
return System.Runtime.CompilerServices.Unsafe.As<System.IntPtr, T>(ref dataPointer); //Pointer to the method table pointer
}
//[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
//public unsafe static T Alloc(System.Span<byte> bytes) => Alloc((System.IntPtr)System.Runtime.CompilerServices.Unsafe.AsPointer(ref bytes.GetPinnableReference()));
//Could be exposed from a static Construct<T>(ref T) method but which constructor to invoke?
//private static unsafe class Constructor
//{
// private static readonly delegate*<T, void> ConstructorHandle;
// static Constructor()
// {
// System.Type type = typeof(T);
// System.Reflection.ConstructorInfo constructorInfo = type.GetConstructor(System.Array.Empty<System.Type>());
// Constructor.ConstructorHandle = (delegate*<T, void>)constructorInfo.MethodHandle.GetFunctionPointer();
// }
// [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
// internal static void Invoke(T returnObject)
// {
// Constructor.ConstructorHandle(returnObject);
// }
//}
/// <summary>
/// Creates a <see cref="System.Span{T}"/>
/// </summary>
/// <returns></returns>
public System.Span<T> GetSpan() => System.Runtime.InteropServices.MemoryMarshal.CreateSpan(ref Value, 1);
/// <summary>
/// Create a <see cref="System.Span{TType}"/>
/// </summary>
/// <typeparam name="TType"></typeparam>
/// <param name="index"></param>
/// <param name="length"></param>
/// <returns></returns>
public System.Span<TType> GetSpan<TType>(int index, int length) => System.Runtime.InteropServices.MemoryMarshal.CreateSpan(ref System.Runtime.CompilerServices.Unsafe.Add(ref System.Runtime.CompilerServices.Unsafe.As<T, TType>(ref Value), index), length);
}
/// <summary>
/// A wrapper around an "invariant" <typeparamref name="T"/> array; that is, without any covariance or contravariance.
/// Will implicitly convert to <see cref="Invariant"/>
/// </summary>
/// <typeparam name="T"></typeparam>
public ref struct InvariantArray<T>
{
public T[] Array;
public static implicit operator Invariant(InvariantArray<T> src) => new Invariant() { Array = src.Array };
/// <summary>
/// Gets a reference to the element at <paramref name="index"/>
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public ref T this[int index]=> ref Array[index];
/// <summary>
/// Create a <see cref="System.Span{T}"/> from <see cref="Array"/>
/// </summary>
/// <param name="index"></param>
/// <param name="length"></param>
/// <returns></returns>
public System.Span<T> GetSpan(int index, int length) => System.Runtime.InteropServices.MemoryMarshal.CreateSpan(ref this[index], length);
/// <summary>
/// Create a <see cref="System.Span{TType}"/> from <see cref="Array"/>
/// </summary>
/// <typeparam name="TType"></typeparam>
/// <param name="index"></param>
/// <param name="length"></param>
/// <returns></returns>
public System.Span<TType> GetSpan<TType>(int index, int length) => System.Runtime.InteropServices.MemoryMarshal.CreateSpan(ref System.Runtime.CompilerServices.Unsafe.As<T, TType>(ref this[index]), length);
}
/// <summary>
/// Allows one to make a generic type which forwards to that type.
/// Allows for <see cref="Type{System.Type}"/>
/// </summary>
/// <typeparam name="T"></typeparam>
public class Type<T> : System.Type
{
public Type()
{
SystemType = typeof(T);
}
readonly System.Type SystemType;
public override System.Reflection.Assembly Assembly => SystemType.Assembly;
public override string AssemblyQualifiedName => SystemType.AssemblyQualifiedName;
public override System.Type BaseType => SystemType.BaseType;
public override string FullName => SystemType.FullName;
public override System.Guid GUID => SystemType.GUID;
public override System.Reflection.Module Module => SystemType.Module;
public override string Namespace => SystemType.Namespace;
public override System.Type UnderlyingSystemType => SystemType.UnderlyingSystemType;
public override string Name => SystemType.Name;
public override System.Reflection.ConstructorInfo[] GetConstructors(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetConstructors(bindingAttr);
}
public override object[] GetCustomAttributes(bool inherit)
{
return SystemType.GetCustomAttributes(inherit);
}
public override object[] GetCustomAttributes(System.Type attributeType, bool inherit)
{
return SystemType.GetCustomAttributes(attributeType, inherit);
}
public override System.Type GetElementType()
{
return SystemType.GetElementType();
}
public override System.Reflection.EventInfo GetEvent(string name, System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetEvent(name, bindingAttr);
}
public override System.Reflection.EventInfo[] GetEvents(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetEvents(bindingAttr);
}
public override System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetField(name, bindingAttr);
}
public override System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetFields(bindingAttr);
}
public override System.Type GetInterface(string name, bool ignoreCase)
{
return SystemType.GetInterface(name, ignoreCase);
}
public override System.Type[] GetInterfaces()
{
return SystemType.GetInterfaces();
}
public override System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetMembers(bindingAttr);
}
public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetMethods(bindingAttr);
}
public override System.Type GetNestedType(string name, System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetNestedType(name, bindingAttr);
}
public override System.Type[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetNestedTypes(bindingAttr);
}
public override System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr)
{
return SystemType.GetProperties(bindingAttr);
}
public override object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
return SystemType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
public override bool IsDefined(System.Type attributeType, bool inherit)
{
return SystemType.IsDefined(attributeType, inherit);
}
protected override System.Reflection.TypeAttributes GetAttributeFlagsImpl()
{
return SystemType.Attributes;
}
protected override System.Reflection.ConstructorInfo GetConstructorImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers)
{
return SystemType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
}
protected override System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers)
{
return SystemType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
}
protected override System.Reflection.PropertyInfo GetPropertyImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers)
{
return SystemType.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
protected override bool HasElementTypeImpl()
{
return SystemType.HasElementType;
}
protected override bool IsArrayImpl()
{
return SystemType.IsArray;
}
protected override bool IsByRefImpl()
{
return SystemType.IsByRef;
}
protected override bool IsCOMObjectImpl()
{
return SystemType.IsCOMObject;
}
protected override bool IsPointerImpl()
{
return SystemType.IsPointer;
}
protected override bool IsPrimitiveImpl()
{
return SystemType.IsPrimitive;
}
}
/// <summary>
/// Reresents a value from <see cref="Type{T}"/>
/// </summary>
/// <typeparam name="T"></typeparam>
public class ValueType<T> : Type<T>
{
public T Value;
}
@juliusfriedman
Copy link
Author

///


/// Reveals the object header size
///

public static Invariant Null = new Invariant();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment