eagle/README.md

93 lines
3.3 KiB
Markdown
Raw Normal View History

2024-06-19 23:25:45 +02:00
# Eagle
2024-06-24 16:58:14 +02:00
## Stability
2024-06-19 23:25:45 +02:00
2024-06-24 16:58:14 +02:00
Eagle is still in early development. Performance is not ideal and the interface is likely to change over time. However,
it is in a usable state currently.
2024-06-19 23:25:45 +02:00
## What is Eagle?
2024-06-24 16:58:14 +02:00
Eagle is a library which allows you to easily build an [RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) protocol.
It uses a macro to generate the required communication code and makes adding new functions easy and quick. Eagle is designed to work specifically with `tokio` and uses `serde` for formatting data.
2024-06-19 23:25:45 +02:00
## Using Eagle
2024-06-24 16:58:14 +02:00
The way that `eagle` is designed to be used is inside a shared dependency between your "server" and your "client". Both of these should be in a workspace. Create a `shared` crate which both components should depend on, this crate should have `eagle` as a dependency. By default `eagle` uses TCP for communication, but you may disable default features and enable the `unix` feature on `eagle` to use unix sockets instead.
Inside this crate, you can define your protocol as an enum:
2024-06-19 23:25:45 +02:00
```rs
use eagle::Protocol;
2024-06-24 16:58:14 +02:00
use serde::{Serialize, Deserliaze};
#[derive(Clone, Serialize, Deserialize)]
pub struct ExampleStruct {
a: i32,
b: i32
}
2024-06-19 23:25:45 +02:00
#[derive(Protocol)]
2024-06-24 16:58:14 +02:00
pub enum Example {
2024-06-19 23:25:45 +02:00
Addition((i32, i32), i32),
2024-06-24 16:58:14 +02:00
StructuredDataAlsoWorks(ExampleStruct, ()),
SetState(i32, i32),
GetState((), i32)
2024-06-19 23:25:45 +02:00
}
```
2024-06-24 16:58:14 +02:00
Each variant describes one of the functions that the client can call, the first field on a variant represents the arguments that the client can send and the second field represents the return value. In the example above, the `addition` function would take in two `i32`s and return another `i32`. Any data passed this way must implement `Clone` as well as `serde::Serialize` and `serde::Deserialize`.
Once your protocol is defined, you can implement it on your server. To do so, you must first implement a handler for your
protocol. A handler must implement `Clone` as well as the `ServerHandler` trait for your protocol. For the above example:
2024-06-19 23:25:45 +02:00
```rs
2024-06-24 16:58:14 +02:00
use shared::ExampleServerHandler;
2024-06-19 23:25:45 +02:00
2024-06-24 16:58:14 +02:00
struct ExampleHandler {
state: i32
}
impl ExampleServerHandler for ExampleHandler {
async fn addition(&mut self, a: i32, b: i32) -> i32 {
2024-06-19 23:25:45 +02:00
a + b
}
2024-06-24 16:58:14 +02:00
async fn get_state(&mut self) -> i32 {
self.state
}
async fn set_state(&mut self, state: i32) -> i32 {
self.state = state;
self.state
2024-06-19 23:25:45 +02:00
}
2024-06-24 16:58:14 +02:00
/* ... */
2024-06-19 23:25:45 +02:00
}
```
2024-06-24 16:58:14 +02:00
Your handler can now be used by the server. You can easily bind your server to a socket with:
2024-06-19 23:25:45 +02:00
```rs
2024-06-24 16:58:14 +02:00
use shared::ExampleServer;
2024-06-19 23:25:45 +02:00
2024-06-24 16:58:14 +02:00
let handler = ExampleHandler { state: 0 };
let server_task = tokio::spawn(ExampleServer::bind(handler, "127.0.0.1:1234"));
// Or, if you're using the 'unix' feature...
let server_task = tokio::spawn(ExampleServer::bind(handler, "/tmp/sock"));
```
Note that bind is an asynchronous function which should never return, you must put it in a separate task. Once bound, the server will await for connections and start responding to queries.
On the client, all you need to do is to use your protocol's `Client` to connect and you can start making requests.
```rs
use shared::ExampleClient;
let client = ExampleClient::connect("127.0.0.1:1234").await.unwrap();
assert_eq!(client.addition(5, 2), 7);
2024-06-19 23:25:45 +02:00
```
## License
2024-06-19 23:29:22 +02:00
Eagle is licensed under the AGPL (GNU Affero General Public License). To learn more, read [LICENSE.md](LICENSE.md)