jubilant-funicular
Errors.h
1 #ifndef NTA_ERRORS_H_INCLUDED
2 #define NTA_ERRORS_H_INCLUDED
3 
4 #include <functional>
5 
6 #include "nta/Option.h"
7 
9 namespace nta {
10  struct Error;
11  typedef std::function<void(const Error*)> ErrorCallback;
13  enum ErrorType {
14  MISSING_RESOURCE,
15  INVALID_VALUE,
16  GL_FAILURE,
17  SDL_FAILURE,
18  DEVIL_FAILURE,
19  IMPOSSIBLE_BEHAVIOR,
20  UNWRAP_WRONG_RESULT_VARIANT,
21  OTHER
22  };
24  struct Error {
25  Error(crstring desc = "", ErrorType t = OTHER) : description(desc), type(t) {
26  }
27  Error(const Error& other) {
28  description = other.description;
29  type = other.type;
30  prev = other.prev;
31  }
32  ~Error() {
33  if (prev) delete prev;
34  }
36  std::string description;
40  const Error* prev = nullptr;
41  };
45  class ErrorManager {
46  private:
48  static const Error* m_errors;
50  static ErrorCallback m_periodic_callback;
52  static ErrorCallback m_push_callback;
53  public:
55  static void handle_errors();
57  static void set_periodic_callback(const ErrorCallback& callback);
59  static void set_push_callback(const ErrorCallback& callback);
61  static void push_error(const Error& err);
63  static const Error* pop_error();
65  static const Error* peek_error();
67  static void clear_errors();
68  };
69 
70  // I wonder how much of my C++ code is influenced by Rust
73  template<typename T>
74  class Result {
75  private:
77  Result() {}
78 
80  union {
81  T data;
82  Error err;
83  };
86  public:
88  Result(const Result& other) {
90  if (is_err_variant) {
91  new(&err) Error(other.err);
92  } else {
93  new(&data) T(other.data);
94  }
95  }
97  ~Result() {}
101  static Result new_ok(const T& data) {
102  Result ret;
103  new(&ret.data) T((data));
104  ret.is_err_variant = false;
105  return ret;
106  }
110  static Result new_err(const Error& err) {
111  Result ret;
112  new(&ret.err) Error(std::move(err));
113  ret.is_err_variant = true;
114  return ret;
115  }
117  bool is_err() const { return is_err_variant; }
119  bool is_ok() const { return !is_err_variant; }
121  T get_data() const {
122  if (is_err()) {
123  ErrorManager::push_error(Error("Called get_data on err Result",
124  UNWRAP_WRONG_RESULT_VARIANT));
125  }
126  return data;
127  }
129  T unwrap() const { return get_data(); }
131  Error get_err() const {
132  if (is_ok()) {
133  ErrorManager::push_error(Error("Called get_err on ok Result",
134  UNWRAP_WRONG_RESULT_VARIANT));
135  }
136  return err;
137  }
139  T get_data_or(T optb) const { return is_err_variant ? optb : data; }
141  T unwrap_or(T optb) const { return get_data_or(optb); }
143  template<typename S>
144  Result<S> map(std::function<S(T)> func) {
145  return is_err_variant ? Result<S>::new_err(err) : Result<S>::new_ok(func(data));
146  }
147  // Result<void> is basically Option<Error>
148  utils::Option<Error> map(std::function<void(T)> func) {
150  func(data);
152  }
154  template<typename S>
156  if (is_ok()) {
157  ErrorManager::push_error(Error("Called convert_error on ok Result",
158  UNWRAP_WRONG_RESULT_VARIANT));
159  }
160  return Result<S>::new_err(err);
161  }
162  };
163 
165  std::string get_errortype_string(ErrorType t);
166 };
167 
168 #endif // NTA_ERRORS_H_INCLUDED
nta::ErrorManager::set_push_callback
static void set_push_callback(const ErrorCallback &callback)
Sets the push callback function.
Definition: Errors.cpp:25
nta::ErrorManager::m_periodic_callback
static ErrorCallback m_periodic_callback
The function used to handle errors at the end of each frame.
Definition: Errors.h:50
nta::ErrorManager::m_errors
static const Error * m_errors
A linked list of unhandled errors.
Definition: Errors.h:48
nta::Result::~Result
~Result()
Public destructor.
Definition: Errors.h:97
nta::ErrorManager::push_error
static void push_error(const Error &err)
Adds and error to the front of the list.
Definition: Errors.cpp:28
nta::Error::prev
const Error * prev
The most recent unhandled error before this one.
Definition: Errors.h:40
nta::get_errortype_string
std::string get_errortype_string(ErrorType t)
converts ErrorType enum to string
Definition: Errors.cpp:48
nta::ErrorManager::peek_error
static const Error * peek_error()
Returns the error at the front of the list.
Definition: Errors.cpp:40
nta::utils::Option::some
static Option some(const T &data)
Creates an Option holding some data.
Definition: Option.h:48
nta::ErrorManager::pop_error
static const Error * pop_error()
Removes (and returns) the error from the front of the list.
Definition: Errors.cpp:35
nta::Result::convert_error
Result< S > convert_error()
Converts an error variant of Result<T> to an error variant of Result
Definition: Errors.h:155
nta::Error::description
std::string description
A description of what when wrong.
Definition: Errors.h:36
nta::ErrorManager
Definition: Errors.h:45
nta::Result::Result
Result(const Result &other)
Public copy constructor.
Definition: Errors.h:88
nta::Result::map
Result< S > map(std::function< S(T)> func)
Applies a function if no error has occured, else returns the same error.
Definition: Errors.h:144
nta::utils::Option
Definition: Option.h:17
nta::Error
Something went wrong.
Definition: Errors.h:24
nta::utils::Option::none
static Option none()
Creates a None variant Option.
Definition: Option.h:50
nta::Result
Definition: Errors.h:74
nta::Result::Result
Result()
Private constructor (use new_ok or new_err)
Definition: Errors.h:77
nta::Result::get_err
Error get_err() const
Get the Error (only use if is_err() returns true)
Definition: Errors.h:131
nta::ErrorManager::clear_errors
static void clear_errors()
Deletes all errors (without handling any of them)
Definition: Errors.cpp:43
nta::ErrorManager::set_periodic_callback
static void set_periodic_callback(const ErrorCallback &callback)
Sets the periodic callback function.
Definition: Errors.cpp:22
nta::Result::is_ok
bool is_ok() const
Is this normal data.
Definition: Errors.h:119
nta
Definition: Animation2D.h:6
nta::Result::is_err
bool is_err() const
Is this an Error.
Definition: Errors.h:117
nta::Result::new_err
static Result new_err(const Error &err)
Definition: Errors.h:110
nta::Result::new_ok
static Result new_ok(const T &data)
Definition: Errors.h:101
nta::Result::get_data_or
T get_data_or(T optb) const
Tries getting data, returning a default value if this is an error.
Definition: Errors.h:139
nta::Result::unwrap_or
T unwrap_or(T optb) const
Same as get_data_or.
Definition: Errors.h:141
nta::ErrorType
ErrorType
Types of Error.
Definition: Errors.h:13
nta::Result::is_err_variant
bool is_err_variant
Whether or not an error occured.
Definition: Errors.h:85
nta::Result::get_data
T get_data() const
Get the data (only use if is_ok() returns true)
Definition: Errors.h:121
nta::Error::type
ErrorType type
The type of error that occured.
Definition: Errors.h:38
nta::ErrorManager::m_push_callback
static ErrorCallback m_push_callback
The function used to handle errors as they occur.
Definition: Errors.h:52
nta::Result::unwrap
T unwrap() const
Same as get_data.
Definition: Errors.h:129
nta::ErrorManager::handle_errors
static void handle_errors()
Handles all outstanding errors.
Definition: Errors.cpp:16