use std::error::Error;
use std::fmt;
use async_trait::async_trait;
use rusoto_core::credential::ProvideAwsCredentials;
use rusoto_core::region;
use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
use rusoto_core::{Client, RusotoError};
use rusoto_core::proto;
use rusoto_core::signature::SignedRequest;
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
use serde_json;
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct BatchMeterUsageRequest {
#[serde(rename = "ProductCode")]
pub product_code: String,
#[serde(rename = "UsageRecords")]
pub usage_records: Vec<UsageRecord>,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct BatchMeterUsageResult {
#[serde(rename = "Results")]
#[serde(skip_serializing_if = "Option::is_none")]
pub results: Option<Vec<UsageRecordResult>>,
#[serde(rename = "UnprocessedRecords")]
#[serde(skip_serializing_if = "Option::is_none")]
pub unprocessed_records: Option<Vec<UsageRecord>>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct MeterUsageRequest {
#[serde(rename = "DryRun")]
#[serde(skip_serializing_if = "Option::is_none")]
pub dry_run: Option<bool>,
#[serde(rename = "ProductCode")]
pub product_code: String,
#[serde(rename = "Timestamp")]
pub timestamp: f64,
#[serde(rename = "UsageDimension")]
pub usage_dimension: String,
#[serde(rename = "UsageQuantity")]
#[serde(skip_serializing_if = "Option::is_none")]
pub usage_quantity: Option<i64>,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct MeterUsageResult {
#[serde(rename = "MeteringRecordId")]
#[serde(skip_serializing_if = "Option::is_none")]
pub metering_record_id: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct RegisterUsageRequest {
#[serde(rename = "Nonce")]
#[serde(skip_serializing_if = "Option::is_none")]
pub nonce: Option<String>,
#[serde(rename = "ProductCode")]
pub product_code: String,
#[serde(rename = "PublicKeyVersion")]
pub public_key_version: i64,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct RegisterUsageResult {
#[serde(rename = "PublicKeyRotationTimestamp")]
#[serde(skip_serializing_if = "Option::is_none")]
pub public_key_rotation_timestamp: Option<f64>,
#[serde(rename = "Signature")]
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct ResolveCustomerRequest {
#[serde(rename = "RegistrationToken")]
pub registration_token: String,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct ResolveCustomerResult {
#[serde(rename = "CustomerIdentifier")]
#[serde(skip_serializing_if = "Option::is_none")]
pub customer_identifier: Option<String>,
#[serde(rename = "ProductCode")]
#[serde(skip_serializing_if = "Option::is_none")]
pub product_code: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UsageRecord {
#[serde(rename = "CustomerIdentifier")]
pub customer_identifier: String,
#[serde(rename = "Dimension")]
pub dimension: String,
#[serde(rename = "Quantity")]
#[serde(skip_serializing_if = "Option::is_none")]
pub quantity: Option<i64>,
#[serde(rename = "Timestamp")]
pub timestamp: f64,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct UsageRecordResult {
#[serde(rename = "MeteringRecordId")]
#[serde(skip_serializing_if = "Option::is_none")]
pub metering_record_id: Option<String>,
#[serde(rename = "Status")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(rename = "UsageRecord")]
#[serde(skip_serializing_if = "Option::is_none")]
pub usage_record: Option<UsageRecord>,
}
#[derive(Debug, PartialEq)]
pub enum BatchMeterUsageError {
DisabledApi(String),
InternalServiceError(String),
InvalidCustomerIdentifier(String),
InvalidProductCode(String),
InvalidUsageDimension(String),
Throttling(String),
TimestampOutOfBounds(String),
}
impl BatchMeterUsageError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<BatchMeterUsageError> {
if let Some(err) = proto::json::Error::parse(&res) {
match err.typ.as_str() {
"DisabledApiException" => {
return RusotoError::Service(BatchMeterUsageError::DisabledApi(err.msg))
}
"InternalServiceErrorException" => {
return RusotoError::Service(BatchMeterUsageError::InternalServiceError(
err.msg,
))
}
"InvalidCustomerIdentifierException" => {
return RusotoError::Service(BatchMeterUsageError::InvalidCustomerIdentifier(
err.msg,
))
}
"InvalidProductCodeException" => {
return RusotoError::Service(BatchMeterUsageError::InvalidProductCode(err.msg))
}
"InvalidUsageDimensionException" => {
return RusotoError::Service(BatchMeterUsageError::InvalidUsageDimension(
err.msg,
))
}
"ThrottlingException" => {
return RusotoError::Service(BatchMeterUsageError::Throttling(err.msg))
}
"TimestampOutOfBoundsException" => {
return RusotoError::Service(BatchMeterUsageError::TimestampOutOfBounds(
err.msg,
))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for BatchMeterUsageError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BatchMeterUsageError::DisabledApi(ref cause) => write!(f, "{}", cause),
BatchMeterUsageError::InternalServiceError(ref cause) => write!(f, "{}", cause),
BatchMeterUsageError::InvalidCustomerIdentifier(ref cause) => write!(f, "{}", cause),
BatchMeterUsageError::InvalidProductCode(ref cause) => write!(f, "{}", cause),
BatchMeterUsageError::InvalidUsageDimension(ref cause) => write!(f, "{}", cause),
BatchMeterUsageError::Throttling(ref cause) => write!(f, "{}", cause),
BatchMeterUsageError::TimestampOutOfBounds(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for BatchMeterUsageError {}
#[derive(Debug, PartialEq)]
pub enum MeterUsageError {
CustomerNotEntitled(String),
DuplicateRequest(String),
InternalServiceError(String),
InvalidEndpointRegion(String),
InvalidProductCode(String),
InvalidUsageDimension(String),
Throttling(String),
TimestampOutOfBounds(String),
}
impl MeterUsageError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<MeterUsageError> {
if let Some(err) = proto::json::Error::parse(&res) {
match err.typ.as_str() {
"CustomerNotEntitledException" => {
return RusotoError::Service(MeterUsageError::CustomerNotEntitled(err.msg))
}
"DuplicateRequestException" => {
return RusotoError::Service(MeterUsageError::DuplicateRequest(err.msg))
}
"InternalServiceErrorException" => {
return RusotoError::Service(MeterUsageError::InternalServiceError(err.msg))
}
"InvalidEndpointRegionException" => {
return RusotoError::Service(MeterUsageError::InvalidEndpointRegion(err.msg))
}
"InvalidProductCodeException" => {
return RusotoError::Service(MeterUsageError::InvalidProductCode(err.msg))
}
"InvalidUsageDimensionException" => {
return RusotoError::Service(MeterUsageError::InvalidUsageDimension(err.msg))
}
"ThrottlingException" => {
return RusotoError::Service(MeterUsageError::Throttling(err.msg))
}
"TimestampOutOfBoundsException" => {
return RusotoError::Service(MeterUsageError::TimestampOutOfBounds(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for MeterUsageError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
MeterUsageError::CustomerNotEntitled(ref cause) => write!(f, "{}", cause),
MeterUsageError::DuplicateRequest(ref cause) => write!(f, "{}", cause),
MeterUsageError::InternalServiceError(ref cause) => write!(f, "{}", cause),
MeterUsageError::InvalidEndpointRegion(ref cause) => write!(f, "{}", cause),
MeterUsageError::InvalidProductCode(ref cause) => write!(f, "{}", cause),
MeterUsageError::InvalidUsageDimension(ref cause) => write!(f, "{}", cause),
MeterUsageError::Throttling(ref cause) => write!(f, "{}", cause),
MeterUsageError::TimestampOutOfBounds(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for MeterUsageError {}
#[derive(Debug, PartialEq)]
pub enum RegisterUsageError {
CustomerNotEntitled(String),
DisabledApi(String),
InternalServiceError(String),
InvalidProductCode(String),
InvalidPublicKeyVersion(String),
InvalidRegion(String),
PlatformNotSupported(String),
Throttling(String),
}
impl RegisterUsageError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<RegisterUsageError> {
if let Some(err) = proto::json::Error::parse(&res) {
match err.typ.as_str() {
"CustomerNotEntitledException" => {
return RusotoError::Service(RegisterUsageError::CustomerNotEntitled(err.msg))
}
"DisabledApiException" => {
return RusotoError::Service(RegisterUsageError::DisabledApi(err.msg))
}
"InternalServiceErrorException" => {
return RusotoError::Service(RegisterUsageError::InternalServiceError(err.msg))
}
"InvalidProductCodeException" => {
return RusotoError::Service(RegisterUsageError::InvalidProductCode(err.msg))
}
"InvalidPublicKeyVersionException" => {
return RusotoError::Service(RegisterUsageError::InvalidPublicKeyVersion(
err.msg,
))
}
"InvalidRegionException" => {
return RusotoError::Service(RegisterUsageError::InvalidRegion(err.msg))
}
"PlatformNotSupportedException" => {
return RusotoError::Service(RegisterUsageError::PlatformNotSupported(err.msg))
}
"ThrottlingException" => {
return RusotoError::Service(RegisterUsageError::Throttling(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for RegisterUsageError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RegisterUsageError::CustomerNotEntitled(ref cause) => write!(f, "{}", cause),
RegisterUsageError::DisabledApi(ref cause) => write!(f, "{}", cause),
RegisterUsageError::InternalServiceError(ref cause) => write!(f, "{}", cause),
RegisterUsageError::InvalidProductCode(ref cause) => write!(f, "{}", cause),
RegisterUsageError::InvalidPublicKeyVersion(ref cause) => write!(f, "{}", cause),
RegisterUsageError::InvalidRegion(ref cause) => write!(f, "{}", cause),
RegisterUsageError::PlatformNotSupported(ref cause) => write!(f, "{}", cause),
RegisterUsageError::Throttling(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for RegisterUsageError {}
#[derive(Debug, PartialEq)]
pub enum ResolveCustomerError {
DisabledApi(String),
ExpiredToken(String),
InternalServiceError(String),
InvalidToken(String),
Throttling(String),
}
impl ResolveCustomerError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<ResolveCustomerError> {
if let Some(err) = proto::json::Error::parse(&res) {
match err.typ.as_str() {
"DisabledApiException" => {
return RusotoError::Service(ResolveCustomerError::DisabledApi(err.msg))
}
"ExpiredTokenException" => {
return RusotoError::Service(ResolveCustomerError::ExpiredToken(err.msg))
}
"InternalServiceErrorException" => {
return RusotoError::Service(ResolveCustomerError::InternalServiceError(
err.msg,
))
}
"InvalidTokenException" => {
return RusotoError::Service(ResolveCustomerError::InvalidToken(err.msg))
}
"ThrottlingException" => {
return RusotoError::Service(ResolveCustomerError::Throttling(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for ResolveCustomerError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ResolveCustomerError::DisabledApi(ref cause) => write!(f, "{}", cause),
ResolveCustomerError::ExpiredToken(ref cause) => write!(f, "{}", cause),
ResolveCustomerError::InternalServiceError(ref cause) => write!(f, "{}", cause),
ResolveCustomerError::InvalidToken(ref cause) => write!(f, "{}", cause),
ResolveCustomerError::Throttling(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for ResolveCustomerError {}
#[async_trait]
pub trait MarketplaceMetering {
async fn batch_meter_usage(
&self,
input: BatchMeterUsageRequest,
) -> Result<BatchMeterUsageResult, RusotoError<BatchMeterUsageError>>;
async fn meter_usage(
&self,
input: MeterUsageRequest,
) -> Result<MeterUsageResult, RusotoError<MeterUsageError>>;
async fn register_usage(
&self,
input: RegisterUsageRequest,
) -> Result<RegisterUsageResult, RusotoError<RegisterUsageError>>;
async fn resolve_customer(
&self,
input: ResolveCustomerRequest,
) -> Result<ResolveCustomerResult, RusotoError<ResolveCustomerError>>;
}
#[derive(Clone)]
pub struct MarketplaceMeteringClient {
client: Client,
region: region::Region,
}
impl MarketplaceMeteringClient {
pub fn new(region: region::Region) -> MarketplaceMeteringClient {
MarketplaceMeteringClient {
client: Client::shared(),
region,
}
}
pub fn new_with<P, D>(
request_dispatcher: D,
credentials_provider: P,
region: region::Region,
) -> MarketplaceMeteringClient
where
P: ProvideAwsCredentials + Send + Sync + 'static,
D: DispatchSignedRequest + Send + Sync + 'static,
{
MarketplaceMeteringClient {
client: Client::new_with(credentials_provider, request_dispatcher),
region,
}
}
pub fn new_with_client(client: Client, region: region::Region) -> MarketplaceMeteringClient {
MarketplaceMeteringClient { client, region }
}
}
#[async_trait]
impl MarketplaceMetering for MarketplaceMeteringClient {
async fn batch_meter_usage(
&self,
input: BatchMeterUsageRequest,
) -> Result<BatchMeterUsageResult, RusotoError<BatchMeterUsageError>> {
let mut request = SignedRequest::new("POST", "aws-marketplace", &self.region, "/");
request.set_endpoint_prefix("metering.marketplace".to_string());
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.add_header("x-amz-target", "AWSMPMeteringService.BatchMeterUsage");
let encoded = serde_json::to_string(&input).unwrap();
request.set_payload(Some(encoded));
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
proto::json::ResponsePayload::new(&response).deserialize::<BatchMeterUsageResult, _>()
} else {
let try_response = response.buffer().await;
let response = try_response.map_err(RusotoError::HttpDispatch)?;
Err(BatchMeterUsageError::from_response(response))
}
}
async fn meter_usage(
&self,
input: MeterUsageRequest,
) -> Result<MeterUsageResult, RusotoError<MeterUsageError>> {
let mut request = SignedRequest::new("POST", "aws-marketplace", &self.region, "/");
request.set_endpoint_prefix("metering.marketplace".to_string());
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.add_header("x-amz-target", "AWSMPMeteringService.MeterUsage");
let encoded = serde_json::to_string(&input).unwrap();
request.set_payload(Some(encoded));
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
proto::json::ResponsePayload::new(&response).deserialize::<MeterUsageResult, _>()
} else {
let try_response = response.buffer().await;
let response = try_response.map_err(RusotoError::HttpDispatch)?;
Err(MeterUsageError::from_response(response))
}
}
async fn register_usage(
&self,
input: RegisterUsageRequest,
) -> Result<RegisterUsageResult, RusotoError<RegisterUsageError>> {
let mut request = SignedRequest::new("POST", "aws-marketplace", &self.region, "/");
request.set_endpoint_prefix("metering.marketplace".to_string());
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.add_header("x-amz-target", "AWSMPMeteringService.RegisterUsage");
let encoded = serde_json::to_string(&input).unwrap();
request.set_payload(Some(encoded));
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
proto::json::ResponsePayload::new(&response).deserialize::<RegisterUsageResult, _>()
} else {
let try_response = response.buffer().await;
let response = try_response.map_err(RusotoError::HttpDispatch)?;
Err(RegisterUsageError::from_response(response))
}
}
async fn resolve_customer(
&self,
input: ResolveCustomerRequest,
) -> Result<ResolveCustomerResult, RusotoError<ResolveCustomerError>> {
let mut request = SignedRequest::new("POST", "aws-marketplace", &self.region, "/");
request.set_endpoint_prefix("metering.marketplace".to_string());
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.add_header("x-amz-target", "AWSMPMeteringService.ResolveCustomer");
let encoded = serde_json::to_string(&input).unwrap();
request.set_payload(Some(encoded));
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
proto::json::ResponsePayload::new(&response).deserialize::<ResolveCustomerResult, _>()
} else {
let try_response = response.buffer().await;
let response = try_response.map_err(RusotoError::HttpDispatch)?;
Err(ResolveCustomerError::from_response(response))
}
}
}