From 11d7d0cc73745e4a9f168101a931b5f8fcce23a3 Mon Sep 17 00:00:00 2001 From: Bill Avery Date: Mon, 21 Oct 2024 18:01:37 -0700 Subject: [PATCH] feat: add ResolverResult::visit and visitErrorValues --- include/graphqlservice/GraphQLService.h | 4 + include/graphqlservice/Service.ixx | 1 + src/GraphQLService.cpp | 107 +++++++++++++++--------- 3 files changed, 74 insertions(+), 38 deletions(-) diff --git a/include/graphqlservice/GraphQLService.h b/include/graphqlservice/GraphQLService.h index a0280fa1..1463739e 100644 --- a/include/graphqlservice/GraphQLService.h +++ b/include/graphqlservice/GraphQLService.h @@ -73,6 +73,9 @@ struct [[nodiscard("unnecessary construction")]] schema_error [[nodiscard("unnecessary memory copy")]] GRAPHQLSERVICE_EXPORT response::Value buildErrorValues( std::list&& structuredErrors); +[[nodiscard("unnecessary memory copy")]] GRAPHQLSERVICE_EXPORT response::ValueTokenStream +visitErrorValues(std::list&& structuredErrors); + // This exception bubbles up 1 or more error messages to the JSON results. class [[nodiscard("unnecessary construction")]] schema_exception : public std::exception { @@ -540,6 +543,7 @@ struct [[nodiscard("unnecessary construction")]] ResolverParams : SelectionSetPa struct [[nodiscard("unnecessary construction")]] ResolverResult { [[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT response::Value document() &&; + [[nodiscard("unnecessary call")]] GRAPHQLSERVICE_EXPORT response::ValueTokenStream visit() &&; response::ValueTokenStream data {}; std::list errors {}; diff --git a/include/graphqlservice/Service.ixx b/include/graphqlservice/Service.ixx index 63cc8119..74cf357c 100644 --- a/include/graphqlservice/Service.ixx +++ b/include/graphqlservice/Service.ixx @@ -33,6 +33,7 @@ using service::buildErrorPath; using service::schema_error; using service::buildErrorValues; +using service::visitErrorValues; using service::schema_exception; using service::unimplemented_method; diff --git a/src/GraphQLService.cpp b/src/GraphQLService.cpp index b1ce3a2c..d19961c1 100644 --- a/src/GraphQLService.cpp +++ b/src/GraphQLService.cpp @@ -17,59 +17,73 @@ using namespace std::literals; namespace graphql::service { -void addErrorMessage(std::string&& message, response::Value& error) +response::ValueTokenStream addErrorMessage(std::string&& message) { - error.emplace_back(std::string { strMessage }, response::Value(std::move(message))); + response::ValueTokenStream result {}; + + result.push_back(response::ValueToken::AddMember { std::string { strMessage } }); + result.push_back(response::ValueToken::StringValue { std::move(message) }); + + return result; } -void addErrorLocation(const schema_location& location, response::Value& error) +response::ValueTokenStream addErrorLocation(const schema_location& location) { + response::ValueTokenStream result {}; + if (location.line == 0) { - return; + return result; } - response::Value errorLocation(response::Type::Map); + result.push_back(response::ValueToken::AddMember { std::string { strLocations } }); - errorLocation.reserve(2); - errorLocation.emplace_back(std::string { strLine }, - response::Value(static_cast(location.line))); - errorLocation.emplace_back(std::string { strColumn }, - response::Value(static_cast(location.column))); + result.push_back(response::ValueToken::StartArray {}); + result.push_back(response::ValueToken::Reserve { 1 }); + result.push_back(response::ValueToken::StartObject {}); + result.push_back(response::ValueToken::Reserve { 2 }); - response::Value errorLocations(response::Type::List); + result.push_back(response::ValueToken::AddMember { std::string { strLine } }); + result.push_back(response::ValueToken::IntValue { static_cast(location.line) }); + result.push_back(response::ValueToken::AddMember { std::string { strColumn } }); + result.push_back(response::ValueToken::IntValue { static_cast(location.column) }); - errorLocations.reserve(1); - errorLocations.emplace_back(std::move(errorLocation)); + result.push_back(response::ValueToken::EndObject {}); + result.push_back(response::ValueToken::EndArray {}); - error.emplace_back(std::string { strLocations }, std::move(errorLocations)); + return result; } -void addErrorPath(const error_path& path, response::Value& error) +response::ValueTokenStream addErrorPath(const error_path& path) { + response::ValueTokenStream result {}; + if (path.empty()) { - return; + return result; } - response::Value errorPath(response::Type::List); + result.push_back(response::ValueToken::AddMember { std::string { strPath } }); + result.push_back(response::ValueToken::StartArray {}); + result.push_back(response::ValueToken::Reserve { path.size() }); - errorPath.reserve(path.size()); for (const auto& segment : path) { if (std::holds_alternative(segment)) { - errorPath.emplace_back( - response::Value { std::string { std::get(segment) } }); + result.push_back(response::ValueToken::StringValue { + std::string { std::get(segment) } }); } else if (std::holds_alternative(segment)) { - errorPath.emplace_back( - response::Value(static_cast(std::get(segment)))); + result.push_back(response::ValueToken::IntValue { + static_cast(std::get(segment)) }); } } - error.emplace_back(std::string { strPath }, std::move(errorPath)); + result.push_back(response::ValueToken::EndArray {}); + + return result; } error_path buildErrorPath(const std::optional& path) @@ -99,22 +113,30 @@ error_path buildErrorPath(const std::optional& path) response::Value buildErrorValues(std::list&& structuredErrors) { - response::Value errors(response::Type::List); + return visitErrorValues(std::move(structuredErrors)).value(); +} + +response::ValueTokenStream visitErrorValues(std::list&& structuredErrors) +{ + response::ValueTokenStream errors; - errors.reserve(structuredErrors.size()); + errors.push_back(response::ValueToken::StartArray {}); + errors.push_back(response::ValueToken::Reserve { structuredErrors.size() }); for (auto& error : structuredErrors) { - response::Value entry(response::Type::Map); + errors.push_back(response::ValueToken::StartObject {}); + errors.push_back(response::ValueToken::Reserve { 3 }); - entry.reserve(3); - addErrorMessage(std::move(error.message), entry); - addErrorLocation(error.location, entry); - addErrorPath(error.path, entry); + errors.append(addErrorMessage(std::move(error.message))); + errors.append(addErrorLocation(error.location)); + errors.append(addErrorPath(error.path)); - errors.emplace_back(std::move(entry)); + errors.push_back(response::ValueToken::EndObject {}); } + errors.push_back(response::ValueToken::EndArray {}); + return errors; } @@ -245,7 +267,7 @@ void await_worker_queue::resumePending() // Default to immediate synchronous execution. await_async::await_async() : _pimpl { std::static_pointer_cast( - std::make_shared>(std::make_shared())) } + std::make_shared>(std::make_shared())) } { } @@ -253,9 +275,9 @@ await_async::await_async() await_async::await_async(std::launch launch) : _pimpl { ((launch & std::launch::async) == std::launch::async) ? std::static_pointer_cast(std::make_shared>( - std::make_shared())) + std::make_shared())) : std::static_pointer_cast(std::make_shared>( - std::make_shared())) } + std::make_shared())) } { } @@ -623,16 +645,25 @@ schema_location ResolverParams::getLocation() const response::Value ResolverResult::document() && { - response::Value document { response::Type::Map }; + return std::move(*this).visit().value(); +} - document.emplace_back(std::string { strData }, std::move(data).value()); +response::ValueTokenStream ResolverResult::visit() && +{ + response::ValueTokenStream result { response::ValueToken::StartObject {} }; + + result.push_back(response::ValueToken::AddMember { std::string { strData } }); + result.append(std::move(data)); if (!errors.empty()) { - document.emplace_back(std::string { strErrors }, buildErrorValues(std::move(errors))); + result.push_back(response::ValueToken::AddMember { std::string { strErrors } }); + result.append(visitErrorValues(std::move(errors))); } - return document; + result.push_back(response::ValueToken::EndObject {}); + + return result; } template <>