$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 #ifndef FABLE_ERROR_HPP_
24 #define FABLE_ERROR_HPP_
25 
26 #include <stdexcept> // for exception
27 #include <string> // for string
28 
29 #include <fmt/format.h> // for format
30 
31 #include <fable/conf.hpp> // for Conf
32 #include <fable/json.hpp> // for Json
33 
34 namespace fable {
35 
36 class Error;
37 class ConfError;
38 class SchemaError;
39 
40 class Error : public std::exception {
41  public:
42  explicit Error(const std::string& what) : err_(what) {}
43  explicit Error(const char* what) : err_(what) {}
44 
45  template <typename... Args>
46  explicit Error(const char* format, const Args&... args) : err_(fmt::format(format, args...)) {}
47 
48  virtual ~Error() noexcept = default;
49 
50  const char* what() const noexcept override { return err_.what(); }
51 
52  private:
53  std::runtime_error err_;
54 };
55 
56 class ConfError : public Error {
57  const Conf data_;
58 
59  public:
60  virtual ~ConfError() noexcept = default;
61 
62  ConfError(const Conf& c, const std::string& msg) : Error(msg), data_(c) {}
63  ConfError(const Conf& c, const char* msg) : Error(msg), data_(c) {}
64  template <typename... Args>
65  ConfError(const Conf& c, const char* format, const Args&... args)
66  : Error(format, args...), data_(c) {}
67 
68  std::string file() const { return data_.file(); }
69  std::string root() const { return data_.root(); }
70  const Conf& conf() const { return data_; }
71  const Json& data() const { return *data_; }
72 
73  virtual std::string message() const {
74  return fmt::format("{}:{}: {}", file(), root(), this->what());
75  }
76 
77  friend SchemaError;
78  friend void to_json(Json& j, const ConfError& e) {
79  j = Json{
80  {"error", e.what()}, {"file", e.file()}, {"root", e.root()},
81  {"data", e.data()}, {"message", e.message()},
82  };
83  }
84 };
85 
86 namespace error {
87 
88 inline ConfError MissingProperty(const Conf& c, const std::string& key) {
89  return ConfError{c, "required property missing: {}", key};
90 }
91 
92 inline ConfError UnexpectedProperty(const Conf& c, const std::string& key) {
93  return ConfError{c, "unexpected property present: {}", key};
94 }
95 
96 inline ConfError WrongType(const Conf& c, JsonType t) {
97  std::string want = to_string(t);
98  std::string got = to_string(c->type());
99  return ConfError{c, "property must have type {}, got {}", want, got};
100 }
101 
102 inline ConfError WrongType(const Conf& c, const std::string& key, JsonType t) {
103  std::string want = to_string(t);
104  std::string got = to_string((*c)[key].type());
105  return ConfError{c, "property must have type {}, got {}", want, got};
106 }
107 
108 inline ConfError WrongType(const Conf& c, const std::string& key) {
109  std::string got = to_string((*c)[key].type());
110  return ConfError{c, "property has wrong type {}", got};
111 }
112 
113 inline ConfError WrongType(const Conf& c) {
114  std::string got = to_string(c->type());
115  return ConfError{c, "property has wrong type {}", got};
116 }
117 
118 } // namespace error
119 
120 class SchemaError : public ConfError {
121  const Json schema_;
122  const Json context_;
123 
124  public: // Constructors
125  virtual ~SchemaError() noexcept = default;
126 
127  SchemaError(const ConfError& c, const Json& s) : ConfError(c), schema_(s) {}
128 
129  SchemaError(const ConfError& c, const Json& s, const Json& ctx)
130  : ConfError(c), schema_(s), context_(ctx) {}
131 
132  template <typename... Args>
133  SchemaError(const Conf& c, const Json& s, const char* format, const Args&... args)
134  : ConfError(c, format, args...), schema_(s) {}
135 
136  template <typename... Args>
137  SchemaError(const Conf& c, const Json& s, const Json& ctx, const char* format,
138  const Args&... args)
139  : ConfError(c, format, args...), schema_(s), context_(ctx) {}
140 
141  public: // Special
142  const Json& schema() const { return schema_; }
143  const Json& context() const { return context_; }
144 
145  friend void to_json(Json& j, const SchemaError& e) {
146  j = Json{
147  {"error", e.what()}, {"file", e.file()}, {"root", e.root()},
148  {"data", e.data()}, {"message", e.message()}, {"schema", e.schema_},
149  };
150  if (!e.context_.empty()) {
151  j["context"] = e.context_;
152  }
153  }
154 };
155 
156 } // namespace fable
157 
158 #endif // FABLE_ERROR_HPP_
Definition: conf.hpp:74
std::string root() const
Definition: conf.hpp:123
Definition: error.hpp:56
nlohmann::json Json
Definition: json.hpp:62
Definition: error.hpp:120
Json::value_t JsonType
Definition: json.hpp:78
Definition: conf.hpp:70
const std::string & file() const
Definition: conf.hpp:97
Definition: error.hpp:40