feat: add async support
This commit is contained in:
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# v0.2.0
|
||||||
|
|
||||||
|
* Added async client support behind a non-default cargo feature flag using tokio's `AsyncRead` and `AsyncWrite`.
|
||||||
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -273,13 +273,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pamsock"
|
name = "pamsock"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"clap",
|
"clap",
|
||||||
"pam",
|
"pam",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@@ -367,6 +374,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.49.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pamsock"
|
name = "pamsock"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
async = ["dep:tokio"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anstyle = "1.0.13"
|
anstyle = "1.0.13"
|
||||||
clap = { version = "4.5.60", features = ["derive"] }
|
clap = { version = "4.5.60", features = ["derive"] }
|
||||||
pam = "0.8.0"
|
pam = "0.8.0"
|
||||||
|
|
||||||
|
tokio = { version = "1.49.0", optional = true }
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
pedantic = { level = "deny", priority = -1 }
|
pedantic = { level = "deny", priority = -1 }
|
||||||
nursery = { level = "deny", priority = -1 }
|
nursery = { level = "deny", priority = -1 }
|
||||||
|
|||||||
62
src/lib.rs
62
src/lib.rs
@@ -80,6 +80,19 @@ pub mod prot {
|
|||||||
ServerResponse::from_u8(ucom::read_u8(&mut stream)?)
|
ServerResponse::from_u8(ucom::read_u8(&mut stream)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
#[cfg(feature = "async")]
|
||||||
|
pub async fn attempt_login_async(
|
||||||
|
mut stream: impl tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin,
|
||||||
|
user: &str,
|
||||||
|
passwd: &str,
|
||||||
|
) -> Option<ServerResponse> {
|
||||||
|
ucom_async::write_str(&mut stream, user).await?;
|
||||||
|
ucom_async::write_str(&mut stream, passwd).await?;
|
||||||
|
|
||||||
|
ServerResponse::from_u8(ucom_async::read_u8(&mut stream).await?)
|
||||||
|
}
|
||||||
|
|
||||||
pub mod ucom {
|
pub mod ucom {
|
||||||
//! # µcom
|
//! # µcom
|
||||||
//!
|
//!
|
||||||
@@ -123,4 +136,53 @@ pub mod prot {
|
|||||||
into.write_all(&size_buf).ok()
|
into.write_all(&size_buf).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "async")]
|
||||||
|
pub mod ucom_async {
|
||||||
|
//! # µcom_async
|
||||||
|
//!
|
||||||
|
//! Analogous to [`super::ucom`] but asynchronous.
|
||||||
|
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
|
pub async fn read_duple(from: &mut (impl AsyncRead + Unpin)) -> Option<(String, String)> {
|
||||||
|
let user = read_str(from).await?;
|
||||||
|
let pass = read_str(from).await?;
|
||||||
|
Some((user, pass))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_str(from: &mut (impl AsyncRead + Unpin)) -> Option<String> {
|
||||||
|
let size = read_u8(from).await? as usize;
|
||||||
|
let mut buf = vec![0; size];
|
||||||
|
from.read_exact(&mut buf).await.ok()?;
|
||||||
|
String::from_utf8(buf).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_u8(from: &mut (impl AsyncRead + Unpin)) -> Option<u8> {
|
||||||
|
let mut size_buf = [0; 1];
|
||||||
|
from.read_exact(&mut size_buf).await.ok()?;
|
||||||
|
Some(u8::from_be_bytes(size_buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_duple(
|
||||||
|
into: &mut (impl AsyncWrite + Unpin),
|
||||||
|
user: &str,
|
||||||
|
pass: &str,
|
||||||
|
) -> Option<()> {
|
||||||
|
write_str(into, user).await?;
|
||||||
|
write_str(into, pass).await?;
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_str(into: &mut (impl AsyncWrite + Unpin), str: &str) -> Option<()> {
|
||||||
|
let buf = str.as_bytes();
|
||||||
|
write_u8(into, buf.len().try_into().ok()?).await?;
|
||||||
|
into.write_all(buf).await.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_u8(into: &mut (impl AsyncWrite + Unpin), u8: u8) -> Option<()> {
|
||||||
|
let size_buf = u8.to_be_bytes();
|
||||||
|
into.write_all(&size_buf).await.ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user