FlatImage
A configurable Linux containerization system
Loading...
Searching...
No Matches
expected.hpp
Go to the documentation of this file.
1
18
19#pragma once
20
21#include <expected>
22#include <string>
23#include <array>
24#include <type_traits>
25
26#include "string.hpp"
27#include "../lib/log.hpp"
28
42template<typename T, typename E = std::string>
43struct Value : std::expected<T, E>
44{
45 using std::expected<T, E>::expected;
46
47private:
53 constexpr static std::array<const char[6], 5> const m_prefix{"D::{}", "I::{}", "W::{}", "E::{}", "C::{}"};
54
61 template<ns_string::static_string fmt>
62 constexpr static int select_prefix()
63 {
64 constexpr std::string_view sv{fmt.data};
65 return sv.starts_with("D")? 0
66 : sv.starts_with("I")? 1
67 : sv.starts_with("W")? 2
68 : sv.starts_with("E")? 3
69 : 4;
70 }
71
72public:
86 template<ns_string::static_string fmt = "Q::", typename... Args>
87 void discard_impl(ns_log::Location const& loc, Args&&... args)
88 {
89 if (not this->has_value())
90 {
91 logger_loc(loc, m_prefix[select_prefix<fmt>()], this->error());
92 logger_loc(loc, fmt.data, std::forward<Args>(args)...);
93 }
94 }
95
110 template<ns_string::static_string fmt = "Q::", typename... Args>
111 Value<T,E> forward_impl(ns_log::Location const& loc, Args&&... args)
112 {
113 if (not this->has_value())
114 {
115 logger_loc(loc, m_prefix[select_prefix<fmt>()], this->error());
116 logger_loc(loc, fmt.data, std::forward<Args>(args)...);
117 return std::unexpected(this->error());
118 }
119 return Value<T,E>(std::move(this->value()));
120 }
121
134 T or_default() requires std::default_initializable<T>
135 {
136 if (!this->has_value()) {
137 return T{};
138 }
139 return std::move(**this);
140 }
141};
142
147constexpr auto __expected_fn = [](auto&& e) { return e; };
148
154#define NOPT(expr, ...) NOPT_IDENTITY(__VA_OPT__(NOPT_EAT) (expr))
155#define NOPT_IDENTITY(...) __VA_ARGS__
156#define NOPT_EAT(...)
158
184#define Pop(expr, ...) \
185({ \
186 auto __expected_ret = (expr); \
187 if (!__expected_ret) \
188 { \
189 std::string error = std::move(__expected_ret).error(); \
190 /* Log expected error at DEBUG level */ \
191 logger("D::{}", error); \
192 /* If a custom error was provided, log and propagate it instead */ \
193 __VA_OPT__( \
194 logger(__VA_ARGS__); \
195 error = [&](auto &&fmt, auto &&...args) \
196 { \
197 if constexpr (sizeof...(args) > 0) \
198 { \
199 return ns_log::vformat(std::string_view(fmt).substr(3), \
200 ns_string::to_string(args)...); \
201 } \
202 else \
203 { \
204 return std::string_view(fmt).substr(3); \
205 } \
206 }(__VA_ARGS__); \
207 ) \
208 return __expected_fn(std::unexpected(error)); \
209 } \
210 std::move(__expected_ret).value(); \
211})
212
224#define discard(fmt,...) discard_impl<fmt>(ns_log::Location() __VA_OPT__(,) __VA_ARGS__)
225
238#define forward(fmt,...) forward_impl<fmt>(ns_log::Location() __VA_OPT__(,) __VA_ARGS__)
239
240
253template<typename Fn>
256 and (not ns_concept::IsInstanceOf<std::invoke_result_t<Fn>, std::expected>)
257{
258 try
259 {
260 if constexpr (std::is_void_v<std::invoke_result_t<Fn>>)
261 {
262 f();
263 return {};
264 }
265 else
266 {
267 return f();
268 }
269 }
270 catch (std::exception const& e)
271 {
272 return std::unexpected(e.what());
273 }
274 catch (...)
275 {
276 return std::unexpected("Unknown exception was thrown");
277 }
278}
279
295#define Try(expr,...) Pop(__except_impl([&]{ return (expr); }), __VA_ARGS__)
296
311#define Catch(expr, ...) (__except_impl([&]{ return (expr); })__VA_OPT__(.template forward(__VA_ARGS__)))
312
313
335#define Error(fmt,...) \
336({ \
337 logger(fmt __VA_OPT__(,) __VA_ARGS__); \
338 [&](auto&&... __fmt_args) \
339 { \
340 if constexpr (sizeof...(__fmt_args) > 0) \
341 { \
342 return std::unexpected( \
343 std::format(std::string_view(fmt).substr(3) \
344 , ns_string::to_string(__fmt_args)...) \
345 ); \
346 } \
347 else \
348 { \
349 return std::unexpected( \
350 std::format(std::string_view(fmt).substr(3)) \
351 ); \
352 } \
353 }(__VA_ARGS__); \
354})
Concept to check if a type is an instance of a specific template.
Definition concept.hpp:72
constexpr auto __expected_fn
Lambda helper for Pop macro error returns.
Definition expected.hpp:147
auto __except_impl(Fn &&f) -> Value< std::invoke_result_t< Fn > >
Convert exceptions to Value errors.
Definition expected.hpp:254
A library for file logging.
#define logger_loc(loc, fmt,...)
Compile-time log level dispatch macro with manual location specification.
Definition log.hpp:727
String helpers.
Enhanced expected type with integrated logging capabilities.
Definition expected.hpp:44
void discard_impl(ns_log::Location const &loc, Args &&... args)
Log error and discard it if present.
Definition expected.hpp:87
Value< T, E > forward_impl(ns_log::Location const &loc, Args &&... args)
Forward error with logging or return value.
Definition expected.hpp:111
Source code location information for log messages.
Definition log.hpp:403
Compile-time string container with fixed size.
Definition string.hpp:35