1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
3 #pragma once
4
5 /*! \file rx-map.hpp
6
7 \brief For each item from this observable use Selector to produce an item to emit from the new observable that is returned.
8
9 \tparam Selector the type of the transforming function
10
11 \param s the selector function
12
13 \return Observable that emits the items from the source observable, transformed by the specified function.
14
15 \sample
16 \snippet map.cpp map sample
17 \snippet output.txt map sample
18 */
19
20 #if !defined(RXCPP_OPERATORS_RX_MAP_HPP)
21 #define RXCPP_OPERATORS_RX_MAP_HPP
22
23 #include "../rx-includes.hpp"
24
25 namespace rxcpp {
26
27 namespace operators {
28
29 namespace detail {
30
31 template<class... AN>
32 struct map_invalid_arguments {};
33
34 template<class... AN>
35 struct map_invalid : public rxo::operator_base<map_invalid_arguments<AN...>> {
36 using type = observable<map_invalid_arguments<AN...>, map_invalid<AN...>>;
37 };
38 template<class... AN>
39 using map_invalid_t = typename map_invalid<AN...>::type;
40
41 template<class T, class Selector>
42 struct map
43 {
44 typedef rxu::decay_t<T> source_value_type;
45 typedef rxu::decay_t<Selector> select_type;
46 typedef decltype((*(select_type*)nullptr)(*(source_value_type*)nullptr)) value_type;
47 select_type selector;
48
maprxcpp::operators::detail::map49 map(select_type s)
50 : selector(std::move(s))
51 {
52 }
53
54 template<class Subscriber>
55 struct map_observer
56 {
57 typedef map_observer<Subscriber> this_type;
58 typedef decltype((*(select_type*)nullptr)(*(source_value_type*)nullptr)) value_type;
59 typedef rxu::decay_t<Subscriber> dest_type;
60 typedef observer<source_value_type, this_type> observer_type;
61 dest_type dest;
62 mutable select_type selector;
63
map_observerrxcpp::operators::detail::map::map_observer64 map_observer(dest_type d, select_type s)
65 : dest(std::move(d))
66 , selector(std::move(s))
67 {
68 }
69 template<class Value>
on_nextrxcpp::operators::detail::map::map_observer70 void on_next(Value&& v) const {
71 auto selected = on_exception(
72 [&](){
73 return this->selector(std::forward<Value>(v));},
74 dest);
75 if (selected.empty()) {
76 return;
77 }
78 dest.on_next(std::move(selected.get()));
79 }
on_errorrxcpp::operators::detail::map::map_observer80 void on_error(rxu::error_ptr e) const {
81 dest.on_error(e);
82 }
on_completedrxcpp::operators::detail::map::map_observer83 void on_completed() const {
84 dest.on_completed();
85 }
86
makerxcpp::operators::detail::map::map_observer87 static subscriber<source_value_type, observer_type> make(dest_type d, select_type s) {
88 auto cs = d.get_subscription();
89 return make_subscriber<source_value_type>(std::move(cs), observer_type(this_type(std::move(d), std::move(s))));
90 }
91 };
92
93 template<class Subscriber>
operator ()rxcpp::operators::detail::map94 auto operator()(Subscriber dest) const
95 -> decltype(map_observer<Subscriber>::make(std::move(dest), selector)) {
96 return map_observer<Subscriber>::make(std::move(dest), selector);
97 }
98 };
99
100 }
101
102 /*! @copydoc rx-map.hpp
103 */
104 template<class... AN>
map(AN &&...an)105 auto map(AN&&... an)
106 -> operator_factory<map_tag, AN...> {
107 return operator_factory<map_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
108 }
109
110 /*! @copydoc rx-map.hpp
111 */
112 template<class... AN>
transform(AN &&...an)113 auto transform(AN&&... an)
114 -> operator_factory<map_tag, AN...> {
115 return operator_factory<map_tag, AN...>(std::make_tuple(std::forward<AN>(an)...));
116 }
117
118 }
119
120 template<>
121 struct member_overload<map_tag>
122 {
123 template<class Observable, class Selector,
124 class Enabled = rxu::enable_if_all_true_type_t<
125 is_observable<Observable>>,
126 class ResolvedSelector = rxu::decay_t<Selector>,
127 class SourceValue = rxu::value_type_t<Observable>,
128 class Map = rxo::detail::map<SourceValue, ResolvedSelector>,
129 class Value = rxu::value_type_t<Map>>
memberrxcpp::member_overload130 static auto member(Observable&& o, Selector&& s)
131 -> decltype(o.template lift<Value>(Map(std::forward<Selector>(s)))) {
132 return o.template lift<Value>(Map(std::forward<Selector>(s)));
133 }
134
135 template<class... AN>
memberrxcpp::member_overload136 static operators::detail::map_invalid_t<AN...> member(const AN...) {
137 std::terminate();
138 return {};
139 static_assert(sizeof...(AN) == 10000, "map takes Selector");
140 }
141 };
142
143 }
144
145 #endif
146