oveRTOS C++ API
C++20 RAII wrappers for the oveRTOS C API
Loading...
Searching...
No Matches
error.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 *
6 * This file is part of oveRTOS.
7 */
8
37#pragma once
38
39#include <ove/ove.h>
40
41#include <expected>
42#include <string>
43#include <system_error>
44#include <type_traits>
45#include <utility>
46
47namespace ove
48{
49
64enum class Error : int {
65 Ok = OVE_OK,
66 NotRegistered = OVE_ERR_NOT_REGISTERED,
67 InvalidParam = OVE_ERR_INVALID_PARAM,
68 NoMemory = OVE_ERR_NO_MEMORY,
69 Timeout = OVE_ERR_TIMEOUT,
70 NotSupported = OVE_ERR_NOT_SUPPORTED,
71 QueueFull = OVE_ERR_QUEUE_FULL,
72 MlFailed = OVE_ERR_ML_FAILED,
73 NetRefused = OVE_ERR_NET_REFUSED,
74 NetUnreachable = OVE_ERR_NET_UNREACHABLE,
75 NetAddrInUse = OVE_ERR_NET_ADDR_IN_USE,
76 NetReset = OVE_ERR_NET_RESET,
77 NetDnsFail = OVE_ERR_NET_DNS_FAIL,
78 NetClosed = OVE_ERR_NET_CLOSED,
79 BusNack = OVE_ERR_BUS_NACK,
80 BusBusy = OVE_ERR_BUS_BUSY,
81 BusError = OVE_ERR_BUS_ERROR,
82 QueueEmpty = OVE_ERR_QUEUE_EMPTY,
83 WouldBlock = OVE_ERR_WOULD_BLOCK,
84 Eof = OVE_ERR_EOF,
85 Inval = OVE_ERR_INVAL,
86 NotFound = OVE_ERR_NOT_FOUND,
87};
88
89/*
90 * Drift pin. `<ove/types.h>` already pins every `OVE_ERR_*` to a
91 * literal integer with `OVE_STATIC_ASSERT`; this second pass pins
92 * `Error::*` to those same substrate values. A future variant must
93 * either land here too or have its substrate constant renumbered —
94 * the silent-drift surface is closed at both ends.
95 */
96static_assert(static_cast<int>(Error::Ok) == OVE_OK, "Error::Ok drifted");
97static_assert(static_cast<int>(Error::NotRegistered) == OVE_ERR_NOT_REGISTERED,
98 "Error::NotRegistered drifted");
99static_assert(static_cast<int>(Error::InvalidParam) == OVE_ERR_INVALID_PARAM,
100 "Error::InvalidParam drifted");
101static_assert(static_cast<int>(Error::NoMemory) == OVE_ERR_NO_MEMORY, "Error::NoMemory drifted");
102static_assert(static_cast<int>(Error::Timeout) == OVE_ERR_TIMEOUT, "Error::Timeout drifted");
103static_assert(static_cast<int>(Error::NotSupported) == OVE_ERR_NOT_SUPPORTED,
104 "Error::NotSupported drifted");
105static_assert(static_cast<int>(Error::QueueFull) == OVE_ERR_QUEUE_FULL, "Error::QueueFull drifted");
106static_assert(static_cast<int>(Error::MlFailed) == OVE_ERR_ML_FAILED, "Error::MlFailed drifted");
107static_assert(static_cast<int>(Error::NetRefused) == OVE_ERR_NET_REFUSED,
108 "Error::NetRefused drifted");
109static_assert(static_cast<int>(Error::NetUnreachable) == OVE_ERR_NET_UNREACHABLE,
110 "Error::NetUnreachable drifted");
111static_assert(static_cast<int>(Error::NetAddrInUse) == OVE_ERR_NET_ADDR_IN_USE,
112 "Error::NetAddrInUse drifted");
113static_assert(static_cast<int>(Error::NetReset) == OVE_ERR_NET_RESET, "Error::NetReset drifted");
114static_assert(static_cast<int>(Error::NetDnsFail) == OVE_ERR_NET_DNS_FAIL,
115 "Error::NetDnsFail drifted");
116static_assert(static_cast<int>(Error::NetClosed) == OVE_ERR_NET_CLOSED, "Error::NetClosed drifted");
117static_assert(static_cast<int>(Error::BusNack) == OVE_ERR_BUS_NACK, "Error::BusNack drifted");
118static_assert(static_cast<int>(Error::BusBusy) == OVE_ERR_BUS_BUSY, "Error::BusBusy drifted");
119static_assert(static_cast<int>(Error::BusError) == OVE_ERR_BUS_ERROR, "Error::BusError drifted");
120static_assert(static_cast<int>(Error::QueueEmpty) == OVE_ERR_QUEUE_EMPTY,
121 "Error::QueueEmpty drifted");
122static_assert(static_cast<int>(Error::WouldBlock) == OVE_ERR_WOULD_BLOCK,
123 "Error::WouldBlock drifted");
124static_assert(static_cast<int>(Error::Eof) == OVE_ERR_EOF, "Error::Eof drifted");
125static_assert(static_cast<int>(Error::Inval) == OVE_ERR_INVAL, "Error::Inval drifted");
126static_assert(static_cast<int>(Error::NotFound) == OVE_ERR_NOT_FOUND, "Error::NotFound drifted");
127
139template <class T = void> using Result = std::expected<T, Error>;
140
141namespace detail
142{
143
152class error_category_impl : public std::error_category
153{
154 public:
155 const char *name() const noexcept override
156 {
157 return "ove";
158 }
159
160 std::string message(int ev) const override
161 {
162 switch (static_cast<Error>(ev)) {
163 case Error::Ok:
164 return "success";
165 case Error::NotRegistered:
166 return "backend or feature not registered";
167 case Error::InvalidParam:
168 return "invalid parameter";
169 case Error::NoMemory:
170 return "out of memory";
171 case Error::Timeout:
172 return "operation timed out";
173 case Error::NotSupported:
174 return "operation not supported";
175 case Error::QueueFull:
176 return "queue full";
177 case Error::MlFailed:
178 return "ML inference failed";
179 case Error::NetRefused:
180 return "connection refused";
181 case Error::NetUnreachable:
182 return "network unreachable";
183 case Error::NetAddrInUse:
184 return "address in use";
185 case Error::NetReset:
186 return "connection reset by peer";
187 case Error::NetDnsFail:
188 return "DNS resolution failed";
189 case Error::NetClosed:
190 return "connection closed";
191 case Error::BusNack:
192 return "bus NACK";
193 case Error::BusBusy:
194 return "bus busy";
195 case Error::BusError:
196 return "bus framing/parity error";
197 case Error::QueueEmpty:
198 return "queue empty";
199 case Error::WouldBlock:
200 return "operation would block";
201 case Error::Eof:
202 return "end of file";
203 case Error::Inval:
204 return "argument or state invalid";
205 case Error::NotFound:
206 return "resource not found";
207 }
208 return "unknown ove error";
209 }
210};
211
212} /* namespace detail */
213
222inline const std::error_category &error_category() noexcept
223{
224 static const detail::error_category_impl instance;
225 return instance;
226}
227
238inline std::error_code make_error_code(Error e) noexcept
239{
240 return {static_cast<int>(e), error_category()};
241}
242
254[[nodiscard]] inline Result<void> from_rc(int rc) noexcept
255{
256 if (rc == OVE_OK)
257 return {};
258 return std::unexpected{static_cast<Error>(rc)};
259}
260
277template <class T> [[nodiscard]] inline Result<std::decay_t<T>> from_rc(int rc, T &&value)
278{
279 using V = std::decay_t<T>;
280 if (rc == OVE_OK)
281 return Result<V>{std::forward<T>(value)};
282 return std::unexpected{static_cast<Error>(rc)};
283}
284
285} /* namespace ove */
286
287/*
288 * Enable `std::error_code ec = ove::Error::X;` — the standard lookup
289 * rule is: if `is_error_code_enum<E>` is true, error_code's
290 * converting constructor calls `make_error_code(E)` via ADL.
291 */
292namespace std
293{
294template <> struct is_error_code_enum<ove::Error> : true_type {
295};
296} /* namespace std */
std::error_category implementation for Error values.
Definition error.hpp:153
Top-level namespace for all oveRTOS C++ abstractions.
Definition app.hpp:20
const std::error_category & error_category() noexcept
Returns the singleton std::error_category for Error.
Definition error.hpp:222
std::error_code make_error_code(Error e) noexcept
ADL-discoverable factory for std::error_code from Error.
Definition error.hpp:238
Result< void > from_rc(int rc) noexcept
Lifts a substrate rc-code into a Result<void>.
Definition error.hpp:254
Error
Strong-typed mirror of substrate OVE_ERR_* codes.
Definition error.hpp:64
std::expected< T, Error > Result
std::expected-based result alias.
Definition error.hpp:139