diff --git a/.gitignore b/.gitignore index 80c423082bb0..8c496b9064be 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,9 @@ toolchains/android/ tools/code-generation/generator/target/ tools/code-generation/smithy/codegen/gradle/ tools/code-generation/smithy/codegen/.gradle/ +tools/code-generation/smithy/cpp-codegen/.gradle/ +tools/code-generation/smithy/cpp-codegen/output/ +tools/code-generation/smithy/cpp-codegen/smithy-build.json #config output aws-cpp-sdk-core/include/aws/core/SDKConfig.h diff --git a/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClient.h b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClient.h index 873154dd938b..a4cfb576b72e 100644 --- a/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClient.h +++ b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClient.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,8 @@ class AWS_DYNAMODB_API DynamoDBClient public smithy::client::AwsSmithyClientT, Aws::Crt::Variant, DynamoDBEndpointProviderBase, smithy::client::JsonOutcomeSerializer, - smithy::client::JsonOutcome, Aws::Client::DynamoDBErrorMarshaller> { + smithy::client::JsonOutcome, Aws::Client::DynamoDBErrorMarshaller>, + public DynamoDBPaginationBase { public: static const char* GetServiceName(); static const char* GetAllocationTag(); diff --git a/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClientPagination.h b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClientPagination.h new file mode 100644 index 000000000000..c421f85b0335 --- /dev/null +++ b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBClientPagination.h @@ -0,0 +1,34 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Aws { +namespace DynamoDB { + +using ListContributorInsightsPaginator = + Aws::Utils::Pagination::Paginator>; +using ListExportsPaginator = + Aws::Utils::Pagination::Paginator>; +using ListImportsPaginator = + Aws::Utils::Pagination::Paginator>; +using ListTablesPaginator = + Aws::Utils::Pagination::Paginator>; +using QueryPaginator = + Aws::Utils::Pagination::Paginator>; +using ScanPaginator = + Aws::Utils::Pagination::Paginator>; + +} // namespace DynamoDB +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBPaginationBase.h b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBPaginationBase.h new file mode 100644 index 000000000000..03daba9e5fdc --- /dev/null +++ b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/DynamoDBPaginationBase.h @@ -0,0 +1,86 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Aws { +namespace DynamoDB { + +class DynamoDBClient; + +template +class DynamoDBPaginationBase { + public: + /** + * Create a paginator for ListContributorInsights operation + */ + Aws::Utils::Pagination::Paginator> + ListContributorInsightsPaginator(const Model::ListContributorInsightsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for ListExports operation + */ + Aws::Utils::Pagination::Paginator> + ListExportsPaginator(const Model::ListExportsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for ListImports operation + */ + Aws::Utils::Pagination::Paginator> + ListImportsPaginator(const Model::ListImportsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for ListTables operation + */ + Aws::Utils::Pagination::Paginator> + ListTablesPaginator(const Model::ListTablesRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for Query operation + */ + Aws::Utils::Pagination::Paginator> QueryPaginator( + const Model::QueryRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for Scan operation + */ + Aws::Utils::Pagination::Paginator> ScanPaginator( + const Model::ScanRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } +}; +} // namespace DynamoDB +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/model/ScanPaginationTraits.h b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/model/ScanPaginationTraits.h new file mode 100644 index 000000000000..41f64ab4cca4 --- /dev/null +++ b/generated/src/aws-cpp-sdk-dynamodb/include/aws/dynamodb/model/ScanPaginationTraits.h @@ -0,0 +1,32 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws { +namespace DynamoDB { +namespace Pagination { + +template +struct ScanPaginationTraits { + using RequestType = Model::ScanRequest; + using ResultType = Model::ScanResult; + using OutcomeType = Model::ScanOutcome; + using ClientType = Client; + + static OutcomeType Invoke(Client& client, const RequestType& request) { return client.Scan(request); } + + static bool HasMoreResults(const ResultType& result) { return !result.GetLastEvaluatedKey().empty(); } + + static void SetNextRequest(const ResultType& result, RequestType& request) { request.SetExclusiveStartKey(result.GetLastEvaluatedKey()); } +}; + +} // namespace Pagination +} // namespace DynamoDB +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2Client.h b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2Client.h index 448f1a952f35..49cf8ca71505 100644 --- a/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2Client.h +++ b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2Client.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -21,7 +22,9 @@ namespace EC2 { * href="https://docs.aws.amazon.com/ec2/latest/devguide">Amazon EC2 Developer * Guide.

