libkazv
validator.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of libkazv.
3  * SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
4  * SPDX-License-Identifier: AGPL-3.0-or-later
5  */
6 
7 #pragma once
8 #include <libkazv-config.hpp>
9 
10 #include <functional>
11 
12 #include <types.hpp>
13 
14 namespace Kazv
15 {
60  template<class Jsonish, class Key, class Validator>
61  bool cast(Jsonish &ret, const Jsonish &input, Key &&k, Validator &&f)
62  {
63  if (!input.contains(k)) {
64  return false;
65  }
66  auto [res, output] = std::invoke(std::forward<Validator>(f), input[k]);
67  if (!res) {
68  return false;
69  }
70  ret[k] = output;
71  return true;
72  }
73 
84  template<class Func>
85  auto identValidate(Func &&f)
86  {
87  return [f=std::forward<Func>(f)](auto &&val) mutable {
88  auto res = std::invoke(std::forward<Func>(f), val);
89  return std::pair<bool, json>(res, std::forward<decltype(val)>(val));
90  };
91  }
92 
96  enum class CastArrayStrategy
97  {
101  FailAll,
102  };
103 
153  template<class Jsonish, class Key, class Validator>
154  bool castArray(Jsonish &ret, const Jsonish &input, Key &&k, Validator &&f, CastArrayStrategy strategy)
155  {
156  using JsonT = std::decay_t<Jsonish>;
157 
158  if (!(input.contains(k) && input[k].is_array())) {
159  return false;
160  }
161 
162  auto array = JsonT::array();
163 
164  for (const auto &inputItem : input[k]) {
165  auto [res, outputItem] = std::invoke(f, inputItem);
166  if (!res) {
167  if (strategy == CastArrayStrategy::FailAll) {
168  return false;
169  }
170  } else {
171  array.push_back(std::move(outputItem));
172  }
173  }
174 
175  ret[k] = std::move(array);
176 
177  return true;
178  }
179 
184  {
188  FailAll,
189  };
190 
244  template<class Jsonish, class Key, class Validator>
245  bool castObject(Jsonish &ret, const Jsonish &input, Key &&k, Validator &&f, CastObjectStrategy strategy)
246  {
247  using JsonT = std::decay_t<Jsonish>;
248 
249  if (!(input.contains(k) && input[k].is_object())) {
250  return false;
251  }
252 
253  auto obj = JsonT::object();
254 
255  for (const auto &[inputKey, inputValue] : input[k].items()) {
256  auto inputItem = JsonT::array({JsonT(inputKey), inputValue});
257  auto [res, outputItem] = std::invoke(f, inputItem);
258  if (!res) {
259  if (strategy == CastObjectStrategy::FailAll) {
260  return false;
261  }
262  } else {
263  auto outputKey = outputItem[0];
264  auto outputValue = std::move(outputItem)[1];
265  obj[std::move(outputKey)] = std::move(outputValue);
266  }
267  }
268 
269  ret[k] = std::move(obj);
270 
271  return true;
272  }
273 
286  template<class Jsonish, class Key, class Jsonish2>
287  std::decay_t<Jsonish> makeDefaultValue(Jsonish &&input, Key &&k, Jsonish2 &&defaultValue)
288  {
289  using JsonT = std::decay_t<Jsonish>;
290 
291  if (input.contains(k)) {
292  return std::forward<Jsonish>(input);
293  } else {
294  JsonT output = std::forward<Jsonish>(input);
295  output[std::forward<Key>(k)] = std::forward<Jsonish2>(defaultValue);
296  return output;
297  }
298  }
299 }
Definition: location.hpp:10
bool castObject(Jsonish &ret, const Jsonish &input, Key &&k, Validator &&f, CastObjectStrategy strategy)
Cast an object of items.
Definition: validator.hpp:245
std::decay_t< Jsonish > makeDefaultValue(Jsonish &&input, Key &&k, Jsonish2 &&defaultValue)
Replace a non-existent value with a default one.
Definition: validator.hpp:287
bool castArray(Jsonish &ret, const Jsonish &input, Key &&k, Validator &&f, CastArrayStrategy strategy)
Cast an array of items.
Definition: validator.hpp:154
CastObjectStrategy
Strategy used for castObject().
Definition: validator.hpp:184
@ IgnoreInvalid
If any item is invalid, ignore them and add all valid entries into the output.
@ FailAll
If any item is invalid, fail the entire cast.
bool cast(Jsonish &ret, const Jsonish &input, Key &&k, Validator &&f)
Run validator against input[k] and add it to ret.
Definition: validator.hpp:61
CastArrayStrategy
Strategy used for castArray().
Definition: validator.hpp:97
@ IgnoreInvalid
If any item is invalid, ignore them and add all valid entries into the output.
@ FailAll
If any item is invalid, fail the entire cast.
auto identValidate(Func &&f)
Make an identity validator.
Definition: validator.hpp:85