diff --git a/CMakeLists.txt b/CMakeLists.txt index 6566c5af..ecbaced9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -303,6 +303,8 @@ list ( json/schema/base.hpp json/schema/combine.cpp json/schema/combine.hpp + json/schema/enum.cpp + json/schema/enum.hpp json/schema/except.hpp json/schema/introspection.hpp json/schema/length.cpp diff --git a/json/schema.cpp b/json/schema.cpp index af4038be..b65bb7f2 100644 --- a/json/schema.cpp +++ b/json/schema.cpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2015-2017 Danny Robson + * Copyright 2015-2018 Danny Robson */ #include "schema.hpp" diff --git a/json/schema/base.cpp b/json/schema/base.cpp index 41377731..acd39835 100644 --- a/json/schema/base.cpp +++ b/json/schema/base.cpp @@ -20,6 +20,7 @@ #include "length.hpp" #include "inequality.hpp" #include "properties.hpp" +#include "enum.hpp" using util::json::schema::constraint::base; @@ -34,6 +35,7 @@ base::instantiate (std::string const &name, ::json::tree::node const &def) if (name == "minimum") return std::make_unique (def); if (name == "maximum") return std::make_unique (def); if (name == "properties") return std::make_unique (def); + if (name == "enum") return std::make_unique (def); throw unknown_constraint (name); } diff --git a/json/schema/enum.cpp b/json/schema/enum.cpp new file mode 100644 index 00000000..22a1b896 --- /dev/null +++ b/json/schema/enum.cpp @@ -0,0 +1,39 @@ +#include "enum.hpp" + +#include "../tree.hpp" + +using util::json::schema::constraint::enumeration; + + +/////////////////////////////////////////////////////////////////////////////// +enumeration::enumeration (::json::tree::node const &def) +{ + for (auto const &i: def.as_array ()) + m_values.push_back (i.clone ()); +} + + +/////////////////////////////////////////////////////////////////////////////// +enumeration::output_iterator +enumeration::validate (util::json::schema::constraint::base::output_iterator res, + ::json::tree::node &target) const noexcept +{ + for (auto const &i: m_values) + if (target == *i) + return res; + + return *res++ = { .rule = *this, .target = target }; +} + + +/////////////////////////////////////////////////////////////////////////////// +std::ostream& +enumeration::describe (std::ostream &os) const +{ + os << "{ enumeration: [ "; + + for (auto const &i: m_values) + os << *i << ", "; + + return os << " ] }"; +} diff --git a/json/schema/enum.hpp b/json/schema/enum.hpp new file mode 100644 index 00000000..98794db5 --- /dev/null +++ b/json/schema/enum.hpp @@ -0,0 +1,38 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2018 Danny Robson + */ + +#pragma once + +#include "base.hpp" + +#include "../fwd.hpp" + +#include + +namespace util::json::schema::constraint { + class enumeration final : public base { + public: + enumeration (::json::tree::node const &def); + + virtual ~enumeration () = default; + + output_iterator validate (output_iterator res, ::json::tree::node &) const noexcept override; + std::ostream& describe (std::ostream&) const override; + + private: + std::vector> m_values; + }; +} \ No newline at end of file diff --git a/test/json/schema/validation/7000_enum/bad/0000_integer.json b/test/json/schema/validation/7000_enum/bad/0000_integer.json new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/0000_integer.json @@ -0,0 +1 @@ +1 diff --git a/test/json/schema/validation/7000_enum/bad/1000_true.json b/test/json/schema/validation/7000_enum/bad/1000_true.json new file mode 100644 index 00000000..27ba77dd --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/1000_true.json @@ -0,0 +1 @@ +true diff --git a/test/json/schema/validation/7000_enum/bad/2000_string.json b/test/json/schema/validation/7000_enum/bad/2000_string.json new file mode 100644 index 00000000..196e5879 --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/2000_string.json @@ -0,0 +1 @@ +"bar" diff --git a/test/json/schema/validation/7000_enum/bad/3000_empty_object.json b/test/json/schema/validation/7000_enum/bad/3000_empty_object.json new file mode 100644 index 00000000..ffcd4415 --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/3000_empty_object.json @@ -0,0 +1 @@ +{ } diff --git a/test/json/schema/validation/7000_enum/bad/3100_single_entry_object.json b/test/json/schema/validation/7000_enum/bad/3100_single_entry_object.json new file mode 100644 index 00000000..810c6f71 --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/3100_single_entry_object.json @@ -0,0 +1 @@ +{ "val": "key" } diff --git a/test/json/schema/validation/7000_enum/bad/3101_multi_entry_object.json b/test/json/schema/validation/7000_enum/bad/3101_multi_entry_object.json new file mode 100644 index 00000000..71e61e3e --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/3101_multi_entry_object.json @@ -0,0 +1 @@ +{ "key": "val", "additional": "error" } diff --git a/test/json/schema/validation/7000_enum/bad/4000_array.json b/test/json/schema/validation/7000_enum/bad/4000_array.json new file mode 100644 index 00000000..58c70395 --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/4000_array.json @@ -0,0 +1 @@ +[ 1.1 ] diff --git a/test/json/schema/validation/7000_enum/bad/5000_none.json b/test/json/schema/validation/7000_enum/bad/5000_none.json new file mode 100644 index 00000000..68787000 --- /dev/null +++ b/test/json/schema/validation/7000_enum/bad/5000_none.json @@ -0,0 +1 @@ +null diff --git a/test/json/schema/validation/7000_enum/good/0000_number.input.json b/test/json/schema/validation/7000_enum/good/0000_number.input.json new file mode 100644 index 00000000..9459d4ba --- /dev/null +++ b/test/json/schema/validation/7000_enum/good/0000_number.input.json @@ -0,0 +1 @@ +1.1 diff --git a/test/json/schema/validation/7000_enum/good/1000_boolean.input.json b/test/json/schema/validation/7000_enum/good/1000_boolean.input.json new file mode 100644 index 00000000..c508d536 --- /dev/null +++ b/test/json/schema/validation/7000_enum/good/1000_boolean.input.json @@ -0,0 +1 @@ +false diff --git a/test/json/schema/validation/7000_enum/good/2000_string.input.json b/test/json/schema/validation/7000_enum/good/2000_string.input.json new file mode 100644 index 00000000..810c96ee --- /dev/null +++ b/test/json/schema/validation/7000_enum/good/2000_string.input.json @@ -0,0 +1 @@ +"foo" diff --git a/test/json/schema/validation/7000_enum/good/3000_object.input.json b/test/json/schema/validation/7000_enum/good/3000_object.input.json new file mode 100644 index 00000000..d3a16359 --- /dev/null +++ b/test/json/schema/validation/7000_enum/good/3000_object.input.json @@ -0,0 +1 @@ +{ "key": "val" } diff --git a/test/json/schema/validation/7000_enum/good/4000_array.input.json b/test/json/schema/validation/7000_enum/good/4000_array.input.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/test/json/schema/validation/7000_enum/good/4000_array.input.json @@ -0,0 +1 @@ +[] diff --git a/test/json/schema/validation/7000_enum/schema.json b/test/json/schema/validation/7000_enum/schema.json new file mode 100644 index 00000000..8b06c85d --- /dev/null +++ b/test/json/schema/validation/7000_enum/schema.json @@ -0,0 +1 @@ +{ "enum": [ 1.1, false, "foo", { "key": "val" }, [] ] }