use std::{
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
hash::{Hash, Hasher},
sync::Arc,
};
use crate::{
aio::Aio,
error::{Result, SendResult},
message::Message,
socket::Socket,
};
#[derive(Clone, Debug)]
pub struct Context
{
inner: Arc<Inner>,
}
impl Context
{
pub fn new(socket: &Socket) -> Result<Context>
{
let mut ctx = nng_sys::nng_ctx::NNG_CTX_INITIALIZER;
let rv = unsafe { nng_sys::nng_ctx_open(&mut ctx as _, socket.handle()) };
rv2res!(rv, Context { inner: Arc::new(Inner { ctx }) })
}
pub fn send<M: Into<Message>>(&self, aio: &Aio, msg: M) -> SendResult<()>
{
let msg = msg.into();
aio.send_ctx(self, msg)
}
pub fn recv(&self, aio: &Aio) -> Result<()> { aio.recv_ctx(self) }
pub fn close(&self) { self.inner.close() }
pub(crate) fn handle(&self) -> nng_sys::nng_ctx { self.inner.ctx }
}
#[cfg(feature = "ffi-module")]
impl Context
{
pub fn nng_ctx(&self) -> nng_sys::nng_ctx { self.handle() }
}
impl PartialEq for Context
{
fn eq(&self, other: &Context) -> bool
{
unsafe { nng_sys::nng_ctx_id(self.inner.ctx) == nng_sys::nng_ctx_id(other.inner.ctx) }
}
}
impl Eq for Context {}
impl PartialOrd for Context
{
fn partial_cmp(&self, other: &Context) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl Ord for Context
{
fn cmp(&self, other: &Context) -> Ordering
{
unsafe {
let us = nng_sys::nng_ctx_id(self.inner.ctx);
let them = nng_sys::nng_ctx_id(other.inner.ctx);
us.cmp(&them)
}
}
}
impl Hash for Context
{
fn hash<H: Hasher>(&self, state: &mut H)
{
let id = unsafe { nng_sys::nng_ctx_id(self.inner.ctx) };
id.hash(state);
}
}
#[rustfmt::skip]
expose_options!{
Context :: inner.ctx -> nng_sys::nng_ctx;
GETOPT_BOOL = nng_sys::nng_ctx_get_bool;
GETOPT_INT = nng_sys::nng_ctx_get_int;
GETOPT_MS = nng_sys::nng_ctx_get_ms;
GETOPT_SIZE = nng_sys::nng_ctx_get_size;
GETOPT_SOCKADDR = nng_sys::nng_ctx_get_addr;
GETOPT_STRING = nng_sys::nng_ctx_get_string;
GETOPT_UINT64 = nng_sys::nng_ctx_get_uint64;
SETOPT = nng_sys::nng_ctx_set;
SETOPT_BOOL = nng_sys::nng_ctx_set_bool;
SETOPT_INT = nng_sys::nng_ctx_set_int;
SETOPT_MS = nng_sys::nng_ctx_set_ms;
SETOPT_PTR = nng_sys::nng_ctx_set_ptr;
SETOPT_SIZE = nng_sys::nng_ctx_set_size;
SETOPT_STRING = nng_sys::nng_ctx_set_string;
Gets -> [protocol::reqrep::ResendTime, protocol::survey::SurveyTime];
Sets -> [protocol::reqrep::ResendTime, protocol::survey::SurveyTime];
}
#[derive(Debug)]
struct Inner
{
ctx: nng_sys::nng_ctx,
}
impl Inner
{
fn close(&self)
{
let rv = unsafe { nng_sys::nng_ctx_close(self.ctx) };
assert!(
rv == 0 || rv == nng_sys::NNG_ECLOSED as i32,
"Unexpected error code while closing context ({})",
rv
);
}
}
impl Drop for Inner
{
fn drop(&mut self) { self.close() }
}