using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Runtime.CompilerServices; using static System.Runtime.CompilerServices.MethodImplOptions; namespace InnovEnergy.Lib.Utils; public static class Utils { public static Boolean IsNull([NotNullWhen(returnValue: false)] this T t) => t is null; public static IEnumerable GetEnumStrings(this T e) where T : Enum { return GetEnumValues().Select(v => v.ToString()); } public static IReadOnlyList GetEnumValues() where TEnum : Enum { return (TEnum[]) Enum.GetValues(typeof(TEnum)); } [DebuggerStepThrough][MethodImpl(AggressiveInlining)] public static T ConvertTo(this IConvertible convertible) where T : IConvertible { return (T)ConvertTo(convertible, typeof(T)); } [DebuggerStepThrough][MethodImpl(AggressiveInlining)] public static Object ConvertTo(this IConvertible convertible, Type type) { var t = type.IsEnum ? Enum.GetUnderlyingType(type) : type; return Convert.ChangeType(convertible, t, CultureInfo.InvariantCulture); } public static T Do(this T t, Action action) { action(); return t; } [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static void Nop(T _) {} [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static T Id(T t) => t; [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static T CastTo(this Object source) => (T) source; [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static T Apply(this T t, Action f) { f(t); return t; } // Below does not work ;( // [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] // public static R Apply(this T t, Func f) where T : S // { // return f(t); // } [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static R Apply(this T t, Func f) => f(t); [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static R Apply(this (T1 p1, T2 p2) t, Func f) => f(t.p1, t.p2); [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static R Apply(this (T1 p1, T2 p2, T3 p3) t, Func f) => f(t.p1, t.p2, t.p3); [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)] public static R ApplyOrDefault(this T t, Func f, R @default) { try { return f(t); } catch { return @default; } } public static Int32 Modulo(this Int32 index, Int32 length) { var res = index % length; return res >= 0 ? res : res + length; } public static Decimal Modulo(this Decimal dividend, Decimal divisor) { var res = dividend % divisor; return res >= 0 ? res : res + divisor; } public static Int32 Clamp(this Int32 value, Int32 minValue, Int32 maxValue) { if (minValue > maxValue) throw new ArgumentException(); var clamped = Math.Min(maxValue, value); clamped = Math.Max(minValue, clamped); return clamped; } public static Double Clamp(this Double value, Double minValue, Double maxValue) { if (minValue > maxValue) throw new ArgumentException(); var clamped = Math.Min(maxValue, value); clamped = Math.Max(minValue, clamped); return clamped; } public static Double ClampMax(this Double value, Double maxValue) { return Math.Min(maxValue, value); } public static Double ClampMin(this Double value, Double minValue) { return Math.Max(minValue, value); } public static Decimal Clamp(this Decimal value, Decimal minValue, Decimal maxValue) { var clamped = Math.Min(maxValue, value); clamped = Math.Max(minValue, clamped); return clamped; } public static R ValueOrDefault(this Dictionary dict, T key, R defaultValue) where T : notnull { return dict.TryGetValue(key, out var value) ? value : defaultValue; } public static void CopyFilesRecursively(String source, String target) { CopyFilesRecursively(new DirectoryInfo(source), new DirectoryInfo(target)); } public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target) { foreach (var file in source.GetFiles()) file.CopyTo(Path.Combine(target.FullName, file.Name)); foreach (var dir in source.GetDirectories()) CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name)); } public static String ExecutingProcessName => Process.GetCurrentProcess().ProcessName; }