$darkmode
error.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  */
22 #pragma once
23 
24 #include <stdexcept> // for exception
25 #include <string> // for string
26 #include <utility> // for move
27 
28 #include <fmt/format.h> // for format
29 
30 #include <fable/conf.hpp>
31 #include <fable/fable_fwd.hpp>
32 #include <fable/json.hpp>
33 
34 namespace fable {
35 
36 class Error;
37 class ConfError;
38 class SchemaError;
39 
40 class Error : public std::exception {
41  std::string message_;
42 
43  public:
44  Error() = delete;
45  Error(const Error&) = default;
46  Error(Error&&) = default;
47  Error& operator=(const Error&) = default;
48  Error& operator=(Error &&) = default;
49  ~Error() noexcept override = default;
50 
51  Error(std::string what) : message_(std::move(what)) {}
52 
53  template <typename... Args>
54  explicit Error(std::string_view format, Args&&... args)
55  : message_(fmt::format(fmt::runtime(format), std::forward<Args>(args)...)) {}
56 
57  [[nodiscard]] const char* what() const noexcept override { return message_.c_str(); }
58 };
59 
60 class ConfError : public Error {
61  Conf data_;
62 
63  public:
64  ConfError() = delete;
65  ConfError(const ConfError&) = default;
66  ConfError(ConfError&&) = default;
67  ConfError& operator=(const ConfError&) = default;
68  ConfError& operator=(ConfError &&) = default;
69  ~ConfError() noexcept override = default;
70 
71  ConfError(Conf conf, const std::string& msg) : Error(msg), data_(std::move(conf)) {}
72  ConfError(Conf conf, const char* msg) : Error(msg), data_(std::move(conf)) {}
73 
74  template <typename... Args>
75  ConfError(Conf conf, std::string_view format, Args&&... args)
76  : Error(format, std::forward<Args>(args)...), data_(std::move(conf)) {}
77 
78  [[nodiscard]] std::string file() const noexcept { return data_.file(); }
79  [[nodiscard]] std::string root() const noexcept { return data_.root(); }
80  [[nodiscard]] const Conf& conf() const noexcept { return data_; }
81  [[nodiscard]] const Json& data() const noexcept { return *data_; }
82 
83  [[nodiscard]] virtual std::string message() const {
84  return fmt::format("{}:{}: {}", file(), root(), this->what());
85  }
86 
87  friend SchemaError;
88  friend void to_json(Json& jref, const ConfError& err) {
89  jref = Json{
90  {"error", err.what()}, {"file", err.file()}, {"root", err.root()},
91  {"data", err.data()}, {"message", err.message()},
92  };
93  }
94 };
95 
96 namespace error {
97 
98 inline ConfError MissingProperty(const Conf& conf, const std::string& key) {
99  return ConfError{conf, "required property missing: {}", key};
100 }
101 
102 inline ConfError UnexpectedProperty(const Conf& conf, const std::string& key) {
103  return ConfError{conf, "unexpected property present: {}", key};
104 }
105 
106 inline ConfError WrongType(const Conf& conf, JsonType type) {
107  std::string want = to_string(type);
108  std::string got = to_string(conf->type());
109  return ConfError{conf, "property must have type {}, got {}", want, got};
110 }
111 
112 inline ConfError WrongType(const Conf& conf, const std::string& key, JsonType type) {
113  std::string want = to_string(type);
114  std::string got = to_string((*conf)[key].type());
115  return ConfError{conf, "property must have type {}, got {}", want, got};
116 }
117 
118 inline ConfError WrongType(const Conf& conf, const std::string& key) {
119  std::string got = to_string((*conf)[key].type());
120  return ConfError{conf, "property has wrong type {}", got};
121 }
122 
123 inline ConfError WrongType(const Conf& conf) {
124  std::string got = to_string(conf->type());
125  return ConfError{conf, "property has wrong type {}", got};
126 }
127 
128 } // namespace error
129 
130 class SchemaError : public ConfError {
131  Json schema_;
132  Json context_;
133 
134  public: // Constructors
135  SchemaError() = delete;
136  SchemaError(const SchemaError&) = default;
137  SchemaError(SchemaError&&) = default;
138  SchemaError& operator=(const SchemaError&) = default;
139  SchemaError& operator=(SchemaError &&) = default;
140  ~SchemaError() noexcept override = default;
141 
148  SchemaError(const ConfError& err, Json schema) : ConfError(err), schema_(std::move(schema)) {}
149 
158  template <typename... Args>
159  SchemaError(const Conf& conf, Json schema, std::string_view format, Args&&... args)
160  : ConfError(conf, format, std::forward<Args>(args)...), schema_(std::move(schema)) {}
161 
162  [[nodiscard]] const Json& schema() const { return schema_; }
163  [[nodiscard]] const Json& context() const { return context_; }
164 
165  SchemaError& with_context(Json ctx) {
166  context_ = std::move(ctx);
167  return *this;
168  }
169 
170  friend void to_json(Json& json, const SchemaError& err) {
171  json = Json{
172  {"error", err.what()}, {"file", err.file()}, {"root", err.root()},
173  {"data", err.data()}, {"message", err.message()}, {"schema", err.schema_},
174  };
175  if (!err.context_.empty()) {
176  json["context"] = err.context_;
177  }
178  }
179 };
180 
181 } // namespace fable
Definition: error.hpp:60
Definition: conf.hpp:76
std::string root() const
Definition: conf.hpp:125
const std::string & file() const
Definition: conf.hpp:99
Definition: error.hpp:40
Definition: error.hpp:130
SchemaError(const ConfError &err, Json schema)
Definition: error.hpp:148
SchemaError(const Conf &conf, Json schema, std::string_view format, Args &&... args)
Definition: error.hpp:159
nlohmann::json Json
Definition: fable_fwd.hpp:35