use std::error::Error;
use std::fmt;
#[allow(warnings)]
use futures::future;
use futures::Future;
use rusoto_core::credential::ProvideAwsCredentials;
use rusoto_core::region;
use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
use rusoto_core::{Client, RusotoError, RusotoFuture};
use rusoto_core::proto;
use rusoto_core::signature::SignedRequest;
use serde_json;
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(test, derive(Serialize))]
pub struct Attribute {
#[serde(rename = "BeginOffset")]
#[serde(skip_serializing_if = "Option::is_none")]
pub begin_offset: Option<i64>,
#[serde(rename = "EndOffset")]
#[serde(skip_serializing_if = "Option::is_none")]
pub end_offset: Option<i64>,
#[serde(rename = "Id")]
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(rename = "RelationshipScore")]
#[serde(skip_serializing_if = "Option::is_none")]
pub relationship_score: Option<f32>,
#[serde(rename = "Score")]
#[serde(skip_serializing_if = "Option::is_none")]
pub score: Option<f32>,
#[serde(rename = "Text")]
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(rename = "Traits")]
#[serde(skip_serializing_if = "Option::is_none")]
pub traits: Option<Vec<Trait>>,
#[serde(rename = "Type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
pub struct DetectEntitiesRequest {
#[serde(rename = "Text")]
pub text: String,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(test, derive(Serialize))]
pub struct DetectEntitiesResponse {
#[serde(rename = "Entities")]
pub entities: Vec<Entity>,
#[serde(rename = "PaginationToken")]
#[serde(skip_serializing_if = "Option::is_none")]
pub pagination_token: Option<String>,
#[serde(rename = "UnmappedAttributes")]
#[serde(skip_serializing_if = "Option::is_none")]
pub unmapped_attributes: Option<Vec<UnmappedAttribute>>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize)]
pub struct DetectPHIRequest {
#[serde(rename = "Text")]
pub text: String,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(test, derive(Serialize))]
pub struct DetectPHIResponse {
#[serde(rename = "Entities")]
pub entities: Vec<Entity>,
#[serde(rename = "PaginationToken")]
#[serde(skip_serializing_if = "Option::is_none")]
pub pagination_token: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(test, derive(Serialize))]
pub struct Entity {
#[serde(rename = "Attributes")]
#[serde(skip_serializing_if = "Option::is_none")]
pub attributes: Option<Vec<Attribute>>,
#[serde(rename = "BeginOffset")]
#[serde(skip_serializing_if = "Option::is_none")]
pub begin_offset: Option<i64>,
#[serde(rename = "Category")]
#[serde(skip_serializing_if = "Option::is_none")]
pub category: Option<String>,
#[serde(rename = "EndOffset")]
#[serde(skip_serializing_if = "Option::is_none")]
pub end_offset: Option<i64>,
#[serde(rename = "Id")]
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(rename = "Score")]
#[serde(skip_serializing_if = "Option::is_none")]
pub score: Option<f32>,
#[serde(rename = "Text")]
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(rename = "Traits")]
#[serde(skip_serializing_if = "Option::is_none")]
pub traits: Option<Vec<Trait>>,
#[serde(rename = "Type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(test, derive(Serialize))]
pub struct Trait {
#[serde(rename = "Name")]
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(rename = "Score")]
#[serde(skip_serializing_if = "Option::is_none")]
pub score: Option<f32>,
}
#[derive(Default, Debug, Clone, PartialEq, Deserialize)]
#[cfg_attr(test, derive(Serialize))]
pub struct UnmappedAttribute {
#[serde(rename = "Attribute")]
#[serde(skip_serializing_if = "Option::is_none")]
pub attribute: Option<Attribute>,
#[serde(rename = "Type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
}
#[derive(Debug, PartialEq)]
pub enum DetectEntitiesError {
InternalServer(String),
InvalidEncoding(String),
InvalidRequest(String),
ServiceUnavailable(String),
TextSizeLimitExceeded(String),
TooManyRequests(String),
}
impl DetectEntitiesError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<DetectEntitiesError> {
if let Some(err) = proto::json::Error::parse(&res) {
match err.typ.as_str() {
"InternalServerException" => {
return RusotoError::Service(DetectEntitiesError::InternalServer(err.msg))
}
"InvalidEncodingException" => {
return RusotoError::Service(DetectEntitiesError::InvalidEncoding(err.msg))
}
"InvalidRequestException" => {
return RusotoError::Service(DetectEntitiesError::InvalidRequest(err.msg))
}
"ServiceUnavailableException" => {
return RusotoError::Service(DetectEntitiesError::ServiceUnavailable(err.msg))
}
"TextSizeLimitExceededException" => {
return RusotoError::Service(DetectEntitiesError::TextSizeLimitExceeded(
err.msg,
))
}
"TooManyRequestsException" => {
return RusotoError::Service(DetectEntitiesError::TooManyRequests(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
return RusotoError::Unknown(res);
}
}
impl fmt::Display for DetectEntitiesError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description())
}
}
impl Error for DetectEntitiesError {
fn description(&self) -> &str {
match *self {
DetectEntitiesError::InternalServer(ref cause) => cause,
DetectEntitiesError::InvalidEncoding(ref cause) => cause,
DetectEntitiesError::InvalidRequest(ref cause) => cause,
DetectEntitiesError::ServiceUnavailable(ref cause) => cause,
DetectEntitiesError::TextSizeLimitExceeded(ref cause) => cause,
DetectEntitiesError::TooManyRequests(ref cause) => cause,
}
}
}
#[derive(Debug, PartialEq)]
pub enum DetectPHIError {
InternalServer(String),
InvalidEncoding(String),
InvalidRequest(String),
ServiceUnavailable(String),
TextSizeLimitExceeded(String),
TooManyRequests(String),
}
impl DetectPHIError {
pub fn from_response(res: BufferedHttpResponse) -> RusotoError<DetectPHIError> {
if let Some(err) = proto::json::Error::parse(&res) {
match err.typ.as_str() {
"InternalServerException" => {
return RusotoError::Service(DetectPHIError::InternalServer(err.msg))
}
"InvalidEncodingException" => {
return RusotoError::Service(DetectPHIError::InvalidEncoding(err.msg))
}
"InvalidRequestException" => {
return RusotoError::Service(DetectPHIError::InvalidRequest(err.msg))
}
"ServiceUnavailableException" => {
return RusotoError::Service(DetectPHIError::ServiceUnavailable(err.msg))
}
"TextSizeLimitExceededException" => {
return RusotoError::Service(DetectPHIError::TextSizeLimitExceeded(err.msg))
}
"TooManyRequestsException" => {
return RusotoError::Service(DetectPHIError::TooManyRequests(err.msg))
}
"ValidationException" => return RusotoError::Validation(err.msg),
_ => {}
}
}
return RusotoError::Unknown(res);
}
}
impl fmt::Display for DetectPHIError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description())
}
}
impl Error for DetectPHIError {
fn description(&self) -> &str {
match *self {
DetectPHIError::InternalServer(ref cause) => cause,
DetectPHIError::InvalidEncoding(ref cause) => cause,
DetectPHIError::InvalidRequest(ref cause) => cause,
DetectPHIError::ServiceUnavailable(ref cause) => cause,
DetectPHIError::TextSizeLimitExceeded(ref cause) => cause,
DetectPHIError::TooManyRequests(ref cause) => cause,
}
}
}
pub trait ComprehendMedical {
fn detect_entities(
&self,
input: DetectEntitiesRequest,
) -> RusotoFuture<DetectEntitiesResponse, DetectEntitiesError>;
fn detect_phi(
&self,
input: DetectPHIRequest,
) -> RusotoFuture<DetectPHIResponse, DetectPHIError>;
}
#[derive(Clone)]
pub struct ComprehendMedicalClient {
client: Client,
region: region::Region,
}
impl ComprehendMedicalClient {
pub fn new(region: region::Region) -> ComprehendMedicalClient {
ComprehendMedicalClient {
client: Client::shared(),
region,
}
}
pub fn new_with<P, D>(
request_dispatcher: D,
credentials_provider: P,
region: region::Region,
) -> ComprehendMedicalClient
where
P: ProvideAwsCredentials + Send + Sync + 'static,
P::Future: Send,
D: DispatchSignedRequest + Send + Sync + 'static,
D::Future: Send,
{
ComprehendMedicalClient {
client: Client::new_with(credentials_provider, request_dispatcher),
region,
}
}
}
impl ComprehendMedical for ComprehendMedicalClient {
fn detect_entities(
&self,
input: DetectEntitiesRequest,
) -> RusotoFuture<DetectEntitiesResponse, DetectEntitiesError> {
let mut request = SignedRequest::new("POST", "comprehendmedical", &self.region, "/");
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.add_header("x-amz-target", "ComprehendMedical_20181030.DetectEntities");
let encoded = serde_json::to_string(&input).unwrap();
request.set_payload(Some(encoded));
self.client.sign_and_dispatch(request, |response| {
if response.status.is_success() {
Box::new(response.buffer().from_err().and_then(|response| {
proto::json::ResponsePayload::new(&response)
.deserialize::<DetectEntitiesResponse, _>()
}))
} else {
Box::new(
response
.buffer()
.from_err()
.and_then(|response| Err(DetectEntitiesError::from_response(response))),
)
}
})
}
fn detect_phi(
&self,
input: DetectPHIRequest,
) -> RusotoFuture<DetectPHIResponse, DetectPHIError> {
let mut request = SignedRequest::new("POST", "comprehendmedical", &self.region, "/");
request.set_content_type("application/x-amz-json-1.1".to_owned());
request.add_header("x-amz-target", "ComprehendMedical_20181030.DetectPHI");
let encoded = serde_json::to_string(&input).unwrap();
request.set_payload(Some(encoded));
self.client.sign_and_dispatch(request, |response| {
if response.status.is_success() {
Box::new(response.buffer().from_err().and_then(|response| {
proto::json::ResponsePayload::new(&response)
.deserialize::<DetectPHIResponse, _>()
}))
} else {
Box::new(
response
.buffer()
.from_err()
.and_then(|response| Err(DetectPHIError::from_response(response))),
)
}
})
}
}