$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 = 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))
79  , prototype_(std::move(prototype))
80  , ptr_(ptr) {
81  prototype_.reset_ptr();
82  }
83 
84  public: // Overrides
85  [[nodiscard]] std::string type_string() const override { return prototype_.type_string() + "?"; }
86  [[nodiscard]] bool is_variant() const override { return true; }
87 
88  [[nodiscard]] Json json_schema() const override {
89  Json j{{
90  "oneOf",
91  {
92  Json{
93  {"type", "null"},
94  },
95  prototype_.json_schema(),
96  },
97  }};
98  this->augment_schema(j);
99  return j;
100  }
101 
102  bool validate(const Conf& c, std::optional<SchemaError>& err) const override {
103  if (c->type() == JsonType::null) {
104  return true;
105  }
106  if (!this->validate_type(c, err)) {
107  return false;
108  }
109  return prototype_.validate(c, err);
110  }
111 
112  using Interface::to_json;
113  void to_json(Json& j) const override {
114  assert(ptr_ != nullptr);
115  j = serialize(*ptr_);
116  }
117 
118  void from_conf(const Conf& c) override {
119  assert(ptr_ != nullptr);
120  *ptr_ = deserialize(c);
121  }
122 
123  [[nodiscard]] Json serialize(const Type& x) const {
124  if (!x) {
125  return nullptr;
126  }
127  return prototype_.serialize(x.value());
128  }
129 
130  [[nodiscard]] Type deserialize(const Conf& c) const {
131  if (c->type() == JsonType::null) {
132  return Type{};
133  }
134  return prototype_.deserialize(c);
135  }
136 
137  void serialize_into(Json& j, const Type& x) const { j = serialize(x); }
138 
139  void deserialize_into(const Conf& c, Type& x) const { x = deserialize(c); }
140 
141  void reset_ptr() override { ptr_ = nullptr; }
142 
143  private:
144  PrototypeSchema prototype_;
145  Type* ptr_{nullptr};
146 };
147 
148 // Define make_schema only for std::optional and boost::optional.
149 template <typename T, typename P, std::enable_if_t<is_optional_v<T>, bool> = true>
150 inline Optional<T, P> make_schema(T* ptr, P prototype, std::string desc) {
151  return Optional<T, P>(ptr, std::move(prototype), std::move(desc));
152 }
153 
154 template <typename T, std::enable_if_t<is_optional_v<T>, bool> = true>
155 Optional<T, decltype(make_prototype<typename T::value_type>())> make_schema(T* ptr,
156  std::string desc) {
157  return Optional<T, decltype(make_prototype<typename T::value_type>())>(ptr, std::move(desc));
158 }
159 
160 } // namespace fable::schema
Definition: conf.hpp:76
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:85
void to_json(Json &j) const override
Definition: optional.hpp:113
bool is_variant() const override
Definition: optional.hpp:86
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: optional.hpp:102
Json json_schema() const override
Definition: optional.hpp:88
void reset_ptr() override
Definition: optional.hpp:141
void from_conf(const Conf &c) override
Definition: optional.hpp:118
nlohmann::json Json
Definition: fable_fwd.hpp:35
Definition: optional.hpp:47