-
Notifications
You must be signed in to change notification settings - Fork 12
refactor: use new return type internally #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,237 @@ | ||
| #pragma once | ||
|
|
||
| #include <utility> | ||
| #include <variant> | ||
| #include <string> | ||
|
|
||
| #include <namespace.h> | ||
|
|
||
| namespace SFRAME_NAMESPACE { | ||
|
|
||
| // Error types to replace exceptions | ||
| enum class SFrameErrorType | ||
| { | ||
| none = 0, | ||
| internal_error, | ||
| invalid_parameter_error, | ||
| buffer_too_small_error, | ||
| crypto_error, | ||
| unsupported_ciphersuite_error, | ||
| authentication_error, | ||
| invalid_key_usage_error, | ||
| }; | ||
|
|
||
| class SFrameError | ||
| { | ||
| public: | ||
| SFrameError() | ||
| : type_(SFrameErrorType::none) | ||
| , message_() | ||
| { | ||
| } | ||
|
|
||
| explicit SFrameError(SFrameErrorType type) | ||
| : type_(type) | ||
| , message_() | ||
| { | ||
| } | ||
|
|
||
| SFrameError(SFrameErrorType type, std::string message) | ||
| : type_(type) | ||
| , message_(std::move(message)) | ||
| { | ||
| } | ||
|
|
||
| // Copy constructor | ||
| SFrameError(const SFrameError& other) | ||
| : type_(SFrameErrorType::none) | ||
| , message_(other.message_) | ||
| { | ||
| type_ = other.type_; | ||
| } | ||
|
Comment on lines
+46
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this need to be non-default? Similar question with several of the methods below. |
||
|
|
||
| // Copy assignment | ||
| SFrameError& operator=(const SFrameError& other) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not clear that this type needs to be assignable. If it causes conflict with the |
||
| { | ||
| if (this != &other) { | ||
| type_ = other.type_; | ||
| message_ = other.message_; | ||
| } | ||
| return *this; | ||
| } | ||
|
|
||
| // Move constructor | ||
| SFrameError(SFrameError&& other) noexcept | ||
| : type_(other.type_) | ||
| , message_(std::move(other.message_)) | ||
| { | ||
| } | ||
|
|
||
| // Move assignment | ||
| SFrameError& operator=(SFrameError&& other) noexcept | ||
| { | ||
| if (this != &other) { | ||
| type_ = other.type_; | ||
| message_ = std::move(other.message_); | ||
| } | ||
| return *this; | ||
| } | ||
|
|
||
| SFrameErrorType type() const { return type_; } | ||
|
|
||
| const char* message() const { return message_.c_str(); } | ||
|
|
||
| bool ok() const { return type_ == SFrameErrorType::none; } | ||
|
|
||
| private: | ||
| SFrameErrorType type_ = SFrameErrorType::none; | ||
| std::string message_; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't love having STL containers here. Since we have a fixed list of messages, let's just define |
||
| }; | ||
|
|
||
| // Helper to convert SFrameError to appropriate exception type | ||
| void | ||
| throw_on_error(const SFrameError& error); | ||
|
Comment on lines
+92
to
+93
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of doing this, I would have a method |
||
|
|
||
| template<typename T> | ||
| class Result | ||
| { | ||
| public: | ||
| typedef T element_type; | ||
|
|
||
| static Result<T> ok(const T& value) { return Result<T>(value); } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need the |
||
|
|
||
| static Result<T> ok(T&& value) { return Result<T>(std::move(value)); } | ||
|
|
||
| static Result<T> err(SFrameErrorType error, const std::string& message = "") | ||
| { | ||
| return Result<T>(SFrameError(error, message)); | ||
| } | ||
|
|
||
| static Result<T> err(SFrameError&& error) | ||
| { | ||
| return Result<T>(std::move(error)); | ||
| } | ||
|
|
||
| Result(SFrameError error) | ||
| : data_(std::move(error)) | ||
| { | ||
| } | ||
|
|
||
| Result(const T& value) | ||
| : data_(value) | ||
| { | ||
| } | ||
|
|
||
| Result(T&& value) | ||
| : data_(std::move(value)) | ||
| { | ||
| } | ||
|
Comment on lines
+115
to
+128
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should probably be private. |
||
|
|
||
| Result(const Result& other) = delete; | ||
| Result& operator=(const Result& other) = delete; | ||
|
|
||
| Result(Result&& other) noexcept | ||
| : data_(std::move(other.data_)) | ||
| { | ||
| } | ||
|
|
||
| Result& operator=(Result&& other) noexcept | ||
| { | ||
| data_ = std::move(other.data_); | ||
| return *this; | ||
| } | ||
|
Comment on lines
+133
to
+142
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these not the same as the default? |
||
|
|
||
| template<typename U> | ||
| Result(Result<U>&& other) | ||
| : data_(std::move(other.data_)) | ||
| { | ||
| } | ||
|
|
||
| template<typename U> | ||
| Result& operator=(Result<U>&& other) | ||
| { | ||
| data_ = std::move(other.data_); | ||
| return *this; | ||
| } | ||
|
|
||
| T value() { return std::move(std::get<T>(data_)); } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would follow Rust here and call this |
||
|
|
||
| SFrameError error() | ||
| { | ||
| if (std::holds_alternative<SFrameError>(data_)) { | ||
| auto error = std::get<SFrameError>(data_); | ||
| return error; | ||
| } | ||
| return SFrameError(); // Default OK error | ||
| } | ||
|
|
||
| bool is_ok() const { return std::holds_alternative<T>(data_); } | ||
|
|
||
| bool is_err() const { return std::holds_alternative<SFrameError>(data_); } | ||
|
|
||
| private: | ||
| std::variant<T, SFrameError> data_; | ||
|
Comment on lines
+172
to
+173
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor note: If |
||
| }; | ||
|
|
||
| // Specialization for Result<void> | ||
| template<> | ||
| class Result<void> | ||
| { | ||
| public: | ||
| typedef void element_type; | ||
|
|
||
| static Result<void> ok() { return Result<void>(); } | ||
|
|
||
| static Result<void> err(SFrameErrorType error, | ||
| const std::string& message = "") | ||
| { | ||
| return Result<void>(SFrameError(error, message)); | ||
| } | ||
|
|
||
| static Result<void> err(SFrameError&& error) | ||
| { | ||
| return Result<void>(std::move(error)); | ||
| } | ||
|
|
||
| Result() | ||
| : is_ok_(true) | ||
| , error_() | ||
| { | ||
| } | ||
|
|
||
| Result(SFrameError error) | ||
| : is_ok_(false) | ||
| , error_(std::move(error)) | ||
| { | ||
| } | ||
|
|
||
| Result(const Result& other) = delete; | ||
| Result& operator=(const Result& other) = delete; | ||
|
|
||
| Result(Result&& other) noexcept | ||
| : is_ok_(other.is_ok_) | ||
| , error_(std::move(other.error_)) | ||
| { | ||
| } | ||
|
|
||
| Result& operator=(Result&& other) noexcept | ||
| { | ||
| is_ok_ = other.is_ok_; | ||
| error_ = std::move(other.error_); | ||
| return *this; | ||
| } | ||
|
|
||
| void value() { /* void has no value to move */ } | ||
|
|
||
| SFrameError error() { return error_; } | ||
|
|
||
| bool is_ok() const { return is_ok_; } | ||
|
|
||
| bool is_err() const { return !is_ok_; } | ||
|
|
||
| private: | ||
| bool is_ok_; | ||
| SFrameError error_; | ||
|
Comment on lines
+233
to
+234
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would replace these with |
||
| }; | ||
|
|
||
| } // namespace SFRAME_NAMESPACE | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #include <sframe/result.h> | ||
| #include <sframe/sframe.h> | ||
|
|
||
| namespace SFRAME_NAMESPACE { | ||
|
|
||
| void | ||
| throw_on_error(const SFrameError& error) | ||
| { | ||
| switch (error.type()) { | ||
| case SFrameErrorType::none: | ||
| return; | ||
| case SFrameErrorType::buffer_too_small_error: | ||
| throw buffer_too_small_error(error.message()); | ||
| case SFrameErrorType::invalid_parameter_error: | ||
| throw invalid_parameter_error(error.message()); | ||
| case SFrameErrorType::crypto_error: | ||
| throw crypto_error(); | ||
| case SFrameErrorType::unsupported_ciphersuite_error: | ||
| throw unsupported_ciphersuite_error(); | ||
| case SFrameErrorType::authentication_error: | ||
| throw authentication_error(); | ||
| case SFrameErrorType::invalid_key_usage_error: | ||
| throw invalid_key_usage_error(error.message()); | ||
| default: | ||
| throw std::runtime_error(error.message()); | ||
| } | ||
| } | ||
|
|
||
| } // namespace SFRAME_NAMESPACE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove this option (but still start numbering at 1) and the
SFrameError::ok()method.