$darkmode
enum.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  */
24 #pragma once
25 
26 #include <map> // for map<>
27 #include <string> // for string
28 #include <type_traits> // for enable_if_t<>, is_enum<>
29 #include <utility> // for move, make_pair
30 #include <vector> // for vector<>
31 
32 #include <fable/enum.hpp>
33 #include <fable/schema/interface.hpp> // for Base<>
34 
35 namespace fable::schema {
36 
37 template <typename T>
38 class Enum : public Base<Enum<T>> {
39  public: // Types and Constructors
40  using Type = T;
41 
42  Enum(Type* ptr, std::string desc)
43  : Base<Enum<T>>(JsonType::string, std::move(desc))
44  , mapping_to_(enum_serialization<T>())
45  , mapping_from_(enum_deserialization<T>())
46  , ptr_(ptr) {
47  keys_.reserve(mapping_to_.size());
48  for (auto const& kv : mapping_to_) {
49  keys_.emplace_back(kv.second);
50  }
51  }
52 
53  public: // Special
54  [[nodiscard]] const std::vector<std::string>& keys() const { return keys_; }
55 
56  public: // Overrides
57  [[nodiscard]] Json json_schema() const override {
58  Json j{
59  {"type", this->type_string()},
60  {"enum", keys_},
61  };
62  this->augment_schema(j);
63  return j;
64  }
65 
66  bool validate(const Conf& c, std::optional<SchemaError>& err) const override {
67  auto s = c.get<std::string>();
68  if (mapping_from_.count(s) == 0) {
69  return this->set_error(err, c, "invalid value for enum: {}", s);
70  }
71  return true;
72  }
73 
74  using Interface::to_json;
75 
76  void to_json(Json& j) const override {
77  assert(ptr_ != nullptr);
78  j = serialize(*ptr_);
79  }
80 
81  void from_conf(const Conf& c) override {
82  assert(ptr_ != nullptr);
83  *ptr_ = deserialize(c);
84  }
85 
86  Json serialize(const Type& x) const { return mapping_to_.at(x); }
87 
88  Type deserialize(const Conf& c) const {
89  auto s = c.get<std::string>();
90  try {
91  return mapping_from_.at(s);
92  } catch (std::out_of_range& e) {
93  throw this->error(c, "invalid value for enum: {}", s);
94  }
95  }
96 
97  void serialize_into(Json& j, const Type& x) const { j = mapping_to_.at(x); }
98 
99  void deserialize_into(const Conf& c, Type& x) const { x = deserialize(c); }
100 
101  void reset_ptr() override { ptr_ = nullptr; }
102 
103  private:
104  const std::map<T, std::string>& mapping_to_; // NOLINT: type-specific global ref
105  const std::map<std::string, T>& mapping_from_; // NOLINT: type-specific global ref
106  std::vector<std::string> keys_;
107  Type* ptr_{nullptr};
108 };
109 
110 template <typename T, typename S, std::enable_if_t<std::is_enum_v<T>, int> = 0>
111 Enum<T> make_schema(T* ptr, S&& desc) {
112  return {ptr, std::forward<S>(desc)};
113 }
114 
115 } // namespace fable::schema
Definition: conf.hpp:82
T get() const
Definition: conf.hpp:298
Definition: interface.hpp:398
std::string type_string() const override
Definition: interface.hpp:419
Definition: enum.hpp:38
Json json_schema() const override
Definition: enum.hpp:57
void to_json(Json &j) const override
Definition: enum.hpp:76
void reset_ptr() override
Definition: enum.hpp:101
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: enum.hpp:66
void from_conf(const Conf &c) override
Definition: enum.hpp:81
virtual Json to_json() const
Definition: interface.hpp:254
nlohmann::json Json
Definition: fable_fwd.hpp:35