ROSE 0.11.145.247
PartialResult.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8#ifndef Sawyer_PartialResult_H
9#define Sawyer_PartialResult_H
10
11#include <Sawyer/Result.h>
12
13#include <boost/lexical_cast.hpp>
14#include <boost/variant.hpp>
15#include <exception>
16#include <string>
17#include <type_traits>
18
19namespace Sawyer {
20
28template<class T, class E>
30public:
31 using OkValue = T;
32 using ErrorValue = E;
33 using OkType = Ok<T>;
34 using ErrorType = Error<E>;
35
36private:
37 Ok<T> ok_;
38 Optional<Error<E>> error_;
39
40#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
41private:
42 friend class boost::serialization::access;
43
44 template<class S>
45 void serialize(S &s, const unsigned /*version*/) const {
46 s <<BOOST_SERIALIZATION_NVP(ok_);
47 s <<BOOST_SERIALIZATION_NVP(error_);
48 }
49#endif
50
51#ifdef SAWYER_HAVE_CEREAL
52private:
53 friend class cereal::access;
54
55 template<class Archive>
56 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) const {
57 archive(CEREAL_NVP(ok_));
58 archive(CEREAL_NVP(error_));
59 }
60#endif
61
62public:
63 template<class U = T>
64 /*implicit*/ PartialResult(const Ok<U> &ok)
65 : ok_(OkType(*ok)) {}
66
67 template<class U = T, class F = E>
68 PartialResult(const U &ok, const F &error)
69 : ok_(OkType(ok)), error_(ErrorType(error)) {}
70
71 template<class U = T, class F = E>
73 : ok_(OkType(other.unwrap())) {
74 if (other.isError())
75 error_ = ErrorType(other.unwrapError());
76 }
77
79 template<class U = T>
81 ok_ = OkType(*ok);
82 return *this;
83 }
84
86 template<class U = T, class F = E>
88 ok_ = OkType(*other.ok_);
89 if (other.error_) {
90 error_ = ErrorType(*other.error_);
91 } else {
92 error_ = Sawyer::Nothing();
93 }
94 }
95
100 template<class U = T>
101 bool operator==(const Ok<U> &ok) const {
102 return unwrap() == *ok;
103 }
104
109 template<class U = T>
110 bool operator!=(const Ok<U> &ok) const {
111 return !(*this == ok);
112 }
113
115 template<class F = E>
116 bool operator==(const Error<F> &error) const {
117 return isError() && *this->error() == *error;
118 }
119
121 template<class F = E>
122 bool operator!=(const Error<F> &error) const {
123 return !(*this == error);
124 }
125
127 template<class U, class F>
128 bool operator==(const PartialResult<U, F> &other) const {
129 return (*ok() == *other.ok() &&
130 isError() == other.isError() &&
131 (!isError() || *error() == *other.error()));
132 }
133
135 template<class U, class F>
136 bool operator!=(const PartialResult<U, F> &other) const {
137 return !(*this == other);
138 }
139
145 bool isOk() const {
146 return !isError();
147 }
148 explicit operator bool() const {
149 return isOk();
150 }
154 bool isError() const {
155 return !!error_;
156 }
157
161 const Sawyer::Optional<T> ok() const {
162 if (isOk()) {
163 return *ok_;
164 } else {
165 return Sawyer::Nothing();
166 }
167 }
168
173 if (error_) {
174 return **error_;
175 } else {
176 return Sawyer::Nothing();
177 }
178 }
179
184 const T& expect(const std::string &mesg) const {
185 if (isOk()) {
186 return *ok_;
187 } else {
188 throw std::runtime_error(mesg);
189 }
190 }
191
197 const T& unwrap() const {
198 return *ok_;
199 }
200 const T& operator*() const {
201 return unwrap();
202 }
208 const T* operator->() const {
209 return &unwrap();
210 }
211
215 const T orElse(const T &dflt) const {
216 return isOk() ? unwrap() : dflt;
217 }
218
223 template<class Fn>
224 typename std::enable_if<is_invocable<Fn, const PartialResult>::value, const PartialResult>::type
225 orElse(Fn fn) const {
226 if (isOk()) {
227 return *this;
228 } else {
229 return fn(*this);
230 }
231 }
232
236 template<class F>
238 if (isOk()) {
239 return ok_;
240 } else {
241 return other;
242 }
243 }
244
246 const T& orDefault() const {
247 static T dflt = T();
248 return isOk() ? unwrap() : dflt;
249 }
250
255 template<class Exception = E>
256 const T& orThrow() const {
257 if (isOk()) {
258 return unwrap();
259 } else {
260 throw Exception(*error());
261 }
262 }
263
265 template<class Exception = E>
266 const T& orThrow(const Exception &e) const {
267 if (isOk()) {
268 return unwrap();
269 } else {
270 throw e;
271 }
272 }
273
278 template<class Fn>
279 typename std::enable_if<is_invocable<Fn, OkValue>::value, const PartialResult>::type
280 andThen(Fn fn) const {
281 if (isOk()) {
282 return fn(*ok());
283 } else {
284 return *this;
285 }
286 }
287
291 template<class U = T, class F = E>
293 if (isOk()) {
294 return other;
295 } else {
296 return *this;
297 }
298 }
299
303 const E& expectError(const std::string &mesg) const {
304 if (error_) {
305 return **error_;
306 } else {
307 throw std::runtime_error(mesg);
308 }
309 }
310
314 const E& unwrapError() const {
315 return expectError("result is not an error");
316 }
317
319 template<class U>
320 bool contains(const U &value) const {
321 return unwrap() == value;
322 }
323
325 template<class F>
326 bool containsError(const F &error) const {
327 return error_ ? unwrapError() == error : false;
328 }
329
335 template<class U>
336 const PartialResult& assignTo(U &out) const {
337 if (isOk())
338 out = unwrap();
339 return *this;
340 }
341
342 template<class U>
343 PartialResult& assignTo(U &out) const {
344 if (isOk())
345 out = unwrap();
346 return *this;
347 }
353 template <class F>
354 auto
355 fmap(F&& f) -> PartialResult<decltype(f(unwrap())), E> {
356 using NewValue = decltype(f(unwrap()));
357 using Retval = PartialResult<NewValue, E>;
358 if (isOk()) {
359 return Retval(Ok<NewValue>(f(unwrap())));
360 } else {
361 return Retval(f(unwrap()), unwrapError());
362 }
363 }
364};
365
366template<class T, class E>
367PartialResult<T, E> makePartialResult(const T &ok, const E &error) {
368 return PartialResult<T, E>(ok, error);
369}
370
371} // namespace
372#endif
Error value.
Definition Result.h:170
Represents no value.
Definition Optional.h:36
Success value.
Definition Result.h:35
Holds a value or nothing.
Definition Optional.h:56
Result containing a value and an error.
bool isOk() const
Returns true if the result is okay.
std::enable_if< is_invocable< Fn, constPartialResult >::value, constPartialResult >::type orElse(Fn fn) const
Returns the contained Ok value, or calls a function.
bool operator==(const Error< F > &error) const
Test whether this result has the specified Error value.
PartialResult & assignTo(U &out) const
Conditionally save a value.
bool isError() const
Returns true if the result has an error.
const Sawyer::Optional< T > ok() const
Convert to Optional<T>.
PartialResult & operator=(const PartialResult< U, F > &other)
Assign another partial result to this result.
bool containsError(const F &error) const
Returns true if this result contains the specified error value.
const PartialResult< T, F > orElse(const PartialResult< T, F > &other) const
Returns this value or the other result.
const T * operator->() const
Returns a pointer to the (partial) success value.
const T & orDefault() const
Returns the okay value or a default constructed value.
const T & operator*() const
Returns the (partial) success value.
const Sawyer::Optional< E > error() const
Convert to Optional<E>.
PartialResult & operator=(const Ok< U > &ok)
Assign an Ok value to this result.
const T orElse(const T &dflt) const
Returns the contained Ok value or a provided default.
bool operator!=(const Error< F > &error) const
Test whether this result does not have the specified Error value.
const PartialResult< U, F > andThen(const PartialResult< U, F > &other) const
Returns this (if error) or the other result.
auto fmap(F &&f) -> PartialResult< decltype(f(unwrap())), E >
Conditionally apply a functor f to the okay contents of a result.
const T & expect(const std::string &mesg) const
Returns the success value or throws an exception.
std::enable_if< is_invocable< Fn, OkValue >::value, constPartialResult >::type andThen(Fn fn) const
Returns the contained Error value, or calls a function.
const E & unwrapError() const
Returns the error value or throws an exception.
const T & orThrow(const Exception &e) const
Returns the value or throws an exception constructed from the specified value.
const E & expectError(const std::string &mesg) const
Returns the error value or throws an exception.
bool operator==(const Ok< U > &ok) const
Test whether this result has the specified Ok value.
bool operator!=(const Ok< U > &ok) const
Test whether this result does not have the specified Ok value.
const PartialResult & assignTo(U &out) const
Conditionally save a value.
bool contains(const U &value) const
Returns true if this result contains the specified (partial) okay value.
bool operator!=(const PartialResult< U, F > &other) const
Test whether this result is unequal to the other result.
bool operator==(const PartialResult< U, F > &other) const
Test whether this result is equal to the other result.
const T & orThrow() const
Returns the success value or throws an exception.
const T & unwrap() const
Returns the (partial) success value.
Sawyer support library.