Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use concepts and type traits instead of specializing service::isInputType() for each input type #249

Merged
merged 6 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.3.1
4.4.0
30 changes: 17 additions & 13 deletions include/graphqlservice/GraphQLClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,23 @@ enum class [[nodiscard]] TypeModifier {
List,
};

// Specialized to return true for all INPUT_OBJECT types.
// These types are used as scalar variables even though they are represented with a class.
template <typename Type>
[[nodiscard]] constexpr bool isInputType() noexcept
{
return false;
}
concept ScalarVariableClass = std::is_same_v<Type, std::string> || std::is_same_v<Type,
response::IdType> || std::is_same_v<Type, response::Value>;

// Special-case an innermost nullable INPUT_OBJECT type.
// Any non-scalar class used in a variable is a generated INPUT_OBJECT type.
template <typename Type>
concept InputVariableClass = std::is_class_v<Type> && !ScalarVariableClass<Type>;

// Test if there are any non-None modifiers left.
template <TypeModifier... Other>
[[nodiscard]] constexpr bool onlyNoneModifiers() noexcept
{
return (... && (Other == TypeModifier::None));
}
concept OnlyNoneModifiers = (... && (Other == TypeModifier::None));

// Special-case an innermost nullable INPUT_OBJECT type.
template <typename Type, TypeModifier... Other>
concept InputVariableUniquePtr = InputVariableClass<Type> && OnlyNoneModifiers<Other...>;


// Serialize variable input values with chained type modifiers which add nullable or list wrappers.
template <typename Type>
Expand All @@ -94,8 +98,8 @@ struct ModifiedVariable
{
// Peel off modifiers until we get to the underlying type.
using type = typename std::conditional_t<TypeModifier::Nullable == Modifier,
typename std::conditional_t<isInputType<U>() && onlyNoneModifiers<Other...>(),
std::unique_ptr<U>, std::optional<typename VariableTraits<U, Other...>::type>>,
typename std::conditional_t<InputVariableUniquePtr<U, Other...>, std::unique_ptr<U>,
std::optional<typename VariableTraits<U, Other...>::type>>,
typename std::conditional_t<TypeModifier::List == Modifier,
std::vector<typename VariableTraits<U, Other...>::type>, U>>;
};
Expand Down Expand Up @@ -173,7 +177,7 @@ struct ModifiedVariable

