mod client_object;
pub(crate) mod client_socket;
pub(crate) mod event_queue;
mod server_spec;
use crate::implementation::client::ProtocolImplementations;
use crate::implementation::object;
use std::os::fd;
use std::sync::atomic;
use std::{path, sync};
pub struct Client(pub(crate) sync::Arc<client_socket::ClientSocket>);
impl Client {
pub fn connect<P>(path: P) -> crate::Result<Self>
where
P: AsRef<path::Path>,
{
Ok(Self(client_socket::ClientSocket::connect(path)?))
}
pub fn from_fd<F>(fd: F) -> crate::Result<Self>
where
F: Into<fd::OwnedFd>,
{
Ok(Self(client_socket::ClientSocket::from_fd(fd)?))
}
pub fn new_event_queue(&self) -> event_queue::EventQueue {
event_queue::EventQueue::new(sync::Arc::clone(&self.0))
}
pub fn add_implementation<I>(&mut self)
where
I: ProtocolImplementations + 'static,
{
self.0.add_implementation(Box::new(I::new()));
}
#[must_use]
pub fn extract_loop_fd(&self) -> fd::BorrowedFd<'_> {
self.0.extract_loop_fd()
}
#[must_use]
pub fn is_handshake_done(&self) -> bool {
self.0.handshake_done.load(atomic::Ordering::Relaxed)
}
pub fn bind<O, D>(
&self,
event_queue: &event_queue::EventQueue,
state: &mut D,
version: u32,
) -> crate::Result<O>
where
O: crate::Object,
O::ProtocolImpl: ProtocolImplementations,
D: crate::Dispatch<O> + 'static,
{
let advertised = self
.0
.get_spec(O::ProtocolImpl::spec_name())
.ok_or(crate::Error::ProtocolNotFound)?;
let spec = server_spec::ServerSpec::<O::ProtocolImpl>::new(advertised.version());
let obj = self.0.bind_protocol(event_queue, &spec, version)?;
let typed = O::from_object::<D>(sync::Arc::clone(&obj) as sync::Arc<dyn object::Object>);
self.0.wait_for_object(event_queue, &obj, state)?;
Ok(typed)
}
#[must_use]
pub fn get_spec<I>(&self) -> Option<server_spec::ServerSpec<I>>
where
I: ProtocolImplementations,
{
self.0
.get_spec(I::spec_name())
.map(|spec| server_spec::ServerSpec::new(spec.version()))
}
#[must_use]
pub fn object_for_seq(&self, seq: u32) -> Option<sync::Arc<dyn object::Object>> {
self.0
.object_for_seq(seq)
.map(|obj| obj as sync::Arc<dyn object::Object>)
}
#[must_use]
pub fn object_for_id(&self, id: u32) -> Option<sync::Arc<dyn object::Object>> {
self.0
.object_for_id(id)
.map(|obj| obj as sync::Arc<dyn object::Object>)
}
}