2020#pragma once
2121
2222// / \file iceberg/util/error_collector.h
23- // / Utility for collecting validation errors in builder patterns
23+ // / Base class for collecting validation errors in builder patterns
2424
2525#include < string>
2626#include < vector>
2727
28+ #include " iceberg/iceberg_export.h"
2829#include " iceberg/result.h"
2930
3031namespace iceberg {
3132
32- // / \brief Utility class for collecting validation errors in builder patterns
33+ // / \brief Base class for collecting validation errors in builder patterns
3334// /
3435// / This class provides error accumulation functionality for builders that
3536// / cannot throw exceptions. Builder methods can call AddError() to accumulate
3637// / validation errors, and CheckErrors() returns all errors at once.
3738// /
38- // / This allows users to see all validation errors at once rather than fixing
39- // / them one by one (fail-slow instead of fail-fast).
40- // /
4139// / Example usage:
4240// / \code
43- // / class MyBuilder {
44- // / protected:
45- // / ErrorCollector errors_;
46- // /
41+ // / class MyBuilder : public ErrorCollectorBase {
42+ // / public:
4743// / MyBuilder& SetValue(int val) {
4844// / if (val < 0) {
49- // / errors_.AddError(ErrorKind::kInvalidArgument, "Value must be non-negative");
50- // / return *this;
45+ // / return AddError(ErrorKind::kInvalidArgument, "Value must be non-negative");
5146// / }
5247// / value_ = val;
5348// / return *this;
5449// / }
5550// /
5651// / Result<MyObject> Build() {
57- // / ICEBERG_RETURN_UNEXPECTED(errors_. CheckErrors());
52+ // / ICEBERG_RETURN_UNEXPECTED(CheckErrors());
5853// / return MyObject{value_};
5954// / }
55+ // /
56+ // / private:
57+ // / int value_ = 0;
6058// / };
6159// / \endcode
62- class ErrorCollector {
60+ class ICEBERG_EXPORT ErrorCollector {
6361 public:
6462 ErrorCollector () = default ;
63+ virtual ~ErrorCollector () = default ;
6564
66- // / \brief Add a validation error
65+ ErrorCollector (ErrorCollector&&) = default ;
66+ ErrorCollector& operator =(ErrorCollector&&) = default ;
67+
68+ ErrorCollector (const ErrorCollector&) = default ;
69+ ErrorCollector& operator =(const ErrorCollector&) = default ;
70+
71+ // / \brief Add a specific error and return reference to derived class
6772 // /
73+ // / \param self Deduced reference to the derived class instance
6874 // / \param kind The kind of error
6975 // / \param message The error message
70- void AddError (ErrorKind kind, std::string message) {
71- errors_.emplace_back (kind, std::move (message));
76+ // / \return Reference to the derived class for method chaining
77+ auto & AddError (this auto & self, ErrorKind kind, std::string message) {
78+ self.errors_ .emplace_back (kind, std::move (message));
79+ return self;
7280 }
7381
74- // / \brief Add an existing error object
82+ // / \brief Add an existing error object and return reference to derived class
7583 // /
7684 // / Useful when propagating errors from other components or reusing
7785 // / error objects without deconstructing and reconstructing them.
7886 // /
87+ // / \param self Deduced reference to the derived class instance
7988 // / \param err The error to add
80- void AddError (Error err) { errors_.push_back (std::move (err)); }
89+ // / \return Reference to the derived class for method chaining
90+ auto & AddError (this auto & self, Error err) {
91+ self.errors_ .push_back (std::move (err));
92+ return self;
93+ }
8194
8295 // / \brief Check if any errors have been collected
8396 // /
8497 // / \return true if there are accumulated errors
85- bool HasErrors () const { return !errors_.empty (); }
98+ [[nodiscard]] bool HasErrors () const { return !errors_.empty (); }
8699
87100 // / \brief Get the number of errors collected
88101 // /
89102 // / \return The count of accumulated errors
90- size_t ErrorCount () const { return errors_.size (); }
103+ [[nodiscard]] size_t ErrorCount () const { return errors_.size (); }
91104
92105 // / \brief Check for accumulated errors and return them if any exist
93106 // /
@@ -97,7 +110,7 @@ class ErrorCollector {
97110 // /
98111 // / \return Status::OK if no errors, or a ValidationFailed error with
99112 // / all accumulated error messages
100- Status CheckErrors () const {
113+ [[nodiscard]] Status CheckErrors () const {
101114 if (!errors_.empty ()) {
102115 std::string error_msg = " Validation failed due to the following errors:\n " ;
103116 for (const auto & [kind, message] : errors_) {
@@ -117,9 +130,9 @@ class ErrorCollector {
117130 // / \brief Get read-only access to all collected errors
118131 // /
119132 // / \return A const reference to the vector of errors
120- const std::vector<Error>& Errors () const { return errors_; }
133+ [[nodiscard]] const std::vector<Error>& Errors () const { return errors_; }
121134
122- private :
135+ protected :
123136 std::vector<Error> errors_;
124137};
125138
0 commit comments