From bd85564031641415db1597381f07cc7f7002b653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Hibner?= Date: Thu, 21 Nov 2024 11:09:42 +0100 Subject: [PATCH 1/6] Trigger conversion error --- samples/today/schema.today.graphql | 1 + test/ClientTests.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/samples/today/schema.today.graphql b/samples/today/schema.today.graphql index 8c794450..94e9770a 100644 --- a/samples/today/schema.today.graphql +++ b/samples/today/schema.today.graphql @@ -87,6 +87,7 @@ input CompleteTaskInput { testTaskState: TaskState isComplete: Boolean = true clientMutationId: String + boolList: [Boolean!] } type CompleteTaskPayload { diff --git a/test/ClientTests.cpp b/test/ClientTests.cpp index 26a1bcb9..4f674d00 100644 --- a/test/ClientTests.cpp +++ b/test/ClientTests.cpp @@ -246,7 +246,8 @@ TEST_F(ClientCase, MutateCompleteTask) { std::make_unique(CompleteTaskInput { today::getFakeTaskId(), std::nullopt, std::make_optional(true), - std::make_optional("Hi There!"s) }) }); + std::make_optional("Hi There!"s), + std::vector({true,false}) }) }); auto state = std::make_shared(5); auto result = From f7cfbc5ab2db1fa56c7dc7eadab3d55ed23f34c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Hibner?= Date: Thu, 21 Nov 2024 13:42:33 +0000 Subject: [PATCH 2/6] Update generated files --- samples/client/multiple/MultipleQueriesClient.cpp | 9 ++++++++- samples/client/multiple/MultipleQueriesClient.h | 4 +++- samples/client/mutate/MutateClient.cpp | 9 ++++++++- samples/client/mutate/MutateClient.h | 4 +++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/samples/client/multiple/MultipleQueriesClient.cpp b/samples/client/multiple/MultipleQueriesClient.cpp index 1644ddcb..177380a0 100644 --- a/samples/client/multiple/MultipleQueriesClient.cpp +++ b/samples/client/multiple/MultipleQueriesClient.cpp @@ -131,6 +131,7 @@ CompleteTaskInput::CompleteTaskInput() noexcept , testTaskState {} , isComplete {} , clientMutationId {} + , boolList {} { // Explicit definition to prevent ODR violations when LTO is enabled. } @@ -139,11 +140,13 @@ CompleteTaskInput::CompleteTaskInput( response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept : id { std::move(idArg) } , testTaskState { std::move(testTaskStateArg) } , isComplete { std::move(isCompleteArg) } , clientMutationId { std::move(clientMutationIdArg) } + , boolList { std::move(boolListArg) } { } @@ -152,6 +155,7 @@ CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) , testTaskState { ModifiedVariable::duplicate(other.testTaskState) } , isComplete { ModifiedVariable::duplicate(other.isComplete) } , clientMutationId { ModifiedVariable::duplicate(other.clientMutationId) } + , boolList { ModifiedVariable::duplicate(other.boolList) } { } @@ -160,6 +164,7 @@ CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept , testTaskState { std::move(other.testTaskState) } , isComplete { std::move(other.isComplete) } , clientMutationId { std::move(other.clientMutationId) } + , boolList { std::move(other.boolList) } { } @@ -179,6 +184,7 @@ CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexc testTaskState = std::move(other.testTaskState); isComplete = std::move(other.isComplete); clientMutationId = std::move(other.clientMutationId); + boolList = std::move(other.boolList); return *this; } @@ -2316,6 +2322,7 @@ response::Value Variable::serialize(CompleteTaskInput&& input result.emplace_back(R"js(testTaskState)js"s, ModifiedVariable::serialize(std::move(inputValue.testTaskState))); result.emplace_back(R"js(isComplete)js"s, ModifiedVariable::serialize(std::move(inputValue.isComplete))); result.emplace_back(R"js(clientMutationId)js"s, ModifiedVariable::serialize(std::move(inputValue.clientMutationId))); + result.emplace_back(R"js(boolList)js"s, ModifiedVariable::serialize(std::move(inputValue.boolList))); return result; } diff --git a/samples/client/multiple/MultipleQueriesClient.h b/samples/client/multiple/MultipleQueriesClient.h index 4e711034..a7c7460e 100644 --- a/samples/client/multiple/MultipleQueriesClient.h +++ b/samples/client/multiple/MultipleQueriesClient.h @@ -132,7 +132,8 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept; + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept; CompleteTaskInput(const CompleteTaskInput& other); CompleteTaskInput(CompleteTaskInput&& other) noexcept; ~CompleteTaskInput(); @@ -144,6 +145,7 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput std::optional testTaskState; std::optional isComplete; std::optional clientMutationId; + std::optional> boolList; }; namespace client { diff --git a/samples/client/mutate/MutateClient.cpp b/samples/client/mutate/MutateClient.cpp index f54db298..248b86a8 100644 --- a/samples/client/mutate/MutateClient.cpp +++ b/samples/client/mutate/MutateClient.cpp @@ -64,6 +64,7 @@ CompleteTaskInput::CompleteTaskInput() noexcept , testTaskState {} , isComplete {} , clientMutationId {} + , boolList {} { // Explicit definition to prevent ODR violations when LTO is enabled. } @@ -72,11 +73,13 @@ CompleteTaskInput::CompleteTaskInput( response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept : id { std::move(idArg) } , testTaskState { std::move(testTaskStateArg) } , isComplete { std::move(isCompleteArg) } , clientMutationId { std::move(clientMutationIdArg) } + , boolList { std::move(boolListArg) } { } @@ -85,6 +88,7 @@ CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) , testTaskState { ModifiedVariable::duplicate(other.testTaskState) } , isComplete { ModifiedVariable::duplicate(other.isComplete) } , clientMutationId { ModifiedVariable::duplicate(other.clientMutationId) } + , boolList { ModifiedVariable::duplicate(other.boolList) } { } @@ -93,6 +97,7 @@ CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept , testTaskState { std::move(other.testTaskState) } , isComplete { std::move(other.isComplete) } , clientMutationId { std::move(other.clientMutationId) } + , boolList { std::move(other.boolList) } { } @@ -112,6 +117,7 @@ CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexc testTaskState = std::move(other.testTaskState); isComplete = std::move(other.isComplete); clientMutationId = std::move(other.clientMutationId); + boolList = std::move(other.boolList); return *this; } @@ -148,6 +154,7 @@ response::Value Variable::serialize(CompleteTaskInput&& input result.emplace_back(R"js(testTaskState)js"s, ModifiedVariable::serialize(std::move(inputValue.testTaskState))); result.emplace_back(R"js(isComplete)js"s, ModifiedVariable::serialize(std::move(inputValue.isComplete))); result.emplace_back(R"js(clientMutationId)js"s, ModifiedVariable::serialize(std::move(inputValue.clientMutationId))); + result.emplace_back(R"js(boolList)js"s, ModifiedVariable::serialize(std::move(inputValue.boolList))); return result; } diff --git a/samples/client/mutate/MutateClient.h b/samples/client/mutate/MutateClient.h index 4c945b24..72a67a45 100644 --- a/samples/client/mutate/MutateClient.h +++ b/samples/client/mutate/MutateClient.h @@ -65,7 +65,8 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept; + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept; CompleteTaskInput(const CompleteTaskInput& other); CompleteTaskInput(CompleteTaskInput&& other) noexcept; ~CompleteTaskInput(); @@ -77,6 +78,7 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput std::optional testTaskState; std::optional isComplete; std::optional clientMutationId; + std::optional> boolList; }; namespace client { From 523d16f6c4d15315657d2a20e3941612e40c03f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Hibner?= Date: Tue, 19 Nov 2024 13:54:39 +0000 Subject: [PATCH 3/6] Fix list of boolean argument --- include/graphqlservice/GraphQLClient.h | 31 ++++++++++++++++++------- include/graphqlservice/GraphQLService.h | 18 ++++++++++---- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/graphqlservice/GraphQLClient.h b/include/graphqlservice/GraphQLClient.h index a1f5b5d7..13ce6cdf 100644 --- a/include/graphqlservice/GraphQLClient.h +++ b/include/graphqlservice/GraphQLClient.h @@ -168,9 +168,16 @@ struct ModifiedVariable response::Value result { response::Type::List }; result.reserve(listValue.size()); - std::ranges::for_each(listValue, [&result](auto& value) { - result.emplace_back(serialize(std::move(value))); - }); + if constexpr(std::is_same_v){ + for (auto const v: listValue) + result.emplace_back(Variable::serialize(bool{v})); + } + else{ + std::ranges::for_each(listValue, [&result](auto& value) { + result.emplace_back(serialize(std::move(value))); + }); + } + listValue.clear(); return result; @@ -217,11 +224,19 @@ struct ModifiedVariable duplicate(const typename VariableTraits::type& listValue) requires ListModifier { - typename VariableTraits::type result(listValue.size()); - - std::ranges::transform(listValue, result.begin(), duplicate); - - return result; + if constexpr(std::is_same_v){ + typename VariableTraits::type result; + result.reserve(listValue.size()); + for (auto const v: listValue) + result.push_back(v); + return result; + } + else + { + typename VariableTraits::type result(listValue.size()); + std::ranges::transform(listValue, result.begin(), duplicate); + return result; + } } }; diff --git a/include/graphqlservice/GraphQLService.h b/include/graphqlservice/GraphQLService.h index b6c6eac2..dacf9ce5 100644 --- a/include/graphqlservice/GraphQLService.h +++ b/include/graphqlservice/GraphQLService.h @@ -795,11 +795,19 @@ struct ModifiedArgument duplicate(const typename ArgumentTraits::type& listValue) requires ListModifier { - typename ArgumentTraits::type result(listValue.size()); - - std::ranges::transform(listValue, result.begin(), duplicate); - - return result; + if constexpr(std::is_same_v){ + typename ArgumentTraits::type result; + result.reserve(listValue.size()); + for (auto const v: listValue) + result.push_back(v); + return result; + } + else + { + typename ArgumentTraits::type result(listValue.size()); + std::ranges::transform(listValue, result.begin(), duplicate); + return result; + } } }; From 81abdc68bf8eefdf99a3f4c42b9079b48723d364 Mon Sep 17 00:00:00 2001 From: Bill Avery Date: Sat, 7 Dec 2024 15:31:13 -0800 Subject: [PATCH 4/6] fix: #334 --- samples/learn/schema/StarWarsSchema.cpp | 9 ++++++++- samples/today/nointrospection/TodaySchema.cpp | 9 ++++++++- samples/today/schema/TodaySchema.cpp | 9 ++++++++- samples/validation/schema/ValidationSchema.cpp | 18 ++++++++++++++++-- src/SchemaGenerator.cpp | 11 ++++++++++- src/introspection/IntrospectionSchema.cpp | 18 ++++++++++++++++-- 6 files changed, 66 insertions(+), 8 deletions(-) diff --git a/samples/learn/schema/StarWarsSchema.cpp b/samples/learn/schema/StarWarsSchema.cpp index c14d3696..c3ce0a24 100644 --- a/samples/learn/schema/StarWarsSchema.cpp +++ b/samples/learn/schema/StarWarsSchema.cpp @@ -53,9 +53,16 @@ service::AwaitableResolver Result::convert(service::AwaitableSca return ModifiedResult::resolve(std::move(result), std::move(params), [](learn::Episode value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesEpisode.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for Episode)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesEpisode[static_cast(value)] }); + resolvedResult.set(std::string { s_namesEpisode[idx] }); return resolvedResult; }); diff --git a/samples/today/nointrospection/TodaySchema.cpp b/samples/today/nointrospection/TodaySchema.cpp index aee07aac..55d3f6ae 100644 --- a/samples/today/nointrospection/TodaySchema.cpp +++ b/samples/today/nointrospection/TodaySchema.cpp @@ -54,9 +54,16 @@ service::AwaitableResolver Result::convert(service::AwaitableS return ModifiedResult::resolve(std::move(result), std::move(params), [](today::TaskState value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesTaskState.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for TaskState)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesTaskState[static_cast(value)] }); + resolvedResult.set(std::string { s_namesTaskState[idx] }); return resolvedResult; }); diff --git a/samples/today/schema/TodaySchema.cpp b/samples/today/schema/TodaySchema.cpp index d11e9e23..ddde3725 100644 --- a/samples/today/schema/TodaySchema.cpp +++ b/samples/today/schema/TodaySchema.cpp @@ -54,9 +54,16 @@ service::AwaitableResolver Result::convert(service::AwaitableS return ModifiedResult::resolve(std::move(result), std::move(params), [](today::TaskState value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesTaskState.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for TaskState)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesTaskState[static_cast(value)] }); + resolvedResult.set(std::string { s_namesTaskState[idx] }); return resolvedResult; }); diff --git a/samples/validation/schema/ValidationSchema.cpp b/samples/validation/schema/ValidationSchema.cpp index 9a49b7e7..e5d18879 100644 --- a/samples/validation/schema/ValidationSchema.cpp +++ b/samples/validation/schema/ValidationSchema.cpp @@ -54,9 +54,16 @@ service::AwaitableResolver Result::convert(service::Awai return ModifiedResult::resolve(std::move(result), std::move(params), [](validation::DogCommand value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesDogCommand.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for DogCommand)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesDogCommand[static_cast(value)] }); + resolvedResult.set(std::string { s_namesDogCommand[idx] }); return resolvedResult; }); @@ -110,9 +117,16 @@ service::AwaitableResolver Result::convert(service::Awai return ModifiedResult::resolve(std::move(result), std::move(params), [](validation::CatCommand value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesCatCommand.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for CatCommand)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesCatCommand[static_cast(value)] }); + resolvedResult.set(std::string { s_namesCatCommand[idx] }); return resolvedResult; }); diff --git a/src/SchemaGenerator.cpp b/src/SchemaGenerator.cpp index 59c41549..b9aeb3c7 100644 --- a/src/SchemaGenerator.cpp +++ b/src/SchemaGenerator.cpp @@ -1336,10 +1336,19 @@ service::AwaitableResolver Result<)cpp" []()cpp" << _loader.getSchemaNamespace() << R"cpp(::)cpp" << enumType.cppType << R"cpp( value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_names)cpp" + << enumType.cppType << R"cpp(.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for )cpp" + << enumType.type << R"cpp()ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); resolvedResult.set(std::string { s_names)cpp" - << enumType.cppType << R"cpp([static_cast(value)] }); + << enumType.cppType << R"cpp([idx] }); return resolvedResult; }); diff --git a/src/introspection/IntrospectionSchema.cpp b/src/introspection/IntrospectionSchema.cpp index 81b28bf4..b87861cd 100644 --- a/src/introspection/IntrospectionSchema.cpp +++ b/src/introspection/IntrospectionSchema.cpp @@ -48,9 +48,16 @@ service::AwaitableResolver Result::convert(service::Awa return ModifiedResult::resolve(std::move(result), std::move(params), [](introspection::TypeKind value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesTypeKind.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for __TypeKind)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesTypeKind[static_cast(value)] }); + resolvedResult.set(std::string { s_namesTypeKind[idx] }); return resolvedResult; }); @@ -104,9 +111,16 @@ service::AwaitableResolver Result::convert(ser return ModifiedResult::resolve(std::move(result), std::move(params), [](introspection::DirectiveLocation value, const ResolverParams&) { + const auto idx = static_cast(value); + + if (idx >= s_namesDirectiveLocation.size()) + { + throw service::schema_exception { { R"ex(Enum value out of range for __DirectiveLocation)ex" } }; + } + response::Value resolvedResult(response::Type::EnumValue); - resolvedResult.set(std::string { s_namesDirectiveLocation[static_cast(value)] }); + resolvedResult.set(std::string { s_namesDirectiveLocation[idx] }); return resolvedResult; }); From 364311641105d6805eaa826e629e113229d155d6 Mon Sep 17 00:00:00 2001 From: Bill Avery Date: Sat, 7 Dec 2024 16:21:31 -0800 Subject: [PATCH 5/6] fix(merge): regenerate samples after merge --- samples/learn/schema/StarWarsSharedTypes.cpp | 2 +- samples/proxy/schema/ProxySharedTypes.cpp | 2 +- samples/today/nointrospection/TodaySharedTypes.cpp | 2 +- samples/today/schema/TodaySharedTypes.cpp | 2 +- samples/validation/schema/ValidationSharedTypes.cpp | 4 ++-- src/introspection/IntrospectionSharedTypes.cpp | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/samples/learn/schema/StarWarsSharedTypes.cpp b/samples/learn/schema/StarWarsSharedTypes.cpp index 48fcf3a9..697d2181 100644 --- a/samples/learn/schema/StarWarsSharedTypes.cpp +++ b/samples/learn/schema/StarWarsSharedTypes.cpp @@ -50,7 +50,7 @@ service::AwaitableResolver Result::convert(service::AwaitableSca return ModifiedResult::resolve(std::move(result), std::move(params), [](learn::Episode value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesEpisode.size()) { diff --git a/samples/proxy/schema/ProxySharedTypes.cpp b/samples/proxy/schema/ProxySharedTypes.cpp index d58c8f99..e29d62da 100644 --- a/samples/proxy/schema/ProxySharedTypes.cpp +++ b/samples/proxy/schema/ProxySharedTypes.cpp @@ -50,7 +50,7 @@ service::AwaitableResolver Result::convert(service::Awaita return ModifiedResult::resolve(std::move(result), std::move(params), [](proxy::OperationType value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesOperationType.size()) { diff --git a/samples/today/nointrospection/TodaySharedTypes.cpp b/samples/today/nointrospection/TodaySharedTypes.cpp index 727a3253..f733934a 100644 --- a/samples/today/nointrospection/TodaySharedTypes.cpp +++ b/samples/today/nointrospection/TodaySharedTypes.cpp @@ -50,7 +50,7 @@ service::AwaitableResolver Result::convert(service::AwaitableS return ModifiedResult::resolve(std::move(result), std::move(params), [](today::TaskState value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesTaskState.size()) { diff --git a/samples/today/schema/TodaySharedTypes.cpp b/samples/today/schema/TodaySharedTypes.cpp index 727a3253..f733934a 100644 --- a/samples/today/schema/TodaySharedTypes.cpp +++ b/samples/today/schema/TodaySharedTypes.cpp @@ -50,7 +50,7 @@ service::AwaitableResolver Result::convert(service::AwaitableS return ModifiedResult::resolve(std::move(result), std::move(params), [](today::TaskState value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesTaskState.size()) { diff --git a/samples/validation/schema/ValidationSharedTypes.cpp b/samples/validation/schema/ValidationSharedTypes.cpp index 84e32700..aa67bdbb 100644 --- a/samples/validation/schema/ValidationSharedTypes.cpp +++ b/samples/validation/schema/ValidationSharedTypes.cpp @@ -50,7 +50,7 @@ service::AwaitableResolver Result::convert(service::Awai return ModifiedResult::resolve(std::move(result), std::move(params), [](validation::DogCommand value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesDogCommand.size()) { @@ -109,7 +109,7 @@ service::AwaitableResolver Result::convert(service::Awai return ModifiedResult::resolve(std::move(result), std::move(params), [](validation::CatCommand value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesCatCommand.size()) { diff --git a/src/introspection/IntrospectionSharedTypes.cpp b/src/introspection/IntrospectionSharedTypes.cpp index 7d47c719..9457eec6 100644 --- a/src/introspection/IntrospectionSharedTypes.cpp +++ b/src/introspection/IntrospectionSharedTypes.cpp @@ -50,7 +50,7 @@ service::AwaitableResolver Result::convert(service::Awa return ModifiedResult::resolve(std::move(result), std::move(params), [](introspection::TypeKind value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesTypeKind.size()) { @@ -109,7 +109,7 @@ service::AwaitableResolver Result::convert(ser return ModifiedResult::resolve(std::move(result), std::move(params), [](introspection::DirectiveLocation value, const ResolverParams&) { - const size_t idx = static_cast(value); + const auto idx = static_cast(value); if (idx >= s_namesDirectiveLocation.size()) { From 29ccf43a826e2626978f5ae14911185ec17b4770 Mon Sep 17 00:00:00 2001 From: Bill Avery Date: Sat, 7 Dec 2024 16:53:56 -0800 Subject: [PATCH 6/6] fix: handle potential modifiers on bool lists --- include/graphqlservice/GraphQLClient.h | 30 ++++++++++--------- include/graphqlservice/GraphQLService.h | 15 +++++----- samples/today/nointrospection/TodaySchema.cpp | 3 +- .../nointrospection/TodaySharedTypes.cpp | 12 ++++++-- .../today/nointrospection/TodaySharedTypes.h | 4 ++- samples/today/schema/TodaySchema.cpp | 3 +- samples/today/schema/TodaySharedTypes.cpp | 12 ++++++-- samples/today/schema/TodaySharedTypes.h | 4 ++- 8 files changed, 53 insertions(+), 30 deletions(-) diff --git a/include/graphqlservice/GraphQLClient.h b/include/graphqlservice/GraphQLClient.h index 13ce6cdf..8db4830e 100644 --- a/include/graphqlservice/GraphQLClient.h +++ b/include/graphqlservice/GraphQLClient.h @@ -168,16 +168,19 @@ struct ModifiedVariable response::Value result { response::Type::List }; result.reserve(listValue.size()); - if constexpr(std::is_same_v){ - for (auto const v: listValue) - result.emplace_back(Variable::serialize(bool{v})); + if constexpr (std::is_same_v && OnlyNoneModifiers) + { + std::ranges::for_each(listValue, [&result](bool value) { + result.emplace_back(response::Value { value }); + }); } - else{ + else + { std::ranges::for_each(listValue, [&result](auto& value) { result.emplace_back(serialize(std::move(value))); - }); + }); } - + listValue.clear(); return result; @@ -224,19 +227,18 @@ struct ModifiedVariable duplicate(const typename VariableTraits::type& listValue) requires ListModifier { - if constexpr(std::is_same_v){ - typename VariableTraits::type result; - result.reserve(listValue.size()); - for (auto const v: listValue) - result.push_back(v); - return result; + typename VariableTraits::type result(listValue.size()); + + if constexpr (std::is_same_v && OnlyNoneModifiers) + { + std::copy(listValue.begin(), listValue.end(), result.begin()); } else { - typename VariableTraits::type result(listValue.size()); std::ranges::transform(listValue, result.begin(), duplicate); - return result; } + + return result; } }; diff --git a/include/graphqlservice/GraphQLService.h b/include/graphqlservice/GraphQLService.h index dacf9ce5..5c5f11f6 100644 --- a/include/graphqlservice/GraphQLService.h +++ b/include/graphqlservice/GraphQLService.h @@ -795,19 +795,18 @@ struct ModifiedArgument duplicate(const typename ArgumentTraits::type& listValue) requires ListModifier { - if constexpr(std::is_same_v){ - typename ArgumentTraits::type result; - result.reserve(listValue.size()); - for (auto const v: listValue) - result.push_back(v); - return result; + typename ArgumentTraits::type result(listValue.size()); + + if constexpr (std::is_same_v && OnlyNoneModifiers) + { + std::copy(listValue.begin(), listValue.end(), result.begin()); } else { - typename ArgumentTraits::type result(listValue.size()); std::ranges::transform(listValue, result.begin(), duplicate); - return result; } + + return result; } }; diff --git a/samples/today/nointrospection/TodaySchema.cpp b/samples/today/nointrospection/TodaySchema.cpp index fe4ab807..f8a4d23c 100644 --- a/samples/today/nointrospection/TodaySchema.cpp +++ b/samples/today/nointrospection/TodaySchema.cpp @@ -109,7 +109,8 @@ void AddTypesToSchema(const std::shared_ptr& schema) schema::InputValue::Make(R"gql(id)gql"sv, R"md()md"sv, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)), R"gql()gql"sv), schema::InputValue::Make(R"gql(testTaskState)gql"sv, R"md()md"sv, schema->LookupType(R"gql(TaskState)gql"sv), R"gql()gql"sv), schema::InputValue::Make(R"gql(isComplete)gql"sv, R"md()md"sv, schema->LookupType(R"gql(Boolean)gql"sv), R"gql(true)gql"sv), - schema::InputValue::Make(R"gql(clientMutationId)gql"sv, R"md()md"sv, schema->LookupType(R"gql(String)gql"sv), R"gql()gql"sv) + schema::InputValue::Make(R"gql(clientMutationId)gql"sv, R"md()md"sv, schema->LookupType(R"gql(String)gql"sv), R"gql()gql"sv), + schema::InputValue::Make(R"gql(boolList)gql"sv, R"md()md"sv, schema->WrapType(introspection::TypeKind::LIST, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(Boolean)gql"sv))), R"gql()gql"sv) }); typeThirdNestedInput->AddInputValues({ schema::InputValue::Make(R"gql(id)gql"sv, R"md()md"sv, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)), R"gql()gql"sv), diff --git a/samples/today/nointrospection/TodaySharedTypes.cpp b/samples/today/nointrospection/TodaySharedTypes.cpp index f733934a..ecae70c3 100644 --- a/samples/today/nointrospection/TodaySharedTypes.cpp +++ b/samples/today/nointrospection/TodaySharedTypes.cpp @@ -101,12 +101,14 @@ today::CompleteTaskInput Argument::convert(const respo ? std::move(pairIsComplete.first) : service::ModifiedArgument::require("isComplete", defaultValue)); auto valueClientMutationId = service::ModifiedArgument::require("clientMutationId", value); + auto valueBoolList = service::ModifiedArgument::require("boolList", value); return today::CompleteTaskInput { std::move(valueId), valueTestTaskState, std::move(valueIsComplete), - std::move(valueClientMutationId) + std::move(valueClientMutationId), + std::move(valueBoolList) }; } @@ -231,6 +233,7 @@ CompleteTaskInput::CompleteTaskInput() noexcept , testTaskState {} , isComplete {} , clientMutationId {} + , boolList {} { // Explicit definition to prevent ODR violations when LTO is enabled. } @@ -239,11 +242,13 @@ CompleteTaskInput::CompleteTaskInput( response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept : id { std::move(idArg) } , testTaskState { std::move(testTaskStateArg) } , isComplete { std::move(isCompleteArg) } , clientMutationId { std::move(clientMutationIdArg) } + , boolList { std::move(boolListArg) } { } @@ -252,6 +257,7 @@ CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) , testTaskState { service::ModifiedArgument::duplicate(other.testTaskState) } , isComplete { service::ModifiedArgument::duplicate(other.isComplete) } , clientMutationId { service::ModifiedArgument::duplicate(other.clientMutationId) } + , boolList { service::ModifiedArgument::duplicate(other.boolList) } { } @@ -260,6 +266,7 @@ CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept , testTaskState { std::move(other.testTaskState) } , isComplete { std::move(other.isComplete) } , clientMutationId { std::move(other.clientMutationId) } + , boolList { std::move(other.boolList) } { } @@ -283,6 +290,7 @@ CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexc testTaskState = std::move(other.testTaskState); isComplete = std::move(other.isComplete); clientMutationId = std::move(other.clientMutationId); + boolList = std::move(other.boolList); return *this; } diff --git a/samples/today/nointrospection/TodaySharedTypes.h b/samples/today/nointrospection/TodaySharedTypes.h index b3c7b086..a9f1ace9 100644 --- a/samples/today/nointrospection/TodaySharedTypes.h +++ b/samples/today/nointrospection/TodaySharedTypes.h @@ -65,7 +65,8 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept; + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept; CompleteTaskInput(const CompleteTaskInput& other); CompleteTaskInput(CompleteTaskInput&& other) noexcept; ~CompleteTaskInput(); @@ -77,6 +78,7 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput std::optional testTaskState; std::optional isComplete; std::optional clientMutationId; + std::optional> boolList; }; struct SecondNestedInput; diff --git a/samples/today/schema/TodaySchema.cpp b/samples/today/schema/TodaySchema.cpp index c9cadf07..831e7bbf 100644 --- a/samples/today/schema/TodaySchema.cpp +++ b/samples/today/schema/TodaySchema.cpp @@ -112,7 +112,8 @@ void AddTypesToSchema(const std::shared_ptr& schema) schema::InputValue::Make(R"gql(id)gql"sv, R"md()md"sv, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)), R"gql()gql"sv), schema::InputValue::Make(R"gql(testTaskState)gql"sv, R"md()md"sv, schema->LookupType(R"gql(TaskState)gql"sv), R"gql()gql"sv), schema::InputValue::Make(R"gql(isComplete)gql"sv, R"md()md"sv, schema->LookupType(R"gql(Boolean)gql"sv), R"gql(true)gql"sv), - schema::InputValue::Make(R"gql(clientMutationId)gql"sv, R"md()md"sv, schema->LookupType(R"gql(String)gql"sv), R"gql()gql"sv) + schema::InputValue::Make(R"gql(clientMutationId)gql"sv, R"md()md"sv, schema->LookupType(R"gql(String)gql"sv), R"gql()gql"sv), + schema::InputValue::Make(R"gql(boolList)gql"sv, R"md()md"sv, schema->WrapType(introspection::TypeKind::LIST, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(Boolean)gql"sv))), R"gql()gql"sv) }); typeThirdNestedInput->AddInputValues({ schema::InputValue::Make(R"gql(id)gql"sv, R"md()md"sv, schema->WrapType(introspection::TypeKind::NON_NULL, schema->LookupType(R"gql(ID)gql"sv)), R"gql()gql"sv), diff --git a/samples/today/schema/TodaySharedTypes.cpp b/samples/today/schema/TodaySharedTypes.cpp index f733934a..ecae70c3 100644 --- a/samples/today/schema/TodaySharedTypes.cpp +++ b/samples/today/schema/TodaySharedTypes.cpp @@ -101,12 +101,14 @@ today::CompleteTaskInput Argument::convert(const respo ? std::move(pairIsComplete.first) : service::ModifiedArgument::require("isComplete", defaultValue)); auto valueClientMutationId = service::ModifiedArgument::require("clientMutationId", value); + auto valueBoolList = service::ModifiedArgument::require("boolList", value); return today::CompleteTaskInput { std::move(valueId), valueTestTaskState, std::move(valueIsComplete), - std::move(valueClientMutationId) + std::move(valueClientMutationId), + std::move(valueBoolList) }; } @@ -231,6 +233,7 @@ CompleteTaskInput::CompleteTaskInput() noexcept , testTaskState {} , isComplete {} , clientMutationId {} + , boolList {} { // Explicit definition to prevent ODR violations when LTO is enabled. } @@ -239,11 +242,13 @@ CompleteTaskInput::CompleteTaskInput( response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept : id { std::move(idArg) } , testTaskState { std::move(testTaskStateArg) } , isComplete { std::move(isCompleteArg) } , clientMutationId { std::move(clientMutationIdArg) } + , boolList { std::move(boolListArg) } { } @@ -252,6 +257,7 @@ CompleteTaskInput::CompleteTaskInput(const CompleteTaskInput& other) , testTaskState { service::ModifiedArgument::duplicate(other.testTaskState) } , isComplete { service::ModifiedArgument::duplicate(other.isComplete) } , clientMutationId { service::ModifiedArgument::duplicate(other.clientMutationId) } + , boolList { service::ModifiedArgument::duplicate(other.boolList) } { } @@ -260,6 +266,7 @@ CompleteTaskInput::CompleteTaskInput(CompleteTaskInput&& other) noexcept , testTaskState { std::move(other.testTaskState) } , isComplete { std::move(other.isComplete) } , clientMutationId { std::move(other.clientMutationId) } + , boolList { std::move(other.boolList) } { } @@ -283,6 +290,7 @@ CompleteTaskInput& CompleteTaskInput::operator=(CompleteTaskInput&& other) noexc testTaskState = std::move(other.testTaskState); isComplete = std::move(other.isComplete); clientMutationId = std::move(other.clientMutationId); + boolList = std::move(other.boolList); return *this; } diff --git a/samples/today/schema/TodaySharedTypes.h b/samples/today/schema/TodaySharedTypes.h index b3c7b086..a9f1ace9 100644 --- a/samples/today/schema/TodaySharedTypes.h +++ b/samples/today/schema/TodaySharedTypes.h @@ -65,7 +65,8 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput response::IdType idArg, std::optional testTaskStateArg, std::optional isCompleteArg, - std::optional clientMutationIdArg) noexcept; + std::optional clientMutationIdArg, + std::optional> boolListArg) noexcept; CompleteTaskInput(const CompleteTaskInput& other); CompleteTaskInput(CompleteTaskInput&& other) noexcept; ~CompleteTaskInput(); @@ -77,6 +78,7 @@ struct [[nodiscard("unnecessary construction")]] CompleteTaskInput std::optional testTaskState; std::optional isComplete; std::optional clientMutationId; + std::optional> boolList; }; struct SecondNestedInput;