Common System 0.2.0
Common interfaces and patterns for system integration
Loading...
Searching...
No Matches
core.cppm
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
17module;
18
19#include <optional>
20#include <sstream>
21#include <stdexcept>
22#include <string>
23#include <type_traits>
24#include <utility>
25#include <variant>
26
27// Feature detection for source_location
28#if __has_include(<source_location>)
29 #include <source_location>
30 #define KCENON_MODULE_HAS_SOURCE_LOCATION 1
31#else
32 #define KCENON_MODULE_HAS_SOURCE_LOCATION 0
33#endif
34
35export module kcenon.common:result.core;
36
37export namespace kcenon::common {
38
39// ============================================================================
40// Source Location (local definition for this partition)
41// ============================================================================
42
43#if KCENON_MODULE_HAS_SOURCE_LOCATION
44using source_location = std::source_location;
45#else
46struct source_location {
47public:
48 constexpr source_location(
49 const char* file = __builtin_FILE(),
50 const char* function = __builtin_FUNCTION(),
51 int line = __builtin_LINE()
52 ) noexcept
53 : file_(file), function_(function), line_(line), column_(0) {}
54
55 constexpr const char* file_name() const noexcept { return file_; }
56 constexpr const char* function_name() const noexcept { return function_; }
57 constexpr int line() const noexcept { return line_; }
58 constexpr int column() const noexcept { return column_; }
59
60 static constexpr source_location current(
61 const char* file = __builtin_FILE(),
62 const char* function = __builtin_FUNCTION(),
63 int line = __builtin_LINE()
64 ) noexcept {
65 return source_location(file, function, line);
66 }
67
68private:
69 const char* file_;
70 const char* function_;
71 int line_;
72 int column_;
73};
74#endif
75
76// ============================================================================
77// Forward Declarations
78// ============================================================================
79
80struct error_info;
81template<typename T> class Result;
82template<typename T> class Optional;
83
87enum class result_state {
89 ok,
90 error
91};
92
96using VoidResult = Result<std::monostate>;
97
98// ============================================================================
99// Error Info
100// ============================================================================
101
107 int code;
108 std::string message;
109 std::string module;
110 std::optional<std::string> details;
111
112 error_info() : code(0) {}
113
115 error_info(const std::string& msg)
116 : code(-1), message(msg), module("") {}
117
119 error_info(int c, const std::string& msg, const std::string& mod = "")
120 : code(c), message(msg), module(mod) {}
121
123 error_info(int c, const std::string& msg, const std::string& mod,
124 const std::string& det)
125 : code(c), message(msg), module(mod), details(det) {}
126
130 template<typename Enum,
131 typename std::enable_if_t<std::is_enum_v<Enum>, int> = 0>
132 error_info(Enum c, std::string msg, std::string mod = "",
133 std::optional<std::string> det = std::nullopt)
134 : code(static_cast<int>(c)),
135 message(std::move(msg)),
136 module(std::move(mod)),
137 details(std::move(det)) {}
138
139 bool operator==(const error_info& other) const {
140 return code == other.code && message == other.message &&
141 module == other.module && details == other.details;
142 }
143
144 bool operator!=(const error_info& other) const {
145 return !(*this == other);
146 }
147};
148
149
150// ============================================================================
151// Result<T> Class
152// ============================================================================
153
164template<typename T>
165class Result {
166public:
167 using value_type = T;
168 using error_type = error_info;
169
170private:
171 std::optional<T> value_;
172 std::optional<error_info> error_;
173
174public:
175 Result(const T& value) : value_(value), error_(std::nullopt) {}
176 Result(T&& value) : value_(std::move(value)), error_(std::nullopt) {}
177 Result(const error_info& error) : value_(std::nullopt), error_(error) {}
178 Result(error_info&& error) : value_(std::nullopt), error_(std::move(error)) {}
179
180 Result() = delete;
181
182 Result(const Result&) = default;
183 Result(Result&&) = default;
184 Result& operator=(const Result&) = default;
185 Result& operator=(Result&&) = default;
186
187 // Static factory methods
188 template<typename U = T>
189 static Result<T> ok(U&& value) {
190 return Result<T>(std::forward<U>(value));
191 }
192
193 static Result<T> err(const error_info& error) {
194 return Result<T>(error);
195 }
196
198 return Result<T>(std::move(error));
199 }
200
201 static Result<T> err(int code, const std::string& message, const std::string& module = "") {
202 return Result<T>(error_info{code, message, module});
203 }
204
206 return Result<T>(error_info{-6, "Result not initialized", "common::Result"});
207 }
208
209 bool is_ok() const {
210 return value_.has_value();
211 }
212
213 bool is_err() const {
214 return error_.has_value();
215 }
216
217#if KCENON_MODULE_HAS_SOURCE_LOCATION
218 const T& unwrap(source_location loc = source_location::current()) const {
219 if (is_err()) {
220 const auto& err = error_.value();
221 std::ostringstream oss;
222 oss << "Called unwrap on error: " << err.message << "\n"
223 << " Error code: " << err.code << "\n"
224 << " Module: " << (err.module.empty() ? "unknown" : err.module) << "\n"
225 << " Location: " << loc.file_name() << ":" << loc.line() << ":" << loc.column() << "\n"
226 << " Function: " << loc.function_name();
227 if (err.details.has_value()) {
228 oss << "\n Details: " << err.details.value();
229 }
230 throw std::runtime_error(oss.str());
231 }
232 return value_.value();
233 }
234
235 T& unwrap(source_location loc = source_location::current()) {
236 if (is_err()) {
237 const auto& err = error_.value();
238 std::ostringstream oss;
239 oss << "Called unwrap on error: " << err.message << "\n"
240 << " Error code: " << err.code << "\n"
241 << " Module: " << (err.module.empty() ? "unknown" : err.module) << "\n"
242 << " Location: " << loc.file_name() << ":" << loc.line() << ":" << loc.column() << "\n"
243 << " Function: " << loc.function_name();
244 if (err.details.has_value()) {
245 oss << "\n Details: " << err.details.value();
246 }
247 throw std::runtime_error(oss.str());
248 }
249 return value_.value();
250 }
251#else
252 const T& unwrap() const {
253 if (is_err()) {
254 const auto& err = error_.value();
255 throw std::runtime_error("Called unwrap on error: " + err.message);
256 }
257 return value_.value();
258 }
259
260 T& unwrap() {
261 if (is_err()) {
262 const auto& err = error_.value();
263 throw std::runtime_error("Called unwrap on error: " + err.message);
264 }
265 return value_.value();
266 }
267#endif
268
269 T unwrap_or(T default_value) const {
270 if (is_ok()) {
271 return value_.value();
272 }
273 return default_value;
274 }
275
276 T value_or(T default_value) const {
277 return unwrap_or(std::move(default_value));
278 }
279
280 const T& value() const {
281 return value_.value();
282 }
283
284 T& value() {
285 return value_.value();
286 }
287
288 const error_info& error() const {
289 return error_.value();
290 }
291
292 template<typename F>
293 auto map(F&& func) const -> Result<decltype(func(std::declval<T>()))> {
294 using ReturnType = decltype(func(std::declval<T>()));
295
296 if (is_ok()) {
297 return Result<ReturnType>(func(value_.value()));
298 } else if (is_err()) {
299 return Result<ReturnType>(error_.value());
300 } else {
302 }
303 }
304
305 template<typename F>
306 auto and_then(F&& func) const -> decltype(func(std::declval<T>())) {
307 using ReturnType = decltype(func(std::declval<T>()));
308
309 if (is_ok()) {
310 return func(value_.value());
311 } else if (is_err()) {
312 return ReturnType(error_.value());
313 } else {
314 return ReturnType::uninitialized();
315 }
316 }
317
318 template<typename F>
319 Result<T> or_else(F&& func) const {
320 if (is_ok()) {
321 return *this;
322 } else if (is_err()) {
323 return func(error_.value());
324 } else {
325 return *this;
326 }
327 }
328};
329
330// ============================================================================
331// Optional<T> Class
332// ============================================================================
333
340template<typename T>
341class Optional {
342public:
343 using value_type = T;
344
345private:
346 std::optional<T> value_;
347
348public:
349 Optional() : value_(std::nullopt) {}
350 Optional(const T& value) : value_(value) {}
351 Optional(T&& value) : value_(std::move(value)) {}
352 Optional(std::nullopt_t) : value_(std::nullopt) {}
353
354 bool has_value() const { return value_.has_value(); }
355 bool is_some() const { return value_.has_value(); }
356 bool is_none() const { return !value_.has_value(); }
357
358 const T& value() const { return value_.value(); }
359 T& value() { return value_.value(); }
360
361#if KCENON_MODULE_HAS_SOURCE_LOCATION
362 const T& unwrap(source_location loc = source_location::current()) const {
363 if (!has_value()) {
364 std::ostringstream oss;
365 oss << "Called unwrap on None\n"
366 << " Location: " << loc.file_name() << ":" << loc.line() << ":" << loc.column() << "\n"
367 << " Function: " << loc.function_name();
368 throw std::runtime_error(oss.str());
369 }
370 return value_.value();
371 }
372#else
373 const T& unwrap() const {
374 if (!has_value()) {
375 throw std::runtime_error("Called unwrap on None");
376 }
377 return value_.value();
378 }
379#endif
380
381 T unwrap_or(T default_value) const {
382 return value_.value_or(default_value);
383 }
384
385 template<typename F>
386 auto map(F&& func) const -> Optional<decltype(func(std::declval<T>()))> {
387 using ReturnType = decltype(func(std::declval<T>()));
388
389 if (has_value()) {
390 return Optional<ReturnType>(func(value_.value()));
391 } else {
392 return Optional<ReturnType>(std::nullopt);
393 }
394 }
395};
396
397// Optional factory functions
398
402template<typename T>
403inline Optional<T> Some(T value) {
404 return Optional<T>(std::move(value));
405}
406
410template<typename T>
411inline Optional<T> None() {
412 return Optional<T>(std::nullopt);
413}
414
415// ============================================================================
416// VoidResult Factory Functions
417// ============================================================================
418
423inline VoidResult ok() {
424 return VoidResult(std::monostate{});
425}
426
432inline VoidResult err(const error_info& error) {
433 return VoidResult(error);
434}
435
443inline VoidResult err(int code, const std::string& message, const std::string& module = "") {
444 return VoidResult(error_info{code, message, module});
445}
446
447} // namespace kcenon::common
Optional type similar to std::optional with Rust-like API.
Definition core.cppm:341
Optional(const T &value)
Definition core.cppm:350
T value_type
Type alias for the contained value type (for concept compatibility)
Definition core.h:471
Optional(std::nullopt_t)
Definition core.cppm:352
std::optional< T > value_
Definition core.h:474
bool is_some() const
Definition core.cppm:355
bool is_none() const
Definition core.cppm:356
const T & unwrap() const
Get value from optional (throws if None)
Definition core.h:508
T unwrap_or(T default_value) const
Definition core.cppm:381
auto map(F &&func) const -> Optional< decltype(func(std::declval< T >()))>
Definition core.cppm:386
bool has_value() const
Definition core.cppm:354
const T & value() const
Definition core.h:486
Result type for error handling with member function support.
Definition core.cppm:165
const error_info & error() const
Get error reference.
Definition core.h:405
Result(const Result &)=default
static Result< T > err(int code, const std::string &message, const std::string &module="")
Definition core.cppm:201
Result(const T &value)
Definition core.cppm:175
Result & operator=(Result &&)=default
bool is_err() const
Definition core.cppm:213
static Result< T > uninitialized()
Definition core.cppm:205
T value_or(T default_value) const
Definition core.cppm:276
Result(Result &&)=default
auto map(F &&func) const -> Result< decltype(func(std::declval< T >()))>
Definition core.cppm:293
T value_type
Type alias for the contained value type (for concept compatibility)
Definition core.h:169
static Result< T > err(const error_info &error)
Definition core.cppm:193
static Result< T > err(error_info &&error)
Definition core.cppm:197
Result(error_info &&error)
Definition core.cppm:178
static Result< T > ok(U &&value)
Definition core.cppm:189
Result< T > or_else(F &&func) const
Definition core.cppm:319
auto and_then(F &&func) const -> decltype(func(std::declval< T >()))
Definition core.cppm:306
std::optional< error_info > error_
Definition core.h:178
const T & value() const
Get value reference (const)
Definition core.h:391
Result(const error_info &error)
Definition core.cppm:177
std::optional< T > value_
Definition core.h:177
bool is_ok() const
Definition core.cppm:209
Result & operator=(const Result &)=default
const T & unwrap() const
Get value from result (throws if error)
Definition core.h:326
T unwrap_or(T default_value) const
Definition core.cppm:269
Core interfaces.
Definition adapter.h:21
Result< std::monostate > VoidResult
Specialized Result for void operations.
Definition core.h:70
VoidResult err(const error_info &error)
Factory function to create error VoidResult.
Definition core.cppm:432
VoidResult ok()
Create a successful void result.
Definition utilities.h:71
result_state
Result state enum for tracking initialization.
Definition core.h:58
Optional< T > None()
Create an empty Optional.
Definition core.h:546
Optional< T > Some(T value)
Create an Optional with value.
Definition core.h:538
Standard error information used by Result<T>.
Definition core.cppm:106
std::string message
Definition core.h:82
error_info(int c, const std::string &msg, const std::string &mod, const std::string &det)
Construct with code, message, module and details.
Definition core.cppm:123
std::optional< std::string > details
Definition core.h:84
error_info(Enum c, std::string msg, std::string mod="", std::optional< std::string > det=std::nullopt)
Construct from strongly-typed enum error codes.
Definition core.cppm:132
bool operator==(const error_info &other) const
Definition core.cppm:139
std::string module
Definition core.h:83
error_info(int c, const std::string &msg, const std::string &mod="")
Construct with code, message and optional module.
Definition core.cppm:119
bool operator!=(const error_info &other) const
Definition core.cppm:144
error_info(const std::string &msg)
Construct with message only.
Definition core.cppm:115
C++17-compatible source_location implementation using compiler builtins.
Definition utils.cppm:54
constexpr source_location(const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE()) noexcept
Definition core.cppm:48
static constexpr source_location current(const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE()) noexcept
Definition core.cppm:60
constexpr int line() const noexcept
constexpr int column() const noexcept
Definition core.cppm:58
constexpr const char * file_name() const noexcept
Definition core.cppm:55
constexpr const char * function_name() const noexcept
Definition core.cppm:56