1use std::error::Error;
14use std::fmt;
15
16use async_trait::async_trait;
17use rusoto_core::credential::ProvideAwsCredentials;
18use rusoto_core::region;
19use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
20use rusoto_core::{Client, RusotoError};
21
22use rusoto_core::proto;
23use rusoto_core::request::HttpResponse;
24use rusoto_core::signature::SignedRequest;
25#[allow(unused_imports)]
26use serde::{Deserialize, Serialize};
27
28impl ForecastQueryClient {
29 fn new_signed_request(&self, http_method: &str, request_uri: &str) -> SignedRequest {
30 let mut request = SignedRequest::new(http_method, "forecast", &self.region, request_uri);
31 request.set_endpoint_prefix("forecastquery".to_string());
32
33 request.set_content_type("application/x-amz-json-1.1".to_owned());
34
35 request
36 }
37
38 async fn sign_and_dispatch<E>(
39 &self,
40 request: SignedRequest,
41 from_response: fn(BufferedHttpResponse) -> RusotoError<E>,
42 ) -> Result<HttpResponse, RusotoError<E>> {
43 let mut response = self.client.sign_and_dispatch(request).await?;
44 if !response.status.is_success() {
45 let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
46 return Err(from_response(response));
47 }
48
49 Ok(response)
50 }
51}
52
53use serde_json;
54#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
56#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
57pub struct DataPoint {
58 #[serde(rename = "Timestamp")]
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub timestamp: Option<String>,
62 #[serde(rename = "Value")]
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub value: Option<f64>,
66}
67
68#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
70#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
71pub struct Forecast {
72 #[serde(rename = "Predictions")]
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub predictions: Option<::std::collections::HashMap<String, Vec<DataPoint>>>,
76}
77
78#[derive(Clone, Debug, Default, PartialEq, Serialize)]
79#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
80pub struct QueryForecastRequest {
81 #[serde(rename = "EndDate")]
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub end_date: Option<String>,
85 #[serde(rename = "Filters")]
87 pub filters: ::std::collections::HashMap<String, String>,
88 #[serde(rename = "ForecastArn")]
90 pub forecast_arn: String,
91 #[serde(rename = "NextToken")]
93 #[serde(skip_serializing_if = "Option::is_none")]
94 pub next_token: Option<String>,
95 #[serde(rename = "StartDate")]
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub start_date: Option<String>,
99}
100
101#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
102#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
103pub struct QueryForecastResponse {
104 #[serde(rename = "Forecast")]
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub forecast: Option<Forecast>,
108}
109
110#[derive(Debug, PartialEq)]
112pub enum QueryForecastError {
113 InvalidInput(String),
115 InvalidNextToken(String),
117 LimitExceeded(String),
119 ResourceInUse(String),
121 ResourceNotFound(String),
123}
124
125impl QueryForecastError {
126 pub fn from_response(res: BufferedHttpResponse) -> RusotoError<QueryForecastError> {
127 if let Some(err) = proto::json::Error::parse(&res) {
128 match err.typ.as_str() {
129 "InvalidInputException" => {
130 return RusotoError::Service(QueryForecastError::InvalidInput(err.msg))
131 }
132 "InvalidNextTokenException" => {
133 return RusotoError::Service(QueryForecastError::InvalidNextToken(err.msg))
134 }
135 "LimitExceededException" => {
136 return RusotoError::Service(QueryForecastError::LimitExceeded(err.msg))
137 }
138 "ResourceInUseException" => {
139 return RusotoError::Service(QueryForecastError::ResourceInUse(err.msg))
140 }
141 "ResourceNotFoundException" => {
142 return RusotoError::Service(QueryForecastError::ResourceNotFound(err.msg))
143 }
144 "ValidationException" => return RusotoError::Validation(err.msg),
145 _ => {}
146 }
147 }
148 RusotoError::Unknown(res)
149 }
150}
151impl fmt::Display for QueryForecastError {
152 #[allow(unused_variables)]
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 match *self {
155 QueryForecastError::InvalidInput(ref cause) => write!(f, "{}", cause),
156 QueryForecastError::InvalidNextToken(ref cause) => write!(f, "{}", cause),
157 QueryForecastError::LimitExceeded(ref cause) => write!(f, "{}", cause),
158 QueryForecastError::ResourceInUse(ref cause) => write!(f, "{}", cause),
159 QueryForecastError::ResourceNotFound(ref cause) => write!(f, "{}", cause),
160 }
161 }
162}
163impl Error for QueryForecastError {}
164#[async_trait]
166pub trait ForecastQuery {
167 async fn query_forecast(
169 &self,
170 input: QueryForecastRequest,
171 ) -> Result<QueryForecastResponse, RusotoError<QueryForecastError>>;
172}
173#[derive(Clone)]
175pub struct ForecastQueryClient {
176 client: Client,
177 region: region::Region,
178}
179
180impl ForecastQueryClient {
181 pub fn new(region: region::Region) -> ForecastQueryClient {
185 ForecastQueryClient {
186 client: Client::shared(),
187 region,
188 }
189 }
190
191 pub fn new_with<P, D>(
192 request_dispatcher: D,
193 credentials_provider: P,
194 region: region::Region,
195 ) -> ForecastQueryClient
196 where
197 P: ProvideAwsCredentials + Send + Sync + 'static,
198 D: DispatchSignedRequest + Send + Sync + 'static,
199 {
200 ForecastQueryClient {
201 client: Client::new_with(credentials_provider, request_dispatcher),
202 region,
203 }
204 }
205
206 pub fn new_with_client(client: Client, region: region::Region) -> ForecastQueryClient {
207 ForecastQueryClient { client, region }
208 }
209}
210
211#[async_trait]
212impl ForecastQuery for ForecastQueryClient {
213 async fn query_forecast(
215 &self,
216 input: QueryForecastRequest,
217 ) -> Result<QueryForecastResponse, RusotoError<QueryForecastError>> {
218 let mut request = self.new_signed_request("POST", "/");
219 request.add_header("x-amz-target", "AmazonForecastRuntime.QueryForecast");
220 let encoded = serde_json::to_string(&input).unwrap();
221 request.set_payload(Some(encoded));
222
223 let response = self
224 .sign_and_dispatch(request, QueryForecastError::from_response)
225 .await?;
226 let mut response = response;
227 let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
228 proto::json::ResponsePayload::new(&response).deserialize::<QueryForecastResponse, _>()
229 }
230}