forked from qdrvm/kagome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonadic_utils.hpp
111 lines (100 loc) · 3.69 KB
/
monadic_utils.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <optional>
#include <type_traits>
#include "outcome/custom.hpp"
#include "outcome/outcome.hpp"
namespace kagome::common {
/**
* Applies \arg f to the value, stored in an optional.
* @returns a new optional with the result of \arg f call, in case optional
* contains a value. Otherwise, just returns an std::nullopt.
*/
template <typename T,
typename F,
typename R = std::invoke_result_t<F, const T &>>
std::optional<R> map_optional(const std::optional<T> &opt, const F &f) {
if (opt.has_value()) {
return std::optional<R>{f(opt.value())};
}
return std::nullopt;
}
/**
* Applies \arg f to the value, stored in an optional.
* @returns a new optional with the result of \arg f call, in case optional
* contains a value. Otherwise, just returns an std::nullopt.
*/
template <typename T, typename F, typename R = std::invoke_result_t<F, T &&>>
std::optional<R> map_optional(std::optional<T> &&opt, const F &f) {
if (opt.has_value()) {
return std::optional<R>{f(std::move(opt.value()))};
}
return std::nullopt;
}
/**
* Applies \arg f to the value, stored in an outcome::result.
* @returns a new outcome::result with the result of \arg f call, in case
* outcome::result contains a value. Otherwise, just returns the contained
* error.
*/
template <typename T,
typename E,
typename F,
typename R = std::invoke_result_t<F, const T &>>
CustomOutcome<R, E> map_result(const CustomOutcome<T, E> &res, const F &f) {
if (res.has_value()) {
return CustomOutcome<R, E>{f(res.value())};
}
return res.as_failure();
}
/**
* Applies \arg f to the value, stored in an outcome::result.
* @returns a new outcome::result with the result of \arg f call, in case
* outcome::result contains a value. Otherwise, just returns the contained
* error.
*/
template <typename T,
std::invocable<T &&> F,
typename R = std::invoke_result_t<F, T &&>>
outcome::result<R> map_result(outcome::result<T> &&res, const F &f) {
if (res.has_value()) {
return outcome::result<R>{f(std::move(res.value()))};
}
return res.as_failure();
}
/**
* Applies \arg f to the value, stored in an optional wrapped in an
* outcome::result.
* @returns a new outcome::result of optional with the result of \arg f call,
* in case outcome::result AND optional both contain a value. Otherwise, just
* returns the contained error OR std::nullopt.
*/
template <typename T,
typename F,
typename R = std::invoke_result_t<F, const T &>>
outcome::result<std::optional<R>> map_result_optional(
const outcome::result<std::optional<T>> &res_opt, const F &f) {
return map_result(res_opt, [&f](auto &opt) {
return map_optional(opt, [&f](auto &v) { return f(v); });
});
}
/**
* Applies \arg f to the value, stored in an optional wrapped in an
* outcome::result.
* @returns a new outcome::result of optional with the result of \arg f call,
* in case outcome::result AND optional both contain a value. Otherwise, just
* returns the contained error OR std::nullopt.
*/
template <typename T, typename F, typename R = std::invoke_result_t<F, T &&>>
outcome::result<std::optional<R>> map_result_optional(
outcome::result<std::optional<T>> &&res_opt, const F &f) {
return map_result(std::move(res_opt), [&f](std::optional<T> &&opt) {
return map_optional(std::move(opt),
[&f](T &&v) { return f(std::move(v)); });
});
}
} // namespace kagome::common