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 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 result.
72 /// Called by RPC framework
73 fn set_custom_error<C: Codec>(&mut self, codec: &C, e: EncodedErr);
74
75 /// Called by RPC framework
76 fn set_rpc_error(&mut self, e: RpcIntErr);
77
78 fn set_ok(&mut self);
79
80 fn done(self);
81}
82
83/// Get RpcAction from a enum task, or a sub-type that fits multiple RpcActions
84pub trait ClientTaskAction {
85 fn get_action<'a>(&'a self) -> RpcAction<'a>;
86}
87
88/// A common struct for every ClientTask
89///
90/// The fields might be extended in the future
91#[derive(Debug, Default)]
92pub struct ClientTaskCommon {
93 /// Every task should be assigned an ID which is unique inside a socket connection
94 pub seq: u64,
95}
96
97impl ClientTaskCommon {
98 pub fn seq(&self) -> u64 {
99 self.seq
100 }
101 pub fn set_seq(&mut self, seq: u64) {
102 self.seq = seq;
103 }
104}