#![allow(dead_code)]
use super::request_client::RequestClient;
use crate::auth::Authentication;
use crate::error::{ClientErrorKind, Error, Result};
use derivative::Derivative;
use parsec_interface::operations::{Convert, NativeOperation, NativeResult};
use parsec_interface::operations_protobuf::ProtobufConverter;
use parsec_interface::requests::{
request::RequestHeader, Opcode, ProviderId, Request, Response, ResponseStatus,
};
use std::convert::TryInto;
#[derive(Derivative)]
#[derivative(Debug)]
pub struct OperationClient {
#[derivative(Debug = "ignore")]
pub content_converter: Box<dyn Convert + Send + Sync>,
#[derivative(Debug = "ignore")]
pub accept_converter: Box<dyn Convert + Send + Sync>,
pub request_client: RequestClient,
}
#[allow(clippy::new_without_default)]
impl OperationClient {
pub fn new() -> Result<OperationClient> {
Ok(OperationClient {
request_client: RequestClient::new()?,
..Default::default()
})
}
fn operation_to_request(
&self,
operation: NativeOperation,
provider: ProviderId,
auth: &Authentication,
) -> Result<Request> {
let opcode = operation.opcode();
let body = self
.content_converter
.operation_to_body(operation)
.map_err(ClientErrorKind::Interface)?;
let header = RequestHeader {
provider,
session: 0, content_type: self.content_converter.body_type(),
accept_type: self.accept_converter.body_type(),
auth_type: auth.auth_type(),
opcode,
};
Ok(Request {
header,
body,
auth: auth.try_into()?,
})
}
fn response_to_result(
&self,
response: Response,
expected_opcode: Opcode,
) -> Result<NativeResult> {
let status = response.header.status;
if status != ResponseStatus::Success {
return Err(Error::Service(status));
}
let opcode = response.header.opcode;
if opcode != expected_opcode {
return Err(Error::Client(ClientErrorKind::InvalidServiceResponseType));
}
Ok(self
.accept_converter
.body_to_result(response.body, opcode)
.map_err(ClientErrorKind::Interface)?)
}
pub fn process_operation(
&self,
operation: NativeOperation,
provider: ProviderId,
auth: &Authentication,
) -> Result<NativeResult> {
let req_opcode = operation.opcode();
let request = self.operation_to_request(operation, provider, auth)?;
let response = self.request_client.process_request(request)?;
self.response_to_result(response, req_opcode)
}
}
impl Default for OperationClient {
fn default() -> Self {
OperationClient {
content_converter: Box::from(ProtobufConverter {}),
accept_converter: Box::from(ProtobufConverter {}),
request_client: Default::default(),
}
}
}
impl crate::BasicClient {
pub fn set_request_body_converter(
&mut self,
content_converter: Box<dyn Convert + Send + Sync>,
) {
self.op_client.content_converter = content_converter;
}
pub fn set_response_body_converter(
&mut self,
accept_converter: Box<dyn Convert + Send + Sync>,
) {
self.op_client.accept_converter = accept_converter;
}
}