Skip to main content

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}