This commit is contained in:
bbradson
2022-10-24 18:56:18 +02:00
parent 01ef055ff2
commit 9cdc8ccb4f
70 changed files with 19754 additions and 4 deletions
@@ -0,0 +1,86 @@
// Copyright (c) 2022 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
namespace FisheryLib.FunctionPointers;
public static class Convert<TFrom> where TFrom : IConvertible
{
public static class To<TTo>
{
public static readonly unsafe delegate*<TFrom, IFormatProvider, TTo> Default = Convert.GetDefaultConverter<TFrom, TTo>();
}
/// <summary>
/// Used when TFrom isn't a known sealed type, i.e. with just the IConvertible interface
/// </summary>
internal static class Fallback<TTo>
{
internal static readonly Func<TFrom, IFormatProvider, TTo> Func = Convert.GetDefaultConverterFunc<TFrom, TTo>();
internal static TTo FallbackMethod(TFrom from, IFormatProvider provider) => Func(from, provider);
}
}
internal static class Convert
{
private static MethodInfo GetConverterMethod<TFrom>(Type to) where TFrom : IConvertible
{
var info = typeof(TFrom).GetMethod(GetConvertMethodName(to));
if (info.GetParameters().Length > 1)
{
info = typeof(Convert)
.GetMethod(nameof(ConvertToType), AccessTools.allDeclared)
.MakeGenericMethod(new[] { typeof(TFrom), to });
}
return info;
}
internal static Func<TFrom, IFormatProvider, TTo> GetDefaultConverterFunc<TFrom, TTo>() where TFrom : IConvertible
=> (Func<TFrom, IFormatProvider, TTo>)GetConverterMethod<TFrom>(typeof(TTo))
.CreateDelegate(typeof(Func<TFrom, IFormatProvider, TTo>));
internal static unsafe delegate*<TFrom, IFormatProvider, TTo> GetDefaultConverter<TFrom, TTo>() where TFrom : IConvertible
=> !typeof(TFrom).IsValueType && (!typeof(TFrom).IsSealed || typeof(TFrom).IsInterface || typeof(TFrom).IsAbstract)
? &Convert<TFrom>.Fallback<TTo>.FallbackMethod
: (delegate*<TFrom, IFormatProvider, TTo>)GetConverterMethod<TFrom>(typeof(TTo))
.MethodHandle.GetFunctionPointer();
private static TTo ConvertToType<TFrom, TTo>(TFrom from, IFormatProvider provider) where TFrom : IConvertible
=> (TTo)from.ToType(typeof(TTo), provider);
private static string GetConvertMethodName(Type type)
=> type == typeof(bool)
? nameof(IConvertible.ToBoolean)
: type == typeof(char)
? nameof(IConvertible.ToChar)
: type == typeof(sbyte)
? nameof(IConvertible.ToSByte)
: type == typeof(byte)
? nameof(IConvertible.ToByte)
: type == typeof(short)
? nameof(IConvertible.ToInt16)
: type == typeof(ushort)
? nameof(IConvertible.ToUInt16)
: type == typeof(int)
? nameof(IConvertible.ToInt32)
: type == typeof(uint)
? nameof(IConvertible.ToUInt32)
: type == typeof(long)
? nameof(IConvertible.ToInt64)
: type == typeof(ulong)
? nameof(IConvertible.ToUInt64)
: type == typeof(float)
? nameof(IConvertible.ToSingle)
: type == typeof(double)
? nameof(IConvertible.ToDouble)
: type == typeof(decimal)
? nameof(IConvertible.ToDecimal)
: type == typeof(DateTime)
? nameof(IConvertible.ToDateTime)
: type == typeof(string)
? nameof(IConvertible.ToString)
//: type == typeof(object)
//? value
: nameof(IConvertible.ToType);
}
@@ -0,0 +1,122 @@
// Copyright (c) 2022 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Linq;
using System.Runtime.CompilerServices;
namespace FisheryLib.FunctionPointers;
public static class Equals<T>
{
public static readonly unsafe delegate*<T, T, bool> Default = (delegate*<T, T, bool>)FunctionPointers.Equals.MakeDelegate(typeof(T));
}
public static class Equals
{
public static class Methods
{
public static bool Byte(byte x, byte y)
=> x == y;
public static bool Int(int x, int y)
=> x == y;
public static bool Uint(uint x, uint y)
=> x == y;
public static bool Ushort(ushort x, ushort y)
=> x == y;
public static bool IntPtr(IntPtr x, IntPtr y)
=> x == y;
public static bool String(string x, string y)
=> string.Equals(x, y);
public static unsafe bool VoidPtr(void* x, void* y)
=> x == y;
public static bool RuntimeFieldHandle(RuntimeFieldHandle x, RuntimeFieldHandle y)
=> x.Value == y.Value;
public static bool RuntimeTypeHandle(RuntimeTypeHandle x, RuntimeTypeHandle y)
=> x.Value == y.Value;
public static bool RuntimeMethodHandle(RuntimeMethodHandle x, RuntimeMethodHandle y)
=> x.Value == y.Value;
public static bool Enum<T>(T x, T y) where T : struct
=> JitHelpers.UnsafeEnumCast(x) == JitHelpers.UnsafeEnumCast(y);
public static bool LongEnum<T>(T x, T y) where T : struct
=> JitHelpers.UnsafeEnumCastLong(x) == JitHelpers.UnsafeEnumCastLong(y);
public static bool EquatableValueType<T>(T x, T y) where T : struct, IEquatable<T>
=> x.Equals(y);
public static bool Nullable<T>(T? x, T? y) where T : struct, IEquatable<T>
=> x.HasValue
? y.HasValue && x.Value.Equals(y.Value)
: !y.HasValue;
public static bool EquatableReferenceType<T>(T x, T y) where T : IEquatable<T>
=> x != null
? y != null && x.Equals(y)
: y == null;
public static bool Reference<T>(T x, T y) where T : class
=> x == y;
public static bool Object<T>(T x, T y)
=> x != null
? y != null && x.Equals(y)
: y == null;
}
internal static unsafe IntPtr MakeDelegate(Type type)
=> _equalsMethods.Where(m => !m.IsGenericMethod)
.FirstOrDefault(m
=> m.GetParameters().First().ParameterType == type)
is { } specializedMethod
? specializedMethod.GetFunctionPointer()
: type.IsAssignableTo(typeof(IEquatable<>), type)
? GetMethod(
type.IsValueType
? nameof(Methods.EquatableValueType)
: nameof(Methods.EquatableReferenceType))
.MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer()
: type.IsNullable(out var genericArgument)
&& genericArgument.IsAssignableTo(typeof(IEquatable<>), genericArgument)
? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer()
: GetMethod(
type.IsEnum
? Type.GetTypeCode(Enum.GetUnderlyingType(type))
switch
{
TypeCode.Int16
or TypeCode.SByte
or TypeCode.Byte
or TypeCode.UInt16
or TypeCode.Int32
or TypeCode.UInt32 => nameof(Methods.Enum),
TypeCode.Int64
or TypeCode.UInt64 => nameof(Methods.LongEnum),
_ => ThrowHelper.ThrowNotSupportedException<string>()
}
: nameof(Methods.Object)
).MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer();
private static MethodInfo GetMethod(string name)
=> Array.Find(_equalsMethods, m => m.Name == name);
private static MethodInfo[] _equalsMethods
= typeof(Methods)
.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Where(m
=> m.ReturnType == typeof(bool)
&& m.GetParameters().Length == 2)
.ToArray();
//internal delegate bool EqualsDelegate<T>(T x, T y);
}
@@ -0,0 +1,122 @@
// Copyright (c) 2022 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Linq;
using System.Runtime.CompilerServices;
namespace FisheryLib.FunctionPointers;
public static class EqualsByRef<T>
{
public static readonly unsafe delegate*<ref T, ref T, bool> Default = (delegate*<ref T, ref T, bool>)EqualsByRef.MakeDelegate(typeof(T));
}
public static class EqualsByRef
{
public static class Methods
{
public static bool Byte(ref byte x, ref byte y)
=> x == y;
public static bool Int(ref int x, ref int y)
=> x == y;
public static bool Uint(ref uint x, ref uint y)
=> x == y;
public static bool Ushort(ref ushort x, ref ushort y)
=> x == y;
public static bool IntPtr(ref IntPtr x, ref IntPtr y)
=> x == y;
public static bool String(ref string x, ref string y)
=> string.Equals(x, y);
public static unsafe bool VoidPtr(ref void* x, ref void* y)
=> x == y;
public static bool RuntimeFieldHandle(ref RuntimeFieldHandle x, ref RuntimeFieldHandle y)
=> x.Value == y.Value;
public static bool RuntimeTypeHandle(ref RuntimeTypeHandle x, ref RuntimeTypeHandle y)
=> x.Value == y.Value;
public static bool RuntimeMethodHandle(ref RuntimeMethodHandle x, ref RuntimeMethodHandle y)
=> x.Value == y.Value;
public static bool Enum<T>(ref T x, ref T y) where T : struct
=> JitHelpers.UnsafeEnumCast(x) == JitHelpers.UnsafeEnumCast(y);
public static bool LongEnum<T>(ref T x, ref T y) where T : struct
=> JitHelpers.UnsafeEnumCastLong(x) == JitHelpers.UnsafeEnumCastLong(y);
public static bool EquatableValueType<T>(ref T x, ref T y) where T : struct, IEquatable<T>
=> x.Equals(y);
public static bool Nullable<T>(ref T? x, ref T? y) where T : struct, IEquatable<T>
=> x.HasValue
? y.HasValue && x.Value.Equals(y.Value)
: !y.HasValue;
public static bool EquatableReferenceType<T>(ref T x, ref T y) where T : IEquatable<T>
=> x != null
? y != null && x.Equals(y)
: y == null;
public static bool Reference<T>(ref T x, ref T y) where T : class
=> x == y;
public static bool Object<T>(ref T x, ref T y)
=> x != null
? y != null && x.Equals(y)
: y == null;
}
internal static unsafe IntPtr MakeDelegate(Type type)
=> _equalsMethods.Where(m => !m.IsGenericMethod)
.FirstOrDefault(m
=> m.GetParameters().First().ParameterType.GetElementType() == type)
is { } specializedMethod
? specializedMethod.GetFunctionPointer()
: type.IsAssignableTo(typeof(IEquatable<>), type)
? GetMethod(
type.IsValueType
? nameof(Methods.EquatableValueType)
: nameof(Methods.EquatableReferenceType))
.MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer()
: type.IsNullable(out var genericArgument)
&& genericArgument.IsAssignableTo(typeof(IEquatable<>), genericArgument)
? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer()
: GetMethod(
type.IsEnum
? Type.GetTypeCode(Enum.GetUnderlyingType(type))
switch
{
TypeCode.Int16
or TypeCode.SByte
or TypeCode.Byte
or TypeCode.UInt16
or TypeCode.Int32
or TypeCode.UInt32 => nameof(Methods.Enum),
TypeCode.Int64
or TypeCode.UInt64 => nameof(Methods.LongEnum),
_ => ThrowHelper.ThrowNotSupportedException<string>()
}
: nameof(Methods.Object)
).MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer();
private static MethodInfo GetMethod(string name)
=> Array.Find(_equalsMethods, m => m.Name == name);
private static MethodInfo[] _equalsMethods
= typeof(Methods)
.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Where(m
=> m.ReturnType == typeof(bool)
&& m.GetParameters().Length == 2)
.ToArray();
//internal delegate bool EqualsDelegate<T>(ref T x, ref T y);
}
@@ -0,0 +1,106 @@
// Copyright (c) 2022 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Linq;
using System.Runtime.CompilerServices;
namespace FisheryLib.FunctionPointers;
public static class GetHashCode<T>
{
public static readonly unsafe delegate*<T, int> Default = (delegate*<T, int>)FunctionPointers.GetHashCode.MakeDelegate(typeof(T));
}
public static class GetHashCode
{
public static class Methods
{
public static int Byte(byte obj)
=> obj;
public static int Int(int obj)
=> obj;
public static int Uint(uint obj)
=> (int)obj;
public static int Ushort(ushort obj)
=> obj;
public static unsafe int VoidPtr(void* obj)
=> (int)obj;
public static int Enum<T>(T obj) where T : struct
=> JitHelpers.UnsafeEnumCast(obj).GetHashCode();
public static int SbyteEnum<T>(T obj) where T : struct
=> ((sbyte)JitHelpers.UnsafeEnumCast(obj)).GetHashCode();
public static int ShortEnum<T>(T obj) where T : struct
=> ((short)JitHelpers.UnsafeEnumCast(obj)).GetHashCode();
public static int LongEnum<T>(T obj) where T : struct
=> JitHelpers.UnsafeEnumCastLong(obj).GetHashCode();
public static int ValueType<T>(T obj) where T : struct
=> obj.GetHashCode();
public static int Nullable<T>(T? obj) where T : struct
=> obj.GetHashCode();
public static int Reference<T>(T obj) where T : class
=> RuntimeHelpers.GetHashCode(obj);
public static int Object<T>(T obj)
=> obj?.GetHashCode() ?? 0;
}
internal static unsafe IntPtr MakeDelegate(Type type)
=> _getHashCodeMethods.Where(m => !m.IsGenericMethod)
.FirstOrDefault(m
=> m.GetParameters().First().ParameterType == type)
is { } specializedMethod
? specializedMethod.GetFunctionPointer()
: type.IsNullable(out var genericArgument)
&& genericArgument.IsAssignableTo(typeof(IEquatable<>), genericArgument)
? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument).GetFunctionPointer()
: GetMethod(
type.IsEnum
? Type.GetTypeCode(Enum.GetUnderlyingType(type))
switch
{
TypeCode.Int16 => nameof(Methods.ShortEnum),
TypeCode.SByte => nameof(Methods.SbyteEnum),
TypeCode.Byte
or TypeCode.UInt16
or TypeCode.Int32
or TypeCode.UInt32 => nameof(Methods.Enum),
TypeCode.Int64
or TypeCode.UInt64 => nameof(Methods.LongEnum),
_ => ThrowHelper.ThrowNotSupportedException<string>()
}
: type.IsValueType
? nameof(Methods.ValueType)
: nameof(Methods.Object)
).MakeGenericMethod(type).GetFunctionPointer();
private static MethodInfo GetMethod(string name)
=> Array.Find(_getHashCodeMethods, m => m.Name == name);
private static MethodInfo[] _getHashCodeMethods
= typeof(Methods)
.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Where(m
=> m.ReturnType == typeof(int)
&& m.GetParameters().Length == 1)
.ToArray();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe delegate*<V, int> Cast<T,V>(delegate*<T, int> @delegate)
=> (delegate*<V, int>)@delegate;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe delegate*<T, int> CastVoid<T>(delegate*<void*, int> @delegate)
=> (delegate*<T, int>)@delegate;
}
@@ -0,0 +1,98 @@
// Copyright (c) 2022 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Linq;
using System.Runtime.CompilerServices;
namespace FisheryLib.FunctionPointers;
public static class GetHashCodeByRef<T>
{
public static readonly unsafe delegate*<ref T, int> Default = (delegate*<ref T, int>)GetHashCodeByRef.MakeDelegate(typeof(T));
}
public static class GetHashCodeByRef
{
public static class Methods
{
public static int Byte(ref byte obj)
=> obj;
public static int Int(ref int obj)
=> obj;
public static int Uint(ref uint obj)
=> (int)obj;
public static int Ushort(ref ushort obj)
=> obj;
public static unsafe int VoidPtr(ref void* obj)
=> (int)obj;
public static int Enum<T>(ref T obj) where T : struct
=> JitHelpers.UnsafeEnumCast(obj).GetHashCode();
public static int SbyteEnum<T>(ref T obj) where T : struct
=> ((sbyte)JitHelpers.UnsafeEnumCast(obj)).GetHashCode();
public static int ShortEnum<T>(ref T obj) where T : struct
=> ((short)JitHelpers.UnsafeEnumCast(obj)).GetHashCode();
public static int LongEnum<T>(ref T obj) where T : struct
=> JitHelpers.UnsafeEnumCastLong(obj).GetHashCode();
public static int ValueType<T>(ref T obj) where T : struct
=> obj.GetHashCode();
public static int Nullable<T>(ref T? obj) where T : struct
=> obj.GetHashCode();
public static int Reference<T>(ref T obj) where T : class
=> RuntimeHelpers.GetHashCode(obj);
public static int Object<T>(ref T obj)
=> obj?.GetHashCode() ?? 0;
}
internal static unsafe IntPtr MakeDelegate(Type type)
=> _getHashCodeMethods.Where(m => !m.IsGenericMethod)
.FirstOrDefault(m
=> m.GetParameters().First().ParameterType.GetElementType() == type)
is { } specializedMethod
? specializedMethod.GetFunctionPointer()
: type.IsNullable(out var genericArgument)
&& genericArgument.IsAssignableTo(typeof(IEquatable<>), genericArgument)
? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument).GetFunctionPointer()
: GetMethod(
type.IsEnum
? Type.GetTypeCode(Enum.GetUnderlyingType(type))
switch
{
TypeCode.Int16 => nameof(Methods.ShortEnum),
TypeCode.SByte => nameof(Methods.SbyteEnum),
TypeCode.Byte
or TypeCode.UInt16
or TypeCode.Int32
or TypeCode.UInt32 => nameof(Methods.Enum),
TypeCode.Int64
or TypeCode.UInt64 => nameof(Methods.LongEnum),
_ => ThrowHelper.ThrowNotSupportedException<string>()
}
: type.IsValueType
? nameof(Methods.ValueType)
: nameof(Methods.Object)
).MakeGenericMethod(type).GetFunctionPointer();
private static MethodInfo GetMethod(string name)
=> Array.Find(_getHashCodeMethods, m => m.Name == name);
private static MethodInfo[] _getHashCodeMethods
= typeof(Methods)
.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Where(m
=> m.ReturnType == typeof(int)
&& m.GetParameters().Length == 1)
.ToArray();
}