if (nullableValue)
{
if constexpr (isInputType<Type>() && onlyNoneModifiers<Other...>())
if constexpr (InputVariableUniquePtr<Type, Other...>)
{
// Special case duplicating the std::unique_ptr.
result = std::make_unique<Type>(Type { *nullableValue });
Expand Down
31 changes: 17 additions & 14 deletions include/graphqlservice/GraphQLService.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,19 +592,22 @@ enum class [[nodiscard]] TypeModifier {
List,
};

// Specialized to return true for all INPUT_OBJECT types.
// These types are used as scalar arguments even though they are represented with a class.
template <typename Type>
[[nodiscard]] constexpr bool isInputType() noexcept
{
return false;
}
concept ScalarArgumentClass = std::is_same_v<Type, std::string> || std::is_same_v<Type,
response::IdType> || std::is_same_v<Type, response::Value>;

// Special-case an innermost nullable INPUT_OBJECT type.
// Any non-scalar class used in an argument is a generated INPUT_OBJECT type.
template <typename Type>
concept InputArgumentClass = std::is_class_v<Type> && !ScalarArgumentClass<Type>;

// Test if there are any non-None modifiers left.
template <TypeModifier... Other>
[[nodiscard]] constexpr bool onlyNoneModifiers() noexcept
{
return (... && (Other == TypeModifier::None));
}
concept OnlyNoneModifiers = (... && (Other == TypeModifier::None));

// Special-case an innermost nullable INPUT_OBJECT type.
template <typename Type, TypeModifier... Other>
concept InputArgumentUniquePtr = InputArgumentClass<Type> && OnlyNoneModifiers<Other...>;

// Extract individual arguments with chained type modifiers which add nullable or list wrappers.
// If the argument is not optional, use require and let it throw a schema_exception when the
Expand All @@ -619,8 +622,8 @@ struct ModifiedArgument
{
// Peel off modifiers until we get to the underlying type.
using type = typename std::conditional_t<TypeModifier::Nullable == Modifier,
typename std::conditional_t<isInputType<U>() && onlyNoneModifiers<Other...>(),
std::unique_ptr<U>, std::optional<typename ArgumentTraits<U, Other...>::type>>,
typename std::conditional_t<InputArgumentUniquePtr<U, Other...>, std::unique_ptr<U>,
std::optional<typename ArgumentTraits<U, Other...>::type>>,
typename std::conditional_t<TypeModifier::List == Modifier,
std::vector<typename ArgumentTraits<U, Other...>::type>, U>>;
};
Expand Down Expand Up @@ -699,7 +702,7 @@ struct ModifiedArgument

auto result = require<Other...>(name, arguments);

if constexpr (isInputType<Type>() && onlyNoneModifiers<Other...>())
if constexpr (InputArgumentUniquePtr<Type, Other...>)
{
return std::make_unique<decltype(result)>(std::move(result));
}
Expand Down Expand Up @@ -768,7 +771,7 @@ struct ModifiedArgument

if (nullableValue)
{
if constexpr (isInputType<Type>() && onlyNoneModifiers<Other...>())
if constexpr (InputArgumentUniquePtr<Type, Other...>)
{
// Special case duplicating the std::unique_ptr.
result = std::make_unique<Type>(Type { *nullableValue });
Expand Down
6 changes: 3 additions & 3 deletions include/graphqlservice/internal/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

namespace graphql::internal {

constexpr std::string_view FullVersion { "4.3.1" };
constexpr std::string_view FullVersion { "4.4.0" };

constexpr size_t MajorVersion = 4;
constexpr size_t MinorVersion = 3;
constexpr size_t PatchVersion = 1;
constexpr size_t MinorVersion = 4;
constexpr size_t PatchVersion = 0;

} // namespace graphql::internal

Expand Down
4 changes: 2 additions & 2 deletions include/graphqlservice/introspection/IntrospectionSchema.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

#include "graphqlservice/internal/Schema.h"

// Check if the library version is compatible with schemagen 4.3.0
// Check if the library version is compatible with schemagen 4.4.0
static_assert(graphql::internal::MajorVersion == 4, "regenerate with schemagen: major version mismatch");
static_assert(graphql::internal::MinorVersion == 3, "regenerate with schemagen: minor version mismatch");
static_assert(graphql::internal::MinorVersion == 4, "regenerate with schemagen: minor version mismatch");

#include <array>
#include <memory>
Expand Down
4 changes: 2 additions & 2 deletions res/ClientGen.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/SchemaGen.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlclient_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqljson_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlpeg_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlresponse_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
4 changes: 2 additions & 2 deletions res/graphqlservice_version.rc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include <winver.h>

#define GRAPHQL_RC_VERSION 4,3,1,0
#define GRAPHQL_RC_VERSION_STR "4.3.1"
#define GRAPHQL_RC_VERSION 4,4,0,0
#define GRAPHQL_RC_VERSION_STR "4.4.0"

#ifndef DEBUG
#define VER_DEBUG 0
Expand Down
2 changes: 2 additions & 0 deletions samples/client/benchmark/BenchmarkClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "BenchmarkClient.h"

#include "graphqlservice/internal/SortedMap.h"

#include <algorithm>
#include <array>
#include <sstream>
Expand Down
4 changes: 2 additions & 2 deletions samples/client/benchmark/BenchmarkClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

#include "graphqlservice/internal/Version.h"

// Check if the library version is compatible with clientgen 4.3.0
// Check if the library version is compatible with clientgen 4.4.0
static_assert(graphql::internal::MajorVersion == 4, "regenerate with clientgen: major version mismatch");
static_assert(graphql::internal::MinorVersion == 3, "regenerate with clientgen: minor version mismatch");
static_assert(graphql::internal::MinorVersion == 4, "regenerate with clientgen: minor version mismatch");

#include <optional>
#include <string>
Expand Down
35 changes: 23 additions & 12 deletions samples/client/multiple/MultipleQueriesClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "MultipleQueriesClient.h"

#include "graphqlservice/internal/SortedMap.h"

#include <algorithm>
#include <array>
#include <sstream>
Expand Down Expand Up @@ -119,13 +121,6 @@ const peg::ast& GetRequestObject() noexcept
return s_request;
}

static const std::array<std::string_view, 4> s_namesTaskState = {
"New"sv,
"Started"sv,
"Complete"sv,
"Unassigned"sv,
};

CompleteTaskInput::CompleteTaskInput(
response::IdType idArg,
std::optional<TaskState> testTaskStateArg,
Expand Down Expand Up @@ -521,22 +516,31 @@ Response parseResponse(response::Value&& response)

} // namespace query::UnreadCounts

static const std::array<std::pair<std::string_view, TaskState>, 4> s_valuesTaskState = {
std::make_pair(R"gql(New)gql"sv, TaskState::New),
std::make_pair(R"gql(Started)gql"sv, TaskState::Started),
std::make_pair(R"gql(Complete)gql"sv, TaskState::Complete),
std::make_pair(R"gql(Unassigned)gql"sv, TaskState::Unassigned)
};

template <>
TaskState ModifiedResponse<TaskState>::parse(response::Value&& value)
{
if (!value.maybe_enum())
{
throw std::logic_error { "not a valid TaskState value" };
throw std::logic_error { R"ex(not a valid TaskState value)ex" };
}

const auto itr = std::find(s_namesTaskState.cbegin(), s_namesTaskState.cend(), value.release<std::string>());
const auto result = internal::sorted_map_lookup<internal::shorter_or_less>(
s_valuesTaskState,
std::string_view { value.get<std::string>() });

if (itr == s_namesTaskState.cend())
if (!result)
{
throw std::logic_error { "not a valid TaskState value" };
throw std::logic_error { R"ex(not a valid TaskState value)ex" };
}

return static_cast<TaskState>(itr - s_namesTaskState.cbegin());
return *result;
}

template <>
Expand Down Expand Up @@ -633,6 +637,13 @@ Response parseResponse(response::Value&& response)

} // namespace query::Miscellaneous

static const std::array<std::string_view, 4> s_namesTaskState = {
R"gql(New)gql"sv,
R"gql(Started)gql"sv,
R"gql(Complete)gql"sv,
R"gql(Unassigned)gql"sv
};

template <>
response::Value ModifiedVariable<TaskState>::serialize(TaskState&& value)
{
Expand Down
10 changes: 2 additions & 8 deletions samples/client/multiple/MultipleQueriesClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

#include "graphqlservice/internal/Version.h"

// Check if the library version is compatible with clientgen 4.3.0
// Check if the library version is compatible with clientgen 4.4.0
static_assert(graphql::internal::MajorVersion == 4, "regenerate with clientgen: major version mismatch");
static_assert(graphql::internal::MinorVersion == 3, "regenerate with clientgen: minor version mismatch");
static_assert(graphql::internal::MinorVersion == 4, "regenerate with clientgen: minor version mismatch");

#include <optional>
#include <string>
Expand Down Expand Up @@ -146,12 +146,6 @@ struct [[nodiscard]] CompleteTaskInput

} // namespace multiple

template <>
constexpr bool isInputType<multiple::CompleteTaskInput>() noexcept
{
return true;
}

namespace query::Appointments {

using multiple::GetRequestText;
Expand Down
Loading