razor_stream/client/task.rs
1//! Trait and utils for client-side task
2//!
3//! Provided Macros
4//!
5//! - [`#[client_task]`](macro@client_task): For defining a client-side RPC task on a struct. It will not generate ClientTask trait (it's optional to you to define ClientTaskAction with it)
6//! - [`#[client_task_enum]`](macro@client_task_enum): For creating an enum that delegates to client task variants. It will generate ClientTask trait for the enum
7
8use crate::proto::RpcAction;
9use crate::{
10 Codec,
11 error::{EncodedErr, RpcErrCodec, RpcError, RpcIntErr},
12};
13use std::fmt;
14use std::ops::DerefMut;
15
16pub use razor_stream_macros::{client_task, client_task_enum};
17
18/// Sum up trait for client task, including request and response
19pub trait ClientTask:
20 ClientTaskAction
21 + ClientTaskEncode
22 + ClientTaskDecode
23 + ClientTaskDone
24 + DerefMut<Target = ClientTaskCommon>
25 + Send
26 + Sized
27 + 'static
28 + fmt::Debug
29 + Unpin
30{
31}
32
33/// Encode the request to buffer that can be send to server
34pub trait ClientTaskEncode {
35 /// sererialized the msg into buf (with std::io::Writer), and return the size written
36 fn encode_req<C: Codec>(&self, codec: &C, buf: &mut Vec<u8>) -> Result<usize, ()>;
37
38 /// Contain optional extra data to send to server side.
39 ///
40 /// By Default, return None when client task does not have a req_blob field
41 #[inline(always)]
42 fn get_req_blob(&self) -> Option<&[u8]> {
43 None
44 }
45}
46
47/// Decode the response from server and assign to the task struct
48pub trait ClientTaskDecode {
49 fn decode_resp<C: Codec>(&mut self, codec: &C, buf: &[u8]) -> Result<(), ()>;
50
51 /// You can call crate::io::AllocateBuf::reserve(_size) on the following types:
52 /// `Option<Vec<u8>>`, `Vec<u8>`, `Option<io_buffer::Buffer>`, `io_buffer::Buffer`
53 ///
54 /// By Default, return None when client task does not have a resp_blob field
55 #[inline(always)]
56 fn reserve_resp_blob(&mut self, _size: i32) -> Option<&mut [u8]> {
57 None
58 }
59}
60
61/// client_task_enum should impl this for user, not used by framework
62pub trait ClientTaskGetResult<E: RpcErrCodec> {
63 /// Check the result of the task
64 fn get_result(&self) -> Result<(), &RpcError<E>>;
65}
66
67/// How to get notify from Rpc framework to user when a task is done
68///
69/// The rpc framework first call set_ok or set_xxx_error, then call done
70pub trait ClientTaskDone: Sized + 'static {
71 /// Set the custom error Called by RPC transport layer.
72 /// the last_index and conf_ver is for FailoverPool callback to original ClientTask
73 fn set_custom_error<C: Codec>(
74 &mut self, codec: &C, e: EncodedErr, last_index: usize, conf_ver: u64,
75 );
76
77 fn set_rpc_error(&mut self, e: RpcIntErr);
78
79 fn set_ok(&mut self);
80
81 fn done(self);
82}
83
84/// Get RpcAction from a enum task, or a sub-type that fits multiple RpcActions
85pub trait ClientTaskAction {
86 fn get_action<'a>(&'a self) -> RpcAction<'a>;
87}
88
89/// A common struct for every ClientTask
90///
91/// The fields might be extended in the future
92#[derive(Debug, Default)]
93pub struct ClientTaskCommon {
94 /// Every task should be assigned an ID which is unique inside a socket connection
95 pub seq: u64,
96}
97
98impl ClientTaskCommon {
99 pub fn seq(&self) -> u64 {
100 self.seq
101 }
102 pub fn set_seq(&mut self, seq: u64) {
103 self.seq = seq;
104 }
105}