1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! An actor-like RPC framework built for true zero-copy message handling.
//!
//! This framework is inspired by tonic but is *not* a GRPC framework. Instead,
//! it makes use of the incredible [rkyv] (de)serialization framework which provides
//! us with lightning fast (de)serialization and also lets us perform true zero-copy
//! deserialization which can lead to massive performance improvements when processing
//! lots of big messages at once.
//!
//! ### Features
//! - Fast (de)serialization of owned types.
//! - True zero-copy deserialization avoiding heavy allocations.
//! - Dynamic adding and removing of message handlers/services.
//!
//! ### Basic example
//! ```rust
//! use std::net::SocketAddr;
//!
//! use datacake_rpc::{
//! Channel,
//! Handler,
//! Request,
//! RpcClient,
//! RpcService,
//! Server,
//! ServiceRegistry,
//! Status,
//! };
//! use rkyv::{Archive, Deserialize, Serialize};
//!
//! // The framework accepts any messages which implement `Archive` and `Serialize` along
//! // with the archived values implementing `CheckBytes` from the `bytecheck` crate.
//! // This is to ensure safe, validated deserialization of the values.
//! //
//! // Checkout rkyv for more information!
//! #[repr(C)]
//! #[derive(Serialize, Deserialize, Archive, PartialEq, Debug)]
//! #[archive(compare(PartialEq), check_bytes)]
//! #[archive_attr(derive(PartialEq, Debug))]
//! pub struct MyMessage {
//! name: String,
//! age: u32,
//! }
//!
//! pub struct MyService;
//!
//! impl RpcService for MyService {
//! // The `register_handlers` is used to mark messages as something
//! // the given service can handle and process.
//! //
//! // Messages which are not registered will not be dispatched to the handler.
//! fn register_handlers(registry: &mut ServiceRegistry<Self>) {
//! registry.add_handler::<MyMessage>();
//! }
//! }
//!
//! #[datacake_rpc::async_trait]
//! impl Handler<MyMessage> for MyService {
//! type Reply = String;
//!
//! // Our `Request` gives us a zero-copy view to our message, this doesn't actually
//! // allocate the message type.
//! async fn on_message(&self, msg: Request<MyMessage>) -> Result<Self::Reply, Status> {
//! Ok(msg.to_owned().unwrap().name)
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! let address = "127.0.0.1:8000".parse::<SocketAddr>()?;
//!
//! let server = Server::listen(address).await?;
//! // Services can be added and removed at runtime once the server is started.
//! server.add_service(MyService);
//! println!("Listening to address {}!", address);
//!
//! // Channels are cheap to clone similar to tonic.
//! let client = Channel::connect(address);
//! println!("Connected to address {}!", address);
//!
//! let rpc_client = RpcClient::<MyService>::new(client);
//!
//! let msg1 = MyMessage {
//! name: "Bobby".to_string(),
//! age: 12,
//! };
//!
//! // Clients only need references to the message which helps
//! // reduce allocations.
//! let resp = rpc_client.send(&msg1).await?;
//! assert_eq!(resp, msg1.name);
//! Ok(())
//! }
//! ```
extern crate tracing;
pub const SCRATCH_SPACE: usize = 4096;
use DefaultHasher;
use ;
/// A re-export of the async-trait macro.
pub use async_trait;
pub use Body;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Server;
pub use ;
pub Sized>
pub