in src/ClientGenerator.cpp [424:674]
bool Generator::outputSource() const noexcept
{
std::ofstream sourceFile(_sourcePath, std::ios_base::trunc);
sourceFile << R"cpp(// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// WARNING! Do not edit this file manually, your changes will be overwritten.
#include ")cpp" << _schemaLoader.getFilenamePrefix()
<< R"cpp(Client.h"
#include <algorithm>
#include <array>
#include <sstream>
#include <stdexcept>
#include <string_view>
using namespace std::literals;
)cpp";
NamespaceScope clientNamespaceScope { sourceFile, getClientNamespace() };
PendingBlankLine pendingSeparator { sourceFile };
sourceFile << R"cpp(
using namespace )cpp"
<< getRequestNamespace() << R"cpp(;
)cpp";
const auto& variables = _requestLoader.getVariables();
for (const auto& enumType : _requestLoader.getReferencedEnums())
{
pendingSeparator.reset();
const auto& enumValues = enumType->enumValues();
const auto cppType = _schemaLoader.getCppType(enumType->name());
sourceFile << R"cpp(static const std::array<std::string_view, )cpp" << enumValues.size()
<< R"cpp(> s_names)cpp" << cppType << R"cpp( = {
)cpp";
for (const auto& enumValue : enumValues)
{
sourceFile << R"cpp( ")cpp" << SchemaLoader::getSafeCppName(enumValue->name())
<< R"cpp("sv,
)cpp";
}
sourceFile << R"cpp(};
)cpp";
pendingSeparator.add();
}
if (!variables.empty())
{
for (const auto& enumType : _requestLoader.getReferencedEnums())
{
pendingSeparator.reset();
const auto cppType = _schemaLoader.getCppType(enumType->name());
if (!variables.empty())
{
sourceFile << R"cpp(template <>
response::Value ModifiedVariable<)cpp"
<< cppType << R"cpp(>::serialize()cpp" << cppType << R"cpp(&& value)
{
response::Value result { response::Type::EnumValue };
result.set<std::string>(std::string { s_names)cpp"
<< cppType << R"cpp([static_cast<size_t>(value)] });
return result;
}
)cpp";
}
pendingSeparator.add();
}
for (const auto& inputType : _requestLoader.getReferencedInputTypes())
{
pendingSeparator.reset();
const auto cppType = _schemaLoader.getCppType(inputType->name());
sourceFile << R"cpp(template <>
response::Value ModifiedVariable<Variables::)cpp"
<< cppType << R"cpp(>::serialize(Variables::)cpp" << cppType
<< R"cpp(&& inputValue)
{
response::Value result { response::Type::Map };
)cpp";
for (const auto& inputField : inputType->inputFields())
{
const auto [type, modifiers] =
RequestLoader::unwrapSchemaType(inputField->type().lock());
sourceFile << R"cpp( result.emplace_back(R"js()cpp" << inputField->name()
<< R"cpp()js"s, ModifiedVariable<)cpp"
<< _schemaLoader.getCppType(type->name()) << R"cpp(>::serialize)cpp"
<< getTypeModifierList(modifiers) << R"cpp((std::move(inputValue.)cpp"
<< SchemaLoader::getSafeCppName(inputField->name()) << R"cpp()));
)cpp";
}
sourceFile << R"cpp(
return result;
}
)cpp";
pendingSeparator.add();
}
}
for (const auto& enumType : _requestLoader.getReferencedEnums())
{
pendingSeparator.reset();
const auto cppType = _schemaLoader.getCppType(enumType->name());
sourceFile << R"cpp(template <>
)cpp" << cppType << R"cpp( ModifiedResponse<)cpp"
<< cppType << R"cpp(>::parse(response::Value value)
{
if (!value.maybe_enum())
{
throw std::logic_error { "not a valid )cpp"
<< cppType << R"cpp( value" };
}
const auto itr = std::find(s_names)cpp"
<< cppType << R"cpp(.cbegin(), s_names)cpp" << cppType
<< R"cpp(.cend(), value.release<std::string>());
if (itr == s_names)cpp"
<< cppType << R"cpp(.cend())
{
throw std::logic_error { "not a valid )cpp"
<< cppType << R"cpp( value" };
}
return static_cast<)cpp"
<< cppType << R"cpp(>(itr - s_names)cpp" << cppType << R"cpp(.cbegin());
}
)cpp";
pendingSeparator.add();
}
const auto& responseType = _requestLoader.getResponseType();
const auto currentScope = R"cpp(Response)cpp"s;
for (const auto& responseField : responseType.fields)
{
if (outputModifiedResponseImplementation(sourceFile, currentScope, responseField))
{
pendingSeparator.add();
}
}
pendingSeparator.reset();
NamespaceScope requestNamespaceScope { sourceFile, getRequestNamespace() };
pendingSeparator.add();
outputGetRequestImplementation(sourceFile);
if (!variables.empty())
{
sourceFile << R"cpp(
response::Value serializeVariables(Variables&& variables)
{
response::Value result { response::Type::Map };
)cpp";
for (const auto& variable : variables)
{
sourceFile << R"cpp( result.emplace_back(R"js()cpp" << variable.name
<< R"cpp()js"s, ModifiedVariable<)cpp";
const auto& builtinTypes = _schemaLoader.getBuiltinTypes();
if (builtinTypes.find(variable.type->name()) == builtinTypes.cend()
&& _schemaLoader.getSchemaType(variable.type->name()) != SchemaType::Scalar)
{
sourceFile << R"cpp(Variables::)cpp";
}
sourceFile << _schemaLoader.getCppType(variable.type->name()) << R"cpp(>::serialize)cpp"
<< getTypeModifierList(variable.modifiers)
<< R"cpp((std::move(variables.)cpp" << variable.cppName << R"cpp()));
)cpp";
}
sourceFile << R"cpp(
return result;
}
)cpp";
}
sourceFile << R"cpp(
Response parseResponse(response::Value response)
{
Response result;
if (response.type() == response::Type::Map)
{
auto members = response.release<response::MapType>();
for (auto& member : members)
{
)cpp";
std::unordered_set<std::string_view> fieldNames;
for (const auto& responseField : responseType.fields)
{
if (fieldNames.emplace(responseField.name).second)
{
sourceFile << R"cpp( if (member.first == R"js()cpp" << responseField.name
<< R"cpp()js"sv)
{
result.)cpp"
<< responseField.cppName << R"cpp( = ModifiedResponse<)cpp"
<< getResponseFieldCppType(responseField, currentScope)
<< R"cpp(>::parse)cpp" << getTypeModifierList(responseField.modifiers)
<< R"cpp((std::move(member.second));
continue;
}
)cpp";
}
}
sourceFile << R"cpp( }
}
return result;
}
)cpp";
pendingSeparator.reset();
return true;
}