idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
error.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
26#include <concepts>
27#include <expected>
28#include <functional>
29#include <memory>
30#include <new>
31#include <string>
32#include <system_error>
33#include <utility>
34
35typedef int esp_err_t;
36
37namespace idfxx {
38
46enum class errc : esp_err_t {
47 // clang-format off
48 fail = -1,
49 invalid_arg = 0x102,
50 invalid_state = 0x103,
51 invalid_size = 0x104,
52 not_found = 0x105,
53 not_supported = 0x106,
54 timeout = 0x107,
55 invalid_response = 0x108,
56 invalid_crc = 0x109,
57 invalid_version = 0x10A,
58 invalid_mac = 0x10B,
59 not_finished = 0x10C,
60 not_allowed = 0x10D,
61 // clang-format on
62};
63
72class error_category : public std::error_category {
73public:
80
88 [[nodiscard]] std::string message(int ec) const override final;
89};
90
99
102 return {std::to_underlying(e), default_category()};
103}
104
113
119template<typename T>
120using result = std::expected<T, std::error_code>;
121
131template<typename T, typename... Args>
132concept has_factory = requires {
133 { T::make(std::declval<Args>()...) } -> std::same_as<result<T>>;
134};
135
155template<typename T, typename... Args>
156 requires has_factory<T, Args...>
158 auto r = T::make(std::forward<Args>(args)...);
159 if (!r) {
160 return error(r.error());
161 }
162 return std::make_unique<T>(std::move(*r));
163}
164
185template<typename E>
186 requires std::is_error_code_enum_v<E>
187[[nodiscard]] constexpr std::unexpected<std::error_code> error(E e) noexcept {
188 return std::unexpected<std::error_code>(e);
189}
190
211template<typename E>
212 requires std::is_error_condition_enum_v<E>
213[[nodiscard]] constexpr std::unexpected<std::error_code> error(E e) noexcept {
214 return std::unexpected<std::error_code>(make_error_code(e));
215}
216
218namespace detail {
220constexpr esp_err_t esp_err_no_mem = 0x101;
221} // namespace detail
222
229[[noreturn]] inline void raise_no_mem() {
230#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
231 throw std::bad_alloc();
232#else
233 abort();
234#endif
235}
250[[nodiscard]] inline std::unexpected<std::error_code> error(esp_err_t e) {
251 return std::unexpected<std::error_code>(make_error_code(e));
252}
253
273[[nodiscard]] inline std::unexpected<std::error_code> error(std::error_code ec) noexcept {
274 return std::unexpected<std::error_code>(ec);
275}
276
287 if (e) {
288 return error(e);
289 }
290 return {};
291}
292
293#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
306template<typename T>
308 return std::move(result).transform_error([](auto ec) -> std::error_code { throw std::system_error(ec); }).value();
309}
310
311// Specialization for void
312template<>
314 result.transform_error([](auto ec) -> std::error_code { throw std::system_error(ec); });
315}
316#endif
317
334template<typename T, typename Callback>
335 requires std::invocable<Callback, std::error_code> &&
336 std::same_as<std::invoke_result_t<Callback, std::error_code>, void>
338 result.transform_error([&](auto ec) {
339 // Check if the callback is valid (for types with operator bool)
340 if constexpr (requires { static_cast<bool>(on_error); }) {
341 if (!on_error) {
342 abort();
343 return ec;
344 }
345 }
346 std::forward<Callback>(on_error)(ec);
347 abort();
348 return ec;
349 });
350}
351
358template<typename T>
360 result.transform_error([](auto ec) {
361 abort();
362 return ec;
363 });
364}
365
366} // namespace idfxx
367
369namespace std {
370template<>
371struct is_error_code_enum<idfxx::errc> : true_type {};
372} // namespace std
// end of idfxx_core_error
Error category for IDFXX and ESP-IDF error codes.
Definition error.hpp:72
std::string message(int ec) const override final
Returns a human-readable message for the given error code.
const char * name() const noexcept override final
Returns the name of the error category.
Concept for types that provide a static make() factory method returning result<T>.
Definition error.hpp:132
int esp_err_t
Definition error.hpp:35
std::error_code make_error_code(errc e) noexcept
Creates a std::error_code from an idfxx::errc value.
Definition error.hpp:101
void abort_on_error(result< T > result, Callback &&on_error)
Aborts the program if the result contains an error.
Definition error.hpp:337
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
Definition error.hpp:187
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
result< std::unique_ptr< T > > make_unique(Args &&... args)
Constructs a T via its make() factory and wraps it in a std::unique_ptr.
Definition error.hpp:157
errc
IDFXX error codes.
Definition error.hpp:46
@ invalid_size
Invalid size.
@ invalid_version
Version was invalid.
@ invalid_state
Invalid state.
@ not_allowed
Operation is not allowed.
@ invalid_mac
MAC address was invalid.
@ not_found
Requested resource not found.
@ timeout
Operation timed out.
@ not_supported
Operation or feature not supported.
@ invalid_crc
CRC or checksum was invalid.
@ invalid_arg
Invalid argument.
@ not_finished
Operation has not fully completed.
@ fail
Generic failure.
@ invalid_response
Received response was invalid.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120
result< void > wrap(esp_err_t e)
Wraps an esp_err_t into a result<void>.
Definition error.hpp:286
const error_category & default_category() noexcept
Returns a reference to the IDFXX error category singleton.