using System.Reflection; using java.lang; using java.util.concurrent; using java.util.function; using net.luckperms.api.@event; namespace LuckPerms.Torch.Utils.Extensions; public static class DelegateExtensions { private static readonly Func AndThenDefault = (Func)typeof(Consumer).GetMethod("andThen", BindingFlags.Static | BindingFlags.Public)!.CreateDelegate(typeof(Func)); private static readonly Func AndDefault = (Func)typeof(Predicate).GetMethod("and", BindingFlags.Static | BindingFlags.Public)!.CreateDelegate(typeof(Func)); private static readonly Func NegateDefault = (Func)typeof(Predicate).GetMethod("negate", BindingFlags.Static | BindingFlags.Public)!.CreateDelegate(typeof(Func)); private static readonly Func OrDefault = (Func)typeof(Predicate).GetMethod("or", BindingFlags.Static | BindingFlags.Public)!.CreateDelegate(typeof(Func)); public static Runnable ToRunnable(this Action action) => new DelegateRunnable(action); public static Consumer ToConsumer(this Action action) => new DelegateConsumer(action); public static Supplier ToSupplier(this Func func) where T : notnull => new DelegateSupplier(func); public static Predicate ToPredicate(this Predicate predicate) => new DelegatePredicate(predicate); public static Callable ToCallable(this Func func) => new DelegateSupplier(func); private sealed class DelegatePredicate(Predicate predicate) : Predicate { public bool test(object t) => predicate((T)t); public Predicate and(Predicate other) => AndDefault(this, other); public Predicate negate() => NegateDefault(this); public Predicate or(Predicate other) => OrDefault(this, other); } private sealed class DelegateSupplier(Func func) : Supplier, Callable where T : notnull { public object get() => func(); public object call() => func(); } private sealed class DelegateConsumer(Action action) : Consumer { public void accept(object t) { action((T)t); } public Consumer andThen(Consumer after) => AndThenDefault(this, after); } // ReSharper disable once InconsistentNaming // lets make it an overload for convenience public static void execute(this Executor executor, Action action) => executor.execute(action.ToRunnable()); public static EventSubscription subscribe(this EventBus bus, object plugin, Action action) where TEvent : class, LuckPermsEvent => bus.subscribe(plugin, typeof(TEvent), action.ToConsumer()); public static EventSubscription subscribe(this EventBus bus, Action action) where TEvent : class, LuckPermsEvent => bus.subscribe(typeof(TEvent), action.ToConsumer()); private sealed class DelegateRunnable(Action action) : Runnable { public void run() => action(); } }