buffet: Change OneOf constraint to use generic PropValue list
Now ContraintOneOf contains a vector<PropValue> as opposed to
vector<T>. This will enable support for array types, because the
alternative would be to add explicit specializations for combinations
of basic types (int, bool, double, string,... ) and a vector.
BUG=brillo:107
TEST=`FEATURES=test emerge-link buffet`
Change-Id: Ia6bd93db23517c463ba6d915617d9571499a8491
Reviewed-on: https://chromium-review.googlesource.com/261564
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/prop_constraints.cc b/buffet/commands/prop_constraints.cc
index 45448bc..085fe26 100644
--- a/buffet/commands/prop_constraints.cc
+++ b/buffet/commands/prop_constraints.cc
@@ -4,11 +4,27 @@
#include "buffet/commands/prop_constraints.h"
+#include <base/json/json_writer.h>
+
#include "buffet/commands/prop_values.h"
#include "buffet/commands/schema_constants.h"
namespace buffet {
+namespace {
+
+// Helper function to convert a property value to string, which is used for
+// error reporting.
+std::string PropValueToString(const PropValue& value) {
+ std::string result;
+ auto json = value.ToJson(nullptr);
+ if (json)
+ base::JSONWriter::Write(json.get(), &result);
+ return result;
+}
+
+} // anonymous namespace
+
// Constraint ----------------------------------------------------------------
Constraint::~Constraint() {}
@@ -143,4 +159,59 @@
new ConstraintStringLengthMax{limit_.value}};
}
+// ConstraintOneOf --------------------------------------------------
+ConstraintOneOf::ConstraintOneOf(InheritableAttribute<ChoiceList> set)
+ : set_(std::move(set)) {}
+ConstraintOneOf::ConstraintOneOf(ChoiceList set)
+ : set_(std::move(set)) {}
+
+bool ConstraintOneOf::Validate(const PropValue& value,
+ chromeos::ErrorPtr* error) const {
+ for (const auto& item : set_.value) {
+ if (value.IsEqual(item.get()))
+ return true;
+ }
+ std::vector<std::string> choice_list;
+ choice_list.reserve(set_.value.size());
+ for (const auto& item : set_.value) {
+ choice_list.push_back(PropValueToString(*item));
+ }
+ return ReportErrorNotOneOf(error, PropValueToString(value), choice_list);
+}
+
+std::unique_ptr<Constraint> ConstraintOneOf::Clone() const {
+ InheritableAttribute<ChoiceList> attr;
+ attr.is_inherited = set_.is_inherited;
+ attr.value.reserve(set_.value.size());
+ for (const auto& prop_value : set_.value) {
+ attr.value.push_back(prop_value->Clone());
+ }
+ return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(attr)}};
+}
+
+std::unique_ptr<Constraint> ConstraintOneOf::CloneAsInherited() const {
+ ChoiceList cloned;
+ cloned.reserve(set_.value.size());
+ for (const auto& prop_value : set_.value) {
+ cloned.push_back(prop_value->Clone());
+ }
+ return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(cloned)}};
+}
+
+std::unique_ptr<base::Value> ConstraintOneOf::ToJson(
+ chromeos::ErrorPtr* error) const {
+ std::unique_ptr<base::ListValue> list(new base::ListValue);
+ for (const auto& prop_value : set_.value) {
+ auto json = prop_value->ToJson(error);
+ if (!json)
+ return std::unique_ptr<base::Value>();
+ list->Append(json.release());
+ }
+ return std::move(list);
+}
+
+const char* ConstraintOneOf::GetDictKey() const {
+ return commands::attributes::kOneOf_Enum;
+}
+
} // namespace buffet