HAL
result.h
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved.
4 // Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved.
5 // Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved.
6 // Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 
26 #pragma once
27 
28 #include "hal_core/defines.h"
30 
31 #include <functional>
32 #include <type_traits>
33 #include <variant>
34 
35 namespace hal
36 {
37  namespace result_constructor_type
38  {
39  // Constructor type for macro: OK()
40  class OK
41  {
42  };
43  // Constructor type for macro: ERROR()
44  class ER
45  {
46  };
47  } // namespace result_constructor_type
48 
49 #define OK(...) \
50  { \
51  result_constructor_type::OK(), __VA_ARGS__ \
52  }
53 #define ERR(message) \
54  { \
55  result_constructor_type::ER(), Error(__FILE__, __LINE__, message) \
56  }
57 #define ERR_APPEND(prev_error, message) \
58  { \
59  result_constructor_type::ER(), Error(__FILE__, __LINE__, prev_error, message) \
60  }
61 
62  template<typename T>
63  class [[nodiscard]] Result final
64  {
65  public:
67  static_assert(!std::is_same<T, Error>(), "Cannot initialize a Result<Error>.");
68 
69  template<typename... Args, typename U = T, typename std::enable_if_t<std::is_same_v<U, void>, int> = 0>
71  {
72  }
73 
74  template<typename... Args, typename U = T, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
75  Result(result_constructor_type::OK, const T& value) : m_result(value)
76  {
77  }
78 
79  template<typename... Args, typename U = T, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
80  Result(result_constructor_type::OK, std::remove_reference_t<T>&& value) : m_result(std::move(value))
81  {
82  }
83 
84  Result(result_constructor_type::ER, const Error& error) : m_result(error)
85  {
86  }
87 
94  template<typename... Args, typename U = T, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
95  static Result<T> Ok(const T& value)
96  {
97  return OK(value);
98  }
99 
103  template<typename... Args, typename U = T, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
104  static Result<T> Ok(std::remove_reference_t<T>&& value)
105  {
106  return OK(std::move(value));
107  }
108 
115  bool operator==(const Result<T>& other)
116  {
117  return this->m_result == other.m_result;
118  }
119 
126  bool operator!=(const Result<T>& other)
127  {
128  return !(*this == other);
129  }
130 
136  bool is_ok() const
137  {
138  return !is_error();
139  }
140 
146  bool is_error() const
147  {
148  return std::holds_alternative<Error>(m_result);
149  }
150 
158  template<typename U = T, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
159  const T& get() const
160  {
161  return std::get<T>(m_result);
162  }
163 
171  template<typename U = T, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
172  T&& get()
173  {
174  return std::get<T>(std::move(m_result));
175  }
176 
183  const Error& get_error() const
184  {
185  return std::get<Error>(m_result);
186  }
187 
195  {
196  return std::get<Error>(std::move(m_result));
197  }
198 
206  template<typename U, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
207  Result<U> map(const std::function<Result<U>(const T&)>& f) const
208  {
209  if (this->is_ok())
210  {
211  return f(this->get());
212  }
213  else
214  {
215  return ERR(this->get_error());
216  }
217  }
218 
226  template<typename U, typename std::enable_if_t<!std::is_same_v<U, void>, int> = 0>
227  Result<U> map(const std::function<Result<U>(T&&)>& f)
228  {
229  if (this->is_ok())
230  {
231  return f(this->get());
232  }
233  else
234  {
235  return ERR(this->get_error());
236  }
237  }
238 
239  private:
240  std::variant<T, Error> m_result;
241  };
242 } // namespace hal
Error && get_error()
Definition: result.h:194
Result(result_constructor_type::ER, const Error &error)
Definition: result.h:84
bool operator==(const Result< T > &other)
Definition: result.h:115
Result(result_constructor_type::OK)
Definition: result.h:70
bool is_ok() const
Definition: result.h:136
const T & get() const
Definition: result.h:159
static Result< T > Ok(const T &value)
Definition: result.h:95
Result< U > map(const std::function< Result< U >(T &&)> &f)
Definition: result.h:227
const Error & get_error() const
Definition: result.h:183
Result(result_constructor_type::OK, const T &value)
Definition: result.h:75
T && get()
Definition: result.h:172
bool operator!=(const Result< T > &other)
Definition: result.h:126
Result(result_constructor_type::OK, std::remove_reference_t< T > &&value)
Definition: result.h:80
static Result< T > Ok(std::remove_reference_t< T > &&value)
Definition: result.h:104
bool is_error() const
Definition: result.h:146
Result< U > map(const std::function< Result< U >(const T &)> &f) const
Definition: result.h:207
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49