From 43ec83a6e1c7ade5699f94c39568bb09dd15fa65 Mon Sep 17 00:00:00 2001 From: Rafail Date: Thu, 26 Mar 2026 17:22:45 +0300 Subject: [PATCH 1/4] chaotic: IsValid helper function for string enums --- chaotic/chaotic/back/cpp/templates/type.cpp.jinja | 14 ++++++++++++++ chaotic/chaotic/back/cpp/templates/type.hpp.jinja | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/chaotic/chaotic/back/cpp/templates/type.cpp.jinja b/chaotic/chaotic/back/cpp/templates/type.cpp.jinja index 908449e363c7..11b01ddb92d8 100644 --- a/chaotic/chaotic/back/cpp/templates/type.cpp.jinja +++ b/chaotic/chaotic/back/cpp/templates/type.cpp.jinja @@ -210,6 +210,18 @@ {% endif %} {% endmacro %} +{% macro generate_isvalid_definition(type) %} + {# handle subtypes #} + {%- for schema in type.subtypes() -%} + {{ generate_isvalid_definition(schema) }} + {% endfor %} + + {% if type.get_py_type() == 'CppStringEnum' %} + bool IsValid{{ shortest_cpp_name(type) }}(std::string_view value) { + return k{{ type.cpp_global_struct_field_name() }}_Mapping.TryFindBySecond(value).has_value(); + } + {% endif %} +{% endmacro %} {% macro generate_operator_eq_definition(type) %} {% set local_name = shortest_cpp_name(type) %} @@ -312,6 +324,8 @@ {% endif %} {{ generate_tostring_definition(type) }} + + {{ generate_isvalid_definition(type) }} {% endfor %} {{ common.switch_namespace('') }} diff --git a/chaotic/chaotic/back/cpp/templates/type.hpp.jinja b/chaotic/chaotic/back/cpp/templates/type.hpp.jinja index d419794cb7a3..06f091cf3b89 100644 --- a/chaotic/chaotic/back/cpp/templates/type.hpp.jinja +++ b/chaotic/chaotic/back/cpp/templates/type.hpp.jinja @@ -279,6 +279,18 @@ {% endif %} {% endmacro %} +{% macro generate_isvalid_declaration(type) %} + {# handle subtypes #} + {%- for schema in type.subtypes() -%} + {{ generate_isvalid_declaration(schema) }} + {% endfor %} + + {% if type.get_py_type() == 'CppStringEnum' %} + bool IsValid{{ shortest_cpp_name(type) }}(std::string_view value); + {% endif %} +{% endmacro %} + + {% macro generate_fmt_formatter_declaration(type) %} {# handle subtypes #} {%- for schema in type.subtypes() -%} @@ -328,6 +340,8 @@ {% endif %} {{ generate_tostring_declaration(type) }} + + {{ generate_isvalid_declaration(type) }} {% endfor %} {{ common.switch_namespace('') }} From ffc22322a06ee57b7b588b9ca864fa9114880eb4 Mon Sep 17 00:00:00 2001 From: Rafail Date: Thu, 26 Mar 2026 17:34:55 +0300 Subject: [PATCH 2/4] test --- chaotic/integration_tests/tests/render/simple.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/chaotic/integration_tests/tests/render/simple.cpp b/chaotic/integration_tests/tests/render/simple.cpp index 091440e2593c..356263d21e51 100644 --- a/chaotic/integration_tests/tests/render/simple.cpp +++ b/chaotic/integration_tests/tests/render/simple.cpp @@ -296,6 +296,11 @@ TEST(Simple, StringEnum) { EXPECT_EQ("bar", ToString(ns::StringEnum::kBar)); EXPECT_EQ("some!thing", ToString(ns::StringEnum::kSomeThing)); + EXPECT_TRUE(IsValidStringEnum("foo")); + EXPECT_TRUE(IsValidStringEnum("bar")); + EXPECT_TRUE(IsValidStringEnum("some!thing")); + EXPECT_FALSE(IsValidStringEnum("invalid")); + EXPECT_EQ(FromString("foo", formats::parse::To{}), ns::StringEnum::kFoo); UEXPECT_THROW_MSG( FromString("zoo", formats::parse::To{}), From 93480f7f8dc962c99e9d7c0c5ffddb262cbf4023 Mon Sep 17 00:00:00 2001 From: Rafail Date: Fri, 27 Mar 2026 01:28:58 +0300 Subject: [PATCH 3/4] Rename to IsConvertible --- chaotic/chaotic/back/cpp/templates/type.cpp.jinja | 10 ++++++---- chaotic/chaotic/back/cpp/templates/type.hpp.jinja | 9 +++++---- chaotic/integration_tests/tests/render/simple.cpp | 8 ++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/chaotic/chaotic/back/cpp/templates/type.cpp.jinja b/chaotic/chaotic/back/cpp/templates/type.cpp.jinja index 11b01ddb92d8..1752f5da2987 100644 --- a/chaotic/chaotic/back/cpp/templates/type.cpp.jinja +++ b/chaotic/chaotic/back/cpp/templates/type.cpp.jinja @@ -210,14 +210,16 @@ {% endif %} {% endmacro %} -{% macro generate_isvalid_definition(type) %} +{% macro generate_isconvertible_definition(type) %} {# handle subtypes #} {%- for schema in type.subtypes() -%} - {{ generate_isvalid_definition(schema) }} + {{ generate_isconvertible_definition(schema) }} {% endfor %} {% if type.get_py_type() == 'CppStringEnum' %} - bool IsValid{{ shortest_cpp_name(type) }}(std::string_view value) { + bool IsConvertible(std::string_view value, + {{ userver }}::formats::parse::To<{{ shortest_cpp_name(type) }}>) + { return k{{ type.cpp_global_struct_field_name() }}_Mapping.TryFindBySecond(value).has_value(); } {% endif %} @@ -325,7 +327,7 @@ {{ generate_tostring_definition(type) }} - {{ generate_isvalid_definition(type) }} + {{ generate_isconvertible_definition(type) }} {% endfor %} {{ common.switch_namespace('') }} diff --git a/chaotic/chaotic/back/cpp/templates/type.hpp.jinja b/chaotic/chaotic/back/cpp/templates/type.hpp.jinja index 06f091cf3b89..3365bb240b12 100644 --- a/chaotic/chaotic/back/cpp/templates/type.hpp.jinja +++ b/chaotic/chaotic/back/cpp/templates/type.hpp.jinja @@ -279,14 +279,15 @@ {% endif %} {% endmacro %} -{% macro generate_isvalid_declaration(type) %} +{% macro generate_isconvertible_declaration(type) %} {# handle subtypes #} {%- for schema in type.subtypes() -%} - {{ generate_isvalid_declaration(schema) }} + {{ generate_isconvertible_declaration(schema) }} {% endfor %} {% if type.get_py_type() == 'CppStringEnum' %} - bool IsValid{{ shortest_cpp_name(type) }}(std::string_view value); + bool IsConvertible(std::string_view value, + {{ userver }}::formats::parse::To<{{ shortest_cpp_name(type) }}>); {% endif %} {% endmacro %} @@ -341,7 +342,7 @@ {{ generate_tostring_declaration(type) }} - {{ generate_isvalid_declaration(type) }} + {{ generate_isconvertible_declaration(type) }} {% endfor %} {{ common.switch_namespace('') }} diff --git a/chaotic/integration_tests/tests/render/simple.cpp b/chaotic/integration_tests/tests/render/simple.cpp index 356263d21e51..9de4879f96f3 100644 --- a/chaotic/integration_tests/tests/render/simple.cpp +++ b/chaotic/integration_tests/tests/render/simple.cpp @@ -296,10 +296,10 @@ TEST(Simple, StringEnum) { EXPECT_EQ("bar", ToString(ns::StringEnum::kBar)); EXPECT_EQ("some!thing", ToString(ns::StringEnum::kSomeThing)); - EXPECT_TRUE(IsValidStringEnum("foo")); - EXPECT_TRUE(IsValidStringEnum("bar")); - EXPECT_TRUE(IsValidStringEnum("some!thing")); - EXPECT_FALSE(IsValidStringEnum("invalid")); + EXPECT_TRUE(IsConvertible("foo", formats::parse::To{})); + EXPECT_TRUE(IsConvertible("bar", formats::parse::To{})); + EXPECT_TRUE(IsConvertible("some!thing", formats::parse::To{})); + EXPECT_FALSE(IsConvertible("invalid", formats::parse::To{})); EXPECT_EQ(FromString("foo", formats::parse::To{}), ns::StringEnum::kFoo); UEXPECT_THROW_MSG( From 9742c87398f7cea370ae79f4d34f54b3d2629794 Mon Sep 17 00:00:00 2001 From: Rafail Date: Fri, 27 Mar 2026 16:39:22 +0300 Subject: [PATCH 4/4] Fix diff test --- chaotic/golden_tests/output/schemas/enum/enum.cpp | 4 ++++ chaotic/golden_tests/output/schemas/enum/enum.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/chaotic/golden_tests/output/schemas/enum/enum.cpp b/chaotic/golden_tests/output/schemas/enum/enum.cpp index 05844d4c2381..feb3e868bb3a 100644 --- a/chaotic/golden_tests/output/schemas/enum/enum.cpp +++ b/chaotic/golden_tests/output/schemas/enum/enum.cpp @@ -82,6 +82,10 @@ std::string ToString(Enum::Foo value) { throw std::runtime_error(fmt::format("Invalid enum value: {}", static_cast(value))); } +bool IsConvertible(std::string_view value, USERVER_NAMESPACE::formats::parse::To) { + return k__ns__Enum__Foo_Mapping.TryFindBySecond(value).has_value(); +} + } // namespace ns fmt::format_context::iterator fmt::formatter::format(const ns::Enum::Foo& value, diff --git a/chaotic/golden_tests/output/schemas/enum/enum.hpp b/chaotic/golden_tests/output/schemas/enum/enum.hpp index d3a755680297..76a3e889b93a 100644 --- a/chaotic/golden_tests/output/schemas/enum/enum.hpp +++ b/chaotic/golden_tests/output/schemas/enum/enum.hpp @@ -60,6 +60,8 @@ USERVER_NAMESPACE::formats::json::Value Serialize( std::string ToString(Enum::Foo value); +bool IsConvertible(std::string_view value, USERVER_NAMESPACE::formats::parse::To); + } // namespace ns template <>