#pragma once #include #include #include #include namespace rk3588 { // Error type for Result class Error { public: Error() = default; explicit Error(std::string message) : message_(std::move(message)) {} Error(std::string message, int code) : message_(std::move(message)), code_(code) {} const std::string& Message() const { return message_; } int Code() const { return code_; } bool Empty() const { return message_.empty(); } explicit operator bool() const { return !message_.empty(); } private: std::string message_; int code_ = 0; }; // Result for functions that return a value or error template class Result { public: // NOLINTNEXTLINE: implicit conversion is intentional for ergonomic API Result(T value) noexcept(std::is_nothrow_move_constructible_v) : data_(std::move(value)) {} // NOLINTNEXTLINE: implicit conversion is intentional for ergonomic API Result(Error error) noexcept : data_(std::move(error)) {} bool Ok() const noexcept { return std::holds_alternative(data_); } bool Failed() const noexcept { return !Ok(); } explicit operator bool() const noexcept { return Ok(); } const T& Value() const& { return std::get(data_); } T& Value() & { return std::get(data_); } T&& Value() && { return std::get(std::move(data_)); } const T& ValueOr(const T& def) const& { return Ok() ? std::get(data_) : def; } const Error& Err() const { return std::get(data_); } const std::string& ErrMessage() const { static const std::string kEmpty; return Failed() ? std::get(data_).Message() : kEmpty; } // Convenience: extract value, moving it out T Take() { return std::get(std::move(data_)); } private: std::variant data_; }; // Result specialization for functions that only succeed/fail template <> class Result { public: Result() noexcept : error_() {} // NOLINTNEXTLINE: implicit conversion is intentional for ergonomic API Result(Error error) noexcept : error_(std::move(error)) {} static Result Ok() noexcept { return Result(); } static Result Fail(std::string message) { return Result(Error(std::move(message))); } static Result Fail(std::string message, int code) { return Result(Error(std::move(message), code)); } bool IsOk() const noexcept { return error_.Empty(); } bool Failed() const noexcept { return !IsOk(); } explicit operator bool() const noexcept { return IsOk(); } const Error& Err() const { return error_; } const std::string& ErrMessage() const { return error_.Message(); } private: Error error_; }; // Type aliases for common patterns using Status = Result; // Helper macros for early return on error #define RK_TRY(expr) \ do { \ auto _result = (expr); \ if (_result.Failed()) { \ return _result.Err(); \ } \ } while (0) #define RK_TRY_ASSIGN(var, expr) \ auto _result_##var = (expr); \ if (_result_##var.Failed()) { \ return _result_##var.Err(); \ } \ var = std::move(_result_##var).Take() // Helper functions inline Status OkStatus() { return Status::Ok(); } inline Status FailStatus(std::string msg) { return Status::Fail(std::move(msg)); } template Result MakeResult(T value) { return Result(std::move(value)); } template Result MakeError(std::string message) { return Result(Error(std::move(message))); } } // namespace rk3588