parsec_client/core/
operation_client.rs1#![allow(dead_code)]
5
6use super::request_client::RequestClient;
7use crate::auth::Authentication;
8use crate::error::{ClientErrorKind, Error, Result};
9use derivative::Derivative;
10use parsec_interface::operations::{Convert, NativeOperation, NativeResult};
11use parsec_interface::operations_protobuf::ProtobufConverter;
12use parsec_interface::requests::{
13 request::RequestHeader, Opcode, ProviderId, Request, Response, ResponseStatus,
14};
15use std::convert::TryInto;
16
17#[derive(Derivative)]
21#[derivative(Debug)]
22pub struct OperationClient {
23 #[derivative(Debug = "ignore")]
27 pub content_converter: Box<dyn Convert + Send + Sync>,
28 #[derivative(Debug = "ignore")]
32 pub accept_converter: Box<dyn Convert + Send + Sync>,
33 pub request_client: RequestClient,
35}
36
37#[allow(clippy::new_without_default)]
38impl OperationClient {
39 pub fn new() -> Result<OperationClient> {
44 Ok(OperationClient {
45 request_client: RequestClient::new()?,
46 ..Default::default()
47 })
48 }
49
50 fn operation_to_request(
51 &self,
52 operation: NativeOperation,
53 provider: ProviderId,
54 auth: &Authentication,
55 ) -> Result<Request> {
56 let opcode = operation.opcode();
57 let body = self
58 .content_converter
59 .operation_to_body(operation)
60 .map_err(ClientErrorKind::Interface)?;
61 let header = RequestHeader {
62 provider,
63 session: 0, content_type: self.content_converter.body_type(),
65 accept_type: self.accept_converter.body_type(),
66 auth_type: auth.auth_type(),
67 opcode,
68 };
69
70 Ok(Request {
71 header,
72 body,
73 auth: auth.try_into()?,
74 })
75 }
76
77 fn response_to_result(
78 &self,
79 response: Response,
80 expected_opcode: Opcode,
81 ) -> Result<NativeResult> {
82 let status = response.header.status;
83 if status != ResponseStatus::Success {
84 return Err(Error::Service(status));
85 }
86 let opcode = response.header.opcode;
87 if opcode != expected_opcode {
88 return Err(Error::Client(ClientErrorKind::InvalidServiceResponseType));
89 }
90 Ok(self
91 .accept_converter
92 .body_to_result(response.body, opcode)
93 .map_err(ClientErrorKind::Interface)?)
94 }
95
96 pub fn process_operation(
104 &self,
105 operation: NativeOperation,
106 provider: ProviderId,
107 auth: &Authentication,
108 ) -> Result<NativeResult> {
109 let req_opcode = operation.opcode();
110 let request = self.operation_to_request(operation, provider, auth)?;
111
112 let response = self.request_client.process_request(request)?;
113 self.response_to_result(response, req_opcode)
114 }
115}
116
117impl Default for OperationClient {
118 fn default() -> Self {
119 OperationClient {
120 content_converter: Box::from(ProtobufConverter {}),
121 accept_converter: Box::from(ProtobufConverter {}),
122 request_client: Default::default(),
123 }
124 }
125}
126
127impl crate::BasicClient {
129 pub fn set_request_body_converter(
133 &mut self,
134 content_converter: Box<dyn Convert + Send + Sync>,
135 ) {
136 self.op_client.content_converter = content_converter;
137 }
138
139 pub fn set_response_body_converter(
143 &mut self,
144 accept_converter: Box<dyn Convert + Send + Sync>,
145 ) {
146 self.op_client.accept_converter = accept_converter;
147 }
148}