mod json;
mod query;
mod rest_json;
mod rest_xml;
pub use self::json::JsonProtocolHandler;
pub use self::query::QueryProtocolHandler;
pub use self::rest_json::RestJsonProtocolHandler;
pub use self::rest_xml::RestXmlProtocolHandler;
use super::field_mapper::apply_field_mappings;
use super::protocol::{ApiConfig, ApiProtocol, FieldMapping, ParsedResponse};
use crate::aws::client::AwsClients;
use anyhow::Result;
use serde_json::Value;
use std::collections::HashMap;
pub trait ProtocolHandler: Send + Sync {
fn parse_items(
&self,
response: &str,
config: &ApiConfig,
) -> Result<(Vec<Value>, Option<String>)>;
}
pub struct UnifiedProtocolHandler {
protocol: ApiProtocol,
}
impl UnifiedProtocolHandler {
pub fn new(protocol: ApiProtocol) -> Self {
Self { protocol }
}
pub async fn execute(
&self,
clients: &AwsClients,
service: &str,
config: &ApiConfig,
params: &Value,
) -> Result<String> {
match self.protocol {
ApiProtocol::Query => {
QueryProtocolHandler
.execute_impl(clients, service, config, params)
.await
}
ApiProtocol::Json => {
JsonProtocolHandler
.execute_impl(clients, service, config, params)
.await
}
ApiProtocol::RestJson => {
RestJsonProtocolHandler
.execute_impl(clients, service, config, params)
.await
}
ApiProtocol::RestXml => {
RestXmlProtocolHandler
.execute_impl(clients, service, config, params)
.await
}
}
}
pub fn parse_items(
&self,
response: &str,
config: &ApiConfig,
) -> Result<(Vec<Value>, Option<String>)> {
match self.protocol {
ApiProtocol::Query => QueryProtocolHandler.parse_items(response, config),
ApiProtocol::Json => JsonProtocolHandler.parse_items(response, config),
ApiProtocol::RestJson => RestJsonProtocolHandler.parse_items(response, config),
ApiProtocol::RestXml => RestXmlProtocolHandler.parse_items(response, config),
}
}
pub async fn invoke(
&self,
clients: &AwsClients,
service: &str,
config: &ApiConfig,
params: &Value,
field_mappings: &HashMap<String, FieldMapping>,
) -> Result<ParsedResponse> {
let response = self.execute(clients, service, config, params).await?;
let (items, next_token) = self.parse_items(&response, config)?;
let mapped_items = if field_mappings.is_empty() {
items
} else {
items
.iter()
.map(|item| apply_field_mappings(item, field_mappings))
.collect()
};
Ok(ParsedResponse {
items: mapped_items,
next_token,
})
}
}
pub fn get_protocol_handler(protocol: ApiProtocol) -> UnifiedProtocolHandler {
UnifiedProtocolHandler::new(protocol)
}