libkazv
Loading...
Searching...
No Matches
types.hpp
Go to the documentation of this file.
1/*
2 * This file is part of libkazv.
3 * SPDX-FileCopyrightText: 2020-2021 Tusooa Zhu <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 <optional>
12#include <string>
13#include <variant>
14
15#include <nlohmann/json.hpp>
16#include <immer/array.hpp>
17#include <immer/flex_vector.hpp>
18#include <immer/map.hpp>
19#include <boost/hana/type.hpp>
20#include <lager/util.hpp>
21
22#include "jsonwrap.hpp"
23#include "event.hpp"
24
25namespace Kazv
26{
27 using Bytes = std::string;
28
29 enum Status : bool
30 {
33 };
34
35 namespace detail
36 {
37 constexpr auto hasEmptyMethod = boost::hana::is_valid(
38 [](auto t) -> decltype((void)std::declval<typename decltype(t)::type>().empty()) {});
39 template<class U>
40 struct AddToJsonIfNeededT
41 {
42 template<class T>
43 static void call(json &j, std::string name, T &&arg) {
44 using Type = std::decay_t<T>;
45 if constexpr (detail::hasEmptyMethod(boost::hana::type_c<Type>)) {
46 if (! arg.empty()) {
47 j[name] = std::forward<T>(arg);
48 }
49 } else {
50 j[name] = std::forward<T>(arg);
51 }
52 }
53 };
54
55 template<class U>
56 struct AddToJsonIfNeededT<std::optional<U>>
57 {
58 template<class T>
59 static void call(json &j, std::string name, T &&arg) {
60 if (arg.has_value()) {
61 j[name] = std::forward<T>(arg).value();
62 }
63 }
64 };
65
66 template<>
67 struct AddToJsonIfNeededT<JsonWrap>
68 {
69 template<class T>
70 static void call(json &j, std::string name, T &&arg) {
71 if (!arg.get().is_null()) {
72 j[name] = std::forward<T>(arg).get();
73 }
74 }
75 };
76
77 }
78
79 template<class T>
80 inline void addToJsonIfNeeded(json &j, std::string name, T &&arg)
81 {
82 detail::AddToJsonIfNeededT<std::decay_t<T>>::call(j, name, std::forward<T>(arg));
83 };
84
85 // Provide a non-destructive way to add the map
86 // to json.
87 template<class MapT,
88 // disallow json object here
89 std::enable_if_t<!std::is_same_v<std::decay_t<MapT>, json>
90 && !std::is_same_v<std::decay_t<MapT>, JsonWrap>, int> = 0>
91 inline void addPropertyMapToJson(json &j, MapT &&arg)
92 {
93 for (auto kv : std::forward<MapT>(arg)) {
94 auto [k, v] = kv;
95 j[k] = v;
96 }
97 };
98
99 inline void addPropertyMapToJson(json &j, const json &arg)
100 {
101 for (auto kv : arg.items()) {
102 auto [k, v] = kv;
103 j[k] = v;
104 }
105 };
106
107 using EventList = immer::flex_vector<Event>;
108
109 using namespace std::string_literals;
110
111 struct Null {};
112 using Variant = std::variant<std::string, JsonWrap, Null>;
113
114 namespace detail
115 {
116 struct DefaultValT
117 {
118 template<class T>
119 constexpr operator T() const {
120 return T();
121 }
122 };
123 }
124
125 constexpr detail::DefaultValT DEFVAL;
126
131
132 namespace detail
133 {
134 // emulates declval() but returns lvalue reference
135 template<class T>
136 typename std::add_lvalue_reference<T>::type declref() noexcept;
137 }
138}
139
140namespace nlohmann {
141 template <class T, class V>
142 struct adl_serializer<immer::map<T, V>> {
143 static void to_json(json& j, immer::map<T, V> map) {
144 if constexpr (std::is_same_v<T, std::string>) {
145 j = json::object();
146 for (auto [k, v] : map) {
147 j[k] = v;
148 }
149 } else {
150 j = json::array();
151 for (auto [k, v] : map) {
152 j.push_back(k);
153 j.push_back(v);
154 }
155 }
156 }
157
158 static void from_json(const json& j, immer::map<T, V> &m) {
159 immer::map<T, V> ret;
160 if constexpr (std::is_same_v<T, std::string>) {
161 for (const auto &[k, v] : j.items()) {
162 ret = std::move(ret).set(k, v);
163 }
164 } else {
165 for (std::size_t i = 0; i < j.size(); i += 2) {
166 ret = std::move(ret).set(j[i], j[i+1]);
167 }
168 }
169 m = ret;
170 }
171 };
172
173 template <class T>
174 struct adl_serializer<immer::array<T>> {
175 static void to_json(json& j, immer::array<T> arr) {
176 j = json::array();
177 for (auto i : arr) {
178 j.push_back(json(i));
179 }
180 }
181
182 static void from_json(const json& j, immer::array<T> &a) {
183 immer::array<T> ret;
184 if (j.is_array()) {
185 for (const auto &i : j) {
186 ret = std::move(ret).push_back(i);
187 }
188 }
189 a = ret;
190 }
191 };
192
193 template <class T>
194 struct adl_serializer<immer::flex_vector<T>> {
195 static void to_json(json& j, immer::flex_vector<T> arr) {
196 j = json::array();
197 for (auto i : arr) {
198 j.push_back(json(i));
199 }
200 }
201
202 static void from_json(const json& j, immer::flex_vector<T> &a) {
203 immer::flex_vector<T> ret;
204 if (j.is_array()) {
205 for (const auto &i : j) {
206 ret = std::move(ret).push_back(i.get<T>());
207 }
208 }
209 a = ret;
210 }
211 };
212
213 template <>
214 struct adl_serializer<Kazv::Variant> {
215 static void to_json(json& j, const Kazv::Variant &var) {
216 std::visit(lager::visitor{
217 [&j](std::string i) { j = i; },
218 [&j](Kazv::JsonWrap i) { j = i; },
219 [&j](Kazv::Null) { j = nullptr; }
220 }, var);
221 }
222
223 static void from_json(const json& j, Kazv::Variant &var) {
224 if (j.is_string()) {
225 var = j.get<std::string>();
226 } else if (j.is_null()) {
227 var = Kazv::Null{};
228 } else { // is object
230 }
231 }
232 };
233}
Definition jsonwrap.hpp:23
constexpr auto hasEmptyMethod
Definition types.hpp:37
std::add_lvalue_reference< T >::type declref() noexcept
Definition location.hpp:10
std::variant< std::string, JsonWrap, Null > Variant
Definition types.hpp:112
void addToJsonIfNeeded(json &j, std::string name, T &&arg)
Definition types.hpp:80
void addPropertyMapToJson(json &j, MapT &&arg)
Definition types.hpp:91
nlohmann::json json
Definition jsonwrap.hpp:20
std::string Bytes
Definition types.hpp:27
constexpr detail::DefaultValT DEFVAL
Definition types.hpp:125
Status
Definition types.hpp:30
@ FAIL
Definition types.hpp:31
@ SUCC
Definition types.hpp:32
RoomMembership
Definition types.hpp:128
@ Join
Definition types.hpp:129
@ Leave
Definition types.hpp:129
@ Invite
Definition types.hpp:129
immer::flex_vector< Event > EventList
Definition types.hpp:107
Definition location.hpp:27
Definition clientutil.hpp:140
Definition types.hpp:111
static void to_json(json &j, const Kazv::Variant &var)
Definition types.hpp:215
static void from_json(const json &j, Kazv::Variant &var)
Definition types.hpp:223
static void from_json(const json &j, immer::array< T > &a)
Definition types.hpp:182
static void to_json(json &j, immer::array< T > arr)
Definition types.hpp:175
static void from_json(const json &j, immer::flex_vector< T > &a)
Definition types.hpp:202
static void to_json(json &j, immer::flex_vector< T > arr)
Definition types.hpp:195
static void from_json(const json &j, immer::map< T, V > &m)
Definition types.hpp:158
static void to_json(json &j, immer::map< T, V > map)
Definition types.hpp:143