$darkmode
vector.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
24 #pragma once
25 
26 #include <limits> // for numeric_limits<>
27 #include <string> // for string
28 #include <utility> // for move
29 #include <vector> // for vector<>
30 
31 #include <fable/schema/interface.hpp> // for Base<>, Box
32 
33 namespace fable::schema {
34 
35 template <typename T, typename P>
36 class Vector : public Base<Vector<T, P>> {
37  public: // Types and Constructors
38  using Type = std::vector<T>;
39  using PrototypeSchema = std::remove_cv_t<std::remove_reference_t<P>>;
40 
41  Vector(Type* ptr, std::string desc) : Vector(ptr, make_prototype<T>(), std::move(desc)) {}
42 
43  Vector(Type* ptr, PrototypeSchema prototype)
44  : Base<Vector<T, P>>(JsonType::array), prototype_(std::move(prototype)), ptr_(ptr) {}
45 
46  Vector(Type* ptr, PrototypeSchema prototype, std::string desc)
47  : Base<Vector<T, P>>(JsonType::array, std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) {}
48 
49  public: // Specials
56  [[nodiscard]] bool extend() const { return option_extend_; }
57 
61  void set_extend(bool value) { option_extend_ = !value; }
62 
66  [[nodiscard]] Vector<T, P> extend(bool value) && {
67  option_extend_ = value;
68  return std::move(*this);
69  }
70 
71  [[nodiscard]] size_t min_items() const { return min_items_; }
72  void set_min_items(size_t value) { min_items_ = value; }
73  [[nodiscard]] Vector<T, P> min_items(size_t value) && {
74  min_items_ = value;
75  return std::move(*this);
76  }
77 
78  [[nodiscard]] size_t max_items() const { return max_items_; }
79  void set_max_items(size_t value) { max_items_ = value; }
80  [[nodiscard]] Vector<T, P> max_items(size_t value) && {
81  max_items_ = value;
82  return std::move(*this);
83  }
84 
85  public: // Overrides
86  [[nodiscard]] std::string type_string() const override { return "array of " + prototype_.type_string(); }
87 
88  [[nodiscard]] Json json_schema() const override {
89  Json j{
90  {"type", "array"},
91  {"items", prototype_.json_schema()},
92  };
93  if (min_items_ != 0) {
94  j["minItems"] = min_items_;
95  }
96  if (max_items_ != std::numeric_limits<size_t>::max()) {
97  j["maxItems"] = max_items_;
98  }
99  this->augment_schema(j);
100  return j;
101  }
102 
103  bool validate(const Conf& c, std::optional<SchemaError>& err) const override {
104  if (!this->validate_type(c, err)) {
105  return false;
106  }
107  if (c->size() < min_items_) {
108  return this->set_error(err, c, "require at least {} items in array, got {}", min_items_,
109  c->size());
110  }
111  if (c->size() > max_items_) {
112  return this->set_error(err, c, "expect at most {} items in array, got {}", max_items_,
113  c->size());
114  }
115  for (const auto& x : c.to_array()) {
116  if (!prototype_.validate(x, err)) {
117  return false;
118  }
119  }
120  return true;
121  }
122 
123  using Interface::to_json;
124  void to_json(Json& j) const override {
125  assert(ptr_ != nullptr);
126  if (j.type() != JsonType::array) {
127  j = Json::array();
128  }
129  serialize_into(j, *ptr_);
130  }
131 
132  void from_conf(const Conf& c) override {
133  assert(ptr_ != nullptr);
134  assert(c->type() == this->type_);
135  deserialize_into(c, *ptr_);
136  }
137 
138  [[nodiscard]] Json serialize(const Type& xs) const {
139  Json j = Json::array();
140  serialize_into(j, xs);
141  return j;
142  }
143 
144  [[nodiscard]] Type deserialize(const Conf& c) const {
145  Type vec;
146  vec.reserve(c->size());
147  fill(vec, c);
148  return vec;
149  }
150 
151  void serialize_into(Json& j, const Type& xs) const {
152  for (const auto& x : xs) {
153  j.emplace_back(prototype_.serialize(x));
154  }
155  }
156 
157  void deserialize_into(const Conf& c, Type& x) const {
158  auto size = c->size();
159  if (option_extend_) {
160  size += x.size();
161  } else {
162  x.clear();
163  }
164  x.reserve(size);
165  fill(x, c);
166  }
167 
168  void reset_ptr() override { ptr_ = nullptr; }
169 
170  private:
171  void fill(Type& vec, const Conf& c) const {
172  for (const auto& x : c.to_array()) {
173  T inst = prototype_.deserialize(x);
174  vec.emplace_back(std::move(inst));
175  }
176  }
177 
178  private:
179  bool option_extend_{false};
180  size_t min_items_{0};
181  size_t max_items_{std::numeric_limits<size_t>::max()};
182  PrototypeSchema prototype_{};
183  Type* ptr_{nullptr};
184 };
185 
186 template <typename T, typename P, typename S>
187 Vector<T, P> make_schema(std::vector<T>* ptr, P&& prototype, S&& desc) {
188  return {ptr, std::forward<P>(prototype), std::forward<S>(desc)};
189 }
190 
191 template <typename T, typename S>
192 Vector<T, decltype(make_prototype<T>())> make_schema(std::vector<T>* ptr, S&& desc) {
193  return {ptr, std::forward<S>(desc)};
194 }
195 
196 } // namespace fable::schema
Definition: conf.hpp:82
std::vector< Conf > to_array() const
Definition: conf.cpp:93
Definition: interface.hpp:398
bool validate_type(const Conf &c, std::optional< SchemaError > &err) const
Definition: interface.hpp:459
virtual Json to_json() const
Definition: interface.hpp:254
Definition: vector.hpp:36
std::string type_string() const override
Definition: vector.hpp:86
void set_extend(bool value)
Definition: vector.hpp:61
Vector< T, P > extend(bool value) &&
Definition: vector.hpp:66
Json json_schema() const override
Definition: vector.hpp:88
bool extend() const
Definition: vector.hpp:56
void reset_ptr() override
Definition: vector.hpp:168
void from_conf(const Conf &c) override
Definition: vector.hpp:132
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: vector.hpp:103
void to_json(Json &j) const override
Definition: vector.hpp:124
nlohmann::json Json
Definition: fable_fwd.hpp:35