🗝
summary refs log tree commit diff
path: root/src/ipc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipc.rs')
-rw-r--r--src/ipc.rs83
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
+}