CsCrypto  1.0.1
result.h
1 /***********************************************************************
2 *
3 * Copyright (c) 2021-2024 Tim van Deurzen
4 * Copyright (c) 2021-2024 Barbara Geller
5 * Copyright (c) 2021-2024 Ansel Sermersheim
6 *
7 * This file is part of CsCrypto.
8 *
9 * CsCrypto is free software, released under the BSD 2-Clause license.
10 * For license details refer to LICENSE provided with this project.
11 *
12 * CsCrypto is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * https://opensource.org/licenses/BSD-2-Clause
17 *
18 ***********************************************************************/
19 
20 #ifndef CS_CRYPTO_UTIL_RESULT_H
21 #define CS_CRYPTO_UTIL_RESULT_H
22 
23 #include <variant>
24 #include <type_traits>
25 
26 namespace cs_crypto::util {
27 
28 template <typename E>
29 class error
30 {
31  static_assert(! std::is_same_v<E, void>, "Error type can not be void");
32 
33  public:
34  error() = delete;
35 
36  constexpr explicit error(const E &err) noexcept
37  : m_error(err)
38  {
39  }
40 
41  constexpr explicit error(E &&err) noexcept
42  : m_error(std::move(err))
43  {
44  }
45 
46  ~error() noexcept = default;
47 
48  constexpr error(const error &) noexcept = default;
49  constexpr error &operator=(const error &) & noexcept = default;
50 
51  constexpr error(error &&) noexcept = default;
52  constexpr error &operator=(error &&) & noexcept = default;
53 
54  constexpr const E &value() & noexcept
55  {
56  return m_error;
57  }
58 
59  constexpr const E &value() const & noexcept
60  {
61  return m_error;
62  }
63 
64  constexpr E &&value() && noexcept
65  {
66  return std::move(m_error);
67  }
68 
69  private:
70  E m_error;
71 };
72 
73 template <typename Value, typename Error>
74 class result
75 {
76  public:
77  constexpr explicit result(Value &&value) noexcept
78  : m_content(std::forward<Value>(value))
79  {
80  }
81 
82  constexpr explicit result(Error &&err) noexcept
83  : m_content(error(std::move(err)))
84  {
85  }
86 
87  ~result() noexcept = default;
88 
89  constexpr result(const result &) noexcept = default;
90  constexpr result &operator=(const result &) &noexcept = default;
91 
92  constexpr result(result &&) noexcept = default;
93  constexpr result &operator=(result &&) & noexcept = default;
94 
95  constexpr const Value &value() const & noexcept
96  {
97  return std::get<Value>(m_content);
98  }
99 
100  constexpr const Value &value() & noexcept
101  {
102  return std::get<Value>(m_content);
103  }
104 
105  constexpr Value &&value() && noexcept
106  {
107  return std::get<Value>(std::move(m_content));
108  }
109 
110  constexpr const Error &err() const & noexcept
111  {
112  return std::get<error_t>(m_content).value();
113  }
114 
115  constexpr const Error &err() & noexcept
116  {
117  return std::get<error_t>(m_content).value();
118  }
119 
120  constexpr Error &&err() && noexcept
121  {
122  return std::get<error_t>(std::move(m_content)).value();
123  }
124 
125  constexpr bool is_error() const noexcept
126  {
127  return std::holds_alternative<error_t>(m_content);
128  }
129 
130  constexpr bool is_ok() const noexcept
131  {
132  return std::holds_alternative<Value>(m_content);
133  }
134 
135  private:
136  using error_t = error<Error>;
137 
138  // using std::variant means std::terminate can be called if the content is an error
139  const std::variant<Value, error_t> m_content;
140 };
141 
142 } // namespace cs_crypto::util
143 
144 #endif