原文
module arsd.exception;
interface ThrowableBase {
void fly(string file = __FILE__, size_t line = __LINE__);
void printMembers(scope void delegate(in char[]) sink) const;
void getHumanReadableMessage(scope void delegate(in char[]) sink) const;
void printName(scope void delegate(in char[]) sink) const;
void toString(scope void delegate(in char[]) sink) const;
}
mixin template ThrowableBaseImplementation() {
void fly(string file = __FILE__, size_t line = __LINE__) {
this.file = file;
this.line = line;
throw this;
}
void getHumanReadableMessage(scope void delegate(in char[]) sink) const {
sink(msg);
}
void printMembers(scope void delegate(in char[]) sink) const {
}
void printName(scope void delegate(in char[]) sink) const {
sink(typeid(this).name);
}
override void toString(scope void delegate(in char[]) sink) const {
char[32] tmpBuff = void;
printName(sink);
sink("@"); sink(file);
sink("("); sink(line.sizeToTempString(tmpBuff[])); sink(")");
sink(": "); getHumanReadableMessage(sink);
sink("\n");
printMembers(sink);
if (info) {
try {
sink("----------------");
foreach (t; info) {
sink("\n"); sink(t);
}
}
catch (Throwable) {
}
}
}
}
class ExceptionBase : Exception, ThrowableBase {
this() {
super("");
}
mixin ThrowableBaseImplementation;
}
class ErrorBase : Error, ThrowableBase {
this() { super(""); }
mixin ThrowableBaseImplementation;
}
mixin template PrintMembers() {
override void printMembers(scope void delegate(in char[]) sink) const {
foreach(memberName; __traits(derivedMembers, typeof(this))) {
static if(is(typeof(__traits(getMember, this, memberName))) && !is(typeof(__traits(getMember, typeof(this), memberName)) == function)) {
sink("\t");
sink(memberName);
sink(" = ");
static if(is(typeof(__traits(getMember, this, memberName)) : const(char)[]))
sink(__traits(getMember, this, memberName));
else static if(is(typeof(__traits(getMember, this, memberName)) : long)) {
char[32] tmpBuff = void;
sink(sizeToTempString(__traits(getMember, this, memberName), tmpBuff));
}
sink("\n");
}
}
super.printMembers(sink);
}
}
mixin template StaticHumanReadableMessage(string s) {
override void getHumanReadableMessage(scope void delegate(in char[]) sink) const {
sink(s);
}
}
interface DynamicException {
}
template enforceBase(ExceptionBaseClass, string failureCondition = "ret is null") {
auto enforceBase(alias func, string file = __FILE__, size_t line = __LINE__, T...)(T args) {
auto ret = func(args);
if(mixin(failureCondition)) {
class C : ExceptionBaseClass, DynamicException {
T args;
this(T args) {
this.args = args;
}
override void printMembers(scope void delegate(in char[]) sink) const {
import std.traits;
import std.conv;
foreach(idx, arg; args) {
sink("\t");
sink(ParameterIdentifierTuple!func[idx]);
sink(" = ");
sink(to!string(arg));
sink("\n");
}
sink("\treturn value = ");
sink(to!string(ret));
sink("\n");
}
override void printName(scope void delegate(in char[]) sink) const {
sink(__traits(identifier, ExceptionBaseClass));
}
override void getHumanReadableMessage(scope void delegate(in char[]) sink) const {
sink(__traits(identifier, func));
sink(" call failed");
}
}
auto exception = new C(args);
exception.file = file;
exception.line = line;
throw exception;
}
return ret;
}
}
void raise(ExceptionBaseClass, T...)(string file = __FILE__, size_t line = __LINE__) {
class C : ExceptionBaseClass, DynamicException {
override void printMembers(scope void delegate(in char[]) sink) const {
import std.conv;
foreach(idx, arg; T) {
sink("\t");
sink(__traits(identifier, T[idx]));
sink(" = ");
sink(to!string(arg));
sink("\n");
}
}
override void printName(scope void delegate(in char[]) sink) const {
sink(__traits(identifier, ExceptionBaseClass));
}
}
auto exception = new C();
exception.file = file;
exception.line = line;
throw exception;
}
const(char)[] sizeToTempString(long size, char[] buffer) {
size_t pos = buffer.length - 1;
bool negative = size < 0;
if(size < 0)
size = -size;
while(size) {
buffer[pos] = size % 10 + '0';
size /= 10;
pos--;
}
if(negative) {
buffer[pos] = '-';
pos--;
}
return buffer[pos + 1 .. $];
}
class MyRangeError : ErrorBase {
mixin StaticHumanReadableMessage!"越界";
}
class TypedRangeError(T) : MyRangeError {
this(T index) {
this.index = index;
}
mixin StaticHumanReadableMessage!(T.stringof ~ " index out of bounds");
T index;
mixin PrintMembers;
}
version(exception_2_example) {
void stackExample(ThrowableBase exception) {
exception.fly();
}
void main() {
int a = 230;
string file = "lol";
static class BadValues : ExceptionBase {}
alias enforce = enforceBase!ExceptionBase;
import core.stdc.stdio;
auto fp = enforce!fopen("nofile.txt".ptr, "rb".ptr);
auto exception = new TypedRangeError!int(4);
stackExample(exception);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现