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::param::{Params, ServiceParams};
use rusoto_core::proto;
use rusoto_core::signature::SignedRequest;
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
use serde_json;
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct AcceleratorType {
#[serde(rename = "acceleratorTypeName")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_type_name: Option<String>,
#[serde(rename = "memoryInfo")]
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_info: Option<MemoryInfo>,
#[serde(rename = "throughputInfo")]
#[serde(skip_serializing_if = "Option::is_none")]
pub throughput_info: Option<Vec<KeyValuePair>>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct AcceleratorTypeOffering {
#[serde(rename = "acceleratorType")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_type: Option<String>,
#[serde(rename = "location")]
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<String>,
#[serde(rename = "locationType")]
#[serde(skip_serializing_if = "Option::is_none")]
pub location_type: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct DescribeAcceleratorOfferingsRequest {
#[serde(rename = "acceleratorTypes")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_types: Option<Vec<String>>,
#[serde(rename = "locationType")]
pub location_type: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct DescribeAcceleratorOfferingsResponse {
#[serde(rename = "acceleratorTypeOfferings")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_type_offerings: Option<Vec<AcceleratorTypeOffering>>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct DescribeAcceleratorTypesRequest {}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct DescribeAcceleratorTypesResponse {
#[serde(rename = "acceleratorTypes")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_types: Option<Vec<AcceleratorType>>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct DescribeAcceleratorsRequest {
#[serde(rename = "acceleratorIds")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_ids: Option<Vec<String>>,
#[serde(rename = "filters")]
#[serde(skip_serializing_if = "Option::is_none")]
pub filters: Option<Vec<Filter>>,
#[serde(rename = "maxResults")]
#[serde(skip_serializing_if = "Option::is_none")]
pub max_results: Option<i64>,
#[serde(rename = "nextToken")]
#[serde(skip_serializing_if = "Option::is_none")]
pub next_token: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct DescribeAcceleratorsResponse {
#[serde(rename = "acceleratorSet")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_set: Option<Vec<ElasticInferenceAccelerator>>,
#[serde(rename = "nextToken")]
#[serde(skip_serializing_if = "Option::is_none")]
pub next_token: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct ElasticInferenceAccelerator {
#[serde(rename = "acceleratorHealth")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_health: Option<ElasticInferenceAcceleratorHealth>,
#[serde(rename = "acceleratorId")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_id: Option<String>,
#[serde(rename = "acceleratorType")]
#[serde(skip_serializing_if = "Option::is_none")]
pub accelerator_type: Option<String>,
#[serde(rename = "attachedResource")]
#[serde(skip_serializing_if = "Option::is_none")]
pub attached_resource: Option<String>,
#[serde(rename = "availabilityZone")]
#[serde(skip_serializing_if = "Option::is_none")]
pub availability_zone: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct ElasticInferenceAcceleratorHealth {
#[serde(rename = "status")]
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct Filter {
#[serde(rename = "name")]
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(rename = "values")]
#[serde(skip_serializing_if = "Option::is_none")]
pub values: Option<Vec<String>>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct KeyValuePair {
#[serde(rename = "key")]
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<String>,
#[serde(rename = "value")]
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<i64>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct ListTagsForResourceRequest {
#[serde(rename = "resourceArn")]
pub resource_arn: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct ListTagsForResourceResult {
#[serde(rename = "tags")]
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<::std::collections::HashMap<String, String>>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct MemoryInfo {
#[serde(rename = "sizeInMiB")]
#[serde(skip_serializing_if = "Option::is_none")]
pub size_in_mi_b: Option<i64>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct TagResourceRequest {
#[serde(rename = "resourceArn")]
pub resource_arn: String,
#[serde(rename = "tags")]
pub tags: ::std::collections::HashMap<String, String>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct TagResourceResult {}
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
pub struct UntagResourceRequest {
#[serde(rename = "resourceArn")]
pub resource_arn: String,
#[serde(rename = "tagKeys")]
pub tag_keys: Vec<String>,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
pub struct UntagResourceResult {}
#[derive(Debug, PartialEq)]
pub enum DescribeAcceleratorOfferingsError {
BadRequest(String),
InternalServer(String),
ResourceNotFound(String),
}
impl DescribeAcceleratorOfferingsError {
pub fn from_response(
res: BufferedHttpResponse,
) -> RusotoError<DescribeAcceleratorOfferingsError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"BadRequestException" => {
return RusotoError::Service(DescribeAcceleratorOfferingsError::BadRequest(
err.msg,
))
}
"InternalServerException" => {
return RusotoError::Service(DescribeAcceleratorOfferingsError::InternalServer(
err.msg,
))
}
"ResourceNotFoundException" => {
return RusotoError::Service(
DescribeAcceleratorOfferingsError::ResourceNotFound(err.msg),
)
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for DescribeAcceleratorOfferingsError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DescribeAcceleratorOfferingsError::BadRequest(ref cause) => write!(f, "{}", cause),
DescribeAcceleratorOfferingsError::InternalServer(ref cause) => write!(f, "{}", cause),
DescribeAcceleratorOfferingsError::ResourceNotFound(ref cause) => {
write!(f, "{}", cause)
}
}
}
}
impl Error for DescribeAcceleratorOfferingsError {}
#[derive(Debug, PartialEq)]
pub enum DescribeAcceleratorTypesError {
InternalServer(String),
}
impl DescribeAcceleratorTypesError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<DescribeAcceleratorTypesError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"InternalServerException" => {
return RusotoError::Service(DescribeAcceleratorTypesError::InternalServer(
err.msg,
))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for DescribeAcceleratorTypesError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DescribeAcceleratorTypesError::InternalServer(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for DescribeAcceleratorTypesError {}
#[derive(Debug, PartialEq)]
pub enum DescribeAcceleratorsError {
BadRequest(String),
InternalServer(String),
ResourceNotFound(String),
}
impl DescribeAcceleratorsError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<DescribeAcceleratorsError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"BadRequestException" => {
return RusotoError::Service(DescribeAcceleratorsError::BadRequest(err.msg))
}
"InternalServerException" => {
return RusotoError::Service(DescribeAcceleratorsError::InternalServer(err.msg))
}
"ResourceNotFoundException" => {
return RusotoError::Service(DescribeAcceleratorsError::ResourceNotFound(
err.msg,
))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for DescribeAcceleratorsError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DescribeAcceleratorsError::BadRequest(ref cause) => write!(f, "{}", cause),
DescribeAcceleratorsError::InternalServer(ref cause) => write!(f, "{}", cause),
DescribeAcceleratorsError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for DescribeAcceleratorsError {}
#[derive(Debug, PartialEq)]
pub enum ListTagsForResourceError {
BadRequest(String),
InternalServer(String),
ResourceNotFound(String),
}
impl ListTagsForResourceError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<ListTagsForResourceError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"BadRequestException" => {
return RusotoError::Service(ListTagsForResourceError::BadRequest(err.msg))
}
"InternalServerException" => {
return RusotoError::Service(ListTagsForResourceError::InternalServer(err.msg))
}
"ResourceNotFoundException" => {
return RusotoError::Service(ListTagsForResourceError::ResourceNotFound(
err.msg,
))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for ListTagsForResourceError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ListTagsForResourceError::BadRequest(ref cause) => write!(f, "{}", cause),
ListTagsForResourceError::InternalServer(ref cause) => write!(f, "{}", cause),
ListTagsForResourceError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for ListTagsForResourceError {}
#[derive(Debug, PartialEq)]
pub enum TagResourceError {
BadRequest(String),
InternalServer(String),
ResourceNotFound(String),
}
impl TagResourceError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<TagResourceError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"BadRequestException" => {
return RusotoError::Service(TagResourceError::BadRequest(err.msg))
}
"InternalServerException" => {
return RusotoError::Service(TagResourceError::InternalServer(err.msg))
}
"ResourceNotFoundException" => {
return RusotoError::Service(TagResourceError::ResourceNotFound(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for TagResourceError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TagResourceError::BadRequest(ref cause) => write!(f, "{}", cause),
TagResourceError::InternalServer(ref cause) => write!(f, "{}", cause),
TagResourceError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for TagResourceError {}
#[derive(Debug, PartialEq)]
pub enum UntagResourceError {
BadRequest(String),
InternalServer(String),
ResourceNotFound(String),
}
impl UntagResourceError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<UntagResourceError> {
if let Some(err) = proto::json::Error::parse_rest(&res) {
match err.typ.as_str() {
"BadRequestException" => {
return RusotoError::Service(UntagResourceError::BadRequest(err.msg))
}
"InternalServerException" => {
return RusotoError::Service(UntagResourceError::InternalServer(err.msg))
}
"ResourceNotFoundException" => {
return RusotoError::Service(UntagResourceError::ResourceNotFound(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
RusotoError::Unknown(res)
}
}
impl fmt::Display for UntagResourceError {
#[allow(unused_variables)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
UntagResourceError::BadRequest(ref cause) => write!(f, "{}", cause),
UntagResourceError::InternalServer(ref cause) => write!(f, "{}", cause),
UntagResourceError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
}
}
}
impl Error for UntagResourceError {}
#[async_trait]
pub trait ElasticInference {
async fn describe_accelerator_offerings(
&self,
input: DescribeAcceleratorOfferingsRequest,
) -> Result<DescribeAcceleratorOfferingsResponse, RusotoError<DescribeAcceleratorOfferingsError>>;
async fn describe_accelerator_types(
&self,
) -> Result<DescribeAcceleratorTypesResponse, RusotoError<DescribeAcceleratorTypesError>>;
async fn describe_accelerators(
&self,
input: DescribeAcceleratorsRequest,
) -> Result<DescribeAcceleratorsResponse, RusotoError<DescribeAcceleratorsError>>;
async fn list_tags_for_resource(
&self,
input: ListTagsForResourceRequest,
) -> Result<ListTagsForResourceResult, RusotoError<ListTagsForResourceError>>;
async fn tag_resource(
&self,
input: TagResourceRequest,
) -> Result<TagResourceResult, RusotoError<TagResourceError>>;
async fn untag_resource(
&self,
input: UntagResourceRequest,
) -> Result<UntagResourceResult, RusotoError<UntagResourceError>>;
}
#[derive(Clone)]
pub struct ElasticInferenceClient {
client: Client,
region: region::Region,
}
impl ElasticInferenceClient {
pub fn new(region: region::Region) -> ElasticInferenceClient {
ElasticInferenceClient {
client: Client::shared(),
region,
}
}
pub fn new_with<P, D>(
request_dispatcher: D,
credentials_provider: P,
region: region::Region,
) -> ElasticInferenceClient
where
P: ProvideAwsCredentials + Send + Sync + 'static,
D: DispatchSignedRequest + Send + Sync + 'static,
{
ElasticInferenceClient {
client: Client::new_with(credentials_provider, request_dispatcher),
region,
}
}
pub fn new_with_client(client: Client, region: region::Region) -> ElasticInferenceClient {
ElasticInferenceClient { client, region }
}
}
#[async_trait]
impl ElasticInference for ElasticInferenceClient {
#[allow(unused_mut)]
async fn describe_accelerator_offerings(
&self,
input: DescribeAcceleratorOfferingsRequest,
) -> Result<DescribeAcceleratorOfferingsResponse, RusotoError<DescribeAcceleratorOfferingsError>>
{
let request_uri = "/describe-accelerator-offerings";
let mut request =
SignedRequest::new("POST", "elastic-inference", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("api.elastic-inference".to_string());
let encoded = Some(serde_json::to_vec(&input).unwrap());
request.set_payload(encoded);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<DescribeAcceleratorOfferingsResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(DescribeAcceleratorOfferingsError::from_response(response))
}
}
#[allow(unused_mut)]
async fn describe_accelerator_types(
&self,
) -> Result<DescribeAcceleratorTypesResponse, RusotoError<DescribeAcceleratorTypesError>> {
let request_uri = "/describe-accelerator-types";
let mut request =
SignedRequest::new("GET", "elastic-inference", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("api.elastic-inference".to_string());
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<DescribeAcceleratorTypesResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(DescribeAcceleratorTypesError::from_response(response))
}
}
#[allow(unused_mut)]
async fn describe_accelerators(
&self,
input: DescribeAcceleratorsRequest,
) -> Result<DescribeAcceleratorsResponse, RusotoError<DescribeAcceleratorsError>> {
let request_uri = "/describe-accelerators";
let mut request =
SignedRequest::new("POST", "elastic-inference", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("api.elastic-inference".to_string());
let encoded = Some(serde_json::to_vec(&input).unwrap());
request.set_payload(encoded);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<DescribeAcceleratorsResponse, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(DescribeAcceleratorsError::from_response(response))
}
}
#[allow(unused_mut)]
async fn list_tags_for_resource(
&self,
input: ListTagsForResourceRequest,
) -> Result<ListTagsForResourceResult, RusotoError<ListTagsForResourceError>> {
let request_uri = format!("/tags/{resource_arn}", resource_arn = input.resource_arn);
let mut request =
SignedRequest::new("GET", "elastic-inference", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("api.elastic-inference".to_string());
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<ListTagsForResourceResult, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(ListTagsForResourceError::from_response(response))
}
}
#[allow(unused_mut)]
async fn tag_resource(
&self,
input: TagResourceRequest,
) -> Result<TagResourceResult, RusotoError<TagResourceError>> {
let request_uri = format!("/tags/{resource_arn}", resource_arn = input.resource_arn);
let mut request =
SignedRequest::new("POST", "elastic-inference", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("api.elastic-inference".to_string());
let encoded = Some(serde_json::to_vec(&input).unwrap());
request.set_payload(encoded);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<TagResourceResult, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(TagResourceError::from_response(response))
}
}
#[allow(unused_mut)]
async fn untag_resource(
&self,
input: UntagResourceRequest,
) -> Result<UntagResourceResult, RusotoError<UntagResourceError>> {
let request_uri = format!("/tags/{resource_arn}", resource_arn = input.resource_arn);
let mut request =
SignedRequest::new("DELETE", "elastic-inference", &self.region, &request_uri);
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.set_endpoint_prefix("api.elastic-inference".to_string());
let mut params = Params::new();
for item in input.tag_keys.iter() {
params.put("tagKeys", item);
}
request.set_params(params);
let mut response = self
.client
.sign_and_dispatch(request)
.await
.map_err(RusotoError::from)?;
if response.status.is_success() {
let mut response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
let result = proto::json::ResponsePayload::new(&response)
.deserialize::<UntagResourceResult, _>()?;
Ok(result)
} else {
let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
Err(UntagResourceError::from_response(response))
}
}
}