$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 = 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))
48  , prototype_(std::move(prototype))
49  , ptr_(ptr) {}
50 
51  public: // Specials
58  [[nodiscard]] bool extend() const { return option_extend_; }
59 
63  void set_extend(bool value) { option_extend_ = !value; }
64 
68  Vector<T, P> extend(bool value) && {
69  option_extend_ = value;
70  return std::move(*this);
71  }
72 
73  [[nodiscard]] size_t min_items() const { return min_items_; }
74  void set_min_items(size_t value) { min_items_ = value; }
75  Vector<T, P> min_items(size_t value) && {
76  min_items_ = value;
77  return std::move(*this);
78  }
79 
80  [[nodiscard]] size_t max_items() const { return max_items_; }
81  void set_max_items(size_t value) { max_items_ = value; }
82  Vector<T, P> max_items(size_t value) && {
83  max_items_ = value;
84  return std::move(*this);
85  }
86 
87  public: // Overrides
88  [[nodiscard]] std::string type_string() const override { return "array of " + prototype_.type_string(); }
89 
90  [[nodiscard]] Json json_schema() const override {
91  Json j{
92  {"type", "array"},
93  {"items", prototype_.json_schema()},
94  };
95  if (min_items_ != 0) {
96  j["minItems"] = min_items_;
97  }
98  if (max_items_ != std::numeric_limits<size_t>::max()) {
99  j["maxItems"] = max_items_;
100  }
101  this->augment_schema(j);
102  return j;
103  }
104 
105  bool validate(const Conf& c, std::optional<SchemaError>& err) const override {
106  if (!this->validate_type(c, err)) {
107  return false;
108  }
109  if (c->size() < min_items_) {
110  return this->set_error(err, c, "require at least {} items in array, got {}", min_items_,
111  c->size());
112  }
113  if (c->size() > max_items_) {
114  return this->set_error(err, c, "expect at most {} items in array, got {}", max_items_,
115  c->size());
116  }
117  for (const auto& x : c.to_array()) {
118  if (!prototype_.validate(x, err)) {
119  return false;
120  }
121  }
122  return true;
123  }
124 
125  using Interface::to_json;
126  void to_json(Json& j) const override {
127  assert(ptr_ != nullptr);
128  if (j.type() != JsonType::array) {
129  j = Json::array();
130  }
131  serialize_into(j, *ptr_);
132  }
133 
134  void from_conf(const Conf& c) override {
135  assert(ptr_ != nullptr);
136  assert(c->type() == this->type_);
137  deserialize_into(c, *ptr_);
138  }
139 
140  [[nodiscard]] Json serialize(const Type& xs) const {
141  Json j = Json::array();
142  serialize_into(j, xs);
143  return j;
144  }
145 
146  [[nodiscard]] Type deserialize(const Conf& c) const {
147  Type vec;
148  vec.reserve(c->size());
149  fill(vec, c);
150  return vec;
151  }
152 
153  void serialize_into(Json& j, const Type& xs) const {
154  for (const auto& x : xs) {
155  j.emplace_back(prototype_.serialize(x));
156  }
157  }
158 
159  void deserialize_into(const Conf& c, Type& x) const {
160  auto size = c->size();
161  if (option_extend_) {
162  size += x.size();
163  } else {
164  x.clear();
165  }
166  x.reserve(size);
167  fill(x, c);
168  }
169 
170  void reset_ptr() override { ptr_ = nullptr; }
171 
172  private:
173  void fill(Type& vec, const Conf& c) const {
174  for (const auto& x : c.to_array()) {
175  T inst = prototype_.deserialize(x);
176  vec.emplace_back(std::move(inst));
177  }
178  }
179 
180  private:
181  bool option_extend_{false};
182  size_t min_items_{0};
183  size_t max_items_{std::numeric_limits<size_t>::max()};
184  PrototypeSchema prototype_{};
185  Type* ptr_{nullptr};
186 };
187 
188 template <typename T, typename P>
189 Vector<T, P> make_schema(std::vector<T>* ptr, P prototype, std::string desc) {
190  return Vector<T, P>(ptr, std::move(prototype), std::move(desc));
191 }
192 
193 template <typename T>
194 Vector<T, decltype(make_prototype<T>())> make_schema(std::vector<T>* ptr, std::string desc) {
195  return Vector<T, decltype(make_prototype<T>())>(ptr, std::move(desc));
196 }
197 
198 } // namespace fable::schema
Definition: conf.hpp:76
std::vector< Conf > to_array() const
Definition: conf.cpp:92
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:88
void set_extend(bool value)
Definition: vector.hpp:63
Vector< T, P > extend(bool value) &&
Definition: vector.hpp:68
Json json_schema() const override
Definition: vector.hpp:90
bool extend() const
Definition: vector.hpp:58
void reset_ptr() override
Definition: vector.hpp:170
void from_conf(const Conf &c) override
Definition: vector.hpp:134
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: vector.hpp:105
void to_json(Json &j) const override
Definition: vector.hpp:126
nlohmann::json Json
Definition: fable_fwd.hpp:35