#![feature(
non_exhaustive,
integer_atomics,
try_trait,
futures_api,
pin,
arbitrary_self_types,
await_macro,
async_await,
)]
#![deny(missing_docs, missing_debug_implementations)]
pub mod client;
pub mod context;
pub mod server;
pub mod transport;
pub(crate) mod util;
pub use crate::{client::Client, server::Server, transport::Transport};
use futures::{
task::{Spawn, SpawnError, SpawnExt},
Future,
};
use std::{cell::RefCell, io, sync::Once, time::SystemTime};
#[derive(Debug)]
#[cfg_attr(
feature = "serde1",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub struct ClientMessage<T> {
pub trace_context: trace::Context,
pub message: ClientMessageKind<T>,
}
#[derive(Debug)]
#[cfg_attr(
feature = "serde1",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub enum ClientMessageKind<T> {
Request(Request<T>),
Cancel {
request_id: u64,
},
}
#[derive(Debug)]
#[cfg_attr(
feature = "serde1",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub struct Request<T> {
pub id: u64,
pub message: T,
#[cfg_attr(
feature = "serde1",
serde(serialize_with = "util::serde::serialize_epoch_secs")
)]
#[cfg_attr(
feature = "serde1",
serde(deserialize_with = "util::serde::deserialize_epoch_secs")
)]
pub deadline: SystemTime,
}
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(
feature = "serde1",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub struct Response<T> {
pub request_id: u64,
pub message: Result<T, ServerError>,
}
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(
feature = "serde1",
derive(serde::Serialize, serde::Deserialize)
)]
#[non_exhaustive]
pub struct ServerError {
#[cfg_attr(
feature = "serde1",
serde(serialize_with = "util::serde::serialize_io_error_kind_as_u32")
)]
#[cfg_attr(
feature = "serde1",
serde(deserialize_with = "util::serde::deserialize_io_error_kind_from_u32")
)]
pub kind: io::ErrorKind,
pub detail: Option<String>,
}
impl From<ServerError> for io::Error {
fn from(e: ServerError) -> io::Error {
io::Error::new(e.kind, e.detail.unwrap_or_default())
}
}
impl<T> Request<T> {
pub fn deadline(&self) -> &SystemTime {
&self.deadline
}
}
static INIT: Once = Once::new();
static mut SEED_SPAWN: Option<Box<dyn CloneSpawn>> = None;
thread_local! {
static SPAWN: RefCell<Box<dyn CloneSpawn>> = {
unsafe {
INIT.call_once(|| {});
RefCell::new(SEED_SPAWN.clone().expect("init() must be called."))
}
};
}
pub fn init(spawn: impl Spawn + Clone + 'static) {
unsafe {
INIT.call_once(|| {
SEED_SPAWN = Some(Box::new(spawn));
});
}
}
pub(crate) fn spawn(future: impl Future<Output = ()> + Send + 'static) -> Result<(), SpawnError> {
SPAWN.with(|spawn| spawn.borrow_mut().spawn(future))
}
trait CloneSpawn: Spawn {
fn box_clone(&self) -> Box<dyn CloneSpawn>;
}
impl Clone for Box<dyn CloneSpawn> {
fn clone(&self) -> Self {
self.box_clone()
}
}
impl<S: Spawn + Clone + 'static> CloneSpawn for S {
fn box_clone(&self) -> Box<dyn CloneSpawn> {
Box::new(self.clone())
}
}