use std::result;
use derive_more::{Display, From, TryInto};
use quic_rpc::{message::RpcMsg, RpcClient, RpcServer, Service};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct WriteRequest(String, Vec<u8>);
#[derive(Debug, Serialize, Deserialize, From, TryInto)]
enum IoRequest {
Write(WriteRequest),
}
#[derive(Debug, Display, Serialize, Deserialize)]
struct WriteError(String);
impl std::error::Error for WriteError {}
impl From<anyhow::Error> for WriteError {
fn from(e: anyhow::Error) -> Self {
WriteError(format!("{e:?}"))
}
}
#[derive(Debug, Serialize, Deserialize, From, TryInto)]
enum IoResponse {
Write(result::Result<(), WriteError>),
}
#[derive(Debug, Clone)]
struct IoService;
impl Service for IoService {
type Req = IoRequest;
type Res = IoResponse;
}
impl RpcMsg<IoService> for WriteRequest {
type Response = result::Result<(), WriteError>;
}
#[derive(Debug, Clone, Copy)]
struct Fs;
impl Fs {
async fn write(self, _req: WriteRequest) -> anyhow::Result<()> {
Ok(())
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let fs = Fs;
let (server, client) = quic_rpc::transport::flume::channel(1);
let client = RpcClient::<IoService, _>::new(client);
let server = RpcServer::new(server);
let handle = tokio::task::spawn(async move {
for _ in 0..1 {
let (req, chan) = server.accept().await?.read_first().await?;
match req {
IoRequest::Write(req) => chan.rpc_map_err(req, fs, Fs::write).await,
}?
}
anyhow::Ok(())
});
client
.rpc(WriteRequest("hello".to_string(), vec![0u8; 32]))
.await??;
handle.await??;
Ok(())
}