libkazv
Loading...
Searching...
No Matches
store.hpp
Go to the documentation of this file.
1/*
2 * This file is part of libkazv.
3 * SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
4 * SPDX-License-Identifier: AGPL-3.0-or-later
5 */
6
7#pragma once
8
9#include <lager/state.hpp>
10#include <lager/deps.hpp>
11#include <lager/util.hpp>
12#include <lager/context.hpp>
13#include <lager/store.hpp>
14#include "context.hpp"
15
16namespace Kazv
17{
18 template<class Action,
19 class EffectRetType,
20 class Model,
21 class Reducer,
22 class Deps = lager::deps<>,
23 class Tag = lager::automatic_tag>
25 {
26 public:
27 using RetType = EffectRetType;
31
32 template<class PH>
33 StoreBase(Model initialModel, Reducer reducer, PH &&ph, Deps deps)
34 : m_d{std::make_shared<Private>(
35 lager::make_state(std::move(initialModel), Tag{}),
36 reducer,
37 PromiseInterfaceT{std::forward<PH>(ph)},
38 deps)}
39 {}
40
41 StoreBase(const StoreBase &that) = delete;
42 StoreBase &operator=(const StoreBase &that) = delete;
43
45 : m_d(std::move(that.m_d))
46 {}
47
49 m_d = std::move(that.m_d);
50 return *this;
51 }
52
53 auto dispatch(Action a) -> PromiseT {
54 return m_d->dispatch(std::move(a));
55 };
56
57 operator lager::reader<Model>() const {
58 return m_d->state;
59 }
60
61 lager::reader<Model> reader() const {
62 return m_d->state;
63 }
64
65 template<class A2, class D2>
66 operator Context<A2, D2>() const {
67 return m_d->ctx;
68 }
69
70 ContextT context() const {
71 return m_d->ctx;
72 }
73
74 private:
75 struct Private
76 {
77 Private(lager::state<Model, Tag> state,
78 Reducer reducer,
80 Deps deps)
81 : state(std::move(state))
82 , reducer(std::move(reducer))
83 , ph(std::move(ph))
84 // this Private will remain untouched between moves of StoreBases
85 // so it is safe to capture by referenced
86 , ctx([this](auto a) { return dispatch(std::move(a)); }, this->ph, deps)
87 {}
88 ~Private() = default;
89 lager::state<Model, Tag> state;
90 Reducer reducer;
92 ContextT ctx;
93
94 auto dispatch(Action a) -> PromiseT {
95 return ph.createResolved(true)
96 .then(
97 [this, a=std::move(a)](auto) {
98 if constexpr (hasEffect<Reducer, RetType, Model, Action, Deps>) {
99 auto [newModel, eff] = reducer(state.get(), a);
100 state.set(newModel);
101 return eff(ctx);
102 } else {
103 auto newModel = reducer(state.get(), a);
104 state.set(newModel);
105 return ph.createResolved(true);
106 }
107 });
108 }
109 };
110 std::shared_ptr<Private> m_d;
111 };
112
113 template<class Action,
114 class Model,
115 class Reducer,
116 class Deps = lager::deps<>,
117 class Tag = lager::automatic_tag>
119
120 namespace detail
121 {
122 constexpr auto compose()
123 {
124 return zug::identity;
125 }
126
127 template<class F1, class ...Fs>
128 constexpr auto compose(F1 &&f1, Fs &&...fs)
129 {
130 return zug::comp(std::forward<F1>(f1), std::forward<Fs>(fs)...);
131 }
132 }
133
134 template<class Action,
135 class Tag = lager::automatic_tag,
136 class Model,
137 class Reducer,
138 class PH,
139 class ...Enhancers
140 >
141 auto makeStore(Model &&initialModel, Reducer &&reducer, PH &&ph, Enhancers &&...enhancers)
142 {
143 auto enhancer = detail::compose(std::forward<Enhancers>(enhancers)...);
144 auto factory = enhancer(
145 [&](auto actionTraits,
146 auto &&model,
147 auto &&reducer,
148 auto &&ph,
149 auto &&deps,
150 auto &&) {
151 using ActionTraits = decltype(actionTraits);
152
153 using ModelF = decltype(model);
154 using ReducerF = decltype(reducer);
155 using PHF = decltype(ph);
156 using DepsF = decltype(deps);
157
158 using ActionT = typename ActionTraits::type;
159 using ModelT = std::decay_t<ModelF>;
160 using ReducerT = std::decay_t<ReducerF>;
161 using DepsT = std::decay_t<DepsF>;
163 std::forward<ModelF>(initialModel), std::forward<ReducerF>(reducer),
164 std::forward<PHF>(ph), std::forward<DepsF>(deps));
165 });
166 return factory(
167 lager::type_<Action>{},
168 std::forward<Model>(initialModel), std::forward<Reducer>(reducer),
169 std::forward<PH>(ph), lager::deps<>{}, Tag{});
170 }
171}
Definition promise-interface.hpp:122
Definition store.hpp:25
StoreBase(const StoreBase &that)=delete
ContextBase< RetType, Action, Deps > ContextT
Definition store.hpp:30
lager::reader< Model > reader() const
Definition store.hpp:61
StoreBase & operator=(const StoreBase &that)=delete
auto dispatch(Action a) -> PromiseT
Definition store.hpp:53
SingleTypePromiseInterface< RetType > PromiseInterfaceT
Definition store.hpp:28
StoreBase(Model initialModel, Reducer reducer, PH &&ph, Deps deps)
Definition store.hpp:33
StoreBase(StoreBase &&that)
Definition store.hpp:44
EffectRetType RetType
Definition store.hpp:27
ContextT context() const
Definition store.hpp:70
SingleTypePromise< RetType > PromiseT
Definition store.hpp:29
StoreBase & operator=(StoreBase &&that)
Definition store.hpp:48
constexpr auto compose()
Definition store.hpp:122
Definition location.hpp:10
@ Private
Definition client-model.hpp:41
auto makeStore(Model &&initialModel, Reducer &&reducer, PH &&ph, Enhancers &&...enhancers)
Definition store.hpp:141
Definition clientutil.hpp:140