diff options
Diffstat (limited to 'src/ipc.rs')
-rw-r--r-- | src/ipc.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/ipc.rs b/src/ipc.rs new file mode 100644 index 0000000..f3e7d0a --- /dev/null +++ b/src/ipc.rs @@ -0,0 +1,83 @@ +use std::fmt::{Display, Formatter}; + +use bincode::{Decode, Encode}; +use paste::paste; + +pub trait RequestDefinition: Encode { + type Response: ResponseDefinition; + fn into_request(self) -> IPCRequest; +} + +pub trait ResponseDefinition: Sized + Decode { + type Error: std::error::Error; + fn from_response(response: IPCResponse) -> Option<Result<Self, Self::Error>>; + fn into_response(self) -> IPCResponse; +} + +macro_rules! define { + ($(@$name:ident { $($req_n:ident: $req_t:ty),* } => { $($resp_n:ident: $resp_t:ty)* } | $($error:ident),*)*) => { + $( + paste! { + #[derive(Encode, Decode)] + pub struct [<$name Request>] { $(pub $req_n: $req_t),* } + impl RequestDefinition for [<$name Request>] { + type Response = [<$name Response>]; + fn into_request(self) -> IPCRequest { + IPCRequest::$name(self) + } + } + + #[derive(Encode, Decode)] + pub struct [<$name Response>] { $(pub $resp_n: $resp_t),* } + impl ResponseDefinition for [<$name Response>] { + type Error = [<$name Error>]; + fn from_response(response: IPCResponse) -> Option<Result<Self, Self::Error>> { + match response { + IPCResponse::$name(inner) => Some(inner), + _ => None, + } + } + fn into_response(self) -> IPCResponse { + IPCResponse::$name(Ok(self)) + } + } + + #[derive(Encode, Decode, Debug)] + pub enum [<$name Error>] { + $($error,)* + } + + impl Display for [<$name Error>] { + #[allow(unused)] + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match *self { + $(Self::$error => f.write_str(stringify!($error)),)* + } + } + } + + impl std::error::Error for [<$name Error>] {} + } + )* + #[derive(Encode, Decode)] + pub enum IPCRequest { + $( + $name(paste!([<$name Request>])), + )* + } + #[derive(Encode, Decode)] + pub enum IPCResponse { + $( + $name(Result<paste!([<$name Response>]), paste!([<$name Error>])>), + )* + } + }; +} + +define! { + @ListAccounts {} => { names: Vec<String> } | + @GetAccount { name: String } => { scopes: Vec<String> } | NotFound + @DeleteAccount { name: String } => {} | + @CreateInvite {} => { link: String } | + @UpdateScopes { account: String, scopes: Vec<String> } => {} | NotFound +} |