libkazv
clientutil.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of libkazv.
3  * SPDX-FileCopyrightText: 2021-2023 tusooa <tusooa@kazv.moe>
4  * SPDX-License-Identifier: AGPL-3.0-or-later
5  */
6 
7 
8 #pragma once
9 #include <libkazv-config.hpp>
10 
11 #include <string>
12 #include <tuple>
13 #include <immer/map.hpp>
14 #include <zug/transducer/filter.hpp>
15 #include <zug/transducer/eager.hpp>
16 #include <lager/deps.hpp>
17 #include <boost/container_hash/hash.hpp>
18 #include <boost/serialization/string.hpp>
19 
20 #include <cursorutil.hpp>
21 #include <jobinterface.hpp>
22 #include <eventinterface.hpp>
23 #include "thread-safety-helper.hpp"
24 
25 namespace Kazv
26 {
27  struct ClientModel;
28 
29  template<class K, class V, class List, class Func>
30  immer::map<K, V> merge(immer::map<K, V> map, List list, Func keyOf)
31  {
32  for (auto v : list) {
33  auto key = keyOf(v);
34  map = std::move(map).set(key, v);
35  }
36  return map;
37  }
38 
39  inline std::string keyOfPresence(Event e) {
40  return e.sender();
41  }
42 
43  inline std::string keyOfAccountData(Event e) {
44  return e.type();
45  }
46 
47  inline std::string keyOfTimeline(Event e) {
48  return e.id();
49  }
50 
51  inline std::string keyOfEphemeral(Event e) {
52  return e.type();
53  }
54 
55 
56  struct KeyOfState {
57  std::string type;
58  std::string stateKey;
59  };
60  template<class Archive>
61  void serialize(Archive &ar, KeyOfState &m, std::uint32_t const /* version */)
62  {
63  ar & m.type & m.stateKey;
64  }
65 
66  inline bool operator==(KeyOfState a, KeyOfState b)
67  {
68  return a.type == b.type && a.stateKey == b.stateKey;
69  }
70 
72  return {e.type(), e.stateKey()};
73  }
74 
75  template<class Context>
77  {
78  return lager::get<JobInterface &>(std::forward<Context>(ctx));
79  }
80 
81  template<class Context>
83  {
84  return lager::get<EventInterface &>(std::forward<Context>(ctx));
85  }
86 
87  namespace
88  {
89  template<class ImmerT>
90  struct ImmerIterator
91  {
92  using value_type = typename ImmerT::value_type;
93  using reference = typename ImmerT::reference;
94  using pointer = const value_type *;
95  using difference_type = long int;
96  using iterator_category = std::random_access_iterator_tag;
97 
98  ImmerIterator(const ImmerT &container, std::size_t index)
99  : m_container(std::ref(container))
100  , m_index(index)
101  {}
102 
103  ImmerIterator &operator+=(difference_type d) {
104  m_index += d;
105  return *this;
106  }
107 
108  ImmerIterator &operator-=(difference_type d) {
109  m_index -= d;
110  return *this;
111  }
112 
113  difference_type operator-(ImmerIterator b) const {
114  return index() - b.index();
115  }
116 
117  ImmerIterator &operator++() {
118  return *this += 1;
119  }
120 
121  ImmerIterator operator++(int) {
122  auto tmp = *this;
123  *this += 1;
124  return tmp;
125  }
126 
127  ImmerIterator &operator--() {
128  return *this -= 1;
129  }
130 
131  ImmerIterator operator--(int) {
132  auto tmp = *this;
133  *this -= 1;
134  return tmp;
135  }
136 
137 
138  reference &operator*() const {
139  return m_container.get().at(m_index);
140  }
141 
142  reference operator[](difference_type d) const;
143 
144  std::size_t index() const { return m_index; }
145 
146  private:
147 
148  std::reference_wrapper<const ImmerT> m_container;
149  std::size_t m_index;
150  };
151 
152  template<class ImmerT>
153  auto ImmerIterator<ImmerT>::operator[](difference_type d) const -> reference
154  {
155  return *(*this + d);
156  }
157 
158  template<class ImmerT>
159  auto operator+(ImmerIterator<ImmerT> a, long int d)
160  {
161  return a += d;
162  };
163 
164  template<class ImmerT>
165  auto operator+(long int d, ImmerIterator<ImmerT> a)
166  {
167  return a += d;
168  };
169 
170  template<class ImmerT>
171  auto operator-(ImmerIterator<ImmerT> a, long int d)
172  {
173  return a -= d;
174  };
175 
176  template<class ImmerT>
177  auto immerBegin(const ImmerT &c)
178  {
179  return ImmerIterator<ImmerT>(c, 0);
180  }
181 
182  template<class ImmerT>
183  auto immerEnd(const ImmerT &c)
184  {
185  return ImmerIterator<ImmerT>(c, c.size());
186  }
187  }
188 
189  template<class ImmerT1, class RangeT2, class Pred, class Func>
190  ImmerT1 sortedUniqueMerge(ImmerT1 base, RangeT2 addon, Pred exists, Func keyOf)
191  {
192  auto needToAdd = intoImmer(ImmerT1{},
193  zug::filter([=](auto a) {
194  return !exists(a);
195  }),
196  addon);
197 
198  auto cmp = [=](auto a, auto b) {
199  return keyOf(a) < keyOf(b);
200  };
201 
202  for (auto item : needToAdd) {
203  auto it = std::upper_bound(immerBegin(base), immerEnd(base), item, cmp);
204  auto index = it.index();
205  base = std::move(base).insert(index, item);
206  }
207 
208  return base;
209  }
210 
211  std::string increaseTxnId(std::string cur);
212 
213  std::string getTxnId(Event event, ClientModel &m);
214 }
215 
216 namespace std
217 {
218  template<> struct hash<Kazv::KeyOfState>
219  {
220  std::size_t operator()(const Kazv::KeyOfState & k) const noexcept {
221  std::size_t seed = 0;
222  boost::hash_combine(seed, k.type);
223  boost::hash_combine(seed, k.stateKey);
224  return seed;
225  }
226  };
227 }
228 
229 #define KAZV_WRAP_ATTR(_type, _d, _attr) \
230  inline auto _attr() const { \
231  KAZV_VERIFY_THREAD_ID(); \
232  return (_d)[&_type::_attr]; \
233  }
234 
235 BOOST_CLASS_VERSION(Kazv::KeyOfState, 0)
Definition: context.hpp:130
Definition: eventinterface.hpp:15
Definition: event.hpp:21
std::string stateKey() const
Definition: event.cpp:74
std::string type() const
Definition: event.cpp:62
std::string id() const
returns the id of this event
Definition: event.cpp:42
std::string sender() const
Definition: event.cpp:49
auto operator+(Cursor &&c)
Definition: cursorutil.hpp:122
Definition: location.hpp:10
std::string increaseTxnId(std::string cur)
Definition: clientutil.cpp:14
std::string keyOfAccountData(Event e)
Definition: clientutil.hpp:43
immer::map< K, V > merge(immer::map< K, V > map, List list, Func keyOf)
Definition: clientutil.hpp:30
bool operator==(BaseJob a, BaseJob b)
Definition: basejob.cpp:280
detail::IntoImmerT intoImmer
Definition: cursorutil.hpp:88
ImmerT1 sortedUniqueMerge(ImmerT1 base, RangeT2 addon, Pred exists, Func keyOf)
Definition: clientutil.hpp:190
std::string getTxnId(Event, ClientModel &m)
Definition: clientutil.cpp:19
KeyOfState keyOfState(Event e)
Definition: clientutil.hpp:71
std::string keyOfEphemeral(Event e)
Definition: clientutil.hpp:51
std::string keyOfPresence(Event e)
Definition: clientutil.hpp:39
std::string keyOfTimeline(Event e)
Definition: clientutil.hpp:47
void serialize(Archive &ar, ClientModel &m, std::uint32_t const version)
Definition: client-model.hpp:582
JobInterface & getJobHandler(Context &&ctx)
Definition: clientutil.hpp:76
EventInterface & getEventEmitter(Context &&ctx)
Definition: clientutil.hpp:82
Definition: clientutil.hpp:217
Definition: jobinterface.hpp:21
Definition: clientutil.hpp:56
std::string type
Definition: clientutil.hpp:57
std::string stateKey
Definition: clientutil.hpp:58
std::size_t operator()(const Kazv::KeyOfState &k) const noexcept
Definition: clientutil.hpp:220