$darkmode
array.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  */
25 #pragma once
26 #ifndef FABLE_SCHEMA_ARRAY_HPP_
27 #define FABLE_SCHEMA_ARRAY_HPP_
28 
29 #include <limits> // for numeric_limits<>
30 #include <memory> // for shared_ptr<>
31 #include <string> // for string
32 #include <type_traits> // for enable_if_t<>, is_convertible<>
33 #include <utility> // for move
34 #include <vector> // for vector<>
35 
36 #include <fable/schema/interface.hpp> // for Base<>, Box
37 
38 namespace fable {
39 namespace schema {
40 
41 template <typename T, typename P>
42 class Array : public Base<Array<T, P>> {
43  public: // Types and Constructors
44  using Type = std::vector<T>;
45  using PrototypeSchema = P;
46 
47  Array(Type* ptr, std::string&& desc);
48  Array(Type* ptr, const PrototypeSchema& prototype)
49  : Base<Array<T, P>>(JsonType::array), prototype_(prototype), ptr_(ptr) {}
50  Array(Type* ptr, const PrototypeSchema& prototype, std::string&& desc)
51  : Base<Array<T, P>>(JsonType::array, std::move(desc)), prototype_(prototype), ptr_(ptr) {}
52 
53 #if 0
54  // This is defined in: fable/schema/magic.hpp
55  Array(Type* ptr, std::string&& desc)
56  : Array(ptr, make_prototype<T>(), std::move(desc)) {}
57 #endif
58 
59  public: // Specials
66  bool extend() const { return option_extend_; }
67 
71  void set_extend(bool value) { option_extend_ = !value; }
72 
76  Array<T, P> extend(bool value) && {
77  option_extend_ = value;
78  return std::move(*this);
79  }
80 
81  size_t min_items() const { return min_items_; }
82  void set_min_items(size_t value) { min_items_ = value; }
83  Array<T, P> min_items(size_t value) && {
84  min_items_ = value;
85  return std::move(*this);
86  }
87 
88  size_t max_items() const { return max_items_; }
89  void set_max_items(size_t value) { max_items_ = value; }
90  Array<T, P> max_items(size_t value) && {
91  max_items_ = value;
92  return std::move(*this);
93  }
94 
95  public: // Overrides
96  std::string type_string() const override { return "array of " + prototype_.type_string(); }
97 
98  Json json_schema() const override {
99  Json j{
100  {"type", "array"},
101  {"items", prototype_.json_schema()},
102  };
103  if (min_items_ != 0) {
104  j["minItems"] = min_items_;
105  }
106  if (max_items_ != std::numeric_limits<size_t>::max()) {
107  j["maxItems"] = max_items_;
108  }
109  this->augment_schema(j);
110  return j;
111  }
112 
113  void validate(const Conf& c) const override {
114  this->validate_type(c);
115  if (c->size() < min_items_) {
116  this->throw_error(c, "require at least {} items in array, got {}", min_items_, c->size());
117  }
118  if (c->size() > max_items_) {
119  this->throw_error(c, "expect at most {} items in array, got {}", max_items_, c->size());
120  }
121 
122  for (const auto& x : c.to_array()) {
123  prototype_.validate(x);
124  }
125  }
126 
127  using Interface::to_json;
128  void to_json(Json& j) const override {
129  assert(ptr_ != nullptr);
130  j = serialize(*ptr_);
131  }
132 
133  void from_conf(const Conf& c) override {
134  assert(ptr_ != nullptr);
135  assert(c->type() == this->type_);
136 
137  if (!option_extend_) {
138  ptr_->clear();
139  }
140 
141  ptr_->reserve(c->size() + ptr_->size());
142  fill(*ptr_, c);
143  }
144 
145  Json serialize(const Type& xs) const {
146  Json j = Json::array();
147  for (const auto& x : xs) {
148  j.emplace_back(prototype_.serialize(x));
149  }
150  return j;
151  }
152 
153  Type deserialize(const Conf& c) const {
154  Type vec;
155  vec.reserve(c->size());
156  fill(vec, c);
157  return vec;
158  }
159 
160  void reset_ptr() override { ptr_ = nullptr; }
161 
162  private:
163  void fill(Type& vec, const Conf& c) const {
164  for (const auto& x : c.to_array()) {
165  T inst = prototype_.deserialize(x);
166  vec.emplace_back(std::move(inst));
167  }
168  }
169 
170  private:
171  bool option_extend_{false};
172  size_t min_items_{0};
173  size_t max_items_{std::numeric_limits<size_t>::max()};
174  PrototypeSchema prototype_{};
175  Type* ptr_{nullptr};
176 };
177 
178 template <typename T, typename P>
179 Array<T, P> make_schema(std::vector<T>* ptr, const P& prototype, std::string&& desc) {
180  return Array<T, P>(ptr, prototype, std::move(desc));
181 }
182 
183 } // namespace schema
184 } // namespace fable
185 
186 #endif // FABLE_SCHEMA_ARRAY_HPP_
Definition: conf.hpp:74
Definition: array.hpp:42
void to_json(Json &j) const override
Definition: array.hpp:128
void validate(const Conf &c) const override
Definition: array.hpp:113
nlohmann::json Json
Definition: json.hpp:62
void reset_ptr() override
Definition: array.hpp:160
Definition: conf.hpp:70
virtual Json to_json() const
Definition: interface.hpp:220
Json json_schema() const override
Definition: array.hpp:98
void set_extend(bool value)
Definition: array.hpp:71
std::vector< Conf > to_array() const
Definition: conf.cpp:92
Array< T, P > extend(bool value) &&
Definition: array.hpp:76
std::string type_string() const override
Definition: array.hpp:96
void from_conf(const Conf &c) override
Definition: array.hpp:133
Definition: interface.hpp:354
bool extend() const
Definition: array.hpp:66