pars 0.2.1.99
Loading...
Searching...
No Matches
err.h
Go to the documentation of this file.
1/*
2Copyright (c) 2025 Giuseppe Roberti.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without modification,
6are permitted provided that the following conditions are met:
7
81. Redistributions of source code must retain the above copyright notice, this
9list of conditions and the following disclaimer.
10
112. Redistributions in binary form must reproduce the above copyright notice,
12this list of conditions and the following disclaimer in the documentation and/or
13other materials provided with the distribution.
14
153. Neither the name of the copyright holder nor the names of its contributors
16may be used to endorse or promote products derived from this software without
17specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
30#pragma once
31
32#include <nng/nng.h>
33
34#include <expected>
35#include <functional>
36#include <stdexcept>
37#include <system_error>
38
39namespace clev
40{
41
42struct exception : std::runtime_error
43{
44 explicit exception(std::error_code code) noexcept
45 : std::runtime_error(code.message())
46 {
47 }
48};
49
50#if __cpp_exceptions < 199711
51constexpr static bool clev_exception_disabled_v = true;
52#else
53constexpr static bool clev_exception_disabled_v = false;
54#endif
55
56inline static void
57abort_now(const std::error_code err) noexcept(clev_exception_disabled_v)
58{
59 if constexpr (clev_exception_disabled_v)
60 std::quick_exit(err.value());
61 else
62 throw exception{err};
63}
64
65inline static void exit_now(const std::error_code err) noexcept
66{
67 std::quick_exit(err.value());
68}
69
70struct unexpected : std::unexpected<std::error_code>
71{
72private:
73 using parent = std::unexpected<std::error_code>;
74
75public:
76 using parent::parent;
77};
78
79template<typename value_t>
80struct expected;
81
82template<typename>
83struct is_expected_specialization : std::false_type
84{
85};
86
87template<template<typename> typename expected_t, typename value_t>
88struct is_expected_specialization<expected_t<value_t>>
89 : std::is_same<expected_t<value_t>, expected<value_t>>
90{
91};
92
93template<typename expected_t>
94inline constexpr bool is_expected_specialization_v =
96
97template<>
98struct expected<void> : public std::expected<void, std::error_code>
99{
100private:
101 using parent = std::expected<void, std::error_code>;
102
103public:
104 using parent::parent;
105
106 constexpr void or_abort() noexcept(clev_exception_disabled_v)
107 {
108 if (!*this)
109 abort_now(expected::error());
110 }
111
112 constexpr void or_exit() noexcept
113 {
114 if (!*this)
115 exit_now(expected::error());
116 }
117
118 template<typename to_value_t>
119 [[nodiscard]] auto transform_to(to_value_t&& v) && noexcept
120 {
121 if (*this)
122 return expected<to_value_t>(std::move(v));
123 else
124 return expected<to_value_t>(unexpected(std::move(parent::error())));
125 }
126};
127
128template<typename value_t>
129struct expected : public std::expected<value_t, std::error_code>
130{
131private:
132 using parent = std::expected<value_t, std::error_code>;
133
134 using value_type = parent::value_type;
135
136 using error_type = parent::error_type;
137
138public:
139 using parent::parent;
140
141 [[nodiscard]] expected::value_type&
142 value_or_abort() & noexcept(clev_exception_disabled_v)
143 {
144 if (!*this)
145 abort_now(expected::error());
146
147 return expected::value();
148 }
149
150 [[nodiscard]] expected::value_type&&
151 value_or_abort() && noexcept(clev_exception_disabled_v)
152 {
153 if (!*this)
154 abort_now(expected::error());
155
156 return std::move(expected::value());
157 }
158
159 [[nodiscard]] constexpr const expected::value_type&
160 value_or_abort() const& noexcept(clev_exception_disabled_v)
161 {
162 if (!*this)
163 abort_now(expected::error());
164
165 return expected::value();
166 }
167
168 [[nodiscard]] constexpr const expected::value_type&&
169 value_or_abort() const&& noexcept(clev_exception_disabled_v)
170 {
171 if (!*this)
172 abort_now(expected::error());
173
174 return std::move(expected::value());
175 }
176
178 and_assign_to(value_t& dest) && noexcept
179 {
180 if (*this)
181 {
182 dest = std::move(expected::value());
183
184 return std::ref(dest);
185 }
186
187 return unexpected{std::move(expected::error())};
188 }
189
190 template<typename fn_t>
191 requires std::is_constructible_v<error_type, error_type&>
192 [[nodiscard]] auto and_then(fn_t&& f) && noexcept
193 {
194 using exp_t = std::remove_cvref_t<
195 std::invoke_result_t<fn_t, decltype(std::move(expected::value()))>>;
196
198 "expected<value_t>::and_then(fn_t) must specialize");
199
200 static_assert(std::is_same_v<typename exp_t::error_type, error_type>,
201 "expected<value_t>::and_then(fn_t) requires same error");
202
203 if (*this)
204 return std::invoke(std::forward<fn_t>(f), std::move(expected::value()));
205 else
206 return exp_t{std::unexpect, std::move(expected::error())};
207 }
208
209 template<typename to_value_t>
210 [[nodiscard]] auto transform_to() && noexcept
211 {
212 if (*this)
213 return expected<to_value_t>(std::move(parent::value()));
214 else
215 return expected<to_value_t>(unexpected(std::move(parent::error())));
216 }
217
218 template<typename to_value_t>
219 [[nodiscard]] auto transform_to(to_value_t&& v) && noexcept
220 {
221 if (*this)
222 return expected<value_t>(std::move(v));
223 else
224 return std::move(*this);
225 }
226
227 [[nodiscard]] auto discard_value() && noexcept
228 {
229 if (*this)
230 return expected<void>{};
231 else
232 return expected<void>{std::unexpect, expected::error()};
233 }
234};
235
236template<typename value_t>
238
239template<typename enum_t>
240inline clev::expected<void> make_expected(const int e) noexcept
241{
242 if (e != 0)
243 return clev::unexpected(static_cast<enum_t>(e));
244
245 return {};
246}
247
248} // namespace clev
Definition err.h:40
clev::expected< void > make_expected(const int e) noexcept
Definition err.h:240
expected(value_t &&) -> expected< value_t >
constexpr bool is_expected_specialization_v
Definition err.h:94
err
Definition err.h:74
exception(std::error_code code) noexcept
Definition err.h:44
auto transform_to(to_value_t &&v) &&noexcept
Definition err.h:119
constexpr void or_exit() noexcept
Definition err.h:112
constexpr void or_abort() noexcept(clev_exception_disabled_v)
Definition err.h:106
expected::value_type && value_or_abort() &&noexcept(clev_exception_disabled_v)
Definition err.h:151
auto transform_to() &&noexcept
Definition err.h:210
auto and_then(fn_t &&f) &&noexcept
Definition err.h:192
constexpr const expected::value_type && value_or_abort() const &&noexcept(clev_exception_disabled_v)
Definition err.h:169
constexpr const expected::value_type & value_or_abort() const &noexcept(clev_exception_disabled_v)
Definition err.h:160
expected< std::reference_wrapper< value_t > > and_assign_to(value_t &dest) &&noexcept
Definition err.h:178
expected::value_type & value_or_abort() &noexcept(clev_exception_disabled_v)
Definition err.h:142
auto transform_to(to_value_t &&v) &&noexcept
Definition err.h:219
auto discard_value() &&noexcept
Definition err.h:227