use std::{ptr, slice};
use std::ops::{Deref, DerefMut};
use crate::error::Result;
#[derive(Debug)]
pub struct Message
{
msgp: *mut nng_sys::nng_msg,
body: Body,
header: Header,
}
impl Message
{
pub(crate) unsafe fn from_ptr(msgp: *mut nng_sys::nng_msg) -> Self
{
Message {
msgp,
body: Body { msgp },
header: Header { msgp },
}
}
pub(crate) unsafe fn into_ptr(self) -> *mut nng_sys::nng_msg
{
let ptr = self.msgp;
std::mem::forget(self);
ptr
}
pub fn new() -> Result<Self>
{
let mut msgp: *mut nng_sys::nng_msg = ptr::null_mut();
let rv = unsafe {
nng_sys::nng_msg_alloc(&mut msgp as _, 0)
};
validate_ptr!(rv, msgp);
Ok(unsafe { Message::from_ptr(msgp) })
}
pub fn with_capacity(cap: usize) -> Result<Self>
{
let mut msgp: *mut nng_sys::nng_msg = ptr::null_mut();
let rv = unsafe {
nng_sys::nng_msg_alloc(&mut msgp as _, cap)
};
validate_ptr!(rv, msgp);
unsafe { nng_sys::nng_msg_clear(msgp); }
Ok(unsafe { Message::from_ptr(msgp) })
}
pub fn zeros(size: usize) -> Result<Self>
{
let mut msgp: *mut nng_sys::nng_msg = ptr::null_mut();
let rv = unsafe {
nng_sys::nng_msg_alloc(&mut msgp as _, size)
};
validate_ptr!(rv, msgp);
Ok(unsafe { Message::from_ptr(msgp) })
}
pub fn try_from(s: &[u8]) -> Result<Self>
{
let mut msgp: *mut nng_sys::nng_msg = ptr::null_mut();
let rv = unsafe {
nng_sys::nng_msg_alloc(&mut msgp as _, s.len())
};
validate_ptr!(rv, msgp);
unsafe { ptr::copy_nonoverlapping(s.as_ptr(), nng_sys::nng_msg_body(msgp) as _, s.len()) }
Ok(unsafe { Message::from_ptr(msgp) })
}
pub fn try_clone(&self) -> Result<Self>
{
let mut msgp: *mut nng_sys::nng_msg = ptr::null_mut();
let rv = unsafe {
nng_sys::nng_msg_dup(&mut msgp as _, self.msgp)
};
validate_ptr!(rv, msgp);
Ok(unsafe { Message::from_ptr(msgp) })
}
pub fn body(&self) -> &Body
{
&self.body
}
pub fn body_mut(&mut self) -> &mut Body
{
&mut self.body
}
pub fn header(&self) -> &Header
{
&self.header
}
pub fn header_mut(&mut self) -> &mut Header
{
&mut self.header
}
}
impl Drop for Message
{
fn drop(&mut self)
{
unsafe {
nng_sys::nng_msg_free(self.msgp);
}
}
}
unsafe impl Send for Message {}
unsafe impl Sync for Message {}
impl Clone for Message
{
fn clone(&self) -> Self
{
self.try_clone().expect("Nng failed to duplicate the message")
}
}
impl<'a> From<&'a [u8]> for Message
{
fn from(s: &[u8]) -> Message
{
Message::try_from(s).expect("Nng failed to allocate the memory")
}
}
impl Deref for Message
{
type Target = Body;
fn deref(&self) -> &Body
{
&self.body
}
}
impl DerefMut for Message
{
fn deref_mut(&mut self) -> &mut Body
{
&mut self.body
}
}
#[derive(Debug)]
pub struct Body
{
msgp: *mut nng_sys::nng_msg,
}
impl Body
{
pub fn push_back(&mut self, data: &[u8]) -> Result<()>
{
let rv = unsafe {
nng_sys::nng_msg_append(self.msgp, data.as_ptr() as _, data.len())
};
rv2res!(rv)
}
pub fn truncate(&mut self, len: usize)
{
let rv = unsafe {
let current_len = nng_sys::nng_msg_len(self.msgp);
nng_sys::nng_msg_chop(self.msgp, current_len.saturating_sub(len))
};
assert!(rv == 0, "Message was too short to truncate");
}
pub fn clear(&mut self)
{
unsafe {
nng_sys::nng_msg_clear(self.msgp);
}
}
pub fn push_front(&mut self, data: &[u8]) -> Result<()>
{
let rv = unsafe {
nng_sys::nng_msg_insert(self.msgp, data.as_ptr() as _, data.len())
};
rv2res!(rv)
}
pub fn reserve(&mut self, additional: usize) -> Result<()>
{
let rv = unsafe {
let current_len = nng_sys::nng_msg_len(self.msgp);
nng_sys::nng_msg_realloc(self.msgp, current_len + additional)
};
rv2res!(rv)
}
pub fn trim(&mut self, len: usize) -> Result<()>
{
let rv = unsafe {
nng_sys::nng_msg_trim(self.msgp, len)
};
rv2res!(rv)
}
}
unsafe impl Send for Body {}
unsafe impl Sync for Body {}
impl Deref for Body
{
type Target = [u8];
fn deref(&self) -> &[u8]
{
unsafe {
let ptr = nng_sys::nng_msg_body(self.msgp);
let len = nng_sys::nng_msg_len(self.msgp);
slice::from_raw_parts(ptr as _, len)
}
}
}
impl DerefMut for Body
{
fn deref_mut(&mut self) -> &mut [u8]
{
unsafe {
let ptr = nng_sys::nng_msg_body(self.msgp);
let len = nng_sys::nng_msg_len(self.msgp);
slice::from_raw_parts_mut(ptr as _, len)
}
}
}
#[derive(Debug)]
pub struct Header
{
msgp: *mut nng_sys::nng_msg,
}
impl Header
{
pub fn push_back(&mut self, data: &[u8]) -> Result<()>
{
let rv = unsafe {
nng_sys::nng_msg_header_append(self.msgp, data.as_ptr() as _, data.len())
};
rv2res!(rv)
}
pub fn truncate(&mut self, len: usize)
{
let rv = unsafe {
let current_len = nng_sys::nng_msg_header_len(self.msgp);
nng_sys::nng_msg_header_chop(self.msgp, current_len.saturating_sub(len))
};
assert!(rv == 0, "Message was too short to truncate");
}
pub fn clear(&mut self)
{
unsafe {
nng_sys::nng_msg_header_clear(self.msgp);
}
}
pub fn push_front(&mut self, data: &[u8]) -> Result<()>
{
let rv = unsafe {
nng_sys::nng_msg_header_insert(self.msgp, data.as_ptr() as _, data.len())
};
rv2res!(rv)
}
pub fn trim(&mut self, len: usize) -> Result<()>
{
let rv = unsafe {
nng_sys::nng_msg_header_trim(self.msgp, len)
};
rv2res!(rv)
}
}
unsafe impl Send for Header {}
unsafe impl Sync for Header {}
impl Deref for Header
{
type Target = [u8];
fn deref(&self) -> &[u8]
{
unsafe {
let ptr = nng_sys::nng_msg_header(self.msgp);
let len = nng_sys::nng_msg_header_len(self.msgp);
slice::from_raw_parts(ptr as _, len)
}
}
}
impl DerefMut for Header
{
fn deref_mut(&mut self) -> &mut [u8]
{
unsafe {
let ptr = nng_sys::nng_msg_header(self.msgp);
let len = nng_sys::nng_msg_header_len(self.msgp);
slice::from_raw_parts_mut(ptr as _, len)
}
}
}