A simple macro library for RPC in rust
Go to file
Kodi Craft bfd4c1346f
All checks were successful
Build library & run tests / build (unix) (push) Successful in 28s
Build library & run tests / build (tcp) (push) Successful in 30s
Update README.md
2024-06-24 16:58:14 +02:00
.gitea/workflows Run clippy through nix now 2024-06-23 01:50:36 +02:00
src Update README.md 2024-06-24 16:58:14 +02:00
tests Update README.md 2024-06-24 16:58:14 +02:00
.envrc Move away from devenv.sh 2024-06-21 12:35:45 +02:00
.gitignore Implement basic derivation 2024-06-19 23:25:45 +02:00
.pre-commit-config.yaml Move away from devenv.sh 2024-06-21 12:35:45 +02:00
Cargo.lock Fully implement communication 2024-06-24 15:34:14 +02:00
Cargo.toml Fully implement communication 2024-06-24 15:34:14 +02:00
flake.lock Move away from devenv.sh 2024-06-21 12:35:45 +02:00
flake.nix Fully implement communication 2024-06-24 15:34:14 +02:00
LICENSE.md Implement basic derivation 2024-06-19 23:25:45 +02:00
README.md Update README.md 2024-06-24 16:58:14 +02:00

Eagle

Stability

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.

What is Eagle?

Eagle is a library which allows you to easily build an RPC 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.

Using Eagle

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:

use eagle::Protocol;
use serde::{Serialize, Deserliaze};

#[derive(Clone, Serialize, Deserialize)]
pub struct ExampleStruct {
    a: i32,
    b: i32
}

#[derive(Protocol)]
pub enum Example {
    Addition((i32, i32), i32),
    StructuredDataAlsoWorks(ExampleStruct, ()),
    SetState(i32, i32),
    GetState((), i32)
}

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 i32s 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:

use shared::ExampleServerHandler;

struct ExampleHandler {
    state: i32
}
impl ExampleServerHandler for ExampleHandler {
    async fn addition(&mut self, a: i32, b: i32) -> i32 {
        a + b
    }

    async fn get_state(&mut self) -> i32 {
        self.state
    }

    async fn set_state(&mut self, state: i32) -> i32 {
        self.state = state;
        self.state
    }

    /* ... */
}

Your handler can now be used by the server. You can easily bind your server to a socket with:

use shared::ExampleServer;

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.

use shared::ExampleClient;

let client = ExampleClient::connect("127.0.0.1:1234").await.unwrap();
assert_eq!(client.addition(5, 2), 7);

License

Eagle is licensed under the AGPL (GNU Affero General Public License). To learn more, read LICENSE.md