• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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