1 /** Exception base class inspired by Adam Ruppe's exception.d 2 3 Error messages include the names and values of relevant data, but no 4 further introspection capabilities. 5 */ 6 module jsonrpc.exception; @safe: 7 8 // I cannot define an exception within the unittest scope for testing/examples. 9 /// 10 unittest { 11 /* Where InvalidArgumment is defined as: 12 class InvalidArgument : Exception { 13 this() { super(""); } 14 } 15 */ 16 17 void func(bool one, bool two) { 18 if (one == two) { 19 raise!(InvalidArgument, one, two)("The values shouldn't match!"); 20 } 21 } 22 func(false, true); 23 } 24 25 /** Raised when invalid data is passed as an argument to a function. */ 26 class InvalidArgument : Exception { 27 this() { super(""); } 28 } 29 30 /** Raised when invalid data is received by the client or server. */ 31 class InvalidDataReceived : Exception { 32 this() { super(""); } 33 } 34 35 /** Raised when there's a network connection error. */ 36 class ConnectionException : Exception { 37 this() { super(""); } 38 } 39 40 /** Raised when a function call via RPCClient.opDispatch receives an error 41 response. 42 */ 43 class RPCErrorResponse : Exception { 44 this() { super(""); } 45 } 46 47 /** Raised when attempting to access a JSONValue via a different type than the 48 underlying type. 49 */ 50 class IncorrectType : Exception { 51 this() { super(""); } 52 } 53 54 package: 55 56 /** Generate and throw an exception. 57 58 Additional data can be provided, both for inspection by catching code and 59 for viewing/logging if unhandled. 60 61 Template_Parameters: 62 ExceptionClass = The exception class to throw. 63 T... = A list of objects to include as part of the exception. 64 65 Params: 66 msg = An optional message concerning the exception. 67 file = The file in which the exception was raised. 68 line = The line number at which the exception was raised. 69 */ 70 void raise(ExceptionClass, T...)( 71 string msg = "", 72 string file = __FILE__, 73 size_t line = __LINE__) { 74 75 class Except : ExceptionClass { 76 this(string message, string file, size_t line) { 77 super.file = file; 78 super.line = line; 79 msg ~= message ~ "\n Data:"; 80 foreach (i, obj; T) { 81 import std.string : format; 82 msg ~= "\n\t%s: %s".format(__traits(identifier, T[i]), obj); 83 } 84 } 85 } 86 throw new Except(msg, file, line); 87 } 88 89 /** Raise the specified exception of the provided expression evaluates to false. 90 91 Behavior is similar to $(D_INLINECODE assert() ) but throws an exception on 92 failure. 93 94 Example: 95 --- 96 enforce!(OutOfRange, myvar)(myvar > 0, "myvar must be greater than 0"); 97 --- 98 */ 99 auto enforce(ExceptionClass, T...)( 100 bool val, 101 string msg = "", 102 string file = __FILE__, 103 size_t line = __LINE__) { 104 if (!val) raise!(ExceptionClass, T)(msg, file, line); 105 return val; 106 }