$darkmode
optional.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 
27 #include <optional> // for optional<>
28 #include <string> // for string
29 #include <type_traits> // for is_same_v<>, enable_if<>
30 #include <utility> // for move
31 
32 #include <fable/schema/interface.hpp> // for Base<>, Box
33 #include <fable/utility/optional.hpp> // for adl_serializer<>
34 
35 namespace fable::schema {
36 
46 template <typename T>
47 struct is_optional : std::false_type {};
48 
49 template <typename T>
50 inline constexpr bool is_optional_v = is_optional<T>::value;
51 
52 template <typename T>
53 struct is_optional<std::optional<T>> : std::true_type {};
54 
65 template <typename T, typename P>
66 class Optional : public Base<Optional<T, P>> {
67  static_assert(is_optional_v<T>);
68 
69  public: // Types and Constructors
70  using Type = T;
71  using ValueType = typename Type::value_type;
72  using PrototypeSchema = std::remove_cv_t<std::remove_reference_t<P>>;
73 
74  Optional(Type* ptr, std::string desc)
75  : Optional(ptr, make_prototype<typename T::value_type>(), std::move(desc)) {}
76 
77  Optional(Type* ptr, PrototypeSchema prototype, std::string desc)
78  : Base<Optional<T, P>>(prototype.type(), std::move(desc)), prototype_(std::move(prototype)), ptr_(ptr) {
79  prototype_.reset_ptr();
80  }
81 
82  public: // Overrides
83  [[nodiscard]] std::string type_string() const override { return prototype_.type_string() + "?"; }
84  [[nodiscard]] bool is_variant() const override { return true; }
85 
86  [[nodiscard]] Json json_schema() const override {
87  Json j{{
88  "oneOf",
89  {
90  Json{
91  {"type", "null"},
92  },
93  prototype_.json_schema(),
94  },
95  }};
96  this->augment_schema(j);
97  return j;
98  }
99 
100  bool validate(const Conf& c, std::optional<SchemaError>& err) const override {
101  if (c->type() == JsonType::null) {
102  return true;
103  }
104  if (!this->validate_type(c, err)) {
105  return false;
106  }
107  return prototype_.validate(c, err);
108  }
109 
110  using Interface::to_json;
111  void to_json(Json& j) const override {
112  assert(ptr_ != nullptr);
113  j = serialize(*ptr_);
114  }
115 
116  void from_conf(const Conf& c) override {
117  assert(ptr_ != nullptr);
118  *ptr_ = deserialize(c);
119  }
120 
121  [[nodiscard]] Json serialize(const Type& x) const {
122  if (!x) {
123  return nullptr;
124  }
125  return prototype_.serialize(x.value());
126  }
127 
128  [[nodiscard]] Type deserialize(const Conf& c) const {
129  if (c->type() == JsonType::null) {
130  return Type{};
131  }
132  return prototype_.deserialize(c);
133  }
134 
135  void serialize_into(Json& j, const Type& x) const { j = serialize(x); }
136 
137  void deserialize_into(const Conf& c, Type& x) const { x = deserialize(c); }
138 
139  void reset_ptr() override { ptr_ = nullptr; }
140 
141  private:
142  PrototypeSchema prototype_;
143  Type* ptr_{nullptr};
144 };
145 
146 // Define make_schema only for std::optional and boost::optional.
147 template <typename T, typename P, typename S, std::enable_if_t<is_optional_v<T>, bool> = true>
148 Optional<T, P> make_schema(T* ptr, P&& prototype, S&& desc) {
149  return {ptr, std::forward<P>(prototype), std::forward<S>(desc)};
150 }
151 
152 template <typename T, typename S, std::enable_if_t<is_optional_v<T>, bool> = true>
153 Optional<T, decltype(make_prototype<typename T::value_type>())> make_schema(T* ptr, S&& desc) {
154  return {ptr, std::forward<S>(desc)};
155 }
156 
157 } // namespace fable::schema
Definition: conf.hpp:81
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: optional.hpp:66
std::string type_string() const override
Definition: optional.hpp:83
void to_json(Json &j) const override
Definition: optional.hpp:111
bool is_variant() const override
Definition: optional.hpp:84
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: optional.hpp:100
Json json_schema() const override
Definition: optional.hpp:86
void reset_ptr() override
Definition: optional.hpp:139
void from_conf(const Conf &c) override
Definition: optional.hpp:116
nlohmann::json Json
Definition: fable_fwd.hpp:35
Definition: optional.hpp:47