VoltMod
C++23 framework for CS2 server plugins
Loading...
Searching...
No Matches
Result.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <expected>
5#include <string>
6#include <utility>
7
8// std::expected is the whole point of this header; a toolchain without it would silently fall
9// back to nothing usable, so fail at the include instead.
10static_assert(__cpp_lib_expected >= 202202L, "VoltMod requires std::expected (C++23, P0323R12).");
11
12namespace VoltMod
13{
14
15/**
16 * @brief Why an operation did not produce a value.
17 *
18 * Coarse on purpose: the code is what a caller branches on, @ref Error::Detail is what a log line
19 * says. Adding a code is an API change for every switch over it, so prefer a better Detail.
20 */
21enum class ErrorCode : uint8_t
22{
23 NotFound, ///< The named thing does not exist (no such player, convar, row).
24 NotReady, ///< It exists but the subsystem behind it is not usable yet.
25 Invalid, ///< The caller's input does not parse or does not satisfy a precondition.
26 Denied, ///< The caller lacks the permission the operation requires.
27 Immune, ///< The target outranks the caller; a Denied that names the target, not the verb.
28 Unsupported, ///< The build, the game version, or the gamedata does not offer this at all.
29 Engine, ///< The engine or SDK refused, returned nothing, or is not where it was expected.
30 Failed ///< Anything else; the default so a value-initialized Error is never a false success.
31};
32
33/**
34 * @brief One failure: a code to branch on, text for the log, and an optional translation key.
35 *
36 * @ref Detail is operator-facing and never translated - it names offsets, convars, and SQL state.
37 * @ref Key is the translation key a player-facing reply uses; it is empty whenever the failure has
38 * nothing sensible to say to a player. A handler that replies looks at Key, logs Detail, and does
39 * not invent one from the other.
40 */
41struct Error
42{
44 std::string Detail;
45 std::string Key;
46 /** A line already localized for whoever ran the command; shown in place of @ref Key. */
47 std::string Text;
48
49 static Error NotFound(std::string detail) { return {ErrorCode::NotFound, std::move(detail), {}}; }
50 static Error NotReady(std::string detail) { return {ErrorCode::NotReady, std::move(detail), {}}; }
51 static Error Invalid(std::string detail) { return {ErrorCode::Invalid, std::move(detail), {}}; }
52
53 /** @p key is a translation key: these two are the failures a player is told about. */
54 static Error Denied(std::string key) { return {ErrorCode::Denied, "permission denied", std::move(key)}; }
55 static Error Immune(std::string key) { return {ErrorCode::Immune, "target is immune", std::move(key)}; }
56
57 static Error Unsupported(std::string detail) { return {ErrorCode::Unsupported, std::move(detail), {}}; }
58 static Error Engine(std::string detail) { return {ErrorCode::Engine, std::move(detail), {}}; }
59 static Error Failed(std::string detail) { return {ErrorCode::Failed, std::move(detail), {}}; }
60};
61
62/** A @p T or an @ref Error. Check with `if (result)`, read `*result` / `result.error()`. */
63template <class T>
64using Result = std::expected<T, Error>;
65
66/** A @ref Result with nothing to return. `return {};` succeeds. */
67using Status = std::expected<void, Error>;
68
69} // namespace VoltMod
ErrorCode
Why an operation did not produce a value.
Definition Result.hpp:22
@ NotFound
The named thing does not exist (no such player, convar, row).
@ Invalid
The caller's input does not parse or does not satisfy a precondition.
@ Denied
The caller lacks the permission the operation requires.
@ Engine
The engine or SDK refused, returned nothing, or is not where it was expected.
@ Immune
The target outranks the caller; a Denied that names the target, not the verb.
@ Unsupported
The build, the game version, or the gamedata does not offer this at all.
@ Failed
Anything else; the default so a value-initialized Error is never a false success.
@ NotReady
It exists but the subsystem behind it is not usable yet.
static std::string ReadFile(const std::filesystem::path &path)
Definition Loader.cpp:56
std::expected< void, Error > Status
Definition Result.hpp:67
std::expected< T, Error > Result
Definition Result.hpp:64
One failure: a code to branch on, text for the log, and an optional translation key.
Definition Result.hpp:42
std::string Detail
Definition Result.hpp:44
static Error Failed(std::string detail)
Definition Result.hpp:59
static Error Denied(std::string key)
Definition Result.hpp:54
static Error Invalid(std::string detail)
Definition Result.hpp:51
static Error Immune(std::string key)
Definition Result.hpp:55
static Error Engine(std::string detail)
Definition Result.hpp:58
static Error Unsupported(std::string detail)
Definition Result.hpp:57
std::string Key
Definition Result.hpp:45
static Error NotFound(std::string detail)
Definition Result.hpp:49
static Error NotReady(std::string detail)
Definition Result.hpp:50
std::string Text
Definition Result.hpp:47
ErrorCode Code
Definition Result.hpp:43