From 9f36aa09737090540b50e3b6896be077a850f094 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Mon, 5 Jan 2026 01:00:53 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20=D1=81?= =?UTF-8?q?=D0=BE=20=D0=B2=D1=81=D0=BF=D0=BE=D0=BC=D0=BE=D0=B3=D0=B0=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC=D0=B8=20=D1=84=D1=83=D0=BD?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D1=8F=D0=BC=D0=B8-=D0=BF=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=BA=D0=B0=D0=BC=D0=B8=20=D0=B1=D1=8B=D0=BB=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=20=D0=B8=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/ncui/lib/checks.d | 124 +++++++++++++++++++++++++++++++++++++++ source/ncui/lib/common.d | 89 ---------------------------- 2 files changed, 124 insertions(+), 89 deletions(-) create mode 100644 source/ncui/lib/checks.d delete mode 100644 source/ncui/lib/common.d diff --git a/source/ncui/lib/checks.d b/source/ncui/lib/checks.d new file mode 100644 index 0000000..dd94588 --- /dev/null +++ b/source/ncui/lib/checks.d @@ -0,0 +1,124 @@ +module ncui.lib.checks; + +import std.traits : isCallable, isPointer; +import std.exception : enforce; +import std.format : format; + +import deimos.ncurses : ERR; + +/** + * Возвращает имя функции `fn` для сообщений об ошибках. + */ +private string _fnName(alias fn)() +{ + return __traits(identifier, fn); +} + +/** + * Вызывает `fn(args)` и строго проверяет, что результат равен `expected`. + * + * - Тип `expected` обязан совпадать с типом результата `fn`. + * - При несоответствии бросает исключение с местом вызова. + */ +auto ncuiExpect(alias fn, Expected, Args...)( + Expected expected, + Args args, + string file = __FILE__, + size_t line = __LINE__, + string module_ = __MODULE__, + string function_ = __FUNCTION__ +) if (isCallable!fn && __traits(compiles, fn(args))) +{ + auto result = fn(args); + + static assert(is(typeof(result) == Expected), + format("ncuiExpect: expected type must match the result type %s().", _fnName!fn)); + + enforce(result == expected, format( + "Unexpected return value: %s() returned=%s expected=%s [%s:%s | %s | %s]", + _fnName!fn, result, expected, file, line, module_, function_ + )); + + return result; +} + +/** + * Вызывает `fn(args)` и строго проверяет, что результат равен `expected`. + * + * - Тип `expected` обязан совпадать с типом результата `fn`. + * - При несоответствии бросает исключение с пользовательским сообщением и местом вызова. + */ +auto ncuiExpectMsg(alias fn, Expected, Args...)( + string message, + Expected expected, + Args args, + string file = __FILE__, + size_t line = __LINE__, + string module_ = __MODULE__, + string function_ = __FUNCTION__ +) if (isCallable!fn && __traits(compiles, fn(args))) +{ + auto result = fn(args); + + static assert(is(typeof(result) == Expected), + format("ncuiExpect: expected type must match the result type %s().", _fnName!fn)); + + enforce(result == expected, format( + "%s: %s() returned=%s expected=%s [%s:%s | %s | %s]", + message, _fnName!fn, result, expected, file, line, module_, function_ + )); + + return result; +} + +/** + * Вызывает `fn(args)` и проверяет, что результат не равен `ERR`. + * + * Требует, чтобы `fn` возвращала тот же тип, что и `ERR`. + * При `ERR` бросает исключение с местом вызова. + */ +int ncuiNotErr(alias fn, Args...)( + Args args, + string file = __FILE__, + size_t line = __LINE__, + string module_ = __MODULE__, + string function_ = __FUNCTION__ +) if (isCallable!fn && __traits(compiles, fn(args))) +{ + auto result = fn(args); + + static assert(is(typeof(result) == typeof(ERR)), + format("ncuiNotErr expects a function that returns an %s.", typeof(ERR))); + + enforce(result != ERR, format( + "Function returned ERR: %s() [%s:%s | %s | %s]", + _fnName!fn, file, line, module_, function_ + )); + + return result; +} + +/** + * Вызывает `fn(args)` и проверяет, что результат (указатель) не `null`. + * + * При `null` бросает исключение с местом вызова. + */ +auto ncuiNotNull(alias fn, Args...)( + Args args, + string file = __FILE__, + size_t line = __LINE__, + string module_ = __MODULE__, + string function_ = __FUNCTION__ +) if (isCallable!fn && __traits(compiles, fn(args))) +{ + auto result = fn(args); + + static assert(isPointer!(typeof(result)), + "ncuiNotNull expects a function that returns a pointer."); + + enforce(result !is null, format( + "Function returned null: %s() [%s:%s | %s | %s]", + _fnName!fn, file, line, module_, function_ + )); + return result; +} diff --git a/source/ncui/lib/common.d b/source/ncui/lib/common.d deleted file mode 100644 index 38b8817..0000000 --- a/source/ncui/lib/common.d +++ /dev/null @@ -1,89 +0,0 @@ -module ncui.lib.common; - -import std.traits : isCallable; -import std.exception : enforce; -import std.format : format; - -import deimos.ncurses : OK; - -/** - * Вызывает функцию `fn`, проверяет её результат на равенство ожидаемому значению - * и при несоответствии бросает исключение с подробным сообщением и местом вызова. - * - * Параметры шаблона: - * - `fn` — вызываемая функция. - * - `Expected` — тип ожидаемого значения `answer`. - * - `Args...` — типы аргументов, которые будут переданы в `fn`. - * - * Параметры: - * - `answer` — ожидаемое значение результата функции `fn`. - * - `message` — пользовательское сообщение (контекст ошибки) (по умолчанию подставляется "Function call error"). - * - `file` — файл места вызова (по умолчанию подставляется `__FILE__`). - * - `line` — строка места вызова (по умолчанию подставляется `__LINE__`). - * - `module_` — модуль места вызова (по умолчанию подставляется `__MODULE__`). - * - `function_` — функция места вызова (по умолчанию подставляется `__FUNCTION__`). - * - `args` — аргументы, которые будут переданы в `fn`. - * - * Возвращает: - * Возвращает фактический результат вызова `fn(args)` (тот же тип, что и у `fn`). - * - * Исключения: - * Бросает `Exception`, если `fn(args)` вернул значение, отличающееся от `answer`. - */ -auto ncuiCall(alias fn, Expected, Args...)( - Expected answer, - string message = "Function returned an error", - string file = __FILE__, - size_t line = __LINE__, - string module_ = __MODULE__, - string function_ = __FUNCTION__, - Args args) if (isCallable!fn) -{ - auto result = fn(args); - - enforce(result == answer, new Exception( - format("%s: %s() returned=%s expected=%s [%s:%s | %s | %s]", - message, __traits(identifier, fn), result, answer, file, line, module_, function_) - )); - - return result; -} - -/** - * Вызывает функцию `fn`, которая должна вернуть ненулевой указатель, и проверяет, - * что результат не `null`. - * - * Параметры шаблона: - * - `fn` — вызываемая функция (передаётся как `alias`, определяется на этапе компиляции). - * - `Args...` — типы аргументов, которые будут переданы в `fn`. - * - * Параметры: - * - `file` — файл места вызова (по умолчанию подставляется `__FILE__`). - * - `line` — строка места вызова (по умолчанию подставляется `__LINE__`). - * - `module_` — модуль места вызова (по умолчанию подставляется `__MODULE__`). - * - `function_` — функция места вызова (по умолчанию подставляется `__FUNCTION__`). - * - `args` — аргументы, передаваемые в `fn`. - * - * Возвращает: - * Возвращает результат `fn(args)` (ожидается указатель), если он не `null`. - * - * Исключения: - * Бросает `Exception`, если `fn(args)` вернул `null`. - */ -auto ncuiNotNull(alias fn, Args...)( - string file = __FILE__, - size_t line = __LINE__, - string module_ = __MODULE__, - string function_ = __FUNCTION__, - Args args -) if (isCallable!fn) -{ - auto result = fn(args); - - enforce(result !is null, new Exception( - format("%s() returned null [%s:%s | %s | %s]", - __traits(identifier, fn), file, line, module_, function_) - )); - - return result; -}