1 /** 2 Essential tools for nothrow. 3 4 Copyright: 5 Copyright © 2023-2025, Kitsunebi Games 6 Copyright © 2023-2025, Inochi2D Project 7 8 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 Authors: Luna Nielsen 10 */ 11 module numem.core.exception; 12 import numem.core.memory; 13 import numem.core.hooks; 14 import numem.core.traits; 15 import numem.lifetime : nogc_delete, nogc_new; 16 17 /** 18 Assumes that a given function or delegate does not throw. 19 20 Params: 21 expr = The expression to execute. 22 args = Arguments to pass to the function. 23 */ 24 auto assumeNoThrow(T, Args...)(T expr, auto ref Args args) @nogc nothrow if (isSomeFunction!T) { 25 try { 26 return expr(args); 27 } catch (Exception ex) { 28 nu_fatal(ex.msg); 29 assert(0); 30 } 31 } 32 33 /** 34 Assumes that a given function or delegate does not throw. 35 36 Params: 37 expr = The expression to execute. 38 args = Arguments to pass to the function. 39 */ 40 auto assumeNoThrowNoGC(T, Args...)(T expr, auto ref Args args) @nogc nothrow if (isSomeFunction!T) { 41 try { 42 return assumeNoGC(expr, args); 43 } catch (Exception ex) { 44 nu_fatal(ex.msg); 45 assert(0); 46 } 47 } 48 49 /** 50 Assumes that the provided function does not use 51 the D garbage collector. 52 53 Params: 54 expr = The expression to execute. 55 args = Arguments to pass to the function. 56 */ 57 auto assumeNoGC(T, Args...)(T expr, auto ref Args args) @nogc if (isSomeFunction!T) { 58 static if (is(T Fptr : Fptr*) && is(Fptr == function)) 59 alias ft = @nogc ReturnType!T function(Parameters!T); 60 else static if (is(T Fdlg == delegate)) 61 alias ft = @nogc ReturnType!T delegate(Parameters!T); 62 else 63 static assert(0); 64 65 return (cast(ft)expr)(args); 66 } 67 68 /** 69 Assumes that the provided function is pure. 70 71 Params: 72 expr = The expression to execute. 73 args = Arguments to pass to the function. 74 */ 75 auto assumePure(T, Args...)(T expr, auto ref Args args) pure if (isSomeFunction!T) { 76 static if (is(T Fptr : Fptr*) && is(Fptr == function)) 77 alias ft = pure ReturnType!T function(Parameters!T); 78 else static if (is(T Fdlg == delegate)) 79 alias ft = pure ReturnType!T delegate(Parameters!T); 80 else 81 static assert(0); 82 83 return (cast(ft)expr)(args); 84 } 85 86 /** 87 Assumes that the provided function is @nogc, nothrow and pure. 88 89 Params: 90 expr = The expression to execute. 91 args = Arguments to pass to the function. 92 */ 93 auto assumeNoThrowNoGCPure(T, Args...)(T expr, auto ref Args args) pure if (isSomeFunction!T) { 94 static if (is(T Fptr : Fptr*) && is(Fptr == function)) 95 alias ft = @nogc nothrow pure ReturnType!T function(Parameters!T); 96 else static if (is(T Fdlg == delegate)) 97 alias ft = @nogc nothrow pure ReturnType!T delegate(Parameters!T); 98 else 99 static assert(0); 100 101 return (cast(ft)expr)(args); 102 } 103 104 /** 105 An exception which can be thrown from numem 106 */ 107 class NuException : Exception { 108 public: 109 @nogc: 110 111 ~this() { 112 // Free message. 113 msg.nu_resize(0); 114 115 // Free next-in-chain 116 if (Throwable t = this.next()) { 117 nogc_delete(t); 118 } 119 } 120 121 /** 122 Constructs a nogc exception 123 */ 124 this(const(char)[] msg, Throwable nextInChain = null, string file = __FILE__, size_t line = __LINE__) { 125 super(cast(string)msg.nu_dup(), nextInChain, file, line); 126 } 127 128 /** 129 Helper that creates a new exception. 130 */ 131 static NuException create(const(char)[] msg, Throwable nextInChain = null, string file = __FILE__, size_t line = __LINE__) { 132 return nogc_new!NuException(msg, nextInChain, file, line); 133 } 134 135 /** 136 Returns the error message 137 */ 138 override 139 const(char)[] message() const @safe nothrow { 140 return this.msg; 141 } 142 143 /** 144 Helper function to free this exception 145 */ 146 void free() @trusted { 147 NuException ex = this; 148 nogc_delete(ex); 149 } 150 151 /** 152 Helper function to free this exception 153 */ 154 final 155 void freeNoThrow() @trusted nothrow { 156 assumeNoThrowNoGC((NuException self) { 157 nogc_delete(self); 158 }, this); 159 } 160 } 161 162 /** 163 Enforces the truthiness of $(D in_) 164 165 If it evaluates to false, throws a $(D NuException). 166 */ 167 void enforce(T)(T in_, const(char)[] err) @nogc @trusted { 168 if (!in_) { 169 throw nogc_new!NuException(err); 170 } 171 } 172 173 /** 174 Enforces the truthiness of $(D in_) 175 176 If it evaluates to false, throws a $(D NuException). 177 */ 178 void enforce(T)(T in_, NuException t) @nogc @trusted { 179 if (!in_) { 180 throw t; 181 } 182 }