LeviLamina
Loading...
Searching...
No Matches
Expected.h
1#pragma once
2
3#include <concepts>
4#include <memory>
5#include <string_view>
6
7#include "ll/api/base/Macro.h"
8#include "ll/api/io/LogLevel.h"
9
10#include "mc/server/commands/CommandOutputMessageType.h"
11
12class CommandOutput;
13
14namespace ll {
15class Error;
16
17template <class T = void>
18using Expected = ::nonstd::expected<T, ::ll::Error>;
19
20using Unexpected = ::nonstd::unexpected_type<::ll::Error>;
21
22class ErrorInfoBase {
23 friend Error;
24 struct Impl;
25 std::unique_ptr<Impl> impl;
26
27public:
28 LLAPI ErrorInfoBase() noexcept;
29 LLAPI virtual ~ErrorInfoBase();
30
31 virtual std::string message() const noexcept { return message({}); }
32 virtual std::string message(std::string_view locale) const noexcept = 0;
33};
34class Error {
35 mutable std::unique_ptr<ErrorInfoBase> mInfo;
36
37public:
38 Error& operator=(Error&&) noexcept = default;
39 Error& operator=(Error const&) noexcept = delete;
40 [[nodiscard]] Error(Error&&) noexcept = default;
41 [[nodiscard]] Error(Error const&) noexcept = delete;
42
43 LL_CONSTEXPR23 Error() noexcept = default;
44 LL_CONSTEXPR23 ~Error() noexcept = default;
45
46 LL_CONSTEXPR23 Error(std::unique_ptr<ErrorInfoBase> i) noexcept : mInfo(std::move(i)) {}
47
48 LL_CONSTEXPR23 Error(::nonstd::unexpected_type<::ll::Error> i) noexcept : Error(std::move(i.error())) {}
49
50 LL_CONSTEXPR23 operator bool() const noexcept { return mInfo != nullptr; }
51
52 LL_CONSTEXPR23 operator Unexpected() noexcept {
53 return ::nonstd::make_unexpected<Error>(std::in_place, std::move(mInfo));
54 }
55
56 LLNDAPI std::string message() const noexcept;
57
58 LLNDAPI std::string message(std::string_view locale) const noexcept;
59
60 template <class T>
61 LL_CONSTEXPR23 bool isA() noexcept {
62 return mInfo ? typeid(T) == typeid(*mInfo) : false;
63 }
64 template <class T>
65 LL_CONSTEXPR23 T& as() noexcept {
66 return *static_cast<T*>(mInfo.get());
67 }
68 LLAPI Error& join(Error) noexcept;
69
70 Error& join(Unexpected err) noexcept { return join(std::move(err.error())); }
71
72 LLAPI Error const& log(io::Logger&, io::LogLevel = io::LogLevel::Error) const noexcept;
73
74 LLAPI Error const& log(io::Logger&, std::string_view locale, io::LogLevel = io::LogLevel::Error) const noexcept;
75
76 LLAPI Error const& log(CommandOutput&, CommandOutputMessageType = CommandOutputMessageType::Error) const noexcept;
77
78 LLAPI Error const&
79 log(CommandOutput&,
80 std::string_view locale,
81 CommandOutputMessageType = CommandOutputMessageType::Error) const noexcept;
82
83 LLAPI Error const&
84 log(brstd::function_ref<void(std::string_view msg)> out, std::string_view locale = {}) const noexcept;
85};
86
87struct StringError : ErrorInfoBase {
88 std::string str;
89 StringError(std::string str) : str(std::move(str)) {}
90 std::string message(std::string_view) const noexcept override { return str; }
91};
92struct ErrorCodeError : ErrorInfoBase {
93 std::error_code ec;
94 ErrorCodeError(std::error_code ec) : ec(ec) {}
95 std::string message(std::string_view) const noexcept override { return ec.message(); }
96};
97[[nodiscard]] inline Unexpected forwardError(::ll::Error& err) noexcept {
98 return ::nonstd::make_unexpected(std::move(err));
99}
100
101[[nodiscard]] inline Unexpected makeSuccessed() noexcept { return ::nonstd::make_unexpected(Error{}); }
102
103template <std::derived_from<::ll::ErrorInfoBase> T, class... Args>
104[[nodiscard]] LL_CONSTEXPR23 inline Unexpected makeError(Args&&... args) noexcept {
105 return ::nonstd::make_unexpected<Error>(std::in_place, std::make_unique<T>(std::forward<Args>(args)...));
106}
107[[nodiscard]] inline Unexpected makeStringError(std::string str) noexcept {
108 return makeError<StringError>(std::move(str));
109}
110
111[[nodiscard]] inline Unexpected makeErrorCodeError(std::error_code ec) noexcept {
112 return makeError<ErrorCodeError>(ec);
113}
114
115[[nodiscard]] inline Unexpected makeErrorCodeError(std::errc ec) noexcept {
116 return makeError<ErrorCodeError>(make_error_code(ec));
117}
118
119LLNDAPI Unexpected makeExceptionError(std::exception_ptr const& exc = std::current_exception()) noexcept;
120
121} // namespace ll
122
123namespace nonstd::expected_lite {
124template <>
125class bad_expected_access<::ll::Error> : public bad_expected_access<void> {
126 std::shared_ptr<::ll::Error> mError;
127 std::string mMessage;
128
129public:
130 explicit bad_expected_access(::ll::Error& e) noexcept
131 : mError(::std::make_shared<::ll::Error>(::std::move(e))),
132 mMessage(mError->message()) {}
133
134 char const* what() const noexcept override { return mMessage.c_str(); }
135
136 ::ll::Error& error() & { return *mError; }
137
138 ::ll::Error const& error() const& { return *mError; }
139
140 ::ll::Error&& error() && { return ::std::move(*mError); }
141
142 ::ll::Error const&& error() const&& { return ::std::move(*mError); }
143};
144template <>
145struct error_traits<::ll::Error> {
146 static void rethrow(::ll::Error const& e) { throw bad_expected_access<::ll::Error>{const_cast<::ll::Error&>(e)}; }
147};
148} // namespace nonstd::expected_lite
Definition CommandOutput.h:20
Definition function_ref.h:60
Definition Expected.h:34
Definition Logger.h:29