plug/
lib.rs

1//! A library for type-safe interprocess communication.
2//!
3//! # Usage
4//! Define the input and output of a wired connection:
5//!
6//! ```
7//! use serde::{Deserialize, Serialize};
8//!
9//! #[derive(Serialize, Deserialize)]
10//! pub struct Credentials {
11//!     username: String,
12//!     password: String,
13//! }
14//!
15//! #[derive(Serialize, Deserialize)]
16//! pub enum Authentication {
17//!     Success { token: String },
18//!     Error { description: String },
19//! }
20//! ```
21//!
22//! Create a [`Plug`] for this specific action:
23//!
24//! ```
25//! # use serde::{Deserialize, Serialize};
26//! #
27//! # #[derive(Serialize, Deserialize)]
28//! # pub struct Credentials {
29//! #     username: String,
30//! #     password: String,
31//! # }
32//! #
33//! # #[derive(Serialize, Deserialize)]
34//! # pub enum Authentication {
35//! #     Success { token: String },
36//! #     Error { description: String },
37//! # }
38//! use plug::Plug;
39//!
40//! pub const LOG_IN: Plug<Credentials, Authentication> = Plug::new("log_in");
41//! ```
42//!
43//! Connect the [`Plug`] to the server leveraging type-safety:
44//!
45//! ```
46//! # use serde::{Deserialize, Serialize};
47//! #
48//! # #[derive(Serialize, Deserialize)]
49//! # pub struct Credentials {
50//! #     username: String,
51//! #     password: String,
52//! # }
53//! #
54//! # #[derive(Serialize, Deserialize)]
55//! # pub enum Authentication {
56//! #     Success { token: String },
57//! #     Error { description: String },
58//! # }
59//! # use plug::Plug;
60//! #
61//! # pub const LOG_IN: Plug<Credentials, Authentication> = Plug::new("log_in");
62//! #
63//! use std::io;
64//!
65//! async fn log_in(credentials: Credentials) -> io::Result<Authentication> {
66//!     let mut connection = LOG_IN.connect("127.0.0.1:1234").await?;
67//!
68//!     connection.write(credentials).await?;
69//!     connection.read().await
70//! }
71//! ```
72//!
73//! Implement the server by gathering all the [`Plug`] definitions in a [`Strip`]:
74//!
75//! ```
76//! # use serde::{Deserialize, Serialize};
77//! #
78//! # #[derive(Serialize, Deserialize)]
79//! # pub struct Credentials {
80//! #     username: String,
81//! #     password: String,
82//! # }
83//! #
84//! # #[derive(Serialize, Deserialize)]
85//! # pub enum Authentication {
86//! #     Success { token: String },
87//! #     Error { description: String },
88//! # }
89//! # use plug::Plug;
90//! #
91//! # pub const LOG_IN: Plug<Credentials, Authentication> = Plug::new("log_in");
92//! #
93//! use plug::{Connection, Strip};
94//!
95//! use std::io;
96//! use tokio::net;
97//! use tokio::task;
98//!
99//! async fn run_server() -> io::Result<()> {
100//!     let strip = Strip::new().plug(LOG_IN, log_in);
101//!     let server = net::TcpListener::bind("127.0.0.1:1234").await?;
102//!
103//!     loop {
104//!         let Ok((client, _address)) = server.accept().await else {
105//!             continue;
106//!         };
107//!
108//!         let _ = strip.attach(client).await;
109//!     }
110//! }
111//!
112//! async fn log_in(mut connection: Connection<Authentication, Credentials>) -> io::Result<()> {
113//!     let credentials = connection.read().await?;
114//!
115//!     let result = if credentials.username == "admin" && credentials.password == "1234" {
116//!         Authentication::Success { token: "verysecure".to_owned() }
117//!     } else {
118//!         Authentication::Error { description: "Invalid credentials!".to_owned() }
119//!     };
120//!
121//!     connection.write(result).await
122//! }
123//! ```
124mod connection;
125mod plug;
126mod strip;
127
128pub use connection::Connection;
129pub use plug::Plug;
130pub use strip::Strip;
131
132pub use std::convert::Infallible as Never;