$darkmode
schema.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  */
115 #pragma once
116 
117 #include <memory> // for shared_ptr<>
118 #include <string> // for string
119 #include <type_traits> // for enable_if_t<>, is_arithmetic<>, is_enum<>, ...
120 #include <utility> // for move
121 #include <vector> // for vector<>
122 
123 #include <fable/fable_fwd.hpp>
124 #include <fable/schema/array.hpp> // for Array<>
125 #include <fable/schema/boolean.hpp> // for Boolean
126 #include <fable/schema/confable.hpp> // for FromConfable
127 #include <fable/schema/const.hpp> // for Const<>
128 #include <fable/schema/duration.hpp> // for Duration<>
129 #include <fable/schema/enum.hpp> // for Enum<>
130 #include <fable/schema/ignore.hpp> // for Ignore
131 #include <fable/schema/interface.hpp> // for Interface, Box
132 #include <fable/schema/json.hpp> // for FromJson<>
133 #include <fable/schema/map.hpp> // for Map<>
134 #include <fable/schema/number.hpp> // for Number<>
135 #include <fable/schema/optional.hpp> // for Optional<>
136 #include <fable/schema/passthru.hpp> // for Passthru
137 #include <fable/schema/path.hpp> // for Path
138 #include <fable/schema/string.hpp> // for String
139 #include <fable/schema/struct.hpp> // for Struct
140 #include <fable/schema/variant.hpp> // for Variant
141 #include <fable/schema/vector.hpp> // for Vector<>
142 
143 // It is important that this include comes after all the other ones,
144 // so that it has access to ALL the previous definitions.
145 #include <fable/schema/xmagic.hpp> // for make_prototype
146 
147 namespace fable {
148 
149 // Bring all make_* functions into the fable namespace.
150 using schema::make_const_schema;
151 using schema::make_prototype;
152 using schema::make_schema;
153 
161 template <typename T>
162 struct schema_type {
163  using type = decltype(make_schema(static_cast<T*>(nullptr), ""));
164 };
165 
173 class Schema : public schema::Interface {
174  public:
175  // Operators
176  ~Schema() noexcept override = default;
177  Schema(const Schema&) = default;
178  Schema(Schema&&) = default;
179  Schema& operator=(const Schema&) = default;
180  Schema& operator=(Schema&&) = default;
181 
182  // Struct
183  Schema(std::string desc, schema::PropertyList<> props)
184  : impl_(new schema::Struct(std::move(desc), props)) {}
185 
186  Schema(schema::PropertyList<> props) : Schema("", props) {}
187 
188  Schema(std::string desc, const Schema& base, schema::PropertyList<> props)
189  : impl_(new schema::Struct(std::move(desc), base, props)) {}
190 
191  Schema(const Schema& base, schema::PropertyList<> props) : Schema("", base, props) {}
192 
193  // Variant
194  Schema(const std::vector<Schema>& xs); // NOLINT(runtime/explicit)
195  Schema(std::string desc, const std::vector<Schema>& xs);
196 
197  Schema(schema::BoxList props); // NOLINT(runtime/explicit)
198  Schema(std::string desc, schema::BoxList props);
199 
200  Schema(schema::BoxVec&& props); // NOLINT(runtime/explicit)
201  Schema(std::string desc, schema::BoxVec&& props);
202 
203  // Interface
204  template <typename T, std::enable_if_t<std::is_base_of_v<schema::Interface, T>, int> = 0>
205  Schema(const T& value) : impl_(value.clone()) {}
206  Schema(std::unique_ptr<schema::Interface> ptr) : impl_(std::move(ptr)) { assert(impl_); }
207  Schema(std::shared_ptr<schema::Interface> ptr) : impl_(std::move(ptr)) { assert(impl_); }
208 
209  // Ignore
210  Schema() : impl_(new schema::Ignore("")) {}
211  explicit Schema(std::string desc, JsonType t = JsonType::object)
212  : impl_(new schema::Ignore(std::move(desc), t)) {}
213 
214  // Primitives
215  template <typename T>
216  Schema(T* ptr, std::string desc) : impl_(make_schema(ptr, std::move(desc)).clone()) {}
217  template <typename T>
218  Schema(T* ptr, const schema::Box& prototype, std::string desc)
219  : impl_(make_schema(ptr, prototype, std::move(desc)).clone()) {}
220 
221  // FromJson
222  template <typename T>
223  Schema(T* ptr, JsonType t, std::string desc)
224  : impl_(new schema::FromJson<T>(ptr, t, std::move(desc))) {}
225 
226  public: // Special
227  Schema reset_pointer() && {
228  reset_ptr();
229  return std::move(*this);
230  }
231 
232  [[nodiscard]] Json json_schema_qualified() const {
233  Json j = impl_->json_schema();
234  j["$schema"] = "http://json-schema.org/draft-07/schema#";
235  return j;
236  }
237 
238  [[nodiscard]] Json json_schema_qualified(const std::string& id) const {
239  Json j = json_schema_qualified();
240  j["$id"] = id;
241  return j;
242  }
243 
244  public: // Overrides
245  using Interface::to_json;
246  [[nodiscard]] operator schema::Box() const { return schema::Box{impl_}; }
247  [[nodiscard]] std::unique_ptr<Interface> clone() const override { return impl_->clone(); }
248  [[nodiscard]] JsonType type() const override { return impl_->type(); }
249  [[nodiscard]] std::string type_string() const override { return impl_->type_string(); }
250  [[nodiscard]] bool is_required() const override { return impl_->is_required(); }
251  [[nodiscard]] const std::string& description() const override { return impl_->description(); }
252  void set_description(std::string s) override { return impl_->set_description(std::move(s)); }
253  [[nodiscard]] Json usage() const override { return impl_->usage(); }
254  [[nodiscard]] Json json_schema() const override { return impl_->json_schema(); }
255  bool validate(const Conf& c, std::optional<SchemaError>& err) const override {
256  return impl_->validate(c, err);
257  }
258  void to_json(Json& j) const override { impl_->to_json(j); }
259  void from_conf(const Conf& c) override { impl_->from_conf(c); }
260  void reset_ptr() override { impl_->reset_ptr(); }
261 
262  friend void to_json(Json& j, const Schema& s) { s.impl_->to_json(j); }
263 
264  private:
265  std::shared_ptr<schema::Interface> impl_{nullptr};
266 };
267 
268 } // namespace fable
Definition: conf.hpp:82
Definition: schema.hpp:173
bool is_required() const override
Definition: schema.hpp:250
void to_json(Json &j) const override
Definition: schema.hpp:258
Json usage() const override
Definition: schema.hpp:253
const std::string & description() const override
Definition: schema.hpp:251
void reset_ptr() override
Definition: schema.hpp:260
void set_description(std::string s) override
Definition: schema.hpp:252
void from_conf(const Conf &c) override
Definition: schema.hpp:259
Json json_schema() const override
Definition: schema.hpp:254
std::string type_string() const override
Definition: schema.hpp:249
std::unique_ptr< Interface > clone() const override
Definition: schema.hpp:247
JsonType type() const override
Definition: schema.hpp:248
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: schema.hpp:255
Definition: interface.hpp:297
Definition: json.hpp:46
Definition: ignore.hpp:43
Definition: interface.hpp:67
virtual Json to_json() const
Definition: interface.hpp:254
Definition: struct.hpp:70
nlohmann::json Json
Definition: fable_fwd.hpp:35
nlohmann::json::value_t JsonType
Definition: json.hpp:78
Definition: schema.hpp:162