pub struct Connection<S: Socket> { /* private fields */ }
Expand description
A connection.
The low-level API to send and receive messages.
Each connection gets a unique identifier when created that can be queried using
Connection::id
. This ID is shared betwen the read and write halves of the connection. It
can be used to associate the read and write halves of the same connection.
§Cancel safety
All async methods of this type are cancel safe unless explicitly stated otherwise in its documentation.
Implementations§
Source§impl<S> Connection<S>where
S: Socket,
impl<S> Connection<S>where
S: Socket,
Sourcepub fn read(&self) -> &ReadConnection<S::ReadHalf>
pub fn read(&self) -> &ReadConnection<S::ReadHalf>
The reference to the read half of the connection.
Sourcepub fn read_mut(&mut self) -> &mut ReadConnection<S::ReadHalf>
pub fn read_mut(&mut self) -> &mut ReadConnection<S::ReadHalf>
The mutable reference to the read half of the connection.
Sourcepub fn write(&self) -> &WriteConnection<S::WriteHalf>
pub fn write(&self) -> &WriteConnection<S::WriteHalf>
The reference to the write half of the connection.
Sourcepub fn write_mut(&mut self) -> &mut WriteConnection<S::WriteHalf>
pub fn write_mut(&mut self) -> &mut WriteConnection<S::WriteHalf>
The mutable reference to the write half of the connection.
Sourcepub fn split(
self,
) -> (ReadConnection<S::ReadHalf>, WriteConnection<S::WriteHalf>)
pub fn split( self, ) -> (ReadConnection<S::ReadHalf>, WriteConnection<S::WriteHalf>)
Split the connection into read and write halves.
Sourcepub fn join(
read: ReadConnection<S::ReadHalf>,
write: WriteConnection<S::WriteHalf>,
) -> Self
pub fn join( read: ReadConnection<S::ReadHalf>, write: WriteConnection<S::WriteHalf>, ) -> Self
Join the read and write halves into a connection (the opposite of Connection::split
).
Sourcepub async fn send_call<Method>(&mut self, call: &Call<Method>) -> Result<()>
pub async fn send_call<Method>(&mut self, call: &Call<Method>) -> Result<()>
Sends a method call.
Convenience wrapper around WriteConnection::send_call
.
Sourcepub async fn receive_reply<'r, ReplyParams, ReplyError>(
&'r mut self,
) -> Result<Result<ReplyParams, ReplyError>>
pub async fn receive_reply<'r, ReplyParams, ReplyError>( &'r mut self, ) -> Result<Result<ReplyParams, ReplyError>>
Receives a method call reply.
Convenience wrapper around ReadConnection::receive_reply
.
Sourcepub async fn call_method<'r, Method, ReplyParams, ReplyError>(
&'r mut self,
call: &Call<Method>,
) -> Result<Result<ReplyParams, ReplyError>>where
Method: Serialize + Debug,
ReplyParams: Deserialize<'r> + Debug,
ReplyError: Deserialize<'r> + Debug,
pub async fn call_method<'r, Method, ReplyParams, ReplyError>(
&'r mut self,
call: &Call<Method>,
) -> Result<Result<ReplyParams, ReplyError>>where
Method: Serialize + Debug,
ReplyParams: Deserialize<'r> + Debug,
ReplyError: Deserialize<'r> + Debug,
Call a method and receive a reply.
This is a convenience method that combines Connection::send_call
and
Connection::receive_reply
.
Sourcepub async fn receive_call<'m, Method>(&'m mut self) -> Result<Call<Method>>where
Method: Deserialize<'m> + Debug,
pub async fn receive_call<'m, Method>(&'m mut self) -> Result<Call<Method>>where
Method: Deserialize<'m> + Debug,
Receive a method call over the socket.
Convenience wrapper around ReadConnection::receive_call
.
Sourcepub async fn send_reply<ReplyParams>(
&mut self,
reply: &Reply<ReplyParams>,
) -> Result<()>
pub async fn send_reply<ReplyParams>( &mut self, reply: &Reply<ReplyParams>, ) -> Result<()>
Send a reply over the socket.
Convenience wrapper around WriteConnection::send_reply
.
Sourcepub async fn send_error<ReplyError>(&mut self, error: &ReplyError) -> Result<()>
pub async fn send_error<ReplyError>(&mut self, error: &ReplyError) -> Result<()>
Send an error reply over the socket.
Convenience wrapper around WriteConnection::send_error
.
Sourcepub fn enqueue_call<Method>(&mut self, method: &Call<Method>) -> Result<()>
pub fn enqueue_call<Method>(&mut self, method: &Call<Method>) -> Result<()>
Enqueue a call to the server.
Convenience wrapper around WriteConnection::enqueue_call
.
Sourcepub async fn flush(&mut self) -> Result<()>
pub async fn flush(&mut self) -> Result<()>
Flush the connection.
Convenience wrapper around WriteConnection::flush
.
Sourcepub fn chain_call<'c, Method, ReplyParams, ReplyError>(
&'c mut self,
call: &Call<Method>,
) -> Result<Chain<'c, S, ReplyParams, ReplyError>>where
Method: Serialize + Debug,
ReplyParams: Deserialize<'c> + Debug,
ReplyError: Deserialize<'c> + Debug,
pub fn chain_call<'c, Method, ReplyParams, ReplyError>(
&'c mut self,
call: &Call<Method>,
) -> Result<Chain<'c, S, ReplyParams, ReplyError>>where
Method: Serialize + Debug,
ReplyParams: Deserialize<'c> + Debug,
ReplyError: Deserialize<'c> + Debug,
Start a chain of method calls.
This allows batching multiple calls together and sending them in a single write operation.
§Examples
§Basic Usage with Sequential Access
use zlink_core::{Connection, Call, reply};
use serde::{Serialize, Deserialize};
use serde_prefix_all::prefix_all;
use futures_util::{pin_mut, stream::StreamExt};
#[prefix_all("org.example.")]
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "method", content = "parameters")]
enum Methods {
GetUser { id: u32 },
GetProject { id: u32 },
}
#[derive(Debug, Deserialize)]
struct User { name: String }
#[derive(Debug, Deserialize)]
struct Project { title: String }
#[derive(Debug, zlink_core::ReplyError)]
#[zlink(
interface = "org.example",
// Not needed in the real code because you'll use `ReplyError` through `zlink` crate.
crate = "zlink_core",
)]
enum ApiError {
UserNotFound { code: i32 },
ProjectNotFound { code: i32 },
}
let get_user = Call::new(Methods::GetUser { id: 1 });
let get_project = Call::new(Methods::GetProject { id: 2 });
// Chain calls and send them in a batch
let replies = conn
.chain_call::<Methods, User, ApiError>(&get_user)?
.append(&get_project)?
.send().await?;
pin_mut!(replies);
// Access replies sequentially - types are now fixed by the chain
let user_reply = replies.next().await.unwrap()?;
let project_reply = replies.next().await.unwrap()?;
match user_reply {
Ok(user) => println!("User: {}", user.parameters().unwrap().name),
Err(error) => println!("User error: {:?}", error),
}
§Arbitrary Number of Calls
#[zlink(
interface = "org.example",
// Not needed in the real code because you'll use `ReplyError` through `zlink` crate.
crate = "zlink_core",
)]
// Chain many calls (no upper limit)
let mut chain = conn.chain_call::<Methods, User, ApiError>(&get_user)?;
for i in 2..100 {
chain = chain.append(&Call::new(Methods::GetUser { id: i }))?;
}
let replies = chain.send().await?;
pin_mut!(replies);
// Process all replies sequentially - types are fixed by the chain
while let Some(user_reply) = replies.next().await {
let user_reply = user_reply?;
// Handle each reply...
match user_reply {
Ok(user) => println!("User: {}", user.parameters().unwrap().name),
Err(error) => println!("Error: {:?}", error),
}
}
§Performance Benefits
Instead of multiple write operations, the chain sends all calls in a single write operation, reducing context switching and therefore minimizing latency.