aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjansenin <jansenin@yandex-team.com>2023-08-30 15:24:06 +0300
committerjansenin <jansenin@yandex-team.com>2023-08-30 15:58:07 +0300
commit2a6fe42ec1f143aa44c90f8129ae22783f3577bf (patch)
treee2836be7f8e32e9529401f065afb01acc7edc8a2
parent578f59cd45578cc5d3a61e3b1dc1cab146ecab69 (diff)
downloadydb-2a6fe42ec1f143aa44c90f8129ae22783f3577bf.tar.gz
add simple checks
-rw-r--r--ydb/library/yaml_config/validator/CMakeLists.darwin-x86_64.txt1
-rw-r--r--ydb/library/yaml_config/validator/CMakeLists.linux-aarch64.txt1
-rw-r--r--ydb/library/yaml_config/validator/CMakeLists.linux-x86_64.txt1
-rw-r--r--ydb/library/yaml_config/validator/CMakeLists.windows-x86_64.txt1
-rw-r--r--ydb/library/yaml_config/validator/ut/validator_checks/validator_checks_ut.cpp307
-rw-r--r--ydb/library/yaml_config/validator/ut/validator_checks/ya.make11
-rw-r--r--ydb/library/yaml_config/validator/ut/ya.make1
-rw-r--r--ydb/library/yaml_config/validator/validator.cpp97
-rw-r--r--ydb/library/yaml_config/validator/validator.h159
-rw-r--r--ydb/library/yaml_config/validator/validator_builder.cpp114
-rw-r--r--ydb/library/yaml_config/validator/validator_builder.h117
-rw-r--r--ydb/library/yaml_config/validator/validator_checks.cpp390
-rw-r--r--ydb/library/yaml_config/validator/validator_checks.h336
-rw-r--r--ydb/library/yaml_config/validator/ya.make2
14 files changed, 1395 insertions, 143 deletions
diff --git a/ydb/library/yaml_config/validator/CMakeLists.darwin-x86_64.txt b/ydb/library/yaml_config/validator/CMakeLists.darwin-x86_64.txt
index e12028770f..cbeaf2ade8 100644
--- a/ydb/library/yaml_config/validator/CMakeLists.darwin-x86_64.txt
+++ b/ydb/library/yaml_config/validator/CMakeLists.darwin-x86_64.txt
@@ -17,6 +17,7 @@ target_link_libraries(library-yaml_config-validator PUBLIC
target_sources(library-yaml_config-validator PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_checks.cpp
)
generate_enum_serilization(library-yaml_config-validator
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.h
diff --git a/ydb/library/yaml_config/validator/CMakeLists.linux-aarch64.txt b/ydb/library/yaml_config/validator/CMakeLists.linux-aarch64.txt
index ed6cd10ed4..7fd0a3fa98 100644
--- a/ydb/library/yaml_config/validator/CMakeLists.linux-aarch64.txt
+++ b/ydb/library/yaml_config/validator/CMakeLists.linux-aarch64.txt
@@ -18,6 +18,7 @@ target_link_libraries(library-yaml_config-validator PUBLIC
target_sources(library-yaml_config-validator PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_checks.cpp
)
generate_enum_serilization(library-yaml_config-validator
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.h
diff --git a/ydb/library/yaml_config/validator/CMakeLists.linux-x86_64.txt b/ydb/library/yaml_config/validator/CMakeLists.linux-x86_64.txt
index ed6cd10ed4..7fd0a3fa98 100644
--- a/ydb/library/yaml_config/validator/CMakeLists.linux-x86_64.txt
+++ b/ydb/library/yaml_config/validator/CMakeLists.linux-x86_64.txt
@@ -18,6 +18,7 @@ target_link_libraries(library-yaml_config-validator PUBLIC
target_sources(library-yaml_config-validator PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_checks.cpp
)
generate_enum_serilization(library-yaml_config-validator
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.h
diff --git a/ydb/library/yaml_config/validator/CMakeLists.windows-x86_64.txt b/ydb/library/yaml_config/validator/CMakeLists.windows-x86_64.txt
index e12028770f..cbeaf2ade8 100644
--- a/ydb/library/yaml_config/validator/CMakeLists.windows-x86_64.txt
+++ b/ydb/library/yaml_config/validator/CMakeLists.windows-x86_64.txt
@@ -17,6 +17,7 @@ target_link_libraries(library-yaml_config-validator PUBLIC
target_sources(library-yaml_config-validator PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_checks.cpp
)
generate_enum_serilization(library-yaml_config-validator
${CMAKE_SOURCE_DIR}/ydb/library/yaml_config/validator/validator_builder.h
diff --git a/ydb/library/yaml_config/validator/ut/validator_checks/validator_checks_ut.cpp b/ydb/library/yaml_config/validator/ut/validator_checks/validator_checks_ut.cpp
new file mode 100644
index 0000000000..35033f4df3
--- /dev/null
+++ b/ydb/library/yaml_config/validator/ut/validator_checks/validator_checks_ut.cpp
@@ -0,0 +1,307 @@
+#include <util/stream/str.h>
+
+#include <library/cpp/testing/unittest/registar.h>
+#include <util/system/types.h>
+
+#include <ydb/library/yaml_config/validator/validator_builder.h>
+
+using namespace NYamlConfig::NValidator;
+using TIssue = TValidationResult::TIssue;
+
+bool HasOnlyThisIssues(TValidationResult result, TVector<TIssue> issues) {
+ if (result.Issues.size() != issues.size()) {
+ Cerr << "Issue counts are differend. List of actul issues:" << Endl;
+ Cerr << result;
+ Cerr << "------------- List of Expected Issues: " << Endl;
+ Cerr << TValidationResult(issues);
+ Cerr << "------------- End of issue List" << Endl;
+ return false;
+ }
+ Sort(result.Issues);
+ Sort(issues);
+ for (size_t i = 0; i < issues.size(); ++i) {
+ if (result.Issues[i] != issues[i]) {
+ Cerr << "Issues are differend. List of actul issues:" << Endl;
+ Cerr << result;
+ Cerr << "------------- List of Expected Issues: " << Endl;
+ Cerr << TValidationResult(issues);
+ Cerr << "------------- End of issue List" << Endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Valid(TValidationResult result) {
+ if (result.Ok()) return true;
+
+ Cerr << "List of issues:" << Endl;
+ Cerr << result;
+ Cerr << "------------- End of issue list: " << Endl;
+ return false;
+}
+
+Y_UNIT_TEST_SUITE(Checks) {
+ Y_UNIT_TEST(BasicIntChecks) {
+ TInt64Builder b;
+ b.AddCheck("Value must be divisible by 2", [](auto& c) {
+ c.Expect(c.Node() % 2 == 0);
+ }).AddCheck("Value must be divisible by 3", [](auto& c) {
+ c.Expect(c.Node().Value() % 3 == 0);
+ });
+ auto v = b.CreateValidator();
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("1"), {
+ {"/", "Value must be divisible by 3"},
+ {"/", "Value must be divisible by 2"}
+ }));
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("2"), {{"/", "Value must be divisible by 3"}}));
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("3"), {{"/", "Value must be divisible by 2"}}));
+ Y_ENSURE(Valid(v.Validate("6")));
+ }
+
+ Y_UNIT_TEST(BasicStringChecks) {
+ NYamlConfig::NValidator::TStringBuilder b;
+ b.AddCheck("Value length must be divisible by 2", [](auto& c) {
+ c.Expect(c.Node().Value().length() % 2 == 0);
+ }).AddCheck("Value length must be divisible by 3", [](auto& c) {
+ c.Expect(c.Node().Value().length() % 3 == 0);
+ });
+ auto v = b.CreateValidator();
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("1"), {
+ {"/", "Value length must be divisible by 3"},
+ {"/", "Value length must be divisible by 2"}
+ }));
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("22"), {{"/", "Value length must be divisible by 3"}}));
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("333"), {{"/", "Value length must be divisible by 2"}}));
+ Y_ENSURE(Valid(v.Validate("666666")));
+ }
+
+ Y_UNIT_TEST(IntArrayValidation) {
+ TArrayBuilder b;
+ b.Item(TInt64Builder().Range(0, 10))
+ .AddCheck("Array length must be greater than 5", [](auto& c) {
+ c.Expect(c.Node().Length() >= 5);
+ }).AddCheck("Xor of all array elements must be 0", [](auto& c) {
+ i64 totalXor = 0;
+ for (int i = 0; i < c.Node().Length(); ++i) {
+ totalXor ^= c.Node()[i].Int64().Value(); // or just c[i]?
+ }
+ c.Expect(totalXor == 0);
+ });
+ auto v = b.CreateValidator();
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("[]"), {{"/", "Array length must be greater than 5"}}));
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("[1]"), {
+ {"/", "Array length must be greater than 5"},
+ {"/", "Xor of all array elements must be 0"}
+ }));
+ Y_ENSURE(HasOnlyThisIssues(v.Validate("[-1]"), {
+ {"/0", "Value must be greater or equal to min value(i.e >= 0)"}
+ }));
+
+ Y_ENSURE(Valid(v.Validate("[4,5,6,4,5,6]")));
+ Y_ENSURE(Valid(v.Validate("[1,2,3,4,5,6,7]")));
+ }
+
+ Y_UNIT_TEST(MapValidation) {
+ // field1 -> must have field2
+ // field2 -> must have field1
+
+ // field3 -> must have int_arr of 3 even non-negative elements with total sum <= 100
+ // field4 -> must not have int_arr
+
+ auto optionalInt = [](TInt64Builder& b) {
+ b.Optional();
+ };
+ auto evenInt = [](TInt64CheckContext& c) {
+ c.Expect(c.Node().Value() % 2 == 0);
+ };
+ auto arrLengthIs3 = [](TArrayCheckContext& c) {
+ c.Expect(c.Node().Length() == 3);
+ };
+ auto sumIsLessOrEqualTo100 = [](TArrayCheckContext& c) {
+ i64 sum = 0;
+ for (int i = 0; i < c.Node().Length(); ++i) {
+ sum += c.Node()[i].Int64().Value();
+ }
+ c.Expect(sum <= 100);
+ };
+ auto field1AndField2MustBeBothPresentOrAbsent = [](TMapCheckContext& c) {
+ c.Expect(c.Node().Has("field1") == c.Node().Has("field2"));
+ };
+ auto arrayPresenceCheck = [](TMapCheckContext& c) {
+ if (c.Node().Has("field3")) {
+ c.Expect(c.Node().Has("int_arr"), "If you have field3, than you must have int_arr");
+ }
+ if (c.Node().Has("field4")) {
+ c.Expect(!c.Node().Has("int_arr"), "If you have field4, than you must not have int_arr");
+ }
+ };
+
+ auto v =
+ TMapBuilder()
+ .Int64("field1", optionalInt)
+ .Int64("field2", optionalInt)
+ .Int64("field3", optionalInt)
+ .Int64("field4", optionalInt)
+ .Array("int_arr", [=](auto& b) {
+ b.Optional()
+ .Int64Item([=](auto& b) {
+ b.Min(0)
+ .AddCheck("Value must be even", evenInt);
+ })
+ .AddCheck("Array length must be 3", arrLengthIs3)
+ .AddCheck("Sum of all array elements must be less or equal to 100", sumIsLessOrEqualTo100);
+ })
+ .AddCheck(
+ "field1 and field2 either both must be present or both must be absent",
+ field1AndField2MustBeBothPresentOrAbsent)
+ .AddCheck("int_arr precense", arrayPresenceCheck)
+ .CreateValidator();
+
+ {
+ TString yaml =
+ "{}";
+
+ Y_ENSURE(Valid(v.Validate(yaml)));
+ }
+
+ {
+ TString yaml =
+ "{\n"
+ "field1: 0,\n"
+ "field2: 0,\n"
+ "field3: 0,\n"
+ // "field4: 0,\n"
+ "int_arr: [2,4,6]\n"
+ "}";
+ Y_ENSURE(Valid(v.Validate(yaml)));
+ }
+
+ {
+ TString yaml =
+ "{\n"
+ "field1: 0,\n"
+ "field2: 0,\n"
+ "field3: 0,\n"
+ // "field4: 0,\n"
+ "int_arr: [-1,4,601,2]\n"
+ "}";
+ Y_ENSURE(HasOnlyThisIssues(v.Validate(yaml), {
+ {"/int_arr/0", "Value must be greater or equal to min value(i.e >= 0)"},
+ {"/int_arr/2", "Value must be even"}
+ }));
+ }
+
+ {
+ TString yaml =
+ "{\n"
+ // "field1: 0,\n"
+ "field2: 0,\n"
+ "field3: 0,\n"
+ "field4: 0,\n"
+ "int_arr: [2,4,600,4]\n"
+ "}";
+ Y_ENSURE(HasOnlyThisIssues(v.Validate(yaml), {
+ {"/int_arr", "Array length must be 3"},
+ {"/int_arr", "Sum of all array elements must be less or equal to 100"}
+ }));
+ }
+
+ {
+ TString yaml =
+ "{\n"
+ // "field1: 0,\n"
+ "field2: 0,\n"
+ "field3: 0,\n"
+ "field4: 0,\n"
+ "int_arr: [2,4,4]\n"
+ "}";
+ Y_ENSURE(HasOnlyThisIssues(v.Validate(yaml), {
+ {"/", "Check \"int_arr precense\" failed: If you have field4, than you must not have int_arr"},
+ {"/", "field1 and field2 either both must be present or both must be absent"},
+ }));
+ }
+ }
+
+ //TODO: make Some check tests for generic node(and
+ //before that make ability to somehow work with this nodes)
+
+ Y_UNIT_TEST(ErrorInCheck) {
+ auto v =
+ TMapBuilder()
+ .Bool("flag")
+ .Map("a", [](auto& b) {
+ b.Optional()
+ .Map("b", [](auto& b) {
+ b.Int64("c");
+ });
+ })
+ .Map("c", [](auto& b) {
+ b.Optional()
+ .Map("b", [](auto& b) {
+ b.Int64("a");
+ });
+ })
+ .AddCheck("must have even a/b/c if flag is true. Else must have odd c/a/b", [](auto& c) {
+ if (c.Node()["flag"].Bool()) {
+ c.Expect(c.Node()["a"].Map()["b"].Map()["c"].Int64().Value() % 2 == 0);
+ } else {
+ c.Expect(c.Node()["c"].Map()["b"].Map()["a"].Int64().Value() % 2 == 1);
+ }
+ })
+ .CreateValidator();
+
+ const char* yaml =
+ "{"
+ " flag: true"
+ "}";
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate(yaml), {
+ {"/", "Check \"must have even a/b/c if flag is true. Else must have odd c/a/b\" failed: Node \"/a/b/c\" is not presented"},
+ }));
+
+ yaml =
+ "{"
+ " flag: true,"
+ " a: {"
+ " b: {"
+ " c: 0"
+ " }"
+ " }"
+ "}";
+
+ Y_ENSURE(Valid(v.Validate(yaml)));
+
+ yaml =
+ "{"
+ " flag: true,"
+ " a: {"
+ " b: {"
+ " c: 1"
+ " }"
+ " }"
+ "}";
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate(yaml), {
+ {"/", "must have even a/b/c if flag is true. Else must have odd c/a/b"},
+ }));
+
+ yaml =
+ "{"
+ " flag: faLse,"
+ " a: {"
+ " b: {"
+ " c: 0"
+ " }"
+ " }"
+ "}";
+
+ Y_ENSURE(HasOnlyThisIssues(v.Validate(yaml), {
+ {"/", "Check \"must have even a/b/c if flag is true. Else must have odd c/a/b\" failed: Node \"/c/b/a\" is not presented"},
+ }));
+ }
+}
diff --git a/ydb/library/yaml_config/validator/ut/validator_checks/ya.make b/ydb/library/yaml_config/validator/ut/validator_checks/ya.make
new file mode 100644
index 0000000000..ee3c2f122a
--- /dev/null
+++ b/ydb/library/yaml_config/validator/ut/validator_checks/ya.make
@@ -0,0 +1,11 @@
+UNITTEST()
+
+SRCS(
+ validator_checks_ut.cpp
+)
+
+PEERDIR(
+ ydb/library/yaml_config/validator
+)
+
+END()
diff --git a/ydb/library/yaml_config/validator/ut/ya.make b/ydb/library/yaml_config/validator/ut/ya.make
index 3a4573f2fb..ee6ee78e22 100644
--- a/ydb/library/yaml_config/validator/ut/ya.make
+++ b/ydb/library/yaml_config/validator/ut/ya.make
@@ -1,4 +1,5 @@
RECURSE_FOR_TESTS(
validator
validator_builder
+ validator_checks
)
diff --git a/ydb/library/yaml_config/validator/validator.cpp b/ydb/library/yaml_config/validator/validator.cpp
index 87f229daf3..8f7e8f0094 100644
--- a/ydb/library/yaml_config/validator/validator.cpp
+++ b/ydb/library/yaml_config/validator/validator.cpp
@@ -1,5 +1,7 @@
#include "validator.h"
+#include "validator_checks.h"
+
#include <util/string/cast.h>
#include <util/system/types.h>
@@ -83,17 +85,20 @@ TValidationResult TValidator::Validate(const TString& documentStr) {
return Validate(document.Root());
}
-TValidator::TValidator() {}
+TValidator::TValidator(ENodeType nodeType)
+ : NodeType_(nodeType) {}
TValidator::TValidator(TValidator&& validator)
- : Required_(validator.Required_) {}
+ : Required_(validator.Required_)
+ , NodeType_(validator.NodeType_) {}
TValidator::~TValidator() {}
-TGenericValidator::TGenericValidator() {}
+TGenericValidator::TGenericValidator()
+ : TBase(ENodeType::Generic) {}
TGenericValidator::TGenericValidator(TGenericValidator&& validator)
- : TValidator(std::move(validator))
+ : TBase(std::move(validator))
, ValidatorPtrs_(std::move(validator.ValidatorPtrs_)) {}
TValidationResult TGenericValidator::Validate(const NFyaml::TNodeRef& node) {
@@ -134,29 +139,39 @@ TValidationResult TGenericValidator::Validate(const NFyaml::TNodeRef& node) {
addNewLine = true;
}
- return TVector<TValidationResult::TIssue>{{
+ TValidationResult result = TVector<TValidationResult::TIssue>{{
node.Path(),
message
}};
+
+ // put checks code into separete function
+ // think about all combinations of checker name and errors
+ if (result.Ok()) {
+ performChecks(result, node);
+ }
+
+ return result;
}
void TGenericValidator::AddValidator(TSimpleSharedPtr<TValidator> validatorPtr) {
ValidatorPtrs_.emplace_back(std::move(validatorPtr));
}
-TMapValidator::TMapValidator() {}
+TMapValidator::TMapValidator()
+ : TBase(ENodeType::Map) {}
TMapValidator::TMapValidator(TMapValidator&& validator)
- : TValidator(std::move(validator))
+ : TBase(std::move(validator))
, Children_(std::move(validator.Children_))
, Opaque_(validator.Opaque_) {}
TMapValidator::TMapValidator(THashMap<TString, TSimpleSharedPtr<TValidator>>&& children, bool Opaque)
- : Children_(std::move(children))
+ : TBase(ENodeType::Map)
+ , Children_(std::move(children))
, Opaque_(Opaque) {}
TValidationResult TMapValidator::Validate(const TNodeRef& node) {
- if (node.Type() != ENodeType::Mapping) {
+ if (node.Type() != NFyaml::ENodeType::Mapping) {
return TValidationResult({{
node.Path(),
"Node must be Map"
@@ -198,21 +213,28 @@ TValidationResult TMapValidator::Validate(const TNodeRef& node) {
}
}
+ if (validationResult.Ok()) {
+ performChecks(validationResult, node);
+ }
+
return validationResult;
}
-TArrayValidator::TArrayValidator() {}
+TArrayValidator::TArrayValidator()
+ : TBase(ENodeType::Array) {}
TArrayValidator::TArrayValidator(TArrayValidator&& validator)
- : TValidator(std::move(validator))
+ : TBase(std::move(validator))
, ItemValidatorPtr_(std::move(validator.ItemValidatorPtr_))
, Unique_(validator.Unique_) {}
TArrayValidator::TArrayValidator(TSimpleSharedPtr<TValidator> itemValidatorPtr, bool Unique)
- : ItemValidatorPtr_(std::move(itemValidatorPtr)), Unique_(Unique) {}
+ : TBase(ENodeType::Array)
+ , ItemValidatorPtr_(std::move(itemValidatorPtr))
+ , Unique_(Unique) {}
TValidationResult TArrayValidator::Validate(const TNodeRef& node) {
- if (node.Type() != ENodeType::Sequence) {
+ if (node.Type() != NFyaml::ENodeType::Sequence) {
return TValidationResult({{
node.Path(),
"Node must be Array"
@@ -226,22 +248,29 @@ TValidationResult TArrayValidator::Validate(const TNodeRef& node) {
// TODO: check uniqueness
Y_UNUSED(Unique_);
+
+ if (validationResult.Ok()) {
+ performChecks(validationResult, node);
+ }
+
return validationResult;
}
-TInt64Validator::TInt64Validator() {}
+TInt64Validator::TInt64Validator()
+ : TBase(ENodeType::Int64) {}
TInt64Validator::TInt64Validator(TInt64Validator&& validator)
- : TValidator(std::move(validator))
+ : TBase(std::move(validator))
, Min_(validator.Min_)
, Max_(validator.Max_) {}
TInt64Validator::TInt64Validator(i64 min, i64 max)
- : Min_(min)
+ : TBase(ENodeType::Int64)
+ , Min_(min)
, Max_(max) {}
TValidationResult TInt64Validator::Validate(const TNodeRef& node) {
- if (node.Type() != ENodeType::Scalar) {
+ if (node.Type() != NFyaml::ENodeType::Scalar) {
return TValidationResult({{
node.Path(),
"Node must be Scalar(Int64)"
@@ -271,6 +300,10 @@ TValidationResult TInt64Validator::Validate(const TNodeRef& node) {
});
}
+ if (validationResult.Ok()) {
+ performChecks(validationResult, node);
+ }
+
return validationResult;
}
@@ -282,28 +315,37 @@ void TInt64Validator::SetMax(i64 max) {
Max_ = max;
}
-TStringValidator::TStringValidator() {}
+TStringValidator::TStringValidator()
+ : TBase(ENodeType::String) {}
TStringValidator::TStringValidator(TStringValidator&& validator)
- : TValidator(std::move(validator)) {}
+ : TBase(std::move(validator)) {}
TValidationResult TStringValidator::Validate(const TNodeRef& node) {
- if (node.Type() != ENodeType::Scalar) {
+ if (node.Type() != NFyaml::ENodeType::Scalar) {
return TValidationResult({{
node.Path(),
"Node must be Scalar(String)"
}});
}
- return {};
+
+ TValidationResult validationResult;
+
+ if (validationResult.Ok()) {
+ performChecks(validationResult, node);
+ }
+
+ return validationResult;
}
-TBoolValidator::TBoolValidator() {}
+TBoolValidator::TBoolValidator()
+ : TBase(ENodeType::Bool) {}
TBoolValidator::TBoolValidator(TBoolValidator&& validator)
- : TValidator(std::move(validator)) {}
+ : TBase(std::move(validator)) {}
TValidationResult TBoolValidator::Validate(const TNodeRef& node) {
- if (node.Type() != ENodeType::Scalar) {
+ if (node.Type() != NFyaml::ENodeType::Scalar) {
return TValidationResult({{
node.Path(),
"Node must be Scalar(Bool)"
@@ -318,7 +360,12 @@ TValidationResult TBoolValidator::Validate(const TNodeRef& node) {
"Value must be either true or false"
}});
}
- return {};
+
+ TValidationResult validationResult;
+
+ performChecks(validationResult, node);
+
+ return validationResult;
}
} // namespace NYamlConfig::NValidator
diff --git a/ydb/library/yaml_config/validator/validator.h b/ydb/library/yaml_config/validator/validator.h
index a186c32d42..63ff8c4fed 100644
--- a/ydb/library/yaml_config/validator/validator.h
+++ b/ydb/library/yaml_config/validator/validator.h
@@ -12,6 +12,10 @@
namespace NYamlConfig::NValidator {
+enum class ENodeType {
+ Generic, Map, Array, Int64, String, Bool
+};
+
class TValidator;
class TGenericValidator;
class TMapValidator;
@@ -20,6 +24,22 @@ class TInt64Validator;
class TStringValidator;
class TBoolValidator;
+class TGenericNodeWrapper;
+class TMapNodeWrapper;
+class TArrayNodeWrapper;
+class TInt64NodeWrapper;
+class TStringNodeWrapper;
+class TBoolNodeWrapper;
+
+class TGenericCheckContext;
+class TMapCheckContext;
+class TArrayCheckContext;
+class TInt64CheckContext;
+class TStringCheckContext;
+class TBoolCheckContext;
+
+class TCheckContext;
+
class TGenericBuilder;
namespace NDetail {
@@ -28,15 +48,20 @@ class TBuilder;
TSimpleSharedPtr<TValidator> CreateValidatorPtr(const TSimpleSharedPtr<NDetail::TBuilder>& builder);
+template <typename TThis, typename TContext>
+class TValidatorCommonOps;
+
}
class TValidationResult {
+ friend class TCheckContext;
friend class TGenericValidator;
friend class TMapValidator;
friend class TArrayValidator;
friend class TInt64Validator;
friend class TStringValidator;
friend class TBoolValidator;
+ template <typename TThis, typename TContext> friend class NDetail::TValidatorCommonOps;
public:
struct TIssue {
@@ -76,23 +101,98 @@ class TValidator {
friend TSimpleSharedPtr<TValidator> NYamlConfig::NValidator::NDetail::CreateValidatorPtr(const TSimpleSharedPtr<NDetail::TBuilder>& builder);
friend class TMapValidator; // for .Required_
friend class TGenericBuilder; // for .Required_
+ friend class TMapNodeWrapper; // NodeType
+ friend class TArrayNodeWrapper; // NodeType
public:
- TValidator();
-
virtual TValidationResult Validate(const NFyaml::TNodeRef& node) = 0;
TValidationResult Validate(const TString& document);
virtual ~TValidator();
protected:
+ bool Required_ = true;
+
+ TValidator(ENodeType nodeType);
TValidator(TValidator&& validator);
private:
- bool Required_ = true;
+ ENodeType NodeType_;
};
-class TGenericValidator : public TValidator {
+namespace NDetail {
+
+template <typename TThis, typename TContext>
+class TValidatorCommonOps : public TValidator {
+protected:
+ THashMap<TString, std::function<void(TContext&)>> Checkers_;
+
+ TValidatorCommonOps<TThis, TContext>(ENodeType nodeType);
+ TValidatorCommonOps<TThis, TContext>(TValidatorCommonOps<TThis, TContext>&& builder);
+
+ void performChecks(TValidationResult& validationResult, const NFyaml::TNodeRef& node);
+};
+
+template <typename TThis, typename TContext>
+TValidatorCommonOps<TThis, TContext>::TValidatorCommonOps(ENodeType nodeType)
+ : TValidator(nodeType) {}
+
+template <typename TThis, typename TContext>
+TValidatorCommonOps<TThis, TContext>::TValidatorCommonOps(TValidatorCommonOps<TThis, TContext>&& builder)
+ : TValidator(std::move(builder))
+ , Checkers_(std::move(builder.Checkers_)) {}
+
+template <typename TThis, typename TContext>
+void TValidatorCommonOps<TThis, TContext>::performChecks(TValidationResult& validationResult, const NFyaml::TNodeRef& node) {
+ TThis* This = static_cast<TThis*>(this);
+ for (auto& [checkName, checker] : Checkers_) {
+ // TODO: change node.Path() to stored path in validator (or maybe node.Path is better?)
+ TString nodePath = node.Path();
+ if (nodePath == "/") {
+ nodePath = "";
+ }
+
+ TContext context(node, nodePath, This);
+ try {
+ checker(context);
+ } catch (yexception& ye) {
+ context.AddError(ye.what());
+ context.someExpectFailed = true;
+ }
+
+ if (context.someExpectFailed) {
+ if (context.Errors_.empty()) {
+ validationResult.AddIssue({node.Path(), checkName});
+ } else if (context.Errors_.size() == 1) {
+ validationResult.AddIssue({node.Path(), "Check \"" + checkName + "\" failed: " + context.Errors_[0]});
+ } else {
+ TString errorMessages;
+
+ //TODO: add multiline errors support(and maybe extract big
+ //error creation into separete function)
+ bool newLine = false;
+ for (auto& error : context.Errors_) {
+ if (newLine) {
+ errorMessages += "\n";
+ }
+ errorMessages += error;
+ newLine = true;
+ }
+
+ validationResult.AddIssue({node.Path(), "Check \"" + checkName + "\" failed: \n" + errorMessages});
+ }
+ }
+ }
+}
+
+}
+
+class TGenericValidator : public NDetail::TValidatorCommonOps<TGenericValidator, TGenericCheckContext> {
+ friend class TGenericNodeWrapper;
+ friend class TGenericBuilder;
+
+ using TBase = NDetail::TValidatorCommonOps<TGenericValidator, TGenericCheckContext>;
+
public:
TGenericValidator();
@@ -101,51 +201,64 @@ public:
TValidationResult Validate(const NFyaml::TNodeRef& node) override;
using TValidator::Validate;
- void AddValidator(TSimpleSharedPtr<TValidator> validatorPtr);
-
private:
TVector<TSimpleSharedPtr<TValidator>> ValidatorPtrs_;
+
+ void AddValidator(TSimpleSharedPtr<TValidator> validatorPtr);
};
-class TMapValidator : public TValidator {
+class TMapValidator : public NDetail::TValidatorCommonOps<TMapValidator, TMapCheckContext> {
+ friend class TMapNodeWrapper;
+ friend class TMapBuilder;
+
+ using TBase = NDetail::TValidatorCommonOps<TMapValidator, TMapCheckContext>;
+
public:
TMapValidator();
TMapValidator(TMapValidator&& validator);
- explicit TMapValidator(THashMap<TString, TSimpleSharedPtr<TValidator>>&& children, bool Opaque);
-
TValidationResult Validate(const NFyaml::TNodeRef& node) override;
using TValidator::Validate;
private:
THashMap<TString, TSimpleSharedPtr<TValidator>> Children_;
bool Opaque_;
+
+ TMapValidator(THashMap<TString, TSimpleSharedPtr<TValidator>>&& children, bool Opaque);
};
-class TArrayValidator : public TValidator {
+class TArrayValidator : public NDetail::TValidatorCommonOps<TArrayValidator, TArrayCheckContext> {
+ friend class TArrayNodeWrapper;
+ friend class TArrayBuilder;
+
+ using TBase = NDetail::TValidatorCommonOps<TArrayValidator, TArrayCheckContext>;
+
public:
TArrayValidator();
TArrayValidator(TArrayValidator&& validator);
- TArrayValidator(TSimpleSharedPtr<TValidator> itemValidatorPtr, bool Unique);
-
TValidationResult Validate(const NFyaml::TNodeRef& node) override;
using TValidator::Validate;
private:
TSimpleSharedPtr<TValidator> ItemValidatorPtr_;
bool Unique_;
+
+ TArrayValidator(TSimpleSharedPtr<TValidator> itemValidatorPtr, bool Unique);
};
-class TInt64Validator : public TValidator {
+class TInt64Validator : public NDetail::TValidatorCommonOps<TInt64Validator, TInt64CheckContext> {
+ friend class TInt64NodeWrapper;
+ friend class TInt64Builder;
+
+ using TBase = NDetail::TValidatorCommonOps<TInt64Validator, TInt64CheckContext>;
+
public:
TInt64Validator();
TInt64Validator(TInt64Validator&& validator);
-
- TInt64Validator(i64 min, i64 max);
TValidationResult Validate(const NFyaml::TNodeRef& node) override;
using TValidator::Validate;
@@ -154,11 +267,18 @@ private:
i64 Min_ = Min<i64>();
i64 Max_ = Max<i64>();
+ TInt64Validator(i64 min, i64 max);
+
void SetMin(i64 min);
void SetMax(i64 max);
};
-class TStringValidator : public TValidator {
+class TStringValidator : public NDetail::TValidatorCommonOps<TStringValidator, TStringCheckContext> {
+ friend class TStringNodeWrapper;
+ friend class TStringBuilder;
+
+ using TBase = NDetail::TValidatorCommonOps<TStringValidator, TStringCheckContext>;
+
public:
TStringValidator();
@@ -168,7 +288,12 @@ public:
using TValidator::Validate;
};
-class TBoolValidator : public TValidator {
+class TBoolValidator : public NDetail::TValidatorCommonOps<TBoolValidator, TBoolCheckContext> {
+ friend class TBoolNodeWrapper;
+ friend class TBoolBuilder;
+
+ using TBase = NDetail::TValidatorCommonOps<TBoolValidator, TBoolCheckContext>;
+
public:
TBoolValidator();
diff --git a/ydb/library/yaml_config/validator/validator_builder.cpp b/ydb/library/yaml_config/validator/validator_builder.cpp
index df62cc82dd..8813a60045 100644
--- a/ydb/library/yaml_config/validator/validator_builder.cpp
+++ b/ydb/library/yaml_config/validator/validator_builder.cpp
@@ -11,52 +11,40 @@ namespace NYamlConfig::NValidator {
namespace NDetail {
TSimpleSharedPtr<TValidator> CreateValidatorPtr(const TSimpleSharedPtr<TBuilder>& builder) {
- switch (builder->BuilderType_) {
- case EBuilderType::Generic: {
- TGenericValidator v = static_cast<TGenericBuilder*>(builder.Get())->CreateValidator();
- v.Required_ = builder->Required_;
- return TSimpleSharedPtr<TValidator>(new TGenericValidator(std::move(v)));
+ switch (builder->NodeType_) {
+ case ENodeType::Generic: {
+ return MakeSimpleShared<TGenericValidator>(static_cast<TGenericBuilder*>(builder.Get())->CreateValidator());
}
- case EBuilderType::Map: {
- TMapValidator v = static_cast<TMapBuilder*>(builder.Get())->CreateValidator();
- v.Required_ = builder->Required_;
- return TSimpleSharedPtr<TValidator>(new TMapValidator(std::move(v)));
+ case ENodeType::Map: {
+ return MakeSimpleShared<TMapValidator>(static_cast<TMapBuilder*>(builder.Get())->CreateValidator());
}
- case EBuilderType::Array: {
- TArrayValidator v = static_cast<TArrayBuilder*>(builder.Get())->CreateValidator();
- v.Required_ = builder->Required_;
- return TSimpleSharedPtr<TValidator>(new TArrayValidator(std::move(v)));
+ case ENodeType::Array: {
+ return MakeSimpleShared<TArrayValidator>(static_cast<TArrayBuilder*>(builder.Get())->CreateValidator());
}
- case EBuilderType::Int64: {
- TInt64Validator v = static_cast<TInt64Builder*>(builder.Get())->CreateValidator();
- v.Required_ = builder->Required_;
- return TSimpleSharedPtr<TValidator>(new TInt64Validator(std::move(v)));
+ case ENodeType::Int64: {
+ return MakeSimpleShared<TInt64Validator>(static_cast<TInt64Builder*>(builder.Get())->CreateValidator());
}
- case EBuilderType::String: {
- TStringValidator v = static_cast<TStringBuilder*>(builder.Get())->CreateValidator();
- v.Required_ = builder->Required_;
- return TSimpleSharedPtr<TValidator>(new TStringValidator(std::move(v)));
+ case ENodeType::String: {
+ return MakeSimpleShared<TStringValidator>(static_cast<TStringBuilder*>(builder.Get())->CreateValidator());
}
- case EBuilderType::Bool: {
- TBoolValidator v = static_cast<TBoolBuilder*>(builder.Get())->CreateValidator();
- v.Required_ = builder->Required_;
- return TSimpleSharedPtr<TValidator>(new TBoolValidator(std::move(v)));
+ case ENodeType::Bool: {
+ return MakeSimpleShared<TBoolValidator>(static_cast<TBoolBuilder*>(builder.Get())->CreateValidator());
}
}
}
-TBuilder::TBuilder(EBuilderType builderType)
- : BuilderType_(builderType) {}
+TBuilder::TBuilder(ENodeType nodeType)
+ : NodeType_(nodeType) {}
TBuilder& TBuilder::operator=(const TBuilder& builder) {
- Y_ASSERT(BuilderType_ == builder.BuilderType_);
+ Y_ASSERT(NodeType_ == builder.NodeType_);
Required_ = builder.Required_;
Description_ = builder.Description_;
return *this;
}
TBuilder& TBuilder::operator=(TBuilder&& builder) {
- Y_ASSERT(BuilderType_ == builder.BuilderType_);
+ Y_ASSERT(NodeType_ == builder.NodeType_);
Required_ = builder.Required_;
Description_ = std::move(builder.Description_);
return *this;
@@ -64,23 +52,23 @@ TBuilder& TBuilder::operator=(TBuilder&& builder) {
} // namespace NDetail
-TGenericBuilder::NodeTypeAndBuilder::NodeTypeAndBuilder() {}
+TGenericBuilder::TTypedBuilder::TTypedBuilder() {}
-TGenericBuilder::NodeTypeAndBuilder::NodeTypeAndBuilder(EBuilderType type, TSimpleSharedPtr<TBuilder> builder)
+TGenericBuilder::TTypedBuilder::TTypedBuilder(ENodeType type, TSimpleSharedPtr<TBuilder> builder)
: Type(type)
, Builder(std::move(builder)) {}
// TGenericBuilder
TGenericBuilder::TGenericBuilder()
- : TCommonBuilderOps<TGenericBuilder>(EBuilderType::Generic) {};
+ : TBase(ENodeType::Generic) {};
TGenericBuilder::TGenericBuilder(const TGenericBuilder& builder)
- : TCommonBuilderOps<TGenericBuilder>(builder)
+ : TBase(builder)
, PossibleBuilderPtrs_(builder.PossibleBuilderPtrs_) {}
TGenericBuilder::TGenericBuilder(TGenericBuilder&& builder)
- : TCommonBuilderOps<TGenericBuilder>(std::move(builder))
+ : TBase(std::move(builder))
, PossibleBuilderPtrs_(std::move(builder.PossibleBuilderPtrs_)) {}
TGenericBuilder& TGenericBuilder::operator=(const TGenericBuilder& builder) {
@@ -131,21 +119,22 @@ TGenericValidator TGenericBuilder::CreateValidator() {
result.AddValidator(NDetail::CreateValidatorPtr(builderPtr));
}
+ result.Checkers_ = Checkers_;
result.Required_ = Required_;
return result;
}
TMapBuilder::TMapBuilder()
- : TCommonBuilderOps<TMapBuilder>(EBuilderType::Map) {}
+ : TBase(ENodeType::Map) {}
TMapBuilder::TMapBuilder(const TMapBuilder& builder)
- : TCommonBuilderOps<TMapBuilder>(builder)
+ : TBase(builder)
, Children_(builder.Children_)
, Opaque_(builder.Opaque_) {}
TMapBuilder::TMapBuilder(TMapBuilder&& builder)
- : TCommonBuilderOps<TMapBuilder>(std::move(builder))
+ : TBase(std::move(builder))
, Children_(std::move(builder.Children_))
, Opaque_(builder.Opaque_) {}
@@ -254,21 +243,26 @@ TMapValidator TMapBuilder::CreateValidator() {
children[name] = NDetail::CreateValidatorPtr(builderPtr);
}
- return TMapValidator(std::move(children), Opaque_);
+ auto result = TMapValidator(std::move(children), Opaque_);
+
+ result.Checkers_ = Checkers_;
+ result.Required_ = Required_;
+
+ return result;
}
// TArrayBuilder
TArrayBuilder::TArrayBuilder()
- : TCommonBuilderOps<TArrayBuilder>(EBuilderType::Array) {}
+ : TBase(ENodeType::Array) {}
TArrayBuilder::TArrayBuilder(const TArrayBuilder& builder)
- : TCommonBuilderOps<TArrayBuilder>(builder)
+ : TBase(builder)
, ItemPtr_(builder.ItemPtr_)
, Unique_(builder.Unique_) {}
TArrayBuilder::TArrayBuilder(TArrayBuilder&& builder)
- : TCommonBuilderOps<TArrayBuilder>(std::move(builder))
+ : TBase(std::move(builder))
, ItemPtr_(std::move(builder.ItemPtr_))
, Unique_(builder.Unique_) {}
@@ -329,21 +323,24 @@ NDetail::TBuilder& TArrayBuilder::GetItem() {
}
TArrayValidator TArrayBuilder::CreateValidator() {
- return TArrayValidator(NDetail::CreateValidatorPtr(ItemPtr_), Unique_);
+ auto result = TArrayValidator(NDetail::CreateValidatorPtr(ItemPtr_), Unique_);
+ result.Checkers_ = Checkers_;
+ result.Required_ = Required_;
+ return result;
}
// TInt64Builder
TInt64Builder::TInt64Builder()
- : TCommonBuilderOps<TInt64Builder>(EBuilderType::Int64) {}
+ : TBase(ENodeType::Int64) {}
TInt64Builder::TInt64Builder(const TInt64Builder& builder)
- : TCommonBuilderOps<TInt64Builder>(builder)
+ : TBase(builder)
, Min_(builder.Min_)
, Max_(builder.Max_) {}
TInt64Builder::TInt64Builder(TInt64Builder&& builder)
- : TCommonBuilderOps<TInt64Builder>(std::move(builder))
+ : TBase(std::move(builder))
, Min_(builder.Min_)
, Max_(builder.Max_) {}
@@ -383,19 +380,22 @@ TInt64Builder& TInt64Builder::Range(i64 min, i64 max) {
}
TInt64Validator TInt64Builder::CreateValidator() {
- return TInt64Validator(Min_, Max_);
+ auto result = TInt64Validator(Min_, Max_);
+ result.Checkers_ = Checkers_;
+ result.Required_ = Required_;
+ return result;
}
// TStringBuilder
TStringBuilder::TStringBuilder()
- : TCommonBuilderOps<TStringBuilder>(EBuilderType::Int64) {}
+ : TBase(ENodeType::String) {}
TStringBuilder::TStringBuilder(const TStringBuilder& builder)
- : TCommonBuilderOps<TStringBuilder>(builder) {}
+ : TBase(builder) {}
TStringBuilder::TStringBuilder(TStringBuilder&& builder)
- : TCommonBuilderOps<TStringBuilder>(std::move(builder)) {}
+ : TBase(std::move(builder)) {}
TStringBuilder& TStringBuilder::operator=(const TStringBuilder& builder) {
TBuilder::operator=(builder);
@@ -413,19 +413,22 @@ TStringBuilder::TStringBuilder(std::function<void(TStringBuilder&)> configurator
}
TStringValidator TStringBuilder::CreateValidator() {
- return TStringValidator();
+ auto result = TStringValidator();
+ result.Checkers_ = Checkers_;
+ result.Required_ = Required_;
+ return result;
}
// TBoolBuilder
TBoolBuilder::TBoolBuilder()
- : TCommonBuilderOps<TBoolBuilder>(EBuilderType::Bool) {}
+ : TBase(ENodeType::Bool) {}
TBoolBuilder::TBoolBuilder(const TBoolBuilder& builder)
- : TCommonBuilderOps<TBoolBuilder>(builder) {}
+ : TBase(builder) {}
TBoolBuilder::TBoolBuilder(TBoolBuilder&& builder)
- : TCommonBuilderOps<TBoolBuilder>(std::move(builder)) {}
+ : TBase(std::move(builder)) {}
TBoolBuilder& TBoolBuilder::operator=(const TBoolBuilder& builder) {
TBuilder::operator=(builder);
@@ -443,7 +446,10 @@ TBoolBuilder::TBoolBuilder(std::function<void(TBoolBuilder&)> configurator)
}
TBoolValidator TBoolBuilder::CreateValidator() {
- return TBoolValidator();
+ auto result = TBoolValidator();
+ result.Checkers_ = Checkers_;
+ result.Required_ = Required_;
+ return result;
}
} // namespace NYamlConfig::NValidator
diff --git a/ydb/library/yaml_config/validator/validator_builder.h b/ydb/library/yaml_config/validator/validator_builder.h
index eee7b94912..bce7c25b98 100644
--- a/ydb/library/yaml_config/validator/validator_builder.h
+++ b/ydb/library/yaml_config/validator/validator_builder.h
@@ -1,6 +1,7 @@
#pragma once
#include "validator.h"
+#include "validator_checks.h"
#include <util/generic/ptr.h>
#include <util/generic/vector.h>
@@ -15,10 +16,6 @@
namespace NYamlConfig::NValidator {
-enum class EBuilderType {
- Generic, Map, Array, Int64, String, Bool
-};
-
class BuilderException : public yexception {};
class TGenericBuilder;
@@ -38,7 +35,7 @@ class TBuilder {
friend TSimpleSharedPtr<TValidator> NDetail::CreateValidatorPtr(const TSimpleSharedPtr<TBuilder>& builder);
public:
- TBuilder(EBuilderType builderType);
+ TBuilder(ENodeType nodeType);
TBuilder(const TBuilder& builder) = default;
TBuilder(TBuilder&& builder) = default;
@@ -49,30 +46,37 @@ public:
virtual ~TBuilder() = default;
protected:
- const EBuilderType BuilderType_;
+ const ENodeType NodeType_;
bool Required_ = true;
TString Description_;
};
-template <typename ThisType>
+template <typename TThis, typename TCheckContext>
class TCommonBuilderOps : public TBuilder {
public:
- TCommonBuilderOps<ThisType>(EBuilderType builderType);
- TCommonBuilderOps<ThisType>(const TBuilder& builder);
+ TCommonBuilderOps<TThis, TCheckContext>(ENodeType nodeType);
+ TCommonBuilderOps<TThis, TCheckContext>(const TCommonBuilderOps<TThis, TCheckContext>& builder);
- ThisType& Optional();
- ThisType& Required();
- ThisType& Description(const TString& description);
+ TThis& Optional();
+ TThis& Required();
+ TThis& Description(const TString& description);
- ThisType& Configure(std::function<void(ThisType&)> configurator = [](auto&){});
+ TThis& Configure(std::function<void(TThis&)> configurator = [](auto&){});
+
+ TThis& AddCheck(TString name, std::function<void(TCheckContext&)> checker);
+
+protected:
+ THashMap<TString, std::function<void(TCheckContext&)>> Checkers_;
private:
- ThisType& AsDerived();
+ TThis& AsDerived();
};
} // namespace NDetail
-class TGenericBuilder : public NDetail::TCommonBuilderOps<TGenericBuilder> {
+class TGenericBuilder : public NDetail::TCommonBuilderOps<TGenericBuilder, TGenericCheckContext> {
+ using TBase = NDetail::TCommonBuilderOps<TGenericBuilder, TGenericCheckContext>;
+
public:
TGenericBuilder();
@@ -84,8 +88,8 @@ public:
TGenericBuilder(std::function<void(TGenericBuilder&)> configurator);
- template <typename Builder>
- TGenericBuilder& CanBe(Builder builder);
+ template <typename TBuilder>
+ TGenericBuilder& CanBe(TBuilder builder);
TGenericBuilder& CanBeMap(std::function<void(TMapBuilder&)> configurator = [](auto&){});
TGenericBuilder& CanBeArray(std::function<void(TArrayBuilder&)> configurator = [](auto&){});
TGenericBuilder& CanBeInt64(std::function<void(TInt64Builder&)> configurator = [](auto&){});
@@ -95,18 +99,20 @@ public:
TGenericValidator CreateValidator();
private:
- struct NodeTypeAndBuilder {
- EBuilderType Type;
+ struct TTypedBuilder {
+ ENodeType Type;
TSimpleSharedPtr<TBuilder> Builder;
- NodeTypeAndBuilder();
- NodeTypeAndBuilder(EBuilderType type, TSimpleSharedPtr<TBuilder> builder);
+ TTypedBuilder();
+ TTypedBuilder(ENodeType type, TSimpleSharedPtr<TBuilder> builder);
};
TVector<TSimpleSharedPtr<TBuilder>> PossibleBuilderPtrs_;
};
-class TMapBuilder : public NDetail::TCommonBuilderOps<TMapBuilder> {
+class TMapBuilder : public NDetail::TCommonBuilderOps<TMapBuilder, TMapCheckContext> {
+ using TBase = NDetail::TCommonBuilderOps<TMapBuilder, TMapCheckContext>;
+
public:
TMapBuilder();
@@ -118,8 +124,8 @@ public:
TMapBuilder(std::function<void(TMapBuilder&)> configurator);
- template <typename Builder>
- TMapBuilder& Field(const TString& field, Builder builder);
+ template <typename TBuilder>
+ TMapBuilder& Field(const TString& field, TBuilder builder);
TMapBuilder& GenericField(const TString& field, std::function<void(TGenericBuilder&)> configurator = [](auto&){});
TMapBuilder& Map(const TString& field, std::function<void(TMapBuilder&)> configurator = [](auto&){});
@@ -149,7 +155,9 @@ private:
void ThrowIfAlreadyHasField(const TString& field);
};
-class TArrayBuilder : public NDetail::TCommonBuilderOps<TArrayBuilder> {
+class TArrayBuilder : public NDetail::TCommonBuilderOps<TArrayBuilder, TArrayCheckContext> {
+ using TBase = NDetail::TCommonBuilderOps<TArrayBuilder, TArrayCheckContext>;
+
public:
TArrayBuilder();
@@ -163,8 +171,8 @@ public:
TArrayBuilder& Unique();
- template <typename Builder>
- TArrayBuilder& Item(Builder builder);
+ template <typename TBuilder>
+ TArrayBuilder& Item(TBuilder builder);
TArrayBuilder& MapItem(std::function<void(TMapBuilder&)> configurator = [](auto&){});
TArrayBuilder& ArrayItem(std::function<void(TArrayBuilder&)> configurator = [](auto&){});
TArrayBuilder& Int64Item(std::function<void(TInt64Builder&)> configurator = [](auto&){});
@@ -180,7 +188,9 @@ private:
bool Unique_ = false;
};
-class TInt64Builder : public NDetail::TCommonBuilderOps<TInt64Builder> {
+class TInt64Builder : public NDetail::TCommonBuilderOps<TInt64Builder, TInt64CheckContext> {
+ using TBase = NDetail::TCommonBuilderOps<TInt64Builder, TInt64CheckContext>;
+
public:
TInt64Builder();
@@ -203,7 +213,9 @@ private:
i64 Max_ = ::Max<i64>();
};
-class TStringBuilder : public NDetail::TCommonBuilderOps<TStringBuilder> {
+class TStringBuilder : public NDetail::TCommonBuilderOps<TStringBuilder, TStringCheckContext> {
+ using TBase = NDetail::TCommonBuilderOps<TStringBuilder, TStringCheckContext>;
+
public:
TStringBuilder();
@@ -218,7 +230,9 @@ public:
TStringValidator CreateValidator();
};
-class TBoolBuilder : public NDetail::TCommonBuilderOps<TBoolBuilder> {
+class TBoolBuilder : public NDetail::TCommonBuilderOps<TBoolBuilder, TBoolCheckContext> {
+ using TBase = NDetail::TCommonBuilderOps<TBoolBuilder, TBoolCheckContext>;
+
public:
TBoolBuilder();
@@ -233,43 +247,52 @@ public:
TBoolValidator CreateValidator();
};
-template <typename ThisType>
-NDetail::TCommonBuilderOps<ThisType>::TCommonBuilderOps(EBuilderType builderType)
- : TBuilder(builderType) {}
+template <typename TThis, typename TCheckContext>
+NDetail::TCommonBuilderOps<TThis, TCheckContext>::TCommonBuilderOps(ENodeType nodeType)
+ : TBuilder(nodeType) {}
-template <typename ThisType>
-NDetail::TCommonBuilderOps<ThisType>::TCommonBuilderOps(const TBuilder& builder)
- : TBuilder(builder) {}
+template <typename TThis, typename TCheckContext>
+NDetail::TCommonBuilderOps<TThis, TCheckContext>::TCommonBuilderOps(const TCommonBuilderOps<TThis, TCheckContext>& builder)
+ : TBuilder(builder), Checkers_(builder.Checkers_) {}
-template <typename ThisType>
-ThisType& NDetail::TCommonBuilderOps<ThisType>::AsDerived() {
- return static_cast<ThisType&>(*this);
+template <typename TThis, typename TCheckContext>
+TThis& NDetail::TCommonBuilderOps<TThis, TCheckContext>::AsDerived() {
+ return static_cast<TThis&>(*this);
}
-template <typename ThisType>
-ThisType& NDetail::TCommonBuilderOps<ThisType>::Optional() {
+template <typename TThis, typename TCheckContext>
+TThis& NDetail::TCommonBuilderOps<TThis, TCheckContext>::Optional() {
Required_ = false;
return AsDerived();
}
-template <typename ThisType>
-ThisType& NDetail::TCommonBuilderOps<ThisType>::Required() {
+template <typename TThis, typename TCheckContext>
+TThis& NDetail::TCommonBuilderOps<TThis, TCheckContext>::Required() {
Required_ = true;
return AsDerived();
}
-template <typename ThisType>
-ThisType& NDetail::TCommonBuilderOps<ThisType>::Description(const TString& description) {
+template <typename TThis, typename TCheckContext>
+TThis& NDetail::TCommonBuilderOps<TThis, TCheckContext>::Description(const TString& description) {
Description_ = description;
return AsDerived();
}
-template <typename ThisType>
-ThisType& NDetail::TCommonBuilderOps<ThisType>::Configure(std::function<void(ThisType&)> configurator) {
+template <typename TThis, typename TCheckContext>
+TThis& NDetail::TCommonBuilderOps<TThis, TCheckContext>::Configure(std::function<void(TThis&)> configurator) {
configurator(AsDerived());
return AsDerived();
}
+template <typename TThis, typename TCheckContext>
+TThis& NDetail::TCommonBuilderOps<TThis, TCheckContext>::AddCheck(TString name, std::function<void(TCheckContext&)> checker) {
+ if (Checkers_.contains(name)) {
+ ythrow yexception() << "Already has check named \"" << name << "\"";
+ }
+ Checkers_[name] = checker;
+ return AsDerived();
+}
+
template <typename Builder>
TGenericBuilder& TGenericBuilder::CanBe(Builder builder) {
PossibleBuilderPtrs_.emplace_back(new Builder(std::move(builder)));
diff --git a/ydb/library/yaml_config/validator/validator_checks.cpp b/ydb/library/yaml_config/validator/validator_checks.cpp
new file mode 100644
index 0000000000..965bf97545
--- /dev/null
+++ b/ydb/library/yaml_config/validator/validator_checks.cpp
@@ -0,0 +1,390 @@
+#include "validator_checks.h"
+
+#include <util/string/cast.h>
+
+namespace NYamlConfig::NValidator {
+
+TNodeWrapper::TNodeWrapper(
+ TCheckContext* context,
+ NFyaml::TNodeRef node,
+ TValidator* validator,
+ TMaybe<ENodeType> nodeType,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , NodeType_(nodeType)
+ , PathFromCheckNode_(pathFromCheckNode) {}
+
+TGenericNodeWrapper TNodeWrapper::Generic() {
+ TGenericCheckContext* context = nullptr;
+ TGenericValidator* validator = nullptr;
+
+ if (Node_) {
+ Y_ASSERT(NodeType_ == ENodeType::Generic);
+
+ context = static_cast<TGenericCheckContext*>(Context_);
+ validator = static_cast<TGenericValidator*>(Validator_);
+ }
+
+ return TGenericNodeWrapper(
+ context,
+ Node_,
+ validator,
+ PathFromCheckNode_);
+}
+
+TMapNodeWrapper TNodeWrapper::Map() {
+ TMapCheckContext* context = nullptr;
+ TMapValidator* validator = nullptr;
+
+ if (Node_) {
+ Y_ASSERT(NodeType_ == ENodeType::Map);
+
+ context = static_cast<TMapCheckContext*>(Context_);
+ validator = static_cast<TMapValidator*>(Validator_);
+ }
+
+ return TMapNodeWrapper(
+ context,
+ Node_,
+ validator,
+ PathFromCheckNode_);
+}
+
+TArrayNodeWrapper TNodeWrapper::Array() {
+ TArrayCheckContext* context = nullptr;
+ TArrayValidator* validator = nullptr;
+
+ if (Node_) {
+ Y_ASSERT(NodeType_ == ENodeType::Array);
+
+ context = static_cast<TArrayCheckContext*>(Context_);
+ validator = static_cast<TArrayValidator*>(Validator_);
+ }
+
+ return TArrayNodeWrapper(
+ context,
+ Node_,
+ validator,
+ PathFromCheckNode_);
+}
+
+TInt64NodeWrapper TNodeWrapper::Int64() {
+ TInt64CheckContext* context = nullptr;
+ TInt64Validator* validator = nullptr;
+
+ if (Node_) {
+ Y_ASSERT(NodeType_ == ENodeType::Int64);
+
+ context = static_cast<TInt64CheckContext*>(Context_);
+ validator = static_cast<TInt64Validator*>(Validator_);
+ }
+
+ return TInt64NodeWrapper(
+ context,
+ Node_,
+ validator,
+ PathFromCheckNode_);
+}
+
+TStringNodeWrapper TNodeWrapper::String() {
+ TStringCheckContext* context = nullptr;
+ TStringValidator* validator = nullptr;
+
+ if (Node_) {
+ Y_ASSERT(NodeType_ == ENodeType::String);
+
+ context = static_cast<TStringCheckContext*>(Context_);
+ validator = static_cast<TStringValidator*>(Validator_);
+ }
+
+ return TStringNodeWrapper(
+ context,
+ Node_,
+ validator,
+ PathFromCheckNode_);
+}
+
+TBoolNodeWrapper TNodeWrapper::Bool() {
+ TBoolCheckContext* context = nullptr;
+ TBoolValidator* validator = nullptr;
+
+ if (Node_) {
+ Y_ASSERT(NodeType_ == ENodeType::Bool);
+
+ context = static_cast<TBoolCheckContext*>(Context_);
+ validator = static_cast<TBoolValidator*>(Validator_);
+ }
+
+ return TBoolNodeWrapper(
+ context,
+ Node_,
+ validator,
+ PathFromCheckNode_);
+}
+
+ENodeType TNodeWrapper::Type() {
+ ThrowIfNullNode();
+ Y_ASSERT(NodeType_.Defined());
+ return NodeType_.GetRef();
+}
+
+TGenericNodeWrapper::TGenericNodeWrapper(
+ TGenericCheckContext* context,
+ NFyaml::TNodeRef node,
+ TGenericValidator* validator,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , PathFromCheckNode_(pathFromCheckNode) {
+ Y_UNUSED(Validator_);
+ Y_UNUSED(Context_);
+ Y_UNUSED(Node_);
+ }
+
+TMapNodeWrapper::TMapNodeWrapper(
+ TMapCheckContext* context,
+ NFyaml::TNodeRef node,
+ TMapValidator* validator,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , PathFromCheckNode_(pathFromCheckNode) {}
+
+TNodeWrapper TMapNodeWrapper::operator[](const TString& field) {
+ NFyaml::TNodeRef node(nullptr);
+ TValidator* validator = nullptr;
+ TMaybe<ENodeType> nodeType;
+
+ if (Node_ && Map().Has(field)) {
+ node = Map().at(field);
+ }
+ if (Validator_ && Validator_->Children_.contains(field)) {
+ validator = Validator_->Children_.at(field).Get();
+ nodeType = validator->NodeType_;
+ }
+ // TODO: else must deduce node type here or later(in check for
+ // example) for use with opaque maps
+
+ return TNodeWrapper(
+ Context_,
+ node,
+ validator,
+ nodeType,
+ PathFromCheckNode_ + "/" + field);
+}
+
+TNodeWrapper TMapNodeWrapper::At(const TString& field) {
+ ThrowIfNullNode();
+
+ if (!Validator_->Children_.contains(field) || !Map().Has(field)) {
+ TString nodePath = Context_->CheckNodePath_ + "/" + PathFromCheckNode_;
+ TString message = "Node \"" + nodePath + "\" is not presented";
+ Context_->AddError(message);
+ throw yexception() << message;
+ }
+
+ TValidator* validator = Validator_->Children_.at(field).Get();
+ return TNodeWrapper(
+ Context_,
+ Map().at(field),
+ validator,
+ validator->NodeType_,
+ PathFromCheckNode_ + "/" + field);
+}
+
+bool TMapNodeWrapper::Has(const TString& field) {
+ ThrowIfNullNode();
+ return Map().Has(field);
+}
+
+NFyaml::TMapping TMapNodeWrapper::Map() {
+ return Node_.Map();
+}
+
+TArrayNodeWrapper::TArrayNodeWrapper(
+ TArrayCheckContext* context,
+ NFyaml::TNodeRef node,
+ TArrayValidator* validator,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , PathFromCheckNode_(pathFromCheckNode) {}
+
+int TArrayNodeWrapper::Length() {
+ ThrowIfNullNode();
+ return Sequence().size();
+}
+
+TNodeWrapper TArrayNodeWrapper::operator[](size_t index) {
+ NFyaml::TNodeRef node(nullptr);
+ TValidator* validator = nullptr;
+ TMaybe<ENodeType> nodeType;
+
+ if (Node_ && Sequence().size() > index) {
+ node = Sequence()[index];
+ }
+
+ if (Validator_) {
+ validator = Validator_->ItemValidatorPtr_.Get();
+ nodeType = validator->NodeType_;
+ }
+
+ return TNodeWrapper(
+ Context_,
+ node,
+ validator,
+ nodeType,
+ PathFromCheckNode_ + "/" + ToString(index));
+}
+
+NFyaml::TSequence TArrayNodeWrapper::Sequence() {
+ return Node_.Sequence();
+}
+
+TInt64NodeWrapper::TInt64NodeWrapper(
+ TInt64CheckContext* context,
+ NFyaml::TNodeRef node,
+ TInt64Validator* validator,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , PathFromCheckNode_(pathFromCheckNode) {}
+
+i64 TInt64NodeWrapper::Value() {
+ ThrowIfNullNode();
+ return FromString<i64>(Node_.Scalar());
+}
+
+TInt64NodeWrapper::operator i64() {
+ return Value();
+}
+
+TStringNodeWrapper::TStringNodeWrapper(
+ TStringCheckContext* context,
+ NFyaml::TNodeRef node,
+ TStringValidator* validator,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , PathFromCheckNode_(pathFromCheckNode) {}
+
+TString TStringNodeWrapper::Value() {
+ ThrowIfNullNode();
+ return Node_.Scalar();
+}
+
+TStringNodeWrapper::operator TString() {
+ return Value();
+}
+
+TBoolNodeWrapper::TBoolNodeWrapper(
+ TBoolCheckContext* context,
+ NFyaml::TNodeRef node,
+ TBoolValidator* validator,
+ const TString& pathFromCheckNode)
+ : Context_(context)
+ , Node_(node)
+ , Validator_(validator)
+ , PathFromCheckNode_(pathFromCheckNode) {}
+
+bool TBoolNodeWrapper::Value() {
+ ThrowIfNullNode();
+ TString scalar = Node_.Scalar();
+ scalar.to_lower();
+ return scalar == "true";
+}
+
+TBoolNodeWrapper::operator bool() {
+ return Value();
+}
+
+
+TCheckContext::TCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath)
+ : Node_(node)
+ , CheckNodePath_(checkNodePath) {}
+
+void TCheckContext::Expect(bool condition, TString error) {
+ if (!condition) {
+ AddError(error);
+ someExpectFailed = true;
+ }
+}
+
+void TCheckContext::Expect(bool condition) {
+ someExpectFailed |= !condition;
+}
+
+void TCheckContext::AddError(TString error) {
+ Errors_.emplace_back(std::move(error));
+}
+
+TGenericCheckContext::TGenericCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TGenericValidator* validator)
+ : TCheckContext(node, checkNodePath), Validator_(validator) {}
+
+TGenericNodeWrapper TGenericCheckContext::Node() {
+ return TGenericNodeWrapper(this, Node_, Validator_, CheckNodePath_);
+}
+
+TMapCheckContext::TMapCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TMapValidator* validator)
+ : TCheckContext(node, checkNodePath), Validator_(validator) {}
+
+TMapNodeWrapper TMapCheckContext::Node() {
+ return TMapNodeWrapper(this, Node_.Map(), Validator_, CheckNodePath_);
+}
+
+TArrayCheckContext::TArrayCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TArrayValidator* validator)
+ : TCheckContext(node, checkNodePath), Validator_(validator) {}
+
+TArrayNodeWrapper TArrayCheckContext::Node() {
+ return TArrayNodeWrapper(this, Node_.Sequence(), Validator_, CheckNodePath_);
+}
+
+TInt64CheckContext::TInt64CheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TInt64Validator* validator)
+ : TCheckContext(node, checkNodePath), Validator_(validator) {}
+
+TInt64NodeWrapper TInt64CheckContext::Node() {
+ return TInt64NodeWrapper(this, Node_, Validator_, CheckNodePath_);
+}
+
+TStringCheckContext::TStringCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TStringValidator* validator)
+ : TCheckContext(node, checkNodePath), Validator_(validator) {}
+
+TStringNodeWrapper TStringCheckContext::Node() {
+ return TStringNodeWrapper(this, Node_, Validator_, CheckNodePath_);
+}
+
+TBoolCheckContext::TBoolCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TBoolValidator* validator)
+ : TCheckContext(node, checkNodePath), Validator_(validator) {}
+
+TBoolNodeWrapper TBoolCheckContext::Node() {
+ return TBoolNodeWrapper(this, Node_, Validator_, CheckNodePath_);
+}
+
+} \ No newline at end of file
diff --git a/ydb/library/yaml_config/validator/validator_checks.h b/ydb/library/yaml_config/validator/validator_checks.h
new file mode 100644
index 0000000000..09bd313c1e
--- /dev/null
+++ b/ydb/library/yaml_config/validator/validator_checks.h
@@ -0,0 +1,336 @@
+#pragma once
+
+#include "validator.h"
+
+#include <util/generic/maybe.h>
+
+// context is attached to some path
+
+// node wrapper should have context, because of ctx["field1"]["field2"].
+// If field1 exists and field2 doesn't, then NodeWrapper would be responsible
+// for error notification. And in general it may be good for node wrapper to
+// know in what context it exists
+
+// TODO: make something like this
+// (MapContext ctx) {
+// ctx.ExpectEqual(ctx["field"], ctx["Another_field"]["2"], "must be equal");
+// // ExpectEqual(const TNodeWrapper&, const TNodeWrapper&) -> checks types and values (only for scalars)
+// // if (ctx["field"])
+// ctx["field"] // error if field is not presented?
+// if (ctx.Has("field1")) {
+// c.ExpectToExist(ctx["field2"]["field3"]);
+// //Access to methods by this path(when node is not presented) - error
+// } else {
+// ctx.ExpectGreater(ctx["field3"].Int64()/*.Value*/, 10);
+// }
+// }
+
+namespace NYamlConfig::NValidator {
+
+class TNodeWrapper;
+class TGenericNodeWrapper;
+class TMapNodeWrapper;
+class TArrayNodeWrapper;
+class TInt64NodeWrapper;
+class TStringNodeWrapper;
+class TBoolNodeWrapper;
+
+class TCheckContext;
+class TGenericCheckContext;
+class TMapCheckContext;
+class TArrayCheckContext;
+class TInt64CheckContext;
+class TStringCheckContext;
+class TBoolCheckContext;
+
+namespace NDetail {
+
+template <typename TThis, typename TContext>
+class TValidatorCommonOps;
+
+template <typename TThis>
+class TNodeWrapperCommonOps {
+public:
+ void ThrowIfNullNode();
+};
+
+template <typename TThis>
+void TNodeWrapperCommonOps<TThis>::ThrowIfNullNode() {
+ auto& This = static_cast<TThis&>(*this);
+ if (!This.Node_) {
+ throw yexception() <<
+ "Node \"" +
+ This.PathFromCheckNode_ +
+ "\" is not presented";
+ }
+}
+
+}
+
+class TNodeWrapper : public NDetail::TNodeWrapperCommonOps<TNodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TNodeWrapper(
+ TCheckContext* context,
+ NFyaml::TNodeRef node,
+ TValidator* validator,
+ TMaybe<ENodeType> nodeType,
+ const TString& pathFromCheckNode);
+
+ TGenericNodeWrapper Generic();
+ TMapNodeWrapper Map();
+ TArrayNodeWrapper Array();
+ TInt64NodeWrapper Int64();
+ TStringNodeWrapper String();
+ TBoolNodeWrapper Bool();
+
+ ENodeType Type();
+
+protected:
+ TCheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TValidator* Validator_;
+ TMaybe<ENodeType> NodeType_;
+ TString PathFromCheckNode_;
+};
+
+class TGenericNodeWrapper : public NDetail::TNodeWrapperCommonOps<TGenericNodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+// TODO: make some functionality for generic wrapper
+public:
+ TGenericNodeWrapper(
+ TGenericCheckContext* context,
+ NFyaml::TNodeRef node,
+ TGenericValidator* validator,
+ const TString& pathFromCheckNode);
+
+private:
+ TGenericCheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TGenericValidator* Validator_;
+ TString PathFromCheckNode_;
+};
+
+class TMapNodeWrapper : public NDetail::TNodeWrapperCommonOps<TMapNodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TMapNodeWrapper(
+ TMapCheckContext* context,
+ NFyaml::TNodeRef node,
+ TMapValidator* validator,
+ const TString& pathFromCheckNode);
+
+ TNodeWrapper operator[](const TString& field);
+ TNodeWrapper At(const TString& field);
+ bool Has(const TString& field);
+
+private:
+ TMapCheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TMapValidator* Validator_;
+ TString PathFromCheckNode_;
+
+ NFyaml::TMapping Map();
+};
+
+class TArrayNodeWrapper : public NDetail::TNodeWrapperCommonOps<TArrayNodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TArrayNodeWrapper(
+ TArrayCheckContext* context,
+ NFyaml::TNodeRef node,
+ TArrayValidator* validator,
+ const TString& pathFromCheckNode);
+
+ int Length();
+
+ TNodeWrapper operator[](size_t index);
+
+private:
+ TArrayCheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TArrayValidator* Validator_;
+ TString PathFromCheckNode_;
+
+ NFyaml::TSequence Sequence();
+};
+
+class TInt64NodeWrapper : public NDetail::TNodeWrapperCommonOps<TInt64NodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TInt64NodeWrapper(
+ TInt64CheckContext* context,
+ NFyaml::TNodeRef node,
+ TInt64Validator* validator,
+ const TString& pathFromCheckNode);
+
+ i64 Value();
+ operator i64();
+
+private:
+ TInt64CheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TInt64Validator* Validator_;
+ TString PathFromCheckNode_;
+};
+
+class TStringNodeWrapper : public NDetail::TNodeWrapperCommonOps<TStringNodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TStringNodeWrapper(
+ TStringCheckContext* context,
+ NFyaml::TNodeRef node,
+ TStringValidator* validator,
+ const TString& pathFromCheckNode);
+
+ TString Value();
+ operator TString();
+
+private:
+ TStringCheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TStringValidator* Validator_;
+ TString PathFromCheckNode_;
+};
+
+class TBoolNodeWrapper : public NDetail::TNodeWrapperCommonOps<TBoolNodeWrapper> {
+ template <typename> friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TBoolNodeWrapper(
+ TBoolCheckContext* context,
+ NFyaml::TNodeRef node,
+ TBoolValidator* validator,
+ const TString& pathFromCheckNode);
+
+ bool Value();
+ operator bool();
+
+private:
+ TBoolCheckContext* Context_;
+ NFyaml::TNodeRef Node_;
+ TBoolValidator* Validator_;
+ TString PathFromCheckNode_;
+};
+
+
+class TCheckContext {
+ friend class TMapNodeWrapper; // for access to node path
+ template <typename TThis, typename TContext>
+ friend class NDetail::TValidatorCommonOps;
+ template <typename>
+ friend class NDetail::TNodeWrapperCommonOps;
+
+public:
+ TCheckContext(
+ NFyaml::TNodeRef node,
+ const TString& checkNodePath);
+
+ void Expect(bool condition, TString error);
+ void Expect(bool condition);
+ void AddError(TString error);
+
+ virtual ~TCheckContext() = default;
+
+protected:
+ TVector<TString> Errors_;
+ NFyaml::TNodeRef Node_;
+ TString CheckNodePath_;
+ bool someExpectFailed = false;
+};
+
+class TGenericCheckContext : public TCheckContext {
+ friend class TGenericValidator;
+ friend class TGenericNodeWrapper;
+
+public:
+ TGenericCheckContext(NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TGenericValidator* validator);
+
+ TGenericNodeWrapper Node();
+
+private:
+ TGenericValidator* Validator_;
+};
+
+class TMapCheckContext : public TCheckContext {
+ friend class TMapValidator;
+ friend class TMapNodeWrapper;
+
+public:
+ TMapCheckContext(NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TMapValidator* validator);
+
+ TMapNodeWrapper Node();
+
+private:
+ TMapValidator* Validator_;
+};
+
+class TArrayCheckContext : public TCheckContext {
+ friend class TArrayValidator;
+ friend class TArrayNodeWrapper;
+
+public:
+ TArrayCheckContext(NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TArrayValidator* validator);
+
+ TArrayNodeWrapper Node();
+
+private:
+ TArrayValidator* Validator_;
+};
+
+class TInt64CheckContext : public TCheckContext {
+ friend class TInt64Validator;
+ friend class TInt64NodeWrapper;
+
+public:
+ TInt64CheckContext(NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TInt64Validator* validator);
+
+ TInt64NodeWrapper Node();
+
+private:
+ TInt64Validator* Validator_;
+};
+
+class TStringCheckContext : public TCheckContext {
+ friend class TStringNodeWrapper;
+
+public:
+ TStringCheckContext(NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TStringValidator* validator);
+
+ TStringNodeWrapper Node();
+
+private:
+ TStringValidator* Validator_;
+};
+
+class TBoolCheckContext : public TCheckContext {
+ friend class TBoolNodeWrapper;
+
+public:
+ TBoolCheckContext(NFyaml::TNodeRef node,
+ const TString& checkNodePath,
+ TBoolValidator* validator);
+
+ TBoolNodeWrapper Node();
+
+private:
+ TBoolValidator* Validator_;
+};
+
+} // namespace NYamlConfig::NValidator
diff --git a/ydb/library/yaml_config/validator/ya.make b/ydb/library/yaml_config/validator/ya.make
index d6bf8e3449..d2ce3c08ce 100644
--- a/ydb/library/yaml_config/validator/ya.make
+++ b/ydb/library/yaml_config/validator/ya.make
@@ -5,6 +5,8 @@ SRCS(
validator_builder.cpp
validator.h
validator.cpp
+ validator_checks.h
+ validator_checks.cpp
)
PEERDIR(