25 #ifndef FABLE_SCHEMA_MAP_HPP_ 26 #define FABLE_SCHEMA_MAP_HPP_ 36 #include <boost/optional.hpp> 51 template <
typename T,
typename P>
54 using Type = std::map<std::string, T>;
55 using PrototypeSchema = P;
57 Map(Type* ptr, std::string&& desc);
58 Map(Type* ptr,
const PrototypeSchema& prototype)
59 :
Base<Map<T, P>>(JsonType::object), prototype_(prototype), ptr_(ptr) {
60 prototype_.reset_ptr();
62 Map(Type* ptr,
const PrototypeSchema& prototype, std::string&& desc)
63 :
Base<Map<T, P>>(JsonType::object, std::move(desc)), prototype_(prototype), ptr_(ptr) {
64 prototype_.reset_ptr();
69 Map(Type* ptr, std::string&& desc)
70 :
Map(ptr, make_prototype<T>(), std::move(desc)) {}
74 bool unique_properties()
const {
return unique_properties_; }
75 Map<T, P> unique_properties(
bool value) && {
76 unique_properties_ = value;
77 return std::move(*
this);
80 const std::vector<std::string>& required()
const {
return required_; }
81 Map<T, P> require_properties(
const std::vector<std::string>& values) && {
83 return std::move(*
this);
85 Map<T, P> require_property(
const std::string& value) && {
86 required_.emplace_back(value);
87 return std::move(*
this);
90 const std::string& pattern()
const {
return pattern_; }
91 Map<T, P> pattern(
const std::string& value) && {
93 return std::move(*
this);
100 {
"additionalProperties", prototype_.json_schema()},
102 if (!required_.empty()) {
103 j[
"required"] = required_;
105 if (min_properties_ != 0) {
106 j[
"minProperties"] = min_properties_;
108 if (max_properties_ != std::numeric_limits<size_t>::max()) {
109 j[
"maxProperties"] = max_properties_;
111 if (!pattern_.empty()) {
112 j[
"propertyNames"][
"pattern"] = pattern_;
114 this->augment_schema(j);
119 this->validate_type(c);
120 if (c->size() < min_properties_) {
121 this->throw_error(c,
"expect at least {} properties, got {}", max_properties_, c->size());
123 assert(required_.size() <= max_properties_);
124 if (c->size() > max_properties_) {
125 this->throw_error(c,
"expect at most {} properties, got {}", max_properties_, c->size());
127 for (
auto& k : required_) {
131 boost::optional<std::regex> pattern;
132 if (!pattern_.empty()) {
133 *pattern = std::regex(pattern_);
135 for (
const auto& kv : c->items()) {
136 prototype_.validate(c.
at(kv.key()));
137 if (pattern && !std::regex_match(kv.key(), *pattern)) {
138 this->throw_error(c,
"expect property name to match regex '{}': {}", pattern_, kv.key());
145 assert(ptr_ !=
nullptr);
146 j = serialize(*ptr_);
150 assert(ptr_ !=
nullptr);
151 for (
auto& i : c->items()) {
152 const auto key = i.key();
153 if (unique_properties_ && ptr_->count(key)) {
154 this->throw_error(c,
"key {} has already been defined", key);
156 ptr_->insert(std::make_pair(key, deserialize_item(c, key)));
160 Json serialize(
const Type& xm)
const {
162 for (
const auto& kv : xm) {
163 j[kv.first] = prototype_.serialize(kv.second);
168 Type deserialize(
const Conf& c)
const {
170 for (
auto& i : c->items()) {
171 const auto key = i.key();
172 tmp.insert(std::make_pair(key, deserialize_item(c, key)));
177 T deserialize_item(
const Conf& c,
const std::string& key)
const {
178 return prototype_.deserialize(c.
at(key));
184 bool unique_properties_{
true};
185 size_t min_properties_{0};
186 size_t max_properties_{std::numeric_limits<size_t>::max()};
187 std::string pattern_{};
188 std::vector<std::string> required_{};
189 PrototypeSchema prototype_{};
193 template <
typename T,
typename P>
194 Map<T, P> make_schema(std::map<std::string, T>* ptr,
const P& prototype, std::string&& desc) {
195 return Map<T, P>(ptr, prototype, std::move(desc));
201 #endif // FABLE_SCHEMA_MAP_HPP_
void to_json(Json &j) const override
Definition: map.hpp:144
void from_conf(const Conf &c) override
Definition: map.hpp:149
void assert_has(const std::string &key) const
Definition: conf.cpp:109
Json json_schema() const override
Definition: map.hpp:97
nlohmann::json Json
Definition: json.hpp:62
virtual Json to_json() const
Definition: interface.hpp:220
Conf at(const std::string &key) const
Definition: conf.cpp:58
void validate(const Conf &c) const override
Definition: map.hpp:118
Definition: interface.hpp:354
void reset_ptr() override
Definition: map.hpp:181