wren
Vulkan-based game engine
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <fmt/core.h>
4#include <fmt/format.h>
5#include <fmt/ostream.h>
6
7#include <boost/describe.hpp>
8#include <boost/preprocessor.hpp>
9#include <expected>
10#include <optional>
11#include <system_error>
12
13#include "enums.hpp" // IWYU pragma: export
14#include "macros.hpp"
15
16namespace wren {
17
18class Err {
19 public:
20 template <typename T>
21 requires std::is_error_code_enum_v<T>
22 Err(T error) : error_code_(make_error_code(error)) {}
23 Err(const std::error_code& ec) : error_code_(ec) {}
24 Err(int32_t ec, const std::error_category& e_cat) : error_code_(ec, e_cat) {}
25
26 [[nodiscard]] auto error() const { return error_code_; }
27
28 [[nodiscard]] auto message() const { return error_code_.message(); }
29
30 [[nodiscard]] auto extra_msg() const { return extra_message_; }
31
32 private:
33 std::error_code error_code_;
34 std::optional<std::string> extra_message_;
35};
36
37// struct error_code : public std::error_code {
38// error_code(int32_t ec, std::error_category const& cat)
39// : ::error_code(ec, cat) {}
40
41// error_code(std::error_code ec) : std::error_code(ec) {}
42
43// friend auto operator<<(std::ostream& os, error_code const& ec)
44// -> std::ostream& {
45// return os << ec.category().name() << " : " << ec.message();
46// }
47// };
48
49template <typename T>
50using expected = std::expected<T, Err>;
51
52} // namespace wren
53
54template <>
55struct fmt::formatter<wren::Err> : fmt::formatter<std::string> {
56 auto format(wren::Err, fmt::format_context& ctx) const -> decltype(ctx.out());
57};
58
61#define DEFINE_ERROR_IMPL(CAT_NAME, ERROR_ENUM) \
62 class ERROR_ENUM##_category_t : public std::error_category { \
63 public: \
64 [[nodiscard]] auto name() const noexcept -> const char* final { \
65 return CAT_NAME; \
66 } \
67 [[nodiscard]] auto message(int32_t c) const -> std::string final { \
68 auto e = static_cast<ERROR_ENUM>(c); \
69 using namespace boost::describe; \
70 return std::string{wren::utils::enum_to_string(e)}; \
71 } \
72 }; \
73 inline auto ERROR_ENUM##_category()->const ERROR_ENUM##_category_t& { \
74 static const ERROR_ENUM##_category_t kC; \
75 return kC; \
76 } \
77 inline auto make_error_code(ERROR_ENUM ec) noexcept -> std::error_code { \
78 return {static_cast<int32_t>(ec), ERROR_ENUM##_category()}; \
79 }
80
81/* @brief This macro defines an enum with BOOST_DEFINE_ENUM_CLASS and
82 * hooks into the std::error_code system The NAMSPACE arg can be
83 * skipped if the enum is in the global namespace.
84 * @param cat_name The name to use for the Error's category, should
85 * be something similar to the current namespace
86 * @param name the error enum name
87 * @param ... The enum variants to define
88 */
89#define DEFINE_ERROR(cat_name, name, ...) \
90 BOOST_DEFINE_ENUM_CLASS(name, __VA_ARGS__); \
91 DEFINE_ERROR_IMPL(cat_name, name)
92
93#define RESULT_UNIQUE_NAME() BOOST_PP_CAT(__result_tmp, __COUNTER__)
94
95#define TRY_RESULT_IMPL(unique, expr) \
96 auto unique = (expr); \
97 if (!(unique).has_value()) return std::unexpected(unique.error());
98
99#define TRY_RESULT_1(unique, expr) TRY_RESULT_IMPL(unique, expr)
100#define TRY_RESULT_2(unique, out, expr) \
101 TRY_RESULT_IMPL(unique, expr) \
102 out = (unique).value();
103
104#define TRY_RESULT(...) \
105 BOOST_PP_OVERLOAD(TRY_RESULT_, __VA_ARGS__) \
106 (RESULT_UNIQUE_NAME(), __VA_ARGS__)
107
108#define TRY_RESULT_VOID_IMPL(unique, expr) \
109 auto unique = (expr); \
110 if (!(unique).has_value()) return;
111
112#define TRY_RESULT_VOID_1(unique, expr) TRY_RESULT_VOID_IMPL(unique, expr)
113#define TRY_RESULT_VOID_2(unique, out, expr) \
114 TRY_RESULT_VOID_IMPL(unique, expr) \
115 out = (unique).value();
116#define TRY_RESULT_VOID(...) \
117 BOOST_PP_OVERLOAD(TRY_RESULT_VOID_, __VA_ARGS__) \
118 (RESULT_UNIQUE_NAME(), __VA_ARGS__)
119
129// NOLINTNEXTLINE
130#define ERR_VAL_OR(out, err, on_err) \
131 const auto LINEIZE(res, __LINE__) = err; \
132 if (!LINEIZE(res, __LINE__).has_value()) { \
133 on_err \
134 } \
135 out = LINEIZE(res, __LINE__).value();
136
143// NOLINTNEXTLINE
144#define ERR_VOID_OR(err, on_err) \
145 const auto LINEIZE(res, __LINE__) = err; \
146 if (!LINEIZE(res, __LINE__).has_value()) { \
147 on_err \
148 }
Definition result.hpp:18
Err(T error)
Definition result.hpp:22
Err(const std::error_code &ec)
Definition result.hpp:23
auto extra_msg() const
Definition result.hpp:30
auto error() const
Definition result.hpp:26
auto message() const
Definition result.hpp:28
std::error_code error_code_
Definition result.hpp:33
Err(int32_t ec, const std::error_category &e_cat)
Definition result.hpp:24
std::optional< std::string > extra_message_
Definition result.hpp:34
Definition editor_scene.hpp:5
std::expected< T, Err > expected
Definition result.hpp:50