*/ -class AWS_EC2_API EC2Client : public Aws::Client::AWSXMLClient, public Aws::Client::ClientWithAsyncTemplateMethods { +class AWS_EC2_API EC2Client : public Aws::Client::AWSXMLClient, + public Aws::Client::ClientWithAsyncTemplateMethods, + public EC2PaginationBase { public: typedef Aws::Client::AWSXMLClient BASECLASS; static const char* GetServiceName(); diff --git a/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2ClientPagination.h b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2ClientPagination.h new file mode 100644 index 000000000000..8832ec884292 --- /dev/null +++ b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2ClientPagination.h @@ -0,0 +1,625 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Aws { +namespace EC2 { + +using DescribeAddressesAttributePaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeAddressTransfersPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeAwsNetworkPerformanceMetricSubscriptionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeByoipCidrsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeCapacityBlockExtensionHistoryPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityBlockExtensionOfferingsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityBlockOfferingsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityBlocksPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeCapacityBlockStatusPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityManagerDataExportsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityReservationBillingRequestsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityReservationFleetsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCapacityReservationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCarrierGatewaysPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeClassicLinkInstancesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeClientVpnAuthorizationRulesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeClientVpnConnectionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeClientVpnEndpointsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeClientVpnRoutesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeClientVpnTargetNetworksPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeCoipPoolsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeDhcpOptionsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeEgressOnlyInternetGatewaysPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeExportImageTasksPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeFastLaunchImagesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeFastSnapshotRestoresPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeFleetsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeFlowLogsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeFpgaImagesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeHostReservationOfferingsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeHostReservationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeHostsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIamInstanceProfileAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeImageReferencesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeImagesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeImageUsageReportEntriesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeImageUsageReportsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeImportImageTasksPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeImportSnapshotTasksPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceConnectEndpointsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceCreditSpecificationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceEventWindowsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceImageMetadataPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstancesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceStatusPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeInstanceTopologyPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceTypeOfferingsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeInstanceTypesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeInternetGatewaysPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamPoolsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamPrefixListResolversPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamPrefixListResolverTargetsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamResourceDiscoveriesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamResourceDiscoveryAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeIpamScopesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeIpv6PoolsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeLaunchTemplatesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeLaunchTemplateVersionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeLocalGatewayRouteTablesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsPaginator = Aws::Utils::Pagination::Paginator< + EC2Client, Model::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsRequest, + Pagination::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsPaginationTraits>; +using DescribeLocalGatewayRouteTableVpcAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeLocalGatewaysPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeLocalGatewayVirtualInterfaceGroupsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeLocalGatewayVirtualInterfacesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeMacHostsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeMacModificationTasksPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeManagedPrefixListsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeMovingAddressesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeNatGatewaysPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeNetworkAclsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeNetworkInsightsAccessScopeAnalysesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeNetworkInsightsAccessScopesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeNetworkInsightsAnalysesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeNetworkInsightsPathsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeNetworkInterfacePermissionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeNetworkInterfacesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribePrefixListsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribePrincipalIdFormatPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribePublicIpv4PoolsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeReplaceRootVolumeTasksPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeReservedInstancesModificationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeReservedInstancesOfferingsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeRouteServerEndpointsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeRouteServerPeersPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeRouteServersPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeRouteTablesPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeScheduledInstanceAvailabilityPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeScheduledInstancesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSecurityGroupRulesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSecurityGroupsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeSecurityGroupVpcAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSnapshotsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSnapshotTierStatusPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSpotFleetRequestsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSpotInstanceRequestsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeSpotPriceHistoryPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeStaleSecurityGroupsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeStoreImageTasksPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeSubnetsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTagsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTrafficMirrorFiltersPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTrafficMirrorSessionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTrafficMirrorTargetsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayAttachmentsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayConnectPeersPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayConnectsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayMulticastDomainsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayPeeringAttachmentsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayPolicyTablesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayRouteTableAnnouncementsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayRouteTablesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewaysPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeTransitGatewayVpcAttachmentsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeTrunkInterfaceAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVerifiedAccessEndpointsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVerifiedAccessGroupsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVerifiedAccessInstanceLoggingConfigurationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVerifiedAccessInstancesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVerifiedAccessTrustProvidersPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVolumesPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVolumesModificationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVolumeStatusPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeVpcClassicLinkDnsSupportPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpcEndpointConnectionNotificationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpcEndpointConnectionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpcEndpointsPaginator = Aws::Utils::Pagination::Paginator>; +using DescribeVpcEndpointServiceConfigurationsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpcEndpointServicePermissionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpcPeeringConnectionsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpcsPaginator = + Aws::Utils::Pagination::Paginator>; +using DescribeVpnConcentratorsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetAssociatedIpv6PoolCidrsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetAwsNetworkPerformanceDataPaginator = + Aws::Utils::Pagination::Paginator>; +using GetCapacityManagerMetricDataPaginator = + Aws::Utils::Pagination::Paginator>; +using GetCapacityManagerMetricDimensionsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetGroupsForCapacityReservationPaginator = + Aws::Utils::Pagination::Paginator>; +using GetInstanceTypesFromInstanceRequirementsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamAddressHistoryPaginator = Aws::Utils::Pagination::Paginator>; +using GetIpamDiscoveredAccountsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamDiscoveredResourceCidrsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamPoolAllocationsPaginator = Aws::Utils::Pagination::Paginator>; +using GetIpamPoolCidrsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamPrefixListResolverRulesPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamPrefixListResolverVersionEntriesPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamPrefixListResolverVersionsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetIpamResourceCidrsPaginator = Aws::Utils::Pagination::Paginator>; +using GetManagedPrefixListAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetManagedPrefixListEntriesPaginator = + Aws::Utils::Pagination::Paginator>; +using GetNetworkInsightsAccessScopeAnalysisFindingsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetSecurityGroupsForVpcPaginator = Aws::Utils::Pagination::Paginator>; +using GetSpotPlacementScoresPaginator = Aws::Utils::Pagination::Paginator>; +using GetTransitGatewayAttachmentPropagationsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetTransitGatewayMulticastDomainAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetTransitGatewayPolicyTableAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetTransitGatewayPrefixListReferencesPaginator = + Aws::Utils::Pagination::Paginator>; +using GetTransitGatewayRouteTableAssociationsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetTransitGatewayRouteTablePropagationsPaginator = + Aws::Utils::Pagination::Paginator>; +using GetVpnConnectionDeviceTypesPaginator = + Aws::Utils::Pagination::Paginator>; +using ListImagesInRecycleBinPaginator = Aws::Utils::Pagination::Paginator>; +using ListSnapshotsInRecycleBinPaginator = + Aws::Utils::Pagination::Paginator>; +using SearchLocalGatewayRoutesPaginator = + Aws::Utils::Pagination::Paginator>; +using SearchTransitGatewayMulticastGroupsPaginator = + Aws::Utils::Pagination::Paginator>; +using SearchTransitGatewayRoutesPaginator = + Aws::Utils::Pagination::Paginator>; + +} // namespace EC2 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2PaginationBase.h b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2PaginationBase.h new file mode 100644 index 000000000000..144b80fa08ef --- /dev/null +++ b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/EC2PaginationBase.h @@ -0,0 +1,1988 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Aws { +namespace EC2 { + +class EC2Client; + +template +class EC2PaginationBase { + public: + /** + * Create a paginator for DescribeAddressesAttribute operation + */ + Aws::Utils::Pagination::Paginator> + DescribeAddressesAttributePaginator(const Model::DescribeAddressesAttributeRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeAddressTransfers operation + */ + Aws::Utils::Pagination::Paginator> + DescribeAddressTransfersPaginator(const Model::DescribeAddressTransfersRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeAwsNetworkPerformanceMetricSubscriptions operation + */ + Aws::Utils::Pagination::Paginator> + DescribeAwsNetworkPerformanceMetricSubscriptionsPaginator(const Model::DescribeAwsNetworkPerformanceMetricSubscriptionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeByoipCidrs operation + */ + Aws::Utils::Pagination::Paginator> + DescribeByoipCidrsPaginator(const Model::DescribeByoipCidrsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityBlockExtensionHistory operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityBlockExtensionHistoryPaginator(const Model::DescribeCapacityBlockExtensionHistoryRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityBlockExtensionOfferings operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityBlockExtensionOfferingsPaginator(const Model::DescribeCapacityBlockExtensionOfferingsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityBlockOfferings operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityBlockOfferingsPaginator(const Model::DescribeCapacityBlockOfferingsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityBlocks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityBlocksPaginator(const Model::DescribeCapacityBlocksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityBlockStatus operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityBlockStatusPaginator(const Model::DescribeCapacityBlockStatusRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityManagerDataExports operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityManagerDataExportsPaginator(const Model::DescribeCapacityManagerDataExportsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityReservationBillingRequests operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityReservationBillingRequestsPaginator(const Model::DescribeCapacityReservationBillingRequestsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityReservationFleets operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityReservationFleetsPaginator(const Model::DescribeCapacityReservationFleetsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCapacityReservations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCapacityReservationsPaginator(const Model::DescribeCapacityReservationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCarrierGateways operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCarrierGatewaysPaginator(const Model::DescribeCarrierGatewaysRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeClassicLinkInstances operation + */ + Aws::Utils::Pagination::Paginator> + DescribeClassicLinkInstancesPaginator(const Model::DescribeClassicLinkInstancesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeClientVpnAuthorizationRules operation + */ + Aws::Utils::Pagination::Paginator> + DescribeClientVpnAuthorizationRulesPaginator(const Model::DescribeClientVpnAuthorizationRulesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeClientVpnConnections operation + */ + Aws::Utils::Pagination::Paginator> + DescribeClientVpnConnectionsPaginator(const Model::DescribeClientVpnConnectionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeClientVpnEndpoints operation + */ + Aws::Utils::Pagination::Paginator> + DescribeClientVpnEndpointsPaginator(const Model::DescribeClientVpnEndpointsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeClientVpnRoutes operation + */ + Aws::Utils::Pagination::Paginator> + DescribeClientVpnRoutesPaginator(const Model::DescribeClientVpnRoutesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeClientVpnTargetNetworks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeClientVpnTargetNetworksPaginator(const Model::DescribeClientVpnTargetNetworksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeCoipPools operation + */ + Aws::Utils::Pagination::Paginator> + DescribeCoipPoolsPaginator(const Model::DescribeCoipPoolsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeDhcpOptions operation + */ + Aws::Utils::Pagination::Paginator> + DescribeDhcpOptionsPaginator(const Model::DescribeDhcpOptionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeEgressOnlyInternetGateways operation + */ + Aws::Utils::Pagination::Paginator> + DescribeEgressOnlyInternetGatewaysPaginator(const Model::DescribeEgressOnlyInternetGatewaysRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeExportImageTasks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeExportImageTasksPaginator(const Model::DescribeExportImageTasksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeFastLaunchImages operation + */ + Aws::Utils::Pagination::Paginator> + DescribeFastLaunchImagesPaginator(const Model::DescribeFastLaunchImagesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeFastSnapshotRestores operation + */ + Aws::Utils::Pagination::Paginator> + DescribeFastSnapshotRestoresPaginator(const Model::DescribeFastSnapshotRestoresRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeFleets operation + */ + Aws::Utils::Pagination::Paginator> + DescribeFleetsPaginator(const Model::DescribeFleetsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeFlowLogs operation + */ + Aws::Utils::Pagination::Paginator> + DescribeFlowLogsPaginator(const Model::DescribeFlowLogsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeFpgaImages operation + */ + Aws::Utils::Pagination::Paginator> + DescribeFpgaImagesPaginator(const Model::DescribeFpgaImagesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeHostReservationOfferings operation + */ + Aws::Utils::Pagination::Paginator> + DescribeHostReservationOfferingsPaginator(const Model::DescribeHostReservationOfferingsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeHostReservations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeHostReservationsPaginator(const Model::DescribeHostReservationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeHosts operation + */ + Aws::Utils::Pagination::Paginator> + DescribeHostsPaginator(const Model::DescribeHostsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeIamInstanceProfileAssociations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIamInstanceProfileAssociationsPaginator(const Model::DescribeIamInstanceProfileAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeImageReferences operation + */ + Aws::Utils::Pagination::Paginator> + DescribeImageReferencesPaginator(const Model::DescribeImageReferencesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeImages operation + */ + Aws::Utils::Pagination::Paginator> + DescribeImagesPaginator(const Model::DescribeImagesRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeImageUsageReportEntries operation + */ + Aws::Utils::Pagination::Paginator> + DescribeImageUsageReportEntriesPaginator(const Model::DescribeImageUsageReportEntriesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeImageUsageReports operation + */ + Aws::Utils::Pagination::Paginator> + DescribeImageUsageReportsPaginator(const Model::DescribeImageUsageReportsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeImportImageTasks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeImportImageTasksPaginator(const Model::DescribeImportImageTasksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeImportSnapshotTasks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeImportSnapshotTasksPaginator(const Model::DescribeImportSnapshotTasksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceConnectEndpoints operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceConnectEndpointsPaginator(const Model::DescribeInstanceConnectEndpointsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceCreditSpecifications operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceCreditSpecificationsPaginator(const Model::DescribeInstanceCreditSpecificationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceEventWindows operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceEventWindowsPaginator(const Model::DescribeInstanceEventWindowsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceImageMetadata operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceImageMetadataPaginator(const Model::DescribeInstanceImageMetadataRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstances operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstancesPaginator(const Model::DescribeInstancesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceStatus operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceStatusPaginator(const Model::DescribeInstanceStatusRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceTopology operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceTopologyPaginator(const Model::DescribeInstanceTopologyRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceTypeOfferings operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceTypeOfferingsPaginator(const Model::DescribeInstanceTypeOfferingsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInstanceTypes operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInstanceTypesPaginator(const Model::DescribeInstanceTypesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeInternetGateways operation + */ + Aws::Utils::Pagination::Paginator> + DescribeInternetGatewaysPaginator(const Model::DescribeInternetGatewaysRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpamPools operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamPoolsPaginator(const Model::DescribeIpamPoolsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpamPrefixListResolvers operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamPrefixListResolversPaginator(const Model::DescribeIpamPrefixListResolversRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpamPrefixListResolverTargets operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamPrefixListResolverTargetsPaginator(const Model::DescribeIpamPrefixListResolverTargetsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpamResourceDiscoveries operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamResourceDiscoveriesPaginator(const Model::DescribeIpamResourceDiscoveriesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpamResourceDiscoveryAssociations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamResourceDiscoveryAssociationsPaginator(const Model::DescribeIpamResourceDiscoveryAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpams operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamsPaginator(const Model::DescribeIpamsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeIpamScopes operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpamScopesPaginator(const Model::DescribeIpamScopesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeIpv6Pools operation + */ + Aws::Utils::Pagination::Paginator> + DescribeIpv6PoolsPaginator(const Model::DescribeIpv6PoolsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLaunchTemplates operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLaunchTemplatesPaginator(const Model::DescribeLaunchTemplatesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLaunchTemplateVersions operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLaunchTemplateVersionsPaginator(const Model::DescribeLaunchTemplateVersionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLocalGatewayRouteTables operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLocalGatewayRouteTablesPaginator(const Model::DescribeLocalGatewayRouteTablesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociations operation + */ + Aws::Utils::Pagination::Paginator< + DerivedClient, Model::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsRequest, + Pagination::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsPaginationTraits> + DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsPaginator( + const Model::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator< + DerivedClient, Model::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsRequest, + Pagination::DescribeLocalGatewayRouteTableVirtualInterfaceGroupAssociationsPaginationTraits>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLocalGatewayRouteTableVpcAssociations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLocalGatewayRouteTableVpcAssociationsPaginator(const Model::DescribeLocalGatewayRouteTableVpcAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLocalGateways operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLocalGatewaysPaginator(const Model::DescribeLocalGatewaysRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLocalGatewayVirtualInterfaceGroups operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLocalGatewayVirtualInterfaceGroupsPaginator(const Model::DescribeLocalGatewayVirtualInterfaceGroupsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeLocalGatewayVirtualInterfaces operation + */ + Aws::Utils::Pagination::Paginator> + DescribeLocalGatewayVirtualInterfacesPaginator(const Model::DescribeLocalGatewayVirtualInterfacesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeMacHosts operation + */ + Aws::Utils::Pagination::Paginator> + DescribeMacHostsPaginator(const Model::DescribeMacHostsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeMacModificationTasks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeMacModificationTasksPaginator(const Model::DescribeMacModificationTasksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeManagedPrefixLists operation + */ + Aws::Utils::Pagination::Paginator> + DescribeManagedPrefixListsPaginator(const Model::DescribeManagedPrefixListsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeMovingAddresses operation + */ + Aws::Utils::Pagination::Paginator> + DescribeMovingAddressesPaginator(const Model::DescribeMovingAddressesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNatGateways operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNatGatewaysPaginator(const Model::DescribeNatGatewaysRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkAcls operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkAclsPaginator(const Model::DescribeNetworkAclsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkInsightsAccessScopeAnalyses operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkInsightsAccessScopeAnalysesPaginator(const Model::DescribeNetworkInsightsAccessScopeAnalysesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkInsightsAccessScopes operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkInsightsAccessScopesPaginator(const Model::DescribeNetworkInsightsAccessScopesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkInsightsAnalyses operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkInsightsAnalysesPaginator(const Model::DescribeNetworkInsightsAnalysesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkInsightsPaths operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkInsightsPathsPaginator(const Model::DescribeNetworkInsightsPathsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkInterfacePermissions operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkInterfacePermissionsPaginator(const Model::DescribeNetworkInterfacePermissionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeNetworkInterfaces operation + */ + Aws::Utils::Pagination::Paginator> + DescribeNetworkInterfacesPaginator(const Model::DescribeNetworkInterfacesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribePrefixLists operation + */ + Aws::Utils::Pagination::Paginator> + DescribePrefixListsPaginator(const Model::DescribePrefixListsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribePrincipalIdFormat operation + */ + Aws::Utils::Pagination::Paginator> + DescribePrincipalIdFormatPaginator(const Model::DescribePrincipalIdFormatRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribePublicIpv4Pools operation + */ + Aws::Utils::Pagination::Paginator> + DescribePublicIpv4PoolsPaginator(const Model::DescribePublicIpv4PoolsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeReplaceRootVolumeTasks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeReplaceRootVolumeTasksPaginator(const Model::DescribeReplaceRootVolumeTasksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeReservedInstancesModifications operation + */ + Aws::Utils::Pagination::Paginator> + DescribeReservedInstancesModificationsPaginator(const Model::DescribeReservedInstancesModificationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeReservedInstancesOfferings operation + */ + Aws::Utils::Pagination::Paginator> + DescribeReservedInstancesOfferingsPaginator(const Model::DescribeReservedInstancesOfferingsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeRouteServerEndpoints operation + */ + Aws::Utils::Pagination::Paginator> + DescribeRouteServerEndpointsPaginator(const Model::DescribeRouteServerEndpointsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeRouteServerPeers operation + */ + Aws::Utils::Pagination::Paginator> + DescribeRouteServerPeersPaginator(const Model::DescribeRouteServerPeersRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeRouteServers operation + */ + Aws::Utils::Pagination::Paginator> + DescribeRouteServersPaginator(const Model::DescribeRouteServersRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeRouteTables operation + */ + Aws::Utils::Pagination::Paginator> + DescribeRouteTablesPaginator(const Model::DescribeRouteTablesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeScheduledInstanceAvailability operation + */ + Aws::Utils::Pagination::Paginator> + DescribeScheduledInstanceAvailabilityPaginator(const Model::DescribeScheduledInstanceAvailabilityRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeScheduledInstances operation + */ + Aws::Utils::Pagination::Paginator> + DescribeScheduledInstancesPaginator(const Model::DescribeScheduledInstancesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSecurityGroupRules operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSecurityGroupRulesPaginator(const Model::DescribeSecurityGroupRulesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSecurityGroups operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSecurityGroupsPaginator(const Model::DescribeSecurityGroupsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSecurityGroupVpcAssociations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSecurityGroupVpcAssociationsPaginator(const Model::DescribeSecurityGroupVpcAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSnapshots operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSnapshotsPaginator(const Model::DescribeSnapshotsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSnapshotTierStatus operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSnapshotTierStatusPaginator(const Model::DescribeSnapshotTierStatusRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSpotFleetRequests operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSpotFleetRequestsPaginator(const Model::DescribeSpotFleetRequestsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSpotInstanceRequests operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSpotInstanceRequestsPaginator(const Model::DescribeSpotInstanceRequestsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSpotPriceHistory operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSpotPriceHistoryPaginator(const Model::DescribeSpotPriceHistoryRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeStaleSecurityGroups operation + */ + Aws::Utils::Pagination::Paginator> + DescribeStaleSecurityGroupsPaginator(const Model::DescribeStaleSecurityGroupsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeStoreImageTasks operation + */ + Aws::Utils::Pagination::Paginator> + DescribeStoreImageTasksPaginator(const Model::DescribeStoreImageTasksRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeSubnets operation + */ + Aws::Utils::Pagination::Paginator> + DescribeSubnetsPaginator(const Model::DescribeSubnetsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeTags operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTagsPaginator(const Model::DescribeTagsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeTrafficMirrorFilters operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTrafficMirrorFiltersPaginator(const Model::DescribeTrafficMirrorFiltersRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTrafficMirrorSessions operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTrafficMirrorSessionsPaginator(const Model::DescribeTrafficMirrorSessionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTrafficMirrorTargets operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTrafficMirrorTargetsPaginator(const Model::DescribeTrafficMirrorTargetsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayAttachments operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayAttachmentsPaginator(const Model::DescribeTransitGatewayAttachmentsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayConnectPeers operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayConnectPeersPaginator(const Model::DescribeTransitGatewayConnectPeersRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayConnects operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayConnectsPaginator(const Model::DescribeTransitGatewayConnectsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayMulticastDomains operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayMulticastDomainsPaginator(const Model::DescribeTransitGatewayMulticastDomainsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayPeeringAttachments operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayPeeringAttachmentsPaginator(const Model::DescribeTransitGatewayPeeringAttachmentsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayPolicyTables operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayPolicyTablesPaginator(const Model::DescribeTransitGatewayPolicyTablesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayRouteTableAnnouncements operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayRouteTableAnnouncementsPaginator(const Model::DescribeTransitGatewayRouteTableAnnouncementsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayRouteTables operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayRouteTablesPaginator(const Model::DescribeTransitGatewayRouteTablesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGateways operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewaysPaginator(const Model::DescribeTransitGatewaysRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTransitGatewayVpcAttachments operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTransitGatewayVpcAttachmentsPaginator(const Model::DescribeTransitGatewayVpcAttachmentsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeTrunkInterfaceAssociations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeTrunkInterfaceAssociationsPaginator(const Model::DescribeTrunkInterfaceAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVerifiedAccessEndpoints operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVerifiedAccessEndpointsPaginator(const Model::DescribeVerifiedAccessEndpointsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVerifiedAccessGroups operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVerifiedAccessGroupsPaginator(const Model::DescribeVerifiedAccessGroupsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVerifiedAccessInstanceLoggingConfigurations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVerifiedAccessInstanceLoggingConfigurationsPaginator( + const Model::DescribeVerifiedAccessInstanceLoggingConfigurationsRequest& request) { + return Aws::Utils::Pagination::Paginator< + DerivedClient, Model::DescribeVerifiedAccessInstanceLoggingConfigurationsRequest, + Pagination::DescribeVerifiedAccessInstanceLoggingConfigurationsPaginationTraits>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeVerifiedAccessInstances operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVerifiedAccessInstancesPaginator(const Model::DescribeVerifiedAccessInstancesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVerifiedAccessTrustProviders operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVerifiedAccessTrustProvidersPaginator(const Model::DescribeVerifiedAccessTrustProvidersRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVolumes operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVolumesPaginator(const Model::DescribeVolumesRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeVolumesModifications operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVolumesModificationsPaginator(const Model::DescribeVolumesModificationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVolumeStatus operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVolumeStatusPaginator(const Model::DescribeVolumeStatusRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcClassicLinkDnsSupport operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcClassicLinkDnsSupportPaginator(const Model::DescribeVpcClassicLinkDnsSupportRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcEndpointConnectionNotifications operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcEndpointConnectionNotificationsPaginator(const Model::DescribeVpcEndpointConnectionNotificationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcEndpointConnections operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcEndpointConnectionsPaginator(const Model::DescribeVpcEndpointConnectionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcEndpoints operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcEndpointsPaginator(const Model::DescribeVpcEndpointsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcEndpointServiceConfigurations operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcEndpointServiceConfigurationsPaginator(const Model::DescribeVpcEndpointServiceConfigurationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcEndpointServicePermissions operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcEndpointServicePermissionsPaginator(const Model::DescribeVpcEndpointServicePermissionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcPeeringConnections operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcPeeringConnectionsPaginator(const Model::DescribeVpcPeeringConnectionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for DescribeVpcs operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpcsPaginator(const Model::DescribeVpcsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for DescribeVpnConcentrators operation + */ + Aws::Utils::Pagination::Paginator> + DescribeVpnConcentratorsPaginator(const Model::DescribeVpnConcentratorsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetAssociatedIpv6PoolCidrs operation + */ + Aws::Utils::Pagination::Paginator> + GetAssociatedIpv6PoolCidrsPaginator(const Model::GetAssociatedIpv6PoolCidrsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetAwsNetworkPerformanceData operation + */ + Aws::Utils::Pagination::Paginator> + GetAwsNetworkPerformanceDataPaginator(const Model::GetAwsNetworkPerformanceDataRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetCapacityManagerMetricData operation + */ + Aws::Utils::Pagination::Paginator> + GetCapacityManagerMetricDataPaginator(const Model::GetCapacityManagerMetricDataRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetCapacityManagerMetricDimensions operation + */ + Aws::Utils::Pagination::Paginator> + GetCapacityManagerMetricDimensionsPaginator(const Model::GetCapacityManagerMetricDimensionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetGroupsForCapacityReservation operation + */ + Aws::Utils::Pagination::Paginator> + GetGroupsForCapacityReservationPaginator(const Model::GetGroupsForCapacityReservationRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetInstanceTypesFromInstanceRequirements operation + */ + Aws::Utils::Pagination::Paginator> + GetInstanceTypesFromInstanceRequirementsPaginator(const Model::GetInstanceTypesFromInstanceRequirementsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamAddressHistory operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamAddressHistoryPaginator(const Model::GetIpamAddressHistoryRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamDiscoveredAccounts operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamDiscoveredAccountsPaginator(const Model::GetIpamDiscoveredAccountsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamDiscoveredResourceCidrs operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamDiscoveredResourceCidrsPaginator(const Model::GetIpamDiscoveredResourceCidrsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamPoolAllocations operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamPoolAllocationsPaginator(const Model::GetIpamPoolAllocationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamPoolCidrs operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamPoolCidrsPaginator(const Model::GetIpamPoolCidrsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamPrefixListResolverRules operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamPrefixListResolverRulesPaginator(const Model::GetIpamPrefixListResolverRulesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamPrefixListResolverVersionEntries operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamPrefixListResolverVersionEntriesPaginator(const Model::GetIpamPrefixListResolverVersionEntriesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamPrefixListResolverVersions operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamPrefixListResolverVersionsPaginator(const Model::GetIpamPrefixListResolverVersionsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetIpamResourceCidrs operation + */ + Aws::Utils::Pagination::Paginator> + GetIpamResourceCidrsPaginator(const Model::GetIpamResourceCidrsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetManagedPrefixListAssociations operation + */ + Aws::Utils::Pagination::Paginator> + GetManagedPrefixListAssociationsPaginator(const Model::GetManagedPrefixListAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetManagedPrefixListEntries operation + */ + Aws::Utils::Pagination::Paginator> + GetManagedPrefixListEntriesPaginator(const Model::GetManagedPrefixListEntriesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetNetworkInsightsAccessScopeAnalysisFindings operation + */ + Aws::Utils::Pagination::Paginator> + GetNetworkInsightsAccessScopeAnalysisFindingsPaginator(const Model::GetNetworkInsightsAccessScopeAnalysisFindingsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetSecurityGroupsForVpc operation + */ + Aws::Utils::Pagination::Paginator> + GetSecurityGroupsForVpcPaginator(const Model::GetSecurityGroupsForVpcRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetSpotPlacementScores operation + */ + Aws::Utils::Pagination::Paginator> + GetSpotPlacementScoresPaginator(const Model::GetSpotPlacementScoresRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetTransitGatewayAttachmentPropagations operation + */ + Aws::Utils::Pagination::Paginator> + GetTransitGatewayAttachmentPropagationsPaginator(const Model::GetTransitGatewayAttachmentPropagationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetTransitGatewayMulticastDomainAssociations operation + */ + Aws::Utils::Pagination::Paginator> + GetTransitGatewayMulticastDomainAssociationsPaginator(const Model::GetTransitGatewayMulticastDomainAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetTransitGatewayPolicyTableAssociations operation + */ + Aws::Utils::Pagination::Paginator> + GetTransitGatewayPolicyTableAssociationsPaginator(const Model::GetTransitGatewayPolicyTableAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetTransitGatewayPrefixListReferences operation + */ + Aws::Utils::Pagination::Paginator> + GetTransitGatewayPrefixListReferencesPaginator(const Model::GetTransitGatewayPrefixListReferencesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetTransitGatewayRouteTableAssociations operation + */ + Aws::Utils::Pagination::Paginator> + GetTransitGatewayRouteTableAssociationsPaginator(const Model::GetTransitGatewayRouteTableAssociationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetTransitGatewayRouteTablePropagations operation + */ + Aws::Utils::Pagination::Paginator> + GetTransitGatewayRouteTablePropagationsPaginator(const Model::GetTransitGatewayRouteTablePropagationsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for GetVpnConnectionDeviceTypes operation + */ + Aws::Utils::Pagination::Paginator> + GetVpnConnectionDeviceTypesPaginator(const Model::GetVpnConnectionDeviceTypesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for ListImagesInRecycleBin operation + */ + Aws::Utils::Pagination::Paginator> + ListImagesInRecycleBinPaginator(const Model::ListImagesInRecycleBinRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for ListSnapshotsInRecycleBin operation + */ + Aws::Utils::Pagination::Paginator> + ListSnapshotsInRecycleBinPaginator(const Model::ListSnapshotsInRecycleBinRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for SearchLocalGatewayRoutes operation + */ + Aws::Utils::Pagination::Paginator> + SearchLocalGatewayRoutesPaginator(const Model::SearchLocalGatewayRoutesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for SearchTransitGatewayMulticastGroups operation + */ + Aws::Utils::Pagination::Paginator> + SearchTransitGatewayMulticastGroupsPaginator(const Model::SearchTransitGatewayMulticastGroupsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for SearchTransitGatewayRoutes operation + */ + Aws::Utils::Pagination::Paginator> + SearchTransitGatewayRoutesPaginator(const Model::SearchTransitGatewayRoutesRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } +}; +} // namespace EC2 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/model/DescribeSpotPriceHistoryPaginationTraits.h b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/model/DescribeSpotPriceHistoryPaginationTraits.h new file mode 100644 index 000000000000..1b905d94a799 --- /dev/null +++ b/generated/src/aws-cpp-sdk-ec2/include/aws/ec2/model/DescribeSpotPriceHistoryPaginationTraits.h @@ -0,0 +1,32 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws { +namespace EC2 { +namespace Pagination { + +template +struct DescribeSpotPriceHistoryPaginationTraits { + using RequestType = Model::DescribeSpotPriceHistoryRequest; + using ResultType = Model::DescribeSpotPriceHistoryResponse; + using OutcomeType = Model::DescribeSpotPriceHistoryOutcome; + using ClientType = Client; + + static OutcomeType Invoke(Client& client, const RequestType& request) { return client.DescribeSpotPriceHistory(request); } + + static bool HasMoreResults(const ResultType& result) { return !result.GetNextToken().empty(); } + + static void SetNextRequest(const ResultType& result, RequestType& request) { request.SetNextToken(result.GetNextToken()); } +}; + +} // namespace Pagination +} // namespace EC2 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3Client.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3Client.h index 7e036d82a8c5..65454163aa02 100644 --- a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3Client.h +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3Client.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -36,7 +37,9 @@ static const unsigned MAX_EXPIRATION_SECONDS = 7 * 24 * 60 * 60; /** *

*/ -class AWS_S3_API S3Client : public Aws::Client::AWSXMLClient, public Aws::Client::ClientWithAsyncTemplateMethods { +class AWS_S3_API S3Client : public Aws::Client::AWSXMLClient, + public Aws::Client::ClientWithAsyncTemplateMethods, + public S3PaginationBase { public: typedef Aws::Client::AWSXMLClient BASECLASS; static const char* GetServiceName(); diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h new file mode 100644 index 000000000000..cdac59ee9497 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3ClientPagination.h @@ -0,0 +1,27 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include +#include +#include + +namespace Aws { +namespace S3 { + +using ListBucketsPaginator = + Aws::Utils::Pagination::Paginator>; +using ListDirectoryBucketsPaginator = Aws::Utils::Pagination::Paginator>; +using ListObjectsV2Paginator = + Aws::Utils::Pagination::Paginator>; +using ListPartsPaginator = + Aws::Utils::Pagination::Paginator>; + +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3PaginationBase.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3PaginationBase.h new file mode 100644 index 000000000000..5b22027cf57b --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/S3PaginationBase.h @@ -0,0 +1,65 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace Aws { +namespace S3 { + +class S3Client; + +template +class S3PaginationBase { + public: + /** + * Create a paginator for ListBuckets operation + */ + Aws::Utils::Pagination::Paginator> + ListBucketsPaginator(const Model::ListBucketsRequest& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for ListDirectoryBuckets operation + */ + Aws::Utils::Pagination::Paginator> + ListDirectoryBucketsPaginator(const Model::ListDirectoryBucketsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } + + /** + * Create a paginator for ListObjectsV2 operation + */ + Aws::Utils::Pagination::Paginator> + ListObjectsV2Paginator(const Model::ListObjectsV2Request& request) { + return Aws::Utils::Pagination::Paginator>{*static_cast(this), + request}; + } + + /** + * Create a paginator for ListParts operation + */ + Aws::Utils::Pagination::Paginator> + ListPartsPaginator(const Model::ListPartsRequest& request) { + return Aws::Utils::Pagination::Paginator>{ + *static_cast(this), request}; + } +}; +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListBucketsPaginationTraits.h new file mode 100644 index 000000000000..72b61a8bee02 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListBucketsPaginationTraits.h @@ -0,0 +1,34 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws { +namespace S3 { +namespace Pagination { + +template +struct ListBucketsPaginationTraits { + using RequestType = Model::ListBucketsRequest; + using ResultType = Model::ListBucketsResult; + using OutcomeType = Model::ListBucketsOutcome; + using ClientType = Client; + + static OutcomeType Invoke(Client& client, const RequestType& request) { return client.ListBuckets(request); } + + static bool HasMoreResults(const ResultType& result) { return !result.GetContinuationToken().empty(); } + + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetContinuationToken(result.GetContinuationToken()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListDirectoryBucketsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListDirectoryBucketsPaginationTraits.h new file mode 100644 index 000000000000..180ccb8c4582 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListDirectoryBucketsPaginationTraits.h @@ -0,0 +1,34 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws { +namespace S3 { +namespace Pagination { + +template +struct ListDirectoryBucketsPaginationTraits { + using RequestType = Model::ListDirectoryBucketsRequest; + using ResultType = Model::ListDirectoryBucketsResult; + using OutcomeType = Model::ListDirectoryBucketsOutcome; + using ClientType = Client; + + static OutcomeType Invoke(Client& client, const RequestType& request) { return client.ListDirectoryBuckets(request); } + + static bool HasMoreResults(const ResultType& result) { return !result.GetContinuationToken().empty(); } + + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetContinuationToken(result.GetContinuationToken()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListObjectsV2PaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListObjectsV2PaginationTraits.h new file mode 100644 index 000000000000..e06a96f64371 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListObjectsV2PaginationTraits.h @@ -0,0 +1,34 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws { +namespace S3 { +namespace Pagination { + +template +struct ListObjectsV2PaginationTraits { + using RequestType = Model::ListObjectsV2Request; + using ResultType = Model::ListObjectsV2Result; + using OutcomeType = Model::ListObjectsV2Outcome; + using ClientType = Client; + + static OutcomeType Invoke(Client& client, const RequestType& request) { return client.ListObjectsV2(request); } + + static bool HasMoreResults(const ResultType& result) { return !result.GetNextContinuationToken().empty(); } + + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetContinuationToken(result.GetNextContinuationToken()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListPartsPaginationTraits.h b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListPartsPaginationTraits.h new file mode 100644 index 000000000000..2bda2cfde5d9 --- /dev/null +++ b/generated/src/aws-cpp-sdk-s3/include/aws/s3/model/ListPartsPaginationTraits.h @@ -0,0 +1,34 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once +#include +#include +#include +#include + +namespace Aws { +namespace S3 { +namespace Pagination { + +template +struct ListPartsPaginationTraits { + using RequestType = Model::ListPartsRequest; + using ResultType = Model::ListPartsResult; + using OutcomeType = Model::ListPartsOutcome; + using ClientType = Client; + + static OutcomeType Invoke(Client& client, const RequestType& request) { return client.ListParts(request); } + + static bool HasMoreResults(const ResultType& result) { return result.GetNextPartNumberMarker() != 0; } + + static void SetNextRequest(const ResultType& result, RequestType& request) { + request.SetPartNumberMarker(result.GetNextPartNumberMarker()); + } +}; + +} // namespace Pagination +} // namespace S3 +} // namespace Aws diff --git a/generated/tests/dynamodb-gen-tests/DynamoDBPaginationCompilationTests.cpp b/generated/tests/dynamodb-gen-tests/DynamoDBPaginationCompilationTests.cpp new file mode 100644 index 000000000000..2cf383ab5857 --- /dev/null +++ b/generated/tests/dynamodb-gen-tests/DynamoDBPaginationCompilationTests.cpp @@ -0,0 +1,28 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +// Header compilation test for DynamoDB pagination headers +// This test ensures all generated pagination headers compile successfully + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class DynamoDBPaginationCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite +{ +}; + +TEST_F(DynamoDBPaginationCompilationTest, DynamoDBPaginationHeadersCompile) +{ + // Test passes if compilation succeeds + SUCCEED(); +} diff --git a/generated/tests/ec2-gen-tests/EC2PaginationCompilationTests.cpp b/generated/tests/ec2-gen-tests/EC2PaginationCompilationTests.cpp new file mode 100644 index 000000000000..c89ea3be4780 --- /dev/null +++ b/generated/tests/ec2-gen-tests/EC2PaginationCompilationTests.cpp @@ -0,0 +1,186 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +// Header compilation test for EC2 pagination headers +// This test ensures all generated pagination headers compile successfully + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class EC2PaginationCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite +{ +}; + +TEST_F(EC2PaginationCompilationTest, EC2PaginationHeadersCompile) +{ + // Test passes if compilation succeeds + SUCCEED(); +} diff --git a/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp b/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp new file mode 100644 index 000000000000..d35f2a6692e6 --- /dev/null +++ b/generated/tests/s3-gen-tests/S3PaginationCompilationTests.cpp @@ -0,0 +1,26 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +// Header compilation test for S3 pagination headers +// This test ensures all generated pagination headers compile successfully + +#include +#include +#include +#include +#include +#include + +#include + +class S3PaginationCompilationTest : public Aws::Testing::AwsCppSdkGTestSuite +{ +}; + +TEST_F(S3PaginationCompilationTest, S3PaginationHeadersCompile) +{ + // Test passes if compilation succeeds + SUCCEED(); +} diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/pagination/Paginator.h b/src/aws-cpp-sdk-core/include/aws/core/utils/pagination/Paginator.h index fe671c26d7af..c188d418a391 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/pagination/Paginator.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/pagination/Paginator.h @@ -17,7 +17,7 @@ namespace Pagination { template -class PagePaginator +class Paginator { private: struct EndSentinel {}; @@ -25,7 +25,7 @@ class PagePaginator using OutcomeType = typename OperationTraits::OutcomeType; using ResultType = typename OperationTraits::ResultType; - class PageIterator + class Iterator { public: using iterator_category = std::input_iterator_tag; @@ -34,15 +34,15 @@ class PagePaginator using pointer = const OutcomeType*; using reference = const OutcomeType&; - PageIterator(std::shared_ptr client, const OperationRequest& firstReq) + Iterator(ServiceClient& client, const OperationRequest& firstReq) : m_client(client), m_request(firstReq), - m_currentOutcome{OperationTraits::Invoke(*m_client, m_request)} + m_currentOutcome{OperationTraits::Invoke(m_client, m_request)} {} const OutcomeType& operator*() const { return m_currentOutcome; } - PageIterator& operator++() + Iterator& operator++() { if (m_atEnd) return *this; @@ -59,40 +59,40 @@ class PagePaginator } OperationTraits::SetNextRequest(m_currentOutcome.GetResult(), m_request); - FetchPage(); + Fetch(); return *this; } - friend bool operator==(const PageIterator& lhs, const EndSentinel&) { + friend bool operator==(const Iterator& lhs, const EndSentinel&) { return lhs.m_atEnd; } - friend bool operator!=(const PageIterator& lhs, const EndSentinel& rhs) { + friend bool operator!=(const Iterator& lhs, const EndSentinel& rhs) { return !(lhs == rhs); } private: - void FetchPage() + void Fetch() { - m_currentOutcome = OperationTraits::Invoke(*m_client, m_request); + m_currentOutcome = OperationTraits::Invoke(m_client, m_request); } - std::shared_ptr m_client; + ServiceClient& m_client; OperationRequest m_request{}; OutcomeType m_currentOutcome{}; bool m_atEnd{false}; }; - PagePaginator(std::shared_ptr client, const OperationRequest& firstReq) + Paginator(ServiceClient& client, const OperationRequest& firstReq) : m_client(client), m_firstRequest(firstReq) {} - PageIterator begin() const { return PageIterator(m_client, m_firstRequest); } + Iterator begin() const { return Iterator(m_client, m_firstRequest); } EndSentinel end() const { return EndSentinel{}; } private: - std::shared_ptr m_client; + ServiceClient& m_client; OperationRequest m_firstRequest{}; }; diff --git a/tests/aws-cpp-sdk-core-tests/utils/pagination/PaginatorTest.cpp b/tests/aws-cpp-sdk-core-tests/utils/pagination/PaginatorTest.cpp index 7bf1a3591ff7..b94e0ae47400 100644 --- a/tests/aws-cpp-sdk-core-tests/utils/pagination/PaginatorTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/utils/pagination/PaginatorTest.cpp @@ -129,8 +129,7 @@ class PaginatorTest : public Aws::Testing::AwsCppSdkGTestSuite TEST_F(PaginatorTest, TestIteratesThroughAllPages) { - auto clientPtr = std::make_shared(client); - PagePaginator paginator(clientPtr, request); + Paginator paginator(client, request); Aws::Vector allItems; int pageCount = 0; @@ -160,8 +159,7 @@ TEST_F(PaginatorTest, TestIteratesThroughAllPages) TEST_F(PaginatorTest, TestHandlesErrorGracefully) { client.SetShouldFail(true); - auto clientPtr = std::make_shared(client); - PagePaginator paginator(clientPtr, request); + Paginator paginator(client, request); auto it = paginator.begin(); ASSERT_TRUE(it != paginator.end()); @@ -177,8 +175,7 @@ TEST_F(PaginatorTest, TestHandlesErrorGracefully) TEST_F(PaginatorTest, TestEmptyResultSet) { client.SetData({}); - auto clientPtr = std::make_shared(client); - PagePaginator paginator(clientPtr, request); + Paginator paginator(client, request); auto it = paginator.begin(); ASSERT_TRUE(it != paginator.end()); @@ -194,8 +191,7 @@ TEST_F(PaginatorTest, TestEmptyResultSet) TEST_F(PaginatorTest, TestBeginEndIteratorComparison) { - auto clientPtr = std::make_shared(client); - PagePaginator paginator(clientPtr, request); + Paginator paginator(client, request); auto begin = paginator.begin(); auto end = paginator.end(); @@ -213,8 +209,7 @@ TEST_F(PaginatorTest, TestBeginEndIteratorComparison) TEST_F(PaginatorTest, TestHandlesErrorOnSecondPage) { client.SetFailOnPage(1); // Fail on second page (0-indexed) - auto clientPtr = std::make_shared(client); - PagePaginator paginator(clientPtr, request); + Paginator paginator(client, request); auto it = paginator.begin(); diff --git a/tests/aws-cpp-sdk-dynamodb-integration-tests/ScanPaginationIntegrationTest.cpp b/tests/aws-cpp-sdk-dynamodb-integration-tests/ScanPaginationIntegrationTest.cpp new file mode 100644 index 000000000000..2b16f455b4ee --- /dev/null +++ b/tests/aws-cpp-sdk-dynamodb-integration-tests/ScanPaginationIntegrationTest.cpp @@ -0,0 +1,123 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Aws; +using namespace Aws::DynamoDB; +using namespace Aws::DynamoDB::Model; + +namespace { + const size_t ITEM_COUNT = 19; + const Aws::String HASH_KEY_NAME = "id"; + const Aws::String ATTRIBUTE_FOO = "attribute_foo"; +} + +class ScanPaginationTest : public Aws::Testing::AwsCppSdkGTestSuite { +protected: + DynamoDBClient dynamoClient; + Aws::String tableName; + + void SetUp() override { + tableName = CalculateTableName("scan-paginator-test"); + + CreateTable(); + PutTestData(); + } + + void TearDown() override { + DeleteTableRequest deleteRequest; + deleteRequest.SetTableName(tableName); + dynamoClient.DeleteTable(deleteRequest); + } + + Aws::String CalculateTableName(const Aws::String& tablePrefix) { + return Aws::Testing::GetAwsResourcePrefix() + tablePrefix; + } + + void CreateTable() { + CreateTableRequest createRequest; + createRequest.SetTableName(tableName); + + KeySchemaElement keySchema; + keySchema.SetKeyType(KeyType::HASH); + keySchema.SetAttributeName(HASH_KEY_NAME); + createRequest.AddKeySchema(keySchema); + + AttributeDefinition attrDef; + attrDef.SetAttributeType(ScalarAttributeType::N); + attrDef.SetAttributeName(HASH_KEY_NAME); + createRequest.AddAttributeDefinitions(attrDef); + + ProvisionedThroughput throughput; + throughput.SetReadCapacityUnits(5); + throughput.SetWriteCapacityUnits(5); + createRequest.SetProvisionedThroughput(throughput); + + auto outcome = dynamoClient.CreateTable(createRequest); + AWS_ASSERT_SUCCESS(outcome); + + WaitUntilActive(tableName); + } + + DescribeTableResult WaitUntilActive(const Aws::String& tableNameParam) { + DescribeTableRequest describeTableRequest; + describeTableRequest.SetTableName(tableNameParam); + + DescribeTableOutcome outcome = dynamoClient.DescribeTable(describeTableRequest); + while (outcome.IsSuccess() && outcome.GetResult().GetTable().GetTableStatus() != TableStatus::ACTIVE) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + outcome = dynamoClient.DescribeTable(describeTableRequest); + } + + return outcome.GetResult(); + } + + void PutTestData() { + for (size_t i = 0; i < ITEM_COUNT; ++i) { + PutItemRequest putRequest; + putRequest.SetTableName(tableName); + + Aws::Map item; + item[HASH_KEY_NAME] = AttributeValue().SetN(Aws::Utils::StringUtils::to_string(i)); + item[ATTRIBUTE_FOO] = AttributeValue().SetN(Aws::Utils::StringUtils::to_string(i * 2)); + + putRequest.SetItem(item); + auto outcome = dynamoClient.PutItem(putRequest); + ASSERT_TRUE(outcome.IsSuccess()); + } + } +}; + +TEST_F(ScanPaginationTest, TestPaginationTraits) { + ScanRequest request; + request.SetTableName(tableName); + request.SetLimit(1); // Force pagination + + size_t pageCount = 0; + auto paginator = dynamoClient.ScanPaginator(request); + + for (auto pageIter = paginator.begin(); pageIter != paginator.end(); ++pageIter) { + const auto& outcome = *pageIter; + AWS_ASSERT_SUCCESS(outcome); + pageCount++; + } + + EXPECT_GT(pageCount, 1u); // Should have multiple pages with Limit=1 +} \ No newline at end of file diff --git a/tests/aws-cpp-sdk-ec2-integration-tests/EC2PaginationIntegrationTest.cpp b/tests/aws-cpp-sdk-ec2-integration-tests/EC2PaginationIntegrationTest.cpp new file mode 100644 index 000000000000..70864ae7f618 --- /dev/null +++ b/tests/aws-cpp-sdk-ec2-integration-tests/EC2PaginationIntegrationTest.cpp @@ -0,0 +1,39 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include + +using namespace Aws; +using namespace Aws::EC2; +using namespace Aws::EC2::Model; + +class EC2PaginationTest : public Aws::Testing::AwsCppSdkGTestSuite { +protected: + EC2Client ec2Client; +}; + +TEST_F(EC2PaginationTest, TestPaginationTraits) { + DescribeSpotPriceHistoryRequest request; + request.AddProductDescriptions("Linux/UNIX (Amazon VPC)"); + request.AddInstanceTypes(InstanceType::t1_micro); + request.SetStartTime(Aws::Utils::DateTime::Now() - std::chrono::hours(1)); + request.SetMaxResults(1); // Force pagination + + size_t pageCount = 0; + auto paginator = ec2Client.DescribeSpotPriceHistoryPaginator(request); + + for (auto pageIter = paginator.begin(); pageIter != paginator.end(); ++pageIter) { + const auto& outcome = *pageIter; + AWS_ASSERT_SUCCESS(outcome); + pageCount++; + } + + EXPECT_GE(pageCount, 1u); // Should have at least one page +} \ No newline at end of file diff --git a/tests/aws-cpp-sdk-s3-integration-tests/ListObjectsV2PaginationIntegrationTest.cpp b/tests/aws-cpp-sdk-s3-integration-tests/ListObjectsV2PaginationIntegrationTest.cpp new file mode 100644 index 000000000000..9443dfe3778f --- /dev/null +++ b/tests/aws-cpp-sdk-s3-integration-tests/ListObjectsV2PaginationIntegrationTest.cpp @@ -0,0 +1,142 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Aws; +using namespace Aws::S3; +using namespace Aws::S3::Model; + +namespace { + static const char* ALLOCATION_TAG = "ListObjectsV2PaginationTest"; + static const char* TEST_BUCKET_TAG = "IntegrationTestResource"; + static const int TIMEOUT_MAX = 5; + const size_t OBJECT_COUNT = 3; + + Aws::String CalculateBucketName(const Aws::String& bucketPrefix) { + return Aws::Testing::GetAwsResourcePrefix() + bucketPrefix; + } +} + +class ListObjectsV2PaginationTest : public Aws::Testing::AwsCppSdkGTestSuite { +protected: + S3Client Client; + Aws::String bucketName; + + void SetUp() override { + Aws::Client::ClientConfiguration config; + config.region = Aws::Region::US_EAST_1; + Client = S3Client(config); + + bucketName = CalculateBucketName("listobjectsv2paginationtest"); + + // Create bucket + CreateBucketRequest createRequest; + createRequest.SetBucket(bucketName); + createRequest.SetACL(BucketCannedACL::private_); + auto createOutcome = Client.CreateBucket(createRequest); + AWS_ASSERT_SUCCESS(createOutcome); + + ASSERT_TRUE(WaitForBucketToPropagate()); + TagTestBucket(); + + // Create a few test objects + for (size_t i = 1; i <= OBJECT_COUNT; ++i) { + CreateTestObject("key-" + Aws::Utils::StringUtils::to_string(i)); + } + } + + void TearDown() override { + if (!bucketName.empty()) { + EmptyBucket(); + + DeleteBucketRequest deleteRequest; + deleteRequest.SetBucket(bucketName); + Client.DeleteBucket(deleteRequest); + } + } + + bool WaitForBucketToPropagate() { + unsigned timeoutCount = 0; + while (timeoutCount++ < TIMEOUT_MAX) { + ListObjectsV2Request listRequest; + listRequest.SetBucket(bucketName); + auto listOutcome = Client.ListObjectsV2(listRequest); + if (listOutcome.IsSuccess()) { + return true; + } + std::this_thread::sleep_for(std::chrono::seconds(2)); + } + return false; + } + + void TagTestBucket() { + PutBucketTaggingRequest taggingRequest; + taggingRequest.SetBucket(bucketName); + Tag tag; + tag.SetKey(TEST_BUCKET_TAG); + tag.SetValue(TEST_BUCKET_TAG); + Tagging tagging; + tagging.AddTagSet(tag); + taggingRequest.SetTagging(tagging); + Client.PutBucketTagging(taggingRequest); + } + + void CreateTestObject(const Aws::String& key) { + PutObjectRequest putRequest; + putRequest.SetBucket(bucketName); + putRequest.SetKey(key); + + auto data = Aws::MakeShared(ALLOCATION_TAG); + *data << "Test data for " << key; + putRequest.SetBody(data); + + Client.PutObject(putRequest); + } + + void EmptyBucket() { + ListObjectsV2Request listRequest; + listRequest.SetBucket(bucketName); + auto listOutcome = Client.ListObjectsV2(listRequest); + + if (listOutcome.IsSuccess()) { + for (const auto& object : listOutcome.GetResult().GetContents()) { + DeleteObjectRequest deleteRequest; + deleteRequest.SetBucket(bucketName); + deleteRequest.SetKey(object.GetKey()); + Client.DeleteObject(deleteRequest); + } + } + } +}; + +TEST_F(ListObjectsV2PaginationTest, TestPaginationTraits) { + ListObjectsV2Request request; + request.SetBucket(bucketName); + request.SetMaxKeys(1); // Force pagination + + size_t pageCount = 0; + auto paginator = Client.ListObjectsV2Paginator(request); + + for (auto pageIter = paginator.begin(); pageIter != paginator.end(); ++pageIter) { + const auto& outcome = *pageIter; + AWS_ASSERT_SUCCESS(outcome); + pageCount++; + } + + EXPECT_GT(pageCount, 1u); // Should have multiple pages with MaxKeys=1 +} \ No newline at end of file diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/JsonServiceClientHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/JsonServiceClientHeader.vm index afc2578fc11e..be9467bd20e7 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/JsonServiceClientHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/JsonServiceClientHeader.vm @@ -11,6 +11,7 @@ \#include \#include \#include +\#include namespace ${rootNamespace} { @@ -25,7 +26,7 @@ namespace ${serviceNamespace} #if($serviceModel.enableVirtualOperations) #set($finalClass = "") #end - class ${CppViewHelper.computeExportValue($metadata.classNamePrefix)} ${className}${finalClass} : public Aws::Client::AWSJsonClient, public Aws::Client::ClientWithAsyncTemplateMethods<${className}> + class ${CppViewHelper.computeExportValue($metadata.classNamePrefix)} ${className}${finalClass} : public Aws::Client::AWSJsonClient, public Aws::Client::ClientWithAsyncTemplateMethods<${className}>, public ${metadata.classNamePrefix}PaginationBase<${className}> { public: typedef Aws::Client::AWSJsonClient BASECLASS; diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm index fe7385b9efa5..4d2b11c58ad7 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm @@ -22,6 +22,7 @@ \#include \#include \#include +\#include #if($serviceNamespace == "S3Crt") \#include \#include @@ -94,7 +95,7 @@ namespace ${rootNamespace} #if($serviceModel.enableVirtualOperations) #set($finalClass = "") #end - class ${CppViewHelper.computeExportValue($metadata.classNamePrefix)} ${className}${finalClass} : public Aws::Client::AWSXMLClient, public Aws::Client::ClientWithAsyncTemplateMethods<${className}> + class ${CppViewHelper.computeExportValue($metadata.classNamePrefix)} ${className}${finalClass} : public Aws::Client::AWSXMLClient, public Aws::Client::ClientWithAsyncTemplateMethods<${className}>, public ${metadata.classNamePrefix}PaginationBase<${className}> { public: typedef Aws::Client::AWSXMLClient BASECLASS; diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/smithy/SmithyClientHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/smithy/SmithyClientHeader.vm index da58148a0909..37932a673031 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/smithy/SmithyClientHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/smithy/SmithyClientHeader.vm @@ -17,6 +17,7 @@ \#include \#include \#include +\#include \#include #if($serviceModel.hasBearerAuth()) \#include @@ -56,7 +57,8 @@ namespace ${serviceNamespace} ${metadata.classNamePrefix}EndpointProviderBase, smithy::client::$serializer, smithy::client::$serializerOutcome, - Aws::Client::${metadata.classNamePrefix}ErrorMarshaller> + Aws::Client::${metadata.classNamePrefix}ErrorMarshaller>, + public ${metadata.classNamePrefix}PaginationBase<${className}> { public: static const char* GetServiceName(); diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlServiceClientHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlServiceClientHeader.vm index 9112307c5039..e63b11a64561 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlServiceClientHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/xml/XmlServiceClientHeader.vm @@ -12,6 +12,7 @@ \#include \#include \#include +\#include namespace ${rootNamespace} { @@ -26,7 +27,7 @@ namespace ${serviceNamespace} #if($serviceModel.enableVirtualOperations) #set($finalClass = "") #end - class ${CppViewHelper.computeExportValue($metadata.classNamePrefix)} ${className}$finalClass : public Aws::Client::AWSXMLClient, public Aws::Client::ClientWithAsyncTemplateMethods<${className}> + class ${CppViewHelper.computeExportValue($metadata.classNamePrefix)} ${className}$finalClass : public Aws::Client::AWSXMLClient, public Aws::Client::ClientWithAsyncTemplateMethods<${className}>, public ${metadata.classNamePrefix}PaginationBase<${className}> { public: typedef Aws::Client::AWSXMLClient BASECLASS; diff --git a/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json b/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json index d4865618ff4f..1ff0190e0acb 100644 --- a/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json +++ b/tools/code-generation/smithy/codegen/smithy2c2j_service_map.json @@ -60,7 +60,7 @@ "lex-model-building-service":"lex-models", "cloudwatch-logs":"logs", "directory-service":"ds", - "elasticsearch-service ":"es", + "elasticsearch-service":"es", "importexport":"importexport", "sdb":"sdb", "transcribe-streaming":"transcribestreaming" diff --git a/tools/code-generation/smithy/cpp-codegen/build.gradle.kts b/tools/code-generation/smithy/cpp-codegen/build.gradle.kts new file mode 100644 index 000000000000..2ad7ae705566 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/build.gradle.kts @@ -0,0 +1,94 @@ +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.ServiceShape +import software.amazon.smithy.aws.traits.ServiceTrait +import org.gradle.api.logging.Logging +import kotlin.streams.toList + +val logger = Logging.getLogger("MyLogger") + +plugins { + id("java-library") + id("software.amazon.smithy.gradle.smithy-base").version("1.3.0") +} + +repositories { + mavenLocal() + mavenCentral() +} + +buildscript { + dependencies { + classpath("software.amazon.smithy:smithy-model:1.62.0") + classpath("software.amazon.smithy:smithy-aws-traits:1.62.0") + classpath("software.amazon.smithy:smithy-rules-engine:1.62.0") + } +} + +dependencies { + implementation(project(":smithy-cpp-codegen")) + implementation("software.amazon.smithy:smithy-aws-traits:1.62.0") + implementation("software.amazon.smithy:smithy-aws-cloudformation-traits:1.62.0") + implementation("software.amazon.smithy:smithy-aws-iam-traits:1.62.0") + implementation("software.amazon.smithy:smithy-aws-endpoints:1.62.0") + implementation("software.amazon.smithy:smithy-smoke-test-traits:1.62.0") + implementation("software.amazon.smithy:smithy-aws-smoke-test-model:1.62.0") + implementation("software.amazon.smithy:smithy-waiters:1.62.0") +} + +tasks.register("generate-smithy-build") { + doLast { + val projectionsBuilder = Node.objectNodeBuilder() + val models = project.file("../api-descriptions") + val filteredServices: String = project.findProperty("servicesFilter")?.toString() ?: "" + val filteredServiceList = filteredServices.split(",").map { it.trim() }.filter { it.isNotEmpty() } + val c2jMapStr: String = project.findProperty("c2jMap")?.toString() ?: "" + + fileTree(models).filter { it.isFile }.files.forEach eachFile@{ file -> + val model = Model.assembler() + .addImport(file.absolutePath) + .assemble().result.get() + val services = model.shapes(ServiceShape::class.java).sorted().toList() + if (services.size != 1) return@eachFile + + val service = services[0] + val serviceTrait = service.getTrait(ServiceTrait::class.java).get() + val sdkId = serviceTrait.sdkId.replace(" ", "-").replace("_", "-").lowercase() + + if (filteredServiceList.isNotEmpty() && sdkId !in filteredServiceList) return@eachFile + + val projectionContents = Node.objectNodeBuilder() + .withMember("imports", Node.fromStrings("${models.absolutePath}${File.separator}${file.name}")) + .withMember("plugins", Node.objectNode() + .withMember("smithy-cpp-codegen", Node.objectNodeBuilder() + .withMember("c2jMap", Node.from(c2jMapStr)) + .build())) + .build() + + projectionsBuilder.withMember("$sdkId.${service.version.lowercase()}", projectionContents) + } + + // Legacy services without full Smithy models - generate mock projections for base classes + val legacyServices = mapOf("importexport" to "ImportExport", "sdb" to "SimpleDB", "s3-crt" to "S3Crt") + legacyServices.forEach { (c2jName, serviceName) -> + if (filteredServiceList.isEmpty() || c2jName in filteredServiceList) { + val mockProjectionContents = Node.objectNodeBuilder() + .withMember("plugins", Node.objectNode() + .withMember("smithy-cpp-codegen", Node.objectNodeBuilder() + .withMember("c2jMap", Node.from(c2jMapStr)) + .build())) + .build() + projectionsBuilder.withMember("$c2jName.mock", mockProjectionContents) + } + } + + val outputDirectoryArg = project.findProperty("outputDirectory")?.toString() ?: "output" + file("smithy-build.json").writeText(Node.prettyPrintJson(Node.objectNodeBuilder() + .withMember("version", "1.0") + .withMember("projections", projectionsBuilder.build()) + .withMember("outputDirectory", outputDirectoryArg) + .build())) + } +} + +tasks["build"].dependsOn(tasks["generate-smithy-build"]) diff --git a/tools/code-generation/smithy/cpp-codegen/gradle.properties b/tools/code-generation/smithy/cpp-codegen/gradle.properties new file mode 100644 index 000000000000..5167bec761d5 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/gradle.properties @@ -0,0 +1,11 @@ +org.gradle.jvmargs=-Xmx6g + +# Set the socket timeout to 5 minutes +systemProp.org.gradle.internal.http.connectionTimeout=120000 +systemProp.org.gradle.internal.http.socketTimeout=120000 + +# the number of retries (initial included) (default 3) +systemProp.org.gradle.internal.repository.max.tentative=10 + +# the initial time before retrying, in milliseconds (default 125) +systemProp.org.gradle.internal.repository.initial.backoff=500 diff --git a/tools/code-generation/smithy/cpp-codegen/gradle/wrapper/gradle-wrapper.jar b/tools/code-generation/smithy/cpp-codegen/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000000..a4b76b9530d6 Binary files /dev/null and b/tools/code-generation/smithy/cpp-codegen/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tools/code-generation/smithy/cpp-codegen/gradle/wrapper/gradle-wrapper.properties b/tools/code-generation/smithy/cpp-codegen/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..4e7678544a65 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=file:///opt/gradle-install.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/tools/code-generation/smithy/cpp-codegen/gradlew b/tools/code-generation/smithy/cpp-codegen/gradlew new file mode 100755 index 000000000000..f5feea6d6b11 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/tools/code-generation/smithy/cpp-codegen/gradlew.bat b/tools/code-generation/smithy/cpp-codegen/gradlew.bat new file mode 100644 index 000000000000..9b42019c7915 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tools/code-generation/smithy/cpp-codegen/settings.gradle.kts b/tools/code-generation/smithy/cpp-codegen/settings.gradle.kts new file mode 100644 index 000000000000..b77ed8dbf8f3 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/settings.gradle.kts @@ -0,0 +1,10 @@ +rootProject.name = "smithy-cpp-codegen" + +include("smithy-cpp-codegen") + +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } +} diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/build.gradle.kts b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/build.gradle.kts new file mode 100644 index 000000000000..759dc9e8be00 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + `java-library` +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("software.amazon.smithy:smithy-model:1.62.0") + implementation("software.amazon.smithy:smithy-codegen-core:1.62.0") + implementation("software.amazon.smithy:smithy-aws-traits:1.62.0") + implementation("software.amazon.smithy:smithy-waiters:1.62.0") + implementation("software.amazon.smithy:smithy-rules-engine:1.62.0") + implementation("software.amazon.smithy:smithy-aws-endpoints:1.62.0") + implementation("software.amazon.smithy:smithy-aws-iam-traits:1.62.0") +} diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseCompilationTestGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseCompilationTestGenerator.java new file mode 100644 index 000000000000..d5f9eb0163da --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseCompilationTestGenerator.java @@ -0,0 +1,88 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.shapes.ServiceShape; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import java.util.List; +import java.util.Map; + +public abstract class BaseCompilationTestGenerator { + protected final PluginContext context; + protected final ServiceShape service; + protected final List operations; + protected final Map serviceMap; + private final CppWriterDelegator writerDelegator; + + public BaseCompilationTestGenerator(PluginContext context, ServiceShape service, List operations, Map serviceMap) { + this.context = context; + this.service = service; + this.operations = operations; + this.serviceMap = serviceMap; + this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + } + + protected abstract String getTestType(); + protected abstract String getTestDescription(); + protected abstract void writeTestSpecificIncludes(CppWriter writer); + + public final void run() { + generateCompilationTest(); + writerDelegator.flushWriters(); + } + + private void generateCompilationTest() { + String serviceName = ServiceNameUtil.getServiceName(service); + String c2jServiceName = ServiceNameUtil.getSmithyServiceName(service, serviceMap); + + writerDelegator.useFileWriter( + "generated/tests/" + c2jServiceName + "-gen-tests/" + serviceName + getTestType() + "CompilationTests.cpp", + this::render + ); + } + + private void render(CppWriter writer) { + String serviceName = ServiceNameUtil.getServiceName(service); + + writeHeader(writer, serviceName); + writeTestSpecificIncludes(writer); + writeCommonIncludes(writer); + writeTestClass(writer, serviceName); + writeTestMethod(writer, serviceName); + } + + private void writeHeader(CppWriter writer, String serviceName) { + writer.write("/**") + .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") + .write(" * SPDX-License-Identifier: Apache-2.0.") + .write(" */") + .write("") + .write("// Header compilation test for " + serviceName + " " + getTestType().toLowerCase() + " headers") + .write("// " + getTestDescription()) + .write(""); + } + + private void writeCommonIncludes(CppWriter writer) { + writer.write("") + .write("#include ") + .write(""); + } + + private void writeTestClass(CppWriter writer, String serviceName) { + writer.openBlock("class " + serviceName + getTestType() + "CompilationTest : public Aws::Testing::AwsCppSdkGTestSuite\n{", "};", () -> { + // Empty class body + }); + writer.write(""); + } + + private void writeTestMethod(CppWriter writer, String serviceName) { + writer.openBlock("TEST_F(" + serviceName + getTestType() + "CompilationTest, " + serviceName + getTestType() + "HeadersCompile)\n{", "}", () -> { + writer.write(" // Test passes if compilation succeeds") + .write(" SUCCEED();"); + }); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseHeaderGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseHeaderGenerator.java new file mode 100644 index 000000000000..ebbb6a235c78 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseHeaderGenerator.java @@ -0,0 +1,58 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.shapes.ServiceShape; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import java.util.List; +import java.util.Map; + +public abstract class BaseHeaderGenerator { + protected final ServiceShape service; + protected final List operations; + protected final Map serviceMap; + protected final String smithyServiceName; + + public BaseHeaderGenerator(ServiceShape service, List operations, Map serviceMap) { + this.service = service; + this.operations = operations; + this.serviceMap = serviceMap; + this.smithyServiceName = ServiceNameUtil.getSmithyServiceName(service, serviceMap); + } + + protected abstract void writeSpecificIncludes(CppWriter writer, String serviceName, String smithyServiceName); + protected abstract void writeSpecificContent(CppWriter writer, String serviceName); + + public final void render(CppWriter writer) { + String serviceName = ServiceNameUtil.getServiceName(service); + + writeHeader(writer); + writeSpecificIncludes(writer, serviceName, smithyServiceName); + writeNamespaceOpen(writer, serviceName); + writeSpecificContent(writer, serviceName); + writeNamespaceClose(writer, serviceName); + } + + private void writeHeader(CppWriter writer) { + writer.write("/**") + .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") + .write(" * SPDX-License-Identifier: Apache-2.0.") + .write(" */") + .write("") + .write("#pragma once"); + } + + private void writeNamespaceOpen(CppWriter writer, String serviceName) { + writer.writeNamespaceOpen("Aws"); + writer.writeNamespaceOpen(serviceName); + writer.write(""); + } + + private void writeNamespaceClose(CppWriter writer, String serviceName) { + writer.writeNamespaceClose(serviceName); + writer.writeNamespaceClose("Aws"); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseTraitsGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseTraitsGenerator.java new file mode 100644 index 000000000000..7dfc99f9ae69 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/BaseTraitsGenerator.java @@ -0,0 +1,56 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.shapes.ServiceShape; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import java.util.List; +import java.util.Map; + +public abstract class BaseTraitsGenerator { + protected final PluginContext context; + protected final ServiceShape service; + protected final List operations; + protected final String smithyServiceName; + private final CppWriterDelegator writerDelegator; + + public BaseTraitsGenerator(PluginContext context, ServiceShape service, List operations, String smithyServiceName) { + this.context = context; + this.service = service; + this.operations = operations; + this.smithyServiceName = smithyServiceName; + this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + } + + protected abstract String getFileNameForOperation(T operationData); + protected abstract void generateOperationContent(CppWriter writer, T operationData, String serviceName); + + public final void write() { + String serviceName = ServiceNameUtil.getServiceName(service); + + for (T operationData : operations) { + String fileName = getFileNameForOperation(operationData); + + writerDelegator.useFileWriter(fileName, writer -> { + writeHeader(writer); + generateOperationContent(writer, operationData, serviceName); + }); + } + + writerDelegator.flushWriters(); + } + + private void writeHeader(CppWriter writer) { + writer.write("/**") + .write(" * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.") + .write(" * SPDX-License-Identifier: Apache-2.0.") + .write(" */") + .write("") + .write("#pragma once"); + } +} diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java new file mode 100644 index 000000000000..8c26688ae5f0 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppImportContainer.java @@ -0,0 +1,36 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.codegen.core.ImportContainer; +import software.amazon.smithy.codegen.core.Symbol; +import java.util.HashSet; +import java.util.Set; + +/** + * CppImportContainer tracks symbols used in code generation. + * For C++, we handle includes manually via writeInclude method. + */ +public class CppImportContainer implements ImportContainer { + private final Set imports = new HashSet<>(); + + @Override + public void importSymbol(Symbol symbol, String alias) { + // Track the symbol's namespace for potential future use + if (symbol.getNamespace() != null && !symbol.getNamespace().isEmpty()) { + imports.add(symbol.getNamespace()); + } + } + + public Set getImports() { + return imports; + } + + @Override + public String toString() { + // Return empty string since we handle includes manually + return ""; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java new file mode 100644 index 000000000000..d3729c6223e6 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriter.java @@ -0,0 +1,45 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.codegen.core.SymbolWriter; + +public class CppWriter extends SymbolWriter { + + public CppWriter() { + super(new CppImportContainer()); + + // Add custom formatter for symbols + putFormatter('T', (arg, indent) -> { + if (!(arg instanceof software.amazon.smithy.codegen.core.Symbol symbol)) { + throw new software.amazon.smithy.codegen.core.CodegenException("Expected a symbol but got " + arg); + } + + // Record our symbol so we can generate appropriate includes later if needed + getImportContainer().importSymbol(symbol, null); + + // For C++, use namespace::name syntax (e.g. Aws::S3::Model::ListBucketsRequest) + if (symbol.getNamespace() != null && !symbol.getNamespace().isEmpty()) { + return symbol.getNamespace() + "::" + symbol.getName(); + } + return symbol.getName(); + }); + } + + public CppWriter writeInclude(String header) { + write("#include <$L>", header); + return this; + } + + public CppWriter writeNamespaceOpen(String namespace) { + openBlock("namespace $L\n{", namespace); + return this; + } + + public CppWriter writeNamespaceClose(String namespace) { + closeBlock("} // namespace $L", namespace); + return this; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java new file mode 100644 index 000000000000..9d42e8b70900 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/CppWriterDelegator.java @@ -0,0 +1,37 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.FileManifest; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class CppWriterDelegator { + private final FileManifest fileManifest; + private final Map writers = new HashMap<>(); + + public CppWriterDelegator(FileManifest fileManifest) { + this.fileManifest = fileManifest; + } + + public void useFileWriter(String filename, Consumer writerConsumer) { + CppWriter writer = writers.computeIfAbsent(filename, k -> new CppWriter()); + writerConsumer.accept(writer); + } + + public void flushWriters() { + writers.forEach((filename, writer) -> { + try { + Path outputPath = fileManifest.getBaseDir().resolve(filename); + java.nio.file.Files.createDirectories(outputPath.getParent()); + java.nio.file.Files.writeString(outputPath, writer.toString()); + } catch (Exception e) { + throw new RuntimeException("Failed to write file: " + filename, e); + } + }); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java new file mode 100644 index 000000000000..6d76901b0242 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/FeatureParser.java @@ -0,0 +1,67 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.node.Node; +import software.amazon.smithy.model.node.ObjectNode; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.aws.traits.ServiceTrait; +import java.util.*; +import java.util.function.Consumer; + +public class FeatureParser { + private final PluginContext context; + private final ServiceShape service; + private final List operations; + private final CppWriterDelegator writerDelegator; + private final Map serviceMap; + private final String featureName; + + public FeatureParser(PluginContext context, ServiceShape service, List operations, String featureName) { + this.context = context; + this.service = service; + this.operations = operations; + this.featureName = featureName; + this.writerDelegator = new CppWriterDelegator(context.getFileManifest()); + + // Initialize service map + this.serviceMap = new HashMap<>(); + ObjectNode settings = context.getSettings(); + if (settings.containsMember("c2jMap")) { + Node c2jMapNode = settings.expectMember("c2jMap"); + if (c2jMapNode.isStringNode()) { + String jsonStr = c2jMapNode.expectStringNode().getValue(); + ObjectNode mapNode = Node.parseJsonWithComments(jsonStr).expectObjectNode(); + mapNode.getMembers().forEach((key, value) -> { + this.serviceMap.put(key.getValue(), value.expectStringNode().getValue()); + }); + } + } + } + + public void run(Consumer> generationLogic) { + generationLogic.accept(this); + writerDelegator.flushWriters(); + } + + public void generateClientHeader(String fileName, Consumer generator) { + String serviceName = ServiceNameUtil.getServiceName(service); + String smithyServiceName = ServiceNameUtil.getSmithyServiceName(service, serviceMap); + + writerDelegator.useFileWriter( + "include/aws/" + smithyServiceName + "/" + fileName, + generator + ); + } + + public PluginContext getContext() { return context; } + public ServiceShape getService() { return service; } + public List getOperations() { return operations; } + public String getFeatureName() { return featureName; } + public Map getServiceMap() { return serviceMap; } + public String getServiceName() { return ServiceNameUtil.getServiceName(service); } + public String getSmithyServiceName() { return ServiceNameUtil.getSmithyServiceName(service, serviceMap); } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/OperationData.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/OperationData.java new file mode 100644 index 000000000000..7d4c3bec8897 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/OperationData.java @@ -0,0 +1,32 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.Trait; + +public class OperationData { + private final OperationShape operation; + private final T trait; + private final ServiceShape service; + + public OperationData(OperationShape operation, T trait, ServiceShape service) { + this.operation = operation; + this.trait = trait; + this.service = service; + } + + public OperationShape getOperation() { + return operation; + } + + public T getTrait() { + return trait; + } + + public ServiceShape getService() { + return service; + } +} diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java new file mode 100644 index 000000000000..d97626c7cfca --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ServiceNameUtil.java @@ -0,0 +1,141 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.aws.traits.ServiceTrait; +import software.amazon.smithy.model.traits.TitleTrait; +import java.util.Map; +import java.util.Set; + +public final class ServiceNameUtil { + + // Legacy service IDs that need special handling to match what the legacy c2j code generator produced + // This logic is copied from C2jModelToGeneratorModelTransformer.convertMetadata() method + // Hardcoded mappings for legacy services where C2J used fullServiceName for file naming + // Maps serviceId (lowercase, sanitized) to the sanitized fullServiceName from C2J models + private static final Map LEGACY_FULL_SERVICE_NAME_MAP = Map.ofEntries( + Map.entry("amp", "PrometheusService"), + Map.entry("appintegrations", "AppIntegrationsService"), + Map.entry("billingconductor", "BillingConductor"), + Map.entry("chatbot", "chatbot"), + Map.entry("clouddirectory", "CloudDirectory"), + Map.entry("cloudfront", "CloudFront"), + Map.entry("cloudsearch", "CloudSearch"), + Map.entry("cloudsearchdomain", "CloudSearchDomain"), + Map.entry("codeartifact", "CodeArtifact"), + Map.entry("codestarnotifications", "CodeStarNotifications"), + Map.entry("configservice", "ConfigService"), + Map.entry("databrew", "GlueDataBrew"), + Map.entry("deadline", "deadline"), + Map.entry("elasticache", "ElastiCache"), + Map.entry("emrcontainers", "EMRContainers"), + Map.entry("marketplaceentitlementservice", "MarketplaceEntitlementService"), + Map.entry("cloudwatchevents", "CloudWatchEvents"), + Map.entry("evidently", "CloudWatchEvidently"), + Map.entry("forecast", "ForecastService"), + Map.entry("forecastquery", "ForecastQueryService"), + Map.entry("grafana", "ManagedGrafana"), + Map.entry("importexport", "ImportExport"), + Map.entry("inspector", "Inspector"), + Map.entry("lambda", "Lambda"), + Map.entry("location", "LocationService"), + Map.entry("m2", "MainframeModernization"), + Map.entry("migrationhubstrategy", "MigrationHubStrategyRecommendations"), + Map.entry("mq", "MQ"), + Map.entry("opensearch", "OpenSearchService"), + Map.entry("rbin", "RecycleBin"), + Map.entry("rdsdata", "RDSDataService"), + Map.entry("redshiftdata", "RedshiftDataAPIService"), + Map.entry("resiliencehub", "ResilienceHub"), + Map.entry("rum", "CloudWatchRUM"), + Map.entry("lexruntimeservice", "LexRuntimeService"), + Map.entry("lexruntimev2", "LexRuntimeV2"), + Map.entry("lexmodelsv2", "LexModelsV2"), + Map.entry("sagemakerruntime", "SageMakerRuntime"), + Map.entry("sagemakera2iruntime", "AugmentedAIRuntime"), + Map.entry("sagemakeredge", "SagemakerEdgeManager"), + Map.entry("schemas", "Schemas"), + Map.entry("simpledb", "SimpleDB"), + Map.entry("dynamodbstreams", "DynamoDBStreams"), + Map.entry("transcribe", "TranscribeService"), + Map.entry("transcribestreaming", "TranscribeStreamingService"), + Map.entry("transfer", "TransferFamily"), + Map.entry("wisdom", "ConnectWisdomService"), + Map.entry("marketplaceagreement", "MarketplaceAgreementService") + ); + + // TODO: Remove hardcoded mappings once Smithy models include serviceAbbreviation trait + // Smithy sdkId matches C2J serviceId, but C2J prioritizes serviceAbbreviation (which Smithy lacks). + // 18 of 66 services where C2J abbrev != serviceId require these mappings to match C2J output. + // Hardcoded mappings where Smithy sdkId doesn't match C2J serviceAbbreviation + private static final Map SMITHY_TO_C2J_NAMESPACE = Map.ofEntries( + Map.entry("b2bi", "B2BI"), + Map.entry("cloudcontrol", "CloudControlApi"), + Map.entry("ecrpublic", "ECRPublic"), + Map.entry("evs", "EVS"), + Map.entry("finspacedata", "FinSpaceData"), + Map.entry("fis", "FIS"), + Map.entry("identitystore", "IdentityStore"), + Map.entry("inspectorscan", "inspectorscan"), + Map.entry("iotdeviceadvisor", "IoTDeviceAdvisor"), + Map.entry("ivs", "IVS"), + Map.entry("ivsrealtime", "ivsrealtime"), + Map.entry("kinesisvideosignaling", "KinesisVideoSignalingChannels"), + Map.entry("marketplaceagreement", "AgreementService"), + Map.entry("mediapackagev2", "mediapackagev2"), + Map.entry("savingsplans", "SavingsPlans"), + Map.entry("servicecatalogappregistry", "AppRegistry"), + Map.entry("sesv2", "SESV2"), + Map.entry("synthetics", "Synthetics"), + Map.entry("transfer", "Transfer") + ); + + public static String getServiceName(ServiceShape service) { + String serviceId = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()); + + String sanitized = sanitizeServiceAbbreviation(serviceId); + + // Check serviceAbbreviation mappings first (highest priority in C2J) + String mapped = SMITHY_TO_C2J_NAMESPACE.get(sanitized.toLowerCase()); + if (mapped != null) { + return mapped; + } + + // Check legacy fullServiceName mappings (fallback when serviceAbbreviation missing) + String legacyName = LEGACY_FULL_SERVICE_NAME_MAP.get(sanitized.toLowerCase()); + if (legacyName != null) { + return legacyName; + } + + return sanitized; + } + + public static String getServiceNameUpperCamel(ServiceShape service) { + return capitalize(getServiceName(service)); + } + + public static String capitalize(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + + // Match C2jModelToGeneratorModelTransformer.sanitizeServiceAbbreviation() exactly + private static String sanitizeServiceAbbreviation(String serviceAbbreviation) { + return serviceAbbreviation.replace(" ", "").replace("-", "").replace("_", "").replace("Amazon", "").replace("AWS", "").replace("/", ""); + } + + public static String getSmithyServiceName(ServiceShape service, Map serviceMap) { + String sdkId = service.getTrait(ServiceTrait.class) + .map(ServiceTrait::getSdkId) + .orElse(service.getId().getName()) + .trim() + .toLowerCase() + .replace(" ", "-"); + + return serviceMap != null ? serviceMap.getOrDefault(sdkId, sdkId) : sdkId; + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java new file mode 100644 index 000000000000..1cdfd4c3cd26 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/ShapeUtil.java @@ -0,0 +1,267 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators; + +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.Trait; +import java.util.*; + +public class ShapeUtil { + + private static final List RESULT_SUFFIXES = List.of("Result", "SdkResult", "CppSdkResult"); + + /** + * Backward compatibility map for operations that must use "SdkResult" suffix. + * + * Background: + * The C2J code generator's renameShape() tries suffixes in order: Result -> SdkResult -> CppSdkResult. + * It picks the first suffix that doesn't collide with existing shape names in the model. + * + * Problem: + * Some legacy C2J models (e.g., medialive-2017-10-14.normal.json) defined shapes like: + * - ListNodesResult (a domain shape) + * - ListNodesResponse (the operation output shape) + * + * When the C2J generator tried to create the SDK wrapper for ListNodes operation: + * 1. Tried "ListNodesResult" -> COLLISION with existing shape + * 2. Fell back to "ListNodesSdkResult" -> No collision, used this + * + * The Smithy models are cleaner and don't have these collisions, but we must preserve + * the "SdkResult" suffix for these operations to maintain backward compatibility with + * existing C2J-generated code. + * + * Map format: service-name -> Set of operation names requiring "SdkResult" + * + * Example: + * medialive C2J model had both ListNodesResult and ListNodesResponse shapes, + * forcing ListNodesSdkResult. Smithy model only has ListNodesResponse, but we + * preserve SdkResult to avoid breaking changes. + * + */ + private static final Map> LEGACY_SDK_RESULT_OPERATIONS = Map.of( + "medialive", Set.of("ListChannelPlacementGroups", "ListClusters", "ListNetworks", "ListNodes") + ); + + /** + * Legacy operation name version suffixes required for backwards compatibility. + * The legacy C2J code generator appended API version suffixes to operation names for certain services. + * This maintains compatibility with existing generated code that depends on these versioned method names. + * + * CloudFront: Uses "2020_05_31" suffix (the API version when C++ SDK generation was standardized) + * - Example: "ListDistributions" becomes "ListDistributions2020_05_31" + * - Required because existing C++ code expects these versioned method names + * - CloudFront has had multiple API versions, and the C2J generator historically used version suffixes + */ + private static final Map OPERATION_VERSION_SUFFIXES = Map.of( + "cloudfront", "2020_05_31" + ); + + /** + * C2J/Smithy model mismatches: tokens that are integers in C2J but strings in Smithy. + * + * Background: + * Some services have tokens that were modeled as integers in C2J but changed to + * strings in Smithy models. The C2J-generated code uses int types, so traits must + * use `!= 0` checks instead of `.empty()` checks. + * + * Map format: service-name -> Map of operation-name -> token-name + * + * Example: + * S3's ListParts operation has NextPartNumberMarker as integer in C2J but string in Smithy. + */ + private static final Map>> NUMERIC_TOKEN_OVERRIDES = Map.of( + "s3", Map.of("ListParts", Set.of("NextPartNumberMarker")), + "s3-crt", Map.of("ListParts", Set.of("NextPartNumberMarker")) + ); + + /** + * Gets the operation method name with legacy version suffix if required. + * + * Some services require version suffixes appended to operation names for backwards compatibility + * with the legacy C2J code generator. This ensures existing C++ code continues to work with + * the expected method names. + * + * @param opName The base operation name from the Smithy model + * @param smithyServiceName The Smithy service name (e.g., "cloudfront") + * @return The operation name with version suffix if needed (e.g., "ListDistributions2020_05_31") + */ + public static String getOperationMethodName(String opName, String smithyServiceName) { + String versionSuffix = OPERATION_VERSION_SUFFIXES.get(smithyServiceName); + return versionSuffix != null ? opName + versionSuffix : opName; + } + + /** + * Checks if a token is numeric (integer or long type). + * First checks for C2J/Smithy model mismatch overrides, then inspects the actual shape type. + * + * @param model The Smithy model + * @param op The operation shape + * @param smithyServiceName The Smithy service name + * @param wrapperMember The wrapper member name (null if token is at top level) + * @param tokenName The token name + * @return true if the token is numeric + */ + public static boolean isNumericToken(Model model, OperationShape op, String smithyServiceName, String wrapperMember, String tokenName) { + // Check for C2J/Smithy model mismatch overrides first + Map> serviceOverrides = NUMERIC_TOKEN_OVERRIDES.get(smithyServiceName); + if (serviceOverrides != null) { + Set tokens = serviceOverrides.get(op.getId().getName()); + if (tokens != null && tokens.contains(tokenName)) { + return true; + } + } + + Optional tokenShape = getOutputStructure(model, op) + .flatMap(out -> { + if (wrapperMember == null) { + return out.getMember(tokenName); + } + return out.getMember(wrapperMember) + .flatMap(m -> model.getShape(m.getTarget())) + .flatMap(t -> t.asStructureShape()) + .flatMap(w -> w.getMember(tokenName)); + }) + .flatMap(member -> model.getShape(member.getTarget())); + + return tokenShape.map(ts -> ts instanceof IntegerShape || ts instanceof LongShape).orElse(false); + } + + /** + * Determines the result suffix for an operation based on protocol and naming conflicts. + * Replicates C2J renameShape conflict detection logic. + * + * C2J logic: + * 1. Try "Result" first + * 2. If collision exists (direct name match OR Get/Set accessor conflict), try "SdkResult" + * 3. If still collision, try "CppSdkResult" + * + * @param model The Smithy model + * @param operation The operation shape + * @param smithyServiceName The Smithy service name + * @return "Response" for EC2 protocol, "SdkResult" if naming conflict exists, otherwise "Result" + */ + public static String getResultSuffix(Model model, OperationShape operation, String smithyServiceName) { + // EC2 protocol services rename all Result shapes to Response + if ("ec2".equals(smithyServiceName)) { + return "Response"; + } + + // C2J backward compatibility: preserve SdkResult for operations that had collisions in legacy models + Set legacyOps = LEGACY_SDK_RESULT_OPERATIONS.get(smithyServiceName); + if (legacyOps != null && legacyOps.contains(operation.getId().getName())) { + return "SdkResult"; + } + + String baseName = operation.getId().getName(); + Set allShapeNames = new HashSet<>(); + model.shapes().forEach(s -> allShapeNames.add(s.getId().getName())); + + // Output shape name (used for legacy early-accept behavior) + String outputShapeName = operation.getOutput().isPresent() + ? operation.getOutputShape().getName() + : null; + + // For closer parity with the legacy Get/Set collision rule + Set outputMemberNames = getOutputStructure(model, operation) + .map(struct -> new HashSet<>(struct.getAllMembers().keySet())) + .orElse(new HashSet<>()); + + for (String suffix : RESULT_SUFFIXES) { + String candidate = baseName + suffix; + + // Legacy parity: if the operation's output shape is already named exactly candidate, + // then legacy renameShape() would return immediately (no conflict handling). + if (outputShapeName != null && candidate.equals(outputShapeName)) { + return suffix; + } + + // Legacy: otherwise, direct collision with any existing shape name is a conflict + if (allShapeNames.contains(candidate)) { + continue; + } + + // Closer parity with legacy intent (member-gated Get/Set collisions) + if (!outputMemberNames.isEmpty()) { + boolean hasCollision = false; + for (String shapeName : allShapeNames) { + if (outputMemberNames.contains(shapeName) && + (candidate.equals("Get" + shapeName) || candidate.equals("Set" + shapeName))) { + hasCollision = true; + break; + } + } + if (hasCollision) { + continue; + } + } + + return suffix; + } + + // Legacy would throw if no suffix is available; returning CppSdkResult silently can hide bugs + throw new IllegalStateException("Unhandled result shape name conflict for operation: " + baseName); + } + + /** + * Gets the output structure shape for an operation, or null if not present or not a structure. + */ + private static Optional getOutputStructure(Model model, OperationShape op) { + return op.getOutput() + .flatMap(outputId -> model.getShape(outputId)) + .flatMap(shape -> shape.asStructureShape()); + } + + /** + * Finds the wrapper member in an operation's output that contains the specified token. + * Used for token resolution when tokens are nested in wrapper structures. + * + * @param model The Smithy model + * @param op The operation shape + * @param tokenName The token name to find + * @return The wrapper member name, or null if not found + */ + public static String findWrapperMemberContainingToken(Model model, OperationShape op, String tokenName) { + return getOutputStructure(model, op) + .flatMap(outputShape -> + outputShape.getAllMembers().entrySet().stream() + .filter(entry -> model.getShape(entry.getValue().getTarget()) + .flatMap(t -> t.asStructureShape()) + .map(s -> s.getAllMembers().containsKey(tokenName)) + .orElse(false)) + .map(Map.Entry::getKey) + .findFirst() + ) + .orElse(null); + } + + /** + * Checks if an operation's output has a top-level member with the specified name. + * + * @param model The Smithy model + * @param op The operation shape + * @param memberName The member name to check + * @return true if the member exists at the top level + */ + public static boolean hasTopLevelMember(Model model, OperationShape op, String memberName) { + return getOutputStructure(model, op) + .map(outputShape -> outputShape.getAllMembers().containsKey(memberName)) + .orElse(false); + } + + /** + * Gets service-level token when operation-level traits are missing. + * + * @param service The service shape + * @param traitClass The trait class to look for + * @param tokenExtractor Function to extract the token from the trait + * @return The service-level token, or null if not defined + */ + public static String getServiceLevelToken(ServiceShape service, Class traitClass, java.util.function.Function> tokenExtractor) { + return service.getTrait(traitClass) + .map(trait -> tokenExtractor.apply(trait).orElse(null)) + .orElse(null); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationBaseGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationBaseGenerator.java new file mode 100644 index 000000000000..2982510f9015 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationBaseGenerator.java @@ -0,0 +1,75 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.pagination; + +import com.amazonaws.util.awsclientsmithygenerator.generators.BaseHeaderGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import com.amazonaws.util.awsclientsmithygenerator.generators.ShapeUtil; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.traits.PaginatedTrait; +import java.util.List; +import java.util.Map; + +public class PaginationBaseGenerator extends BaseHeaderGenerator> { + + public PaginationBaseGenerator(ServiceShape service, List> paginatedOps, Map serviceMap) { + super(service, paginatedOps, serviceMap); + } + + @Override + protected void writeSpecificIncludes(CppWriter writer, String serviceName, String smithyServiceName) { + writer.write(""); + writer.writeInclude("aws/core/utils/pagination/Paginator.h"); + + // Include paginator headers + for (OperationData data : operations) { + String opName = data.getOperation().getId().getName(); + writer.writeInclude("aws/" + smithyServiceName + "/model/" + opName + "PaginationTraits.h"); + } + + writer.writeInclude("memory"); + writer.write(""); + } + + @Override + protected void writeSpecificContent(CppWriter writer, String serviceName) { + String classPrefix = ServiceNameUtil.getServiceNameUpperCamel(service); + + // Forward declare the client + writer.write("class " + classPrefix + "Client;"); + writer.write(""); + + // CRTP base class + writer.write("template"); + writer.openBlock("class " + classPrefix + "PaginationBase {\npublic:", "};", () -> { + if (operations.isEmpty()) { + // Empty base class for services without pagination + // Required because legacy C2J generator always includes PaginationBase inheritance in client headers + writer.write("virtual ~" + classPrefix + "PaginationBase() = default;"); + } else { + // Generate paginator methods + for (OperationData data : operations) { + String opName = data.getOperation().getId().getName(); + String methodName = ShapeUtil.getOperationMethodName(opName, smithyServiceName); + + writer.write(""); + writer.write("/**") + .write(" * Create a paginator for " + opName + " operation") + .write(" */"); + + writer.write("Aws::Utils::Pagination::Paginator>") + .write(opName + "Paginator(const Model::" + methodName + "Request& request)"); + + writer.openBlock("{", "}", () -> { + writer.write("return Aws::Utils::Pagination::Paginator>{") + .write(" *static_cast(this), request};"); + }); + } + } + }); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationClientHeaderGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationClientHeaderGenerator.java new file mode 100644 index 000000000000..a18c63b1e284 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationClientHeaderGenerator.java @@ -0,0 +1,48 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.pagination; + +import com.amazonaws.util.awsclientsmithygenerator.generators.BaseHeaderGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import com.amazonaws.util.awsclientsmithygenerator.generators.ShapeUtil; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.traits.PaginatedTrait; +import java.util.List; +import java.util.Map; + +public class PaginationClientHeaderGenerator extends BaseHeaderGenerator> { + + public PaginationClientHeaderGenerator(ServiceShape service, List> paginatedOps, Map serviceMap) { + super(service, paginatedOps, serviceMap); + } + + @Override + protected void writeSpecificIncludes(CppWriter writer, String serviceName, String smithyServiceName) { + String classPrefix = ServiceNameUtil.getServiceNameUpperCamel(service); + writer.writeInclude("aws/" + smithyServiceName + "/" + classPrefix + "Client.h"); + writer.writeInclude("aws/core/utils/pagination/Paginator.h"); + + for (OperationData data : operations) { + String opName = data.getOperation().getId().getName(); + writer.writeInclude("aws/" + smithyServiceName + "/model/" + opName + "PaginationTraits.h"); + } + writer.write(""); + } + + @Override + protected void writeSpecificContent(CppWriter writer, String serviceName) { + String classPrefix = ServiceNameUtil.getServiceNameUpperCamel(service); + + for (OperationData data : operations) { + String opName = data.getOperation().getId().getName(); + String methodName = ShapeUtil.getOperationMethodName(opName, smithyServiceName); + writer.write("using $LPaginator = Aws::Utils::Pagination::Paginator<$LClient, Model::$LRequest, Pagination::$LPaginationTraits<$LClient>>;", + opName, classPrefix, methodName, opName, classPrefix); + } + writer.write(""); + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationCodegenPlugin.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationCodegenPlugin.java new file mode 100644 index 000000000000..e3d5cfdbffeb --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationCodegenPlugin.java @@ -0,0 +1,88 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.pagination; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.build.SmithyBuildPlugin; +import software.amazon.smithy.model.knowledge.TopDownIndex; +import software.amazon.smithy.model.traits.PaginatedTrait; +import software.amazon.smithy.model.traits.DeprecatedTrait; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.shapes.OperationShape; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.FeatureParser; +import com.amazonaws.util.awsclientsmithygenerator.generators.pagination.PaginationTraitsGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.pagination.PaginationClientHeaderGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.pagination.PaginationCompilationTestGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.pagination.PaginationBaseGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.pagination.PaginationEmptyHeaderGenerator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class PaginationCodegenPlugin implements SmithyBuildPlugin { + + @Override + public String getName() { + return "smithy-cpp-codegen"; + } + + @Override + public void execute(PluginContext context) { + var model = context.getModel(); + + // Handle legacy services without Smithy models + if (context.getProjectionName().endsWith(".mock")) { + PaginationEmptyHeaderGenerator.generate(context); + return; + } + + for (ServiceShape service : model.getServiceShapes()) { + // Find paginated operations using TopDownIndex, excluding deprecated operations + List> paginatedOps = TopDownIndex.of(model).getContainedOperations(service).stream() + .filter(op -> op.hasTrait(PaginatedTrait.class)) + .filter(op -> !op.hasTrait(DeprecatedTrait.class)) + .map(op -> new OperationData<>(op, op.expectTrait(PaginatedTrait.class), service)) + .collect(Collectors.toList()); + + // Always generate base class, even if empty + // Required because legacy C2J generator always includes PaginationBase inheritance in client headers + FeatureParser> parser = new FeatureParser<>(context, service, paginatedOps, "Pagination"); + parser.run(featureParser -> { + String serviceName = ServiceNameUtil.getServiceNameUpperCamel(featureParser.getService()); + + // Generate CRTP pagination (always, even if empty) + featureParser.generateClientHeader( + serviceName + "PaginationBase.h", + writer -> new PaginationBaseGenerator(featureParser.getService(), featureParser.getOperations(), featureParser.getServiceMap()).render(writer) + ); + + if (!paginatedOps.isEmpty()) { + // Generate client pagination header + featureParser.generateClientHeader( + serviceName + "ClientPagination.h", + writer -> new PaginationClientHeaderGenerator(featureParser.getService(), featureParser.getOperations(), featureParser.getServiceMap()).render(writer) + ); + + // Generate pagination traits headers + PaginationTraitsGenerator traitsGenerator = new PaginationTraitsGenerator( + featureParser.getContext(), + featureParser.getService(), + featureParser.getOperations(), + featureParser.getSmithyServiceName() + ); + traitsGenerator.write(); + } + }); + + if (!paginatedOps.isEmpty()) { + // Generate compilation test + PaginationCompilationTestGenerator testGenerator = new PaginationCompilationTestGenerator(context, service, paginatedOps, parser.getServiceMap()); + testGenerator.run(); + } + } + } +} diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationCompilationTestGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationCompilationTestGenerator.java new file mode 100644 index 000000000000..5956ba37b350 --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationCompilationTestGenerator.java @@ -0,0 +1,69 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.pagination; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.shapes.*; +import com.amazonaws.util.awsclientsmithygenerator.generators.BaseCompilationTestGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import software.amazon.smithy.model.traits.PaginatedTrait; +import java.util.*; + +public class PaginationCompilationTestGenerator extends BaseCompilationTestGenerator> { + + public PaginationCompilationTestGenerator(PluginContext context, ServiceShape service, List> allPaginatedOps, Map serviceMap) { + super(context, service, allPaginatedOps, serviceMap); + } + + @Override + protected String getTestType() { + return "Pagination"; + } + + @Override + protected String getTestDescription() { + return "This test ensures all generated pagination headers compile successfully"; + } + + @Override + protected void writeTestSpecificIncludes(CppWriter writer) { + Set clientHeaders = new HashSet<>(); + Set traitHeaders = new HashSet<>(); + Set serviceHeaders = new HashSet<>(); + + for (OperationData paginationData : operations) { + ServiceShape service = paginationData.getService(); + String serviceName = ServiceNameUtil.getServiceNameUpperCamel(service); + String smithyServiceName = ServiceNameUtil.getSmithyServiceName(service, serviceMap); + + // Collect unique client headers + clientHeaders.add("aws/" + smithyServiceName + "/" + serviceName + "ClientPagination.h"); + + // Collect unique service headers + serviceHeaders.add("aws/" + smithyServiceName + "/" + serviceName + "PaginationBase.h"); + + // Collect unique trait headers + String operationName = paginationData.getOperation().getId().getName(); + traitHeaders.add("aws/" + smithyServiceName + "/model/" + operationName + "PaginationTraits.h"); + } + + // Write unique client headers + for (String header : clientHeaders) { + writer.writeInclude(header); + } + + // Write unique service headers + for (String header : serviceHeaders) { + writer.writeInclude(header); + } + + // Write unique trait headers + for (String header : traitHeaders) { + writer.writeInclude(header); + } + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationEmptyHeaderGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationEmptyHeaderGenerator.java new file mode 100644 index 000000000000..ab66e86e1e8a --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationEmptyHeaderGenerator.java @@ -0,0 +1,54 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.pagination; + +import software.amazon.smithy.build.PluginContext; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriterDelegator; +import java.util.Map; +import java.util.HashMap; + +/** + * Generates empty pagination base headers for legacy services that don't have Smithy pagination models. + * TODO: Remove this workaround once all services have proper Smithy models. + */ +public class PaginationEmptyHeaderGenerator { + // Legacy services without Smithy models that still need pagination base headers + // TODO: Remove once all services have proper Smithy models + private static final Map LEGACY_SERVICES = Map.of( + "importexport", "ImportExport", + "sdb", "SimpleDB", + "s3-crt", "S3Crt" + ); + + public static void generate(PluginContext context) { + String projectionName = context.getProjectionName(); + if (!projectionName.endsWith(".mock")) { + return; + } + + String c2jName = projectionName.replace(".mock", ""); + String serviceName = LEGACY_SERVICES.get(c2jName); + + if (serviceName == null) { + return; + } + + CppWriterDelegator writers = new CppWriterDelegator(context.getFileManifest()); + + writers.useFileWriter("include/aws/" + c2jName + "/" + serviceName + "PaginationBase.h", writer -> { + writer.write("#pragma once"); + writer.write(""); + writer.writeNamespaceOpen("Aws"); + writer.writeNamespaceOpen(serviceName); + writer.openBlock("template \nclass $LPaginationBase {\n public:", "};", serviceName, () -> { + writer.write(" virtual ~$LPaginationBase() = default;", serviceName); + }); + writer.writeNamespaceClose(serviceName); + writer.writeNamespaceClose("Aws"); + }); + + writers.flushWriters(); + } +} diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationTraitsGenerator.java b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationTraitsGenerator.java new file mode 100644 index 000000000000..45ab4b2d003f --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/java/com/amazonaws/util/awsclientsmithygenerator/generators/pagination/PaginationTraitsGenerator.java @@ -0,0 +1,213 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +package com.amazonaws.util.awsclientsmithygenerator.generators.pagination; + +import software.amazon.smithy.build.PluginContext; +import software.amazon.smithy.model.shapes.*; +import software.amazon.smithy.model.traits.PaginatedTrait; +import com.amazonaws.util.awsclientsmithygenerator.generators.BaseTraitsGenerator; +import com.amazonaws.util.awsclientsmithygenerator.generators.OperationData; +import com.amazonaws.util.awsclientsmithygenerator.generators.CppWriter; +import com.amazonaws.util.awsclientsmithygenerator.generators.ServiceNameUtil; +import com.amazonaws.util.awsclientsmithygenerator.generators.ShapeUtil; +import java.util.List; +import java.util.Optional; + +public class PaginationTraitsGenerator extends BaseTraitsGenerator> { + + public PaginationTraitsGenerator(PluginContext context, ServiceShape service, List> paginatedOps, String smithyServiceName) { + super(context, service, paginatedOps, smithyServiceName); + } + + @Override + protected String getFileNameForOperation(OperationData operationData) { + return "include/aws/" + smithyServiceName + "/model/" + operationData.getOperation().getId().getName() + "PaginationTraits.h"; + } + + @Override + protected void generateOperationContent(CppWriter writer, OperationData data, String serviceName) { + OperationShape op = data.getOperation(); + PaginatedTrait trait = data.getTrait(); + String opName = op.getId().getName(); + + // Includes - detect suffix like C2J renameShape logic + String resultSuffix = ShapeUtil.getResultSuffix(context.getModel(), op, smithyServiceName); + String capitalizedServiceName = ServiceNameUtil.getServiceNameUpperCamel(service); + String requestFileName = ShapeUtil.getOperationMethodName(opName, smithyServiceName) + "Request"; + String resultFileName = ShapeUtil.getOperationMethodName(opName, smithyServiceName) + resultSuffix; + String methodName = ShapeUtil.getOperationMethodName(opName, smithyServiceName); + + writer.writeInclude("aws/" + smithyServiceName + "/" + capitalizedServiceName + "_EXPORTS.h") + .writeInclude("aws/" + smithyServiceName + "/model/" + requestFileName + ".h") + .writeInclude("aws/" + smithyServiceName + "/model/" + resultFileName + ".h") + .writeInclude("aws/" + smithyServiceName + "/" + capitalizedServiceName + "ServiceClientModel.h") + .write(""); + + // Namespaces + writer.writeNamespaceOpen("Aws") + .writeNamespaceOpen(serviceName) + .writeNamespaceOpen("Pagination") + .write(""); + + // Struct definition + writer.openBlock("template\nstruct " + opName + "PaginationTraits\n{", "};", () -> { + // Use detected suffix to match C2J renameShape logic + writer.write(" using RequestType = Model::$LRequest;", methodName) + .write(" using ResultType = Model::$L$L;", methodName, resultSuffix) + .write(" using OutcomeType = Model::$LOutcome;", methodName) + .write(" using ClientType = Client;") + .write(""); + + // Invoke method - no template needed since struct is templated + writer.openBlock(" static OutcomeType Invoke(Client& client, const RequestType& request)\n {", " }", () -> { + writer.write(" return client.$L(request);", methodName); + }); + + writer.write(""); + + // HasMoreResults method + writer.openBlock(" static bool HasMoreResults(const ResultType& result)\n {", " }", () -> { + generateHasMoreResultsLogic(writer, trait, op); + }); + + writer.write(""); + + // SetNextRequest method + writer.openBlock(" static void SetNextRequest(const ResultType& result, RequestType& request)\n {", " }", () -> { + generateSetNextRequestLogic(writer, trait, op); + }); + }); + + writer.write(""); + writer.writeNamespaceClose("Pagination"); + writer.writeNamespaceClose(serviceName); + writer.writeNamespaceClose("Aws"); + } + + private interface TokenResolver { + boolean canResolve(String token, OperationShape op); + void writeLogic(CppWriter writer, String token, OperationShape op); + } + + private void generateHasMoreResultsLogic(CppWriter writer, PaginatedTrait trait, OperationShape op) { + Optional outToken = trait.getOutputToken() + .or(() -> Optional.ofNullable(ShapeUtil.getServiceLevelToken(service, + software.amazon.smithy.model.traits.PaginatedTrait.class, t -> t.getOutputToken()))); + + if (outToken.isEmpty()) { + writer.write(" return result.GetIsTruncated();"); + return; + } + + String token = outToken.get(); + List resolvers = List.of( + // Pattern A: Nested token + new TokenResolver() { + public boolean canResolve(String token, OperationShape op) { return token.contains("."); } + public void writeLogic(CppWriter writer, String token, OperationShape op) { + String[] parts = token.split("\\.", 2); + boolean isNumeric = ShapeUtil.isNumericToken(context.getModel(), op, smithyServiceName, parts[0], parts[1]); + writeResultLogic(writer, Optional.of(ServiceNameUtil.capitalize(parts[0])), + ServiceNameUtil.capitalize(parts[1]), isNumeric); + } + }, + // Pattern B: Top-level token + new TokenResolver() { + public boolean canResolve(String token, OperationShape op) { + return ShapeUtil.hasTopLevelMember(context.getModel(), op, token); + } + public void writeLogic(CppWriter writer, String token, OperationShape op) { + boolean isNumeric = ShapeUtil.isNumericToken(context.getModel(), op, smithyServiceName, null, token); + writeResultLogic(writer, Optional.empty(), ServiceNameUtil.capitalize(token), isNumeric); + } + }, + // Pattern C: Wrapped token + new TokenResolver() { + public boolean canResolve(String token, OperationShape op) { + return Optional.ofNullable(ShapeUtil.findWrapperMemberContainingToken(context.getModel(), op, token)).isPresent(); + } + public void writeLogic(CppWriter writer, String token, OperationShape op) { + Optional.ofNullable(ShapeUtil.findWrapperMemberContainingToken(context.getModel(), op, token)) + .ifPresent(wrapper -> { + boolean isNumeric = ShapeUtil.isNumericToken(context.getModel(), op, smithyServiceName, wrapper, token); + writeResultLogic(writer, Optional.of(ServiceNameUtil.capitalize(wrapper)), + ServiceNameUtil.capitalize(token), isNumeric); + }); + } + } + ); + + for (TokenResolver resolver : resolvers) { + if (resolver.canResolve(token, op)) { + resolver.writeLogic(writer, token, op); + return; + } + } + + // Fallback + if (ShapeUtil.hasTopLevelMember(context.getModel(), op, "IsTruncated")) { + writer.write(" return result.GetIsTruncated();"); + } else { + writer.write(" return false;"); + } + } + + private void writeResultLogic(CppWriter writer, Optional wrapperMember, String tokenName, boolean isNumeric) { + String getter = wrapperMember.isPresent() ? "result.Get$L().Get$L()" : "result.Get$L()"; + String condition = isNumeric ? " != 0" : ".empty()"; + String prefix = isNumeric ? "" : "!"; + + if (wrapperMember.isPresent()) { + writer.write(" return " + prefix + getter + condition + ";", wrapperMember.get(), tokenName); + } else { + writer.write(" return " + prefix + getter + condition + ";", tokenName); + } + } + + private void generateSetNextRequestLogic(CppWriter writer, PaginatedTrait trait, OperationShape op) { + Optional inToken = Optional.empty(); + Optional outToken = Optional.empty(); + + if (trait.getInputToken().isPresent() && trait.getOutputToken().isPresent()) { + inToken = trait.getInputToken(); + outToken = trait.getOutputToken(); + } else { + // Fallback to service-level pagination configuration + Optional serviceLevelInputToken = Optional.ofNullable(ShapeUtil.getServiceLevelToken(service, software.amazon.smithy.model.traits.PaginatedTrait.class, t -> t.getInputToken())); + Optional serviceLevelOutputToken = Optional.ofNullable(ShapeUtil.getServiceLevelToken(service, software.amazon.smithy.model.traits.PaginatedTrait.class, t -> t.getOutputToken())); + if (serviceLevelInputToken.isPresent() && serviceLevelOutputToken.isPresent()) { + inToken = serviceLevelInputToken; + outToken = serviceLevelOutputToken; + } + } + + if (inToken.isPresent() && outToken.isPresent()) { + String inTokenValue = inToken.get(); + String outTokenValue = outToken.get(); + // Pattern A: Explicit nested token like "EngineDefaults.Marker" + if (outTokenValue.contains(".")) { + String[] parts = outTokenValue.split("\\.", 2); + String memberName = parts[0]; + String nestedTokenName = parts[1]; + writer.write(" request.Set$L(result.Get$L().Get$L());", ServiceNameUtil.capitalize(inTokenValue), ServiceNameUtil.capitalize(memberName), ServiceNameUtil.capitalize(nestedTokenName)); + } + // Pattern B: Check if token is on top-level output + else if (ShapeUtil.hasTopLevelMember(context.getModel(), op, outTokenValue)) { + writer.write(" request.Set$L(result.Get$L());", ServiceNameUtil.capitalize(inTokenValue), ServiceNameUtil.capitalize(outTokenValue)); + } + // Pattern C: Find wrapper member containing the token + else { + Optional.ofNullable(ShapeUtil.findWrapperMemberContainingToken(context.getModel(), op, outTokenValue)) + .ifPresentOrElse( + wrapperMember -> writer.write(" request.Set$L(result.Get$L().Get$L());", + ServiceNameUtil.capitalize(inTokenValue), ServiceNameUtil.capitalize(wrapperMember), ServiceNameUtil.capitalize(outTokenValue)), + () -> writer.write(" (void)result; (void)request; // Token not found") + ); + } + } else { + writer.write(" (void)result; (void)request; // Unused parameters"); + } + } +} \ No newline at end of file diff --git a/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin new file mode 100644 index 000000000000..d1ade5942e3d --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy-cpp-codegen/src/main/resources/META-INF/services/software.amazon.smithy.build.SmithyBuildPlugin @@ -0,0 +1 @@ +com.amazonaws.util.awsclientsmithygenerator.generators.pagination.PaginationCodegenPlugin diff --git a/tools/code-generation/smithy/cpp-codegen/smithy2c2j_service_map.json b/tools/code-generation/smithy/cpp-codegen/smithy2c2j_service_map.json new file mode 100644 index 000000000000..1ff0190e0acb --- /dev/null +++ b/tools/code-generation/smithy/cpp-codegen/smithy2c2j_service_map.json @@ -0,0 +1,68 @@ +{ + "api-gateway": "apigateway", + "application-auto-scaling": "application-autoscaling", + "app-mesh": "appmesh", + "auto-scaling": "autoscaling", + "auto-scaling-plans": "autoscaling-plans", + "cloudhsm-v2": "cloudhsmv2", + "cloudsearch-domain": "cloudsearchdomain", + "config-service": "config", + "cost-and-usage-report-service": "cur", + "data-pipeline": "datapipeline", + "device-farm": "devicefarm", + "direct-connect": "directconnect", + "dynamodb-streams": "dynamodbstreams", + "elastic-beanstalk": "elasticbeanstalk", + "elastic-load-balancing": "elasticloadbalancing", + "elastic-load-balancing-v2": "elasticloadbalancingv2", + "global-accelerator": "globalaccelerator", + "iot-1click-devices-service": "iot1click-devices", + "iot-1click-projects": "iot1click-projects", + "iot-data-plane": "iot-data", + "iot-events-data": "iotevents-data", + "iot-events": "iotevents", + "iot-jobs-data-plane": "iot-jobs-data", + "iot-wireless": "iotwireless", + "kinesis-analytics": "kinesisanalytics", + "kinesis-analytics-v2": "kinesisanalyticsv2", + "kinesis-video": "kinesisvideo", + "lex-models-v2": "lexv2-models", + "lex-runtime-service": "lex", + "lex-runtime-v2": "lexv2-runtime", + "machine-learning": "machinelearning", + "marketplace-commerce-analytics": "marketplacecommerceanalytics", + "marketplace-entitlement-service": "marketplace-entitlement", + "marketplace-metering": "meteringmarketplace", + "migration-hub": "AWSMigrationHub", + "mturk": "mturk-requester", + "pinpoint-sms-voice": "sms-voice", + "resource-groups-tagging-api": "resourcegroupstaggingapi", + "route-53-domains": "route53domains", + "route-53": "route53", + "s3-control": "s3control", + "sagemaker-runtime": "sagemaker-runtime", + "secrets-manager": "secretsmanager", + "serverlessapplicationrepository": "serverlessrepo", + "service-catalog-appregistry": "servicecatalog-appregistry", + "service-catalog": "servicecatalog", + "transfer": "awstransfer", + "cloudwatch": "monitoring", + "cloudwatch-events": "events", + "storage-gateway":"storagegateway", + "efs":"elasticfilesystem", + "emr":"elasticmapreduce", + "ses":"email", + "cognito-identity-provider":"cognito-idp", + "cost-explorer":"ce", + "application-discovery-service":"discovery", + "database-migration-service":"dms", + "sfn":"states", + "lex-model-building-service":"lex-models", + "cloudwatch-logs":"logs", + "directory-service":"ds", + "elasticsearch-service":"es", + "importexport":"importexport", + "sdb":"sdb", + "transcribe-streaming":"transcribestreaming" + } + \ No newline at end of file diff --git a/tools/scripts/codegen/legacy_c2j_cpp_gen.py b/tools/scripts/codegen/legacy_c2j_cpp_gen.py index 7e1df6be35f1..ee77eaa90c4b 100644 --- a/tools/scripts/codegen/legacy_c2j_cpp_gen.py +++ b/tools/scripts/codegen/legacy_c2j_cpp_gen.py @@ -16,7 +16,6 @@ from concurrent.futures import ProcessPoolExecutor, wait, FIRST_COMPLETED, ALL_COMPLETED from pathlib import Path -from codegen.format_util import format_directories from codegen.include_tests_util import IncludeTestsUtil from codegen.model_utils import ServiceModel @@ -149,12 +148,6 @@ def generate(self, executor: ProcessPoolExecutor, max_workers: int, args: dict) print(f"Code generation done, (re)generated {len(done)} packages.") # Including defaults and partitions - # Format generated client code - generated_clients = [service for service in self.c2j_models.keys()] - if generated_clients: - client_dirs = [f"{self.output_location}/src/aws-cpp-sdk-{client}" for client in generated_clients] - format_directories(client_dirs) - return 0 def _init_common_java_cli(self, diff --git a/tools/scripts/codegen/pagination_gen.py b/tools/scripts/codegen/pagination_gen.py new file mode 100644 index 000000000000..9bfb444c9baa --- /dev/null +++ b/tools/scripts/codegen/pagination_gen.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 + +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. + +""" +Wrapper for Smithy pagination generator +""" +import json +import os +import shutil +import subprocess +from typing import List + +SMITHY_GENERATOR_LOCATION = "tools/code-generation/smithy/cpp-codegen" +SMITHY_TO_C2J_MAP_FILE = "tools/code-generation/smithy/cpp-codegen/smithy2c2j_service_map.json" + + +class PaginationGen(object): + """Wrapper for Smithy pagination generator for C++ SDK""" + + def __init__(self, debug: bool, **kwargs): + self.debug = debug + with open(os.path.abspath(SMITHY_TO_C2J_MAP_FILE), 'r') as file: + self.smithy_c2j_data = json.load(file) + self.c2j_smithy_data = {value: key for key, value in self.smithy_c2j_data.items()} + + def generate(self, clients_to_build: set): + """Generate pagination APIs for SDK clients""" + smithy_services = [self.c2j_smithy_data.get(service, service) for service in clients_to_build] + if self.debug: + print(f"Generating pagination for: {','.join(smithy_services)}") + + if self._generate_pagination(smithy_services, json.dumps(self.smithy_c2j_data)): + target_dir = os.path.abspath("generated/src") + self._copy_cpp_codegen_contents( + os.path.abspath("tools/code-generation/smithy/cpp-codegen"), + "smithy-cpp-codegen", + target_dir + ) + return 0 + return -1 + + def _generate_pagination(self, smithy_services: List[str], smithy_c2j_data: str): + smithy_codegen_command = [ + "./gradlew", + "build", + "-PservicesFilter=" + ",".join(smithy_services), + "-Pc2jMap=" + smithy_c2j_data + ] + + try: + if self.debug: + print(f"RUNNING: {' '.join(smithy_codegen_command)}\nFROM: {SMITHY_GENERATOR_LOCATION}") + + process = subprocess.run( + smithy_codegen_command, + timeout=6*60, + check=True, + capture_output=True, + text=True, + cwd=SMITHY_GENERATOR_LOCATION + ) + print("Pagination codegen successful!") + if self.debug: + print(process.stdout) + print(f"Pagination generation done, (re)generated {len(smithy_services)} package(s).") + return True + + except subprocess.CalledProcessError as e: + print(f"Command failed: {e.returncode}\nError: {e.stderr}") + return False + + def _copy_cpp_codegen_contents(self, top_level_dir: str, plugin_name: str, target_dir: str): + # Walk output directory to find generated code + output_dir = os.path.join(top_level_dir, "output") + # TODO: Verify if this check is still needed after Smithy generator always creates output + if not os.path.exists(output_dir): + if self.debug: + print(f"No output directory found at '{output_dir}'") + return + + for root, dirs, files in os.walk(output_dir): + if plugin_name in dirs: + source_dir = os.path.join(root, plugin_name) + + # Extract service name from the projection directory + projection_dir = os.path.basename(os.path.dirname(source_dir)) + smithy_service_name = projection_dir.split('.')[0] # e.g., "api-gateway.2017-11-27" -> "api-gateway" + + # Map to c2j service name + c2j_service_name = self.smithy_c2j_data.get(smithy_service_name, smithy_service_name) + + service_target_dir = os.path.join(target_dir, f"aws-cpp-sdk-{c2j_service_name}") + os.makedirs(service_target_dir, exist_ok=True) + + for item in os.listdir(source_dir): + source_item = os.path.join(source_dir, item) + + # Handle test directories separately - move to generated/tests + if item == "generated" and os.path.isdir(source_item): + generated_source = os.path.join(source_item, "tests") + if os.path.exists(generated_source): + test_target_dir = os.path.abspath("generated/tests") + os.makedirs(test_target_dir, exist_ok=True) + shutil.copytree(generated_source, test_target_dir, dirs_exist_ok=True) + if self.debug: + print(f"Copied tests from '{generated_source}' to '{test_target_dir}'") + continue + + target_item = os.path.join(service_target_dir, item) + if os.path.isdir(source_item): + shutil.copytree(source_item, target_item, dirs_exist_ok=True) + else: + shutil.copy2(source_item, target_item) + + if self.debug: + print(f"Copied from '{source_dir}' to '{service_target_dir}'") + + # Cleanup output directory + if os.path.exists(output_dir): + shutil.rmtree(output_dir) + if self.debug: + print(f"Cleaned up '{output_dir}'") + diff --git a/tools/scripts/run_code_generation.py b/tools/scripts/run_code_generation.py index 014ee39ce3dc..b88ee081179e 100644 --- a/tools/scripts/run_code_generation.py +++ b/tools/scripts/run_code_generation.py @@ -13,6 +13,8 @@ from codegen.model_utils import ModelUtils from codegen.protocol_tests_gen import ProtocolTestsGen from codegen.smoke_tests_gen import SmokeTestsGen +from codegen.pagination_gen import PaginationGen +from codegen.format_util import format_directories def parse_arguments() -> dict: @@ -154,12 +156,26 @@ def main(): # generate code using smithy for all discoverable clients # clients_to_build check is present because user can generate only defaults or partitions or protocol-tests clients_to_build = model_utils.get_clients_to_build() + + if clients_to_build: + pagination_gen = PaginationGen(args["debug"]) + if pagination_gen.generate(clients_to_build) != 0: + print("ERROR: Failed to generate pagination!") + return -1 + if args["generate_smoke_tests"] and clients_to_build: smoke_tests_gen = SmokeTestsGen(args["debug"]) if smoke_tests_gen.generate(clients_to_build) != 0: print("ERROR: Failed to generate smoke test(s)!") return -1 + # Format all generated C++ code at the end + if clients_to_build: + client_dirs = [f"{args['output_location']}/src/aws-cpp-sdk-{client}" for client in clients_to_build] + existing_dirs = [d for d in client_dirs if os.path.exists(d)] + if existing_dirs: + format_directories(existing_dirs) + return 0