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  friend bool operator==(const KeyOfState &a, const KeyOfState &b) = default;
60  };
61  template<class Archive>
62  void serialize(Archive &ar, KeyOfState &m, std::uint32_t const /* version */)
63  {
64  ar & m.type & m.stateKey;
65  }
66 
68  return {e.type(), e.stateKey()};
69  }
70 
71  template<class Context>
73  {
74  return lager::get<JobInterface &>(std::forward<Context>(ctx));
75  }
76 
77  template<class Context>
79  {
80  return lager::get<EventInterface &>(std::forward<Context>(ctx));
81  }
82 
83  namespace
84  {
85  template<class ImmerT>
86  struct ImmerIterator
87  {
88  using value_type = typename ImmerT::value_type;
89  using reference = typename ImmerT::reference;
90  using pointer = const value_type *;
91  using difference_type = long int;
92  using iterator_category = std::random_access_iterator_tag;
93 
94  ImmerIterator(const ImmerT &container, std::size_t index)
95  : m_container(std::ref(container))
96  , m_index(index)
97  {}
98 
99  ImmerIterator &operator+=(difference_type d) {
100  m_index += d;
101  return *this;
102  }
103 
104  ImmerIterator &operator-=(difference_type d) {
105  m_index -= d;
106  return *this;
107  }
108 
109  difference_type operator-(ImmerIterator b) const {
110  return index() - b.index();
111  }
112 
113  ImmerIterator &operator++() {
114  return *this += 1;
115  }
116 
117  ImmerIterator operator++(int) {
118  auto tmp = *this;
119  *this += 1;
120  return tmp;
121  }
122 
123  ImmerIterator &operator--() {
124  return *this -= 1;
125  }
126 
127  ImmerIterator operator--(int) {
128  auto tmp = *this;
129  *this -= 1;
130  return tmp;
131  }
132 
133 
134  reference &operator*() const {
135  return m_container.get().at(m_index);
136  }
137 
138  reference operator[](difference_type d) const;
139 
140  std::size_t index() const { return m_index; }
141 
142  private:
143 
144  std::reference_wrapper<const ImmerT> m_container;
145  std::size_t m_index;
146  };
147 
148  template<class ImmerT>
149  auto ImmerIterator<ImmerT>::operator[](difference_type d) const -> reference
150  {
151  return *(*this + d);
152  }
153 
154  template<class ImmerT>
155  auto operator+(ImmerIterator<ImmerT> a, long int d)
156  {
157  return a += d;
158  };
159 
160  template<class ImmerT>
161  auto operator+(long int d, ImmerIterator<ImmerT> a)
162  {
163  return a += d;
164  };
165 
166  template<class ImmerT>
167  auto operator-(ImmerIterator<ImmerT> a, long int d)
168  {
169  return a -= d;
170  };
171 
172  template<class ImmerT>
173  auto immerBegin(const ImmerT &c)
174  {
175  return ImmerIterator<ImmerT>(c, 0);
176  }
177 
178  template<class ImmerT>
179  auto immerEnd(const ImmerT &c)
180  {
181  return ImmerIterator<ImmerT>(c, c.size());
182  }
183  }
184 
185  template<class ImmerT1, class RangeT2, class Pred, class Func>
186  ImmerT1 sortedUniqueMerge(ImmerT1 base, RangeT2 addon, Pred exists, Func keyOf)
187  {
188  auto needToAdd = intoImmer(ImmerT1{},
189  zug::filter([=](auto a) {
190  return !exists(a);
191  }),
192  addon);
193 
194  auto cmp = [=](auto a, auto b) {
195  return keyOf(a) < keyOf(b);
196  };
197 
198  for (auto item : needToAdd) {
199  auto it = std::upper_bound(immerBegin(base), immerEnd(base), item, cmp);
200  auto index = it.index();
201  base = std::move(base).insert(index, item);
202  }
203 
204  return base;
205  }
206 
207  std::string increaseTxnId(std::string cur);
208 
209  std::string getTxnId(Event event, ClientModel &m);
210 }
211 
212 namespace std
213 {
214  template<> struct hash<Kazv::KeyOfState>
215  {
216  std::size_t operator()(const Kazv::KeyOfState & k) const noexcept {
217  std::size_t seed = 0;
218  boost::hash_combine(seed, k.type);
219  boost::hash_combine(seed, k.stateKey);
220  return seed;
221  }
222  };
223 }
224 
225 #define KAZV_WRAP_ATTR(_type, _d, _attr) \
226  inline auto _attr() const { \
227  KAZV_VERIFY_THREAD_ID(); \
228  return (_d)[&_type::_attr]; \
229  }
230 
231 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
detail::IntoImmerT intoImmer
Definition: cursorutil.hpp:88
ImmerT1 sortedUniqueMerge(ImmerT1 base, RangeT2 addon, Pred exists, Func keyOf)
Definition: clientutil.hpp:186
std::string getTxnId(Event, ClientModel &m)
Definition: clientutil.cpp:19
KeyOfState keyOfState(Event e)
Definition: clientutil.hpp:67
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:584
JobInterface & getJobHandler(Context &&ctx)
Definition: clientutil.hpp:72
EventInterface & getEventEmitter(Context &&ctx)
Definition: clientutil.hpp:78
Definition: clientutil.hpp:213
Definition: jobinterface.hpp:21
Definition: clientutil.hpp:56
std::string type
Definition: clientutil.hpp:57
std::string stateKey
Definition: clientutil.hpp:58
friend bool operator==(const KeyOfState &a, const KeyOfState &b)=default
std::size_t operator()(const Kazv::KeyOfState &k) const noexcept
Definition: clientutil.hpp:216