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