nng_c/
msg.rs

1use core::{ops, ptr, slice, mem, fmt};
2
3use crate::error::{ErrorCode, error};
4
5use nng_c_sys::nng_msg;
6use nng_c_sys::{nng_msg_alloc, nng_msg_free, nng_msg_capacity, nng_msg_reserve};
7use nng_c_sys::{nng_msg_clear, nng_msg_dup};
8use nng_c_sys::{nng_msg_body, nng_msg_len};
9use nng_c_sys::{nng_msg_trim, nng_msg_chop};
10use nng_c_sys::{nng_msg_chop_u16, nng_msg_chop_u32, nng_msg_chop_u64};
11use nng_c_sys::{nng_msg_trim_u16, nng_msg_trim_u32, nng_msg_trim_u64};
12use nng_c_sys::{nng_msg_append, nng_msg_append_u16, nng_msg_append_u32, nng_msg_append_u64};
13use nng_c_sys::{nng_msg_insert, nng_msg_insert_u16, nng_msg_insert_u32, nng_msg_insert_u64};
14use nng_c_sys::{nng_msg_header, nng_msg_header_len};
15
16///Message primitive
17pub struct Message(pub(crate) ptr::NonNull<nng_msg>);
18
19impl Message {
20    #[inline(always)]
21    ///Creates empty message
22    ///
23    ///Returns `None` if unable to allocate memory
24    pub fn new() -> Option<Self> {
25        Self::with_capaicty(0)
26    }
27
28    #[inline]
29    ///Creates message with pre-allocated buffer of provided `size`
30    ///
31    ///Returns `None` if unable to allocate memory
32    pub fn with_capaicty(size: usize) -> Option<Self> {
33        let mut ptr = ptr::null_mut();
34        unsafe {
35            nng_msg_alloc(&mut ptr, size);
36        }
37
38        ptr::NonNull::new(ptr).map(Self)
39    }
40
41    #[inline]
42    ///Creates new copy of the message.
43    ///
44    ///Returns `None` if unable to allocate memory
45    pub fn dup(&self) -> Option<Self> {
46        let mut ptr = ptr::null_mut();
47        unsafe {
48            nng_msg_dup(&mut ptr, self.0.as_ptr());
49        }
50
51        ptr::NonNull::new(ptr).map(Self)
52    }
53
54    #[inline(always)]
55    ///Reserves additional space to accommodate specified `capacity`
56    ///
57    ///Does nothing, if message already has enough space.
58    ///
59    ///Returns error only if reallocation failed
60    pub fn reserve(&mut self, capacity: usize) -> Result<(), ErrorCode> {
61        let result = unsafe {
62            nng_msg_reserve(self.0.as_ptr(), capacity)
63        };
64
65        match result {
66            0 => Ok(()),
67            code => Err(error(code))
68        }
69    }
70
71    #[inline(always)]
72    ///Returns length of message body
73    pub fn len(&self) -> usize {
74        unsafe {
75            nng_msg_len(self.0.as_ptr())
76        }
77    }
78
79    #[inline(always)]
80    ///Returns capacity of message body
81    pub fn capaciy(&self) -> usize {
82        unsafe {
83            nng_msg_capacity(self.0.as_ptr())
84        }
85    }
86
87    #[inline(always)]
88    ///Clears content of the message.
89    ///
90    ///Note that it is primarily sets length of body to 0.
91    ///Allocated capacity remains the same.
92    pub fn clear(&mut self) {
93        unsafe {
94            nng_msg_clear(self.0.as_ptr())
95        }
96    }
97
98    #[inline(always)]
99    ///Shortens body length, keeping `len` starting elements
100    ///
101    ///Has no effect if `len` is equal or greater to current body's length
102    pub fn truncate(&mut self, len: usize) {
103        let size = self.len().saturating_sub(len);
104        unsafe {
105            nng_msg_chop(self.0.as_ptr(), size);
106        }
107    }
108
109    #[inline(always)]
110    ///Shortens body length, keeping `len` last elements inside
111    ///
112    ///Has no effect if `len` is equal or greater to current body's length
113    pub fn truncate_start(&mut self, len: usize) {
114        let size = self.len().saturating_sub(len);
115        unsafe {
116            nng_msg_trim(self.0.as_ptr(), size);
117        }
118    }
119
120    #[inline(always)]
121    ///Returns reference to the body content
122    pub fn body(&self) -> &[u8] {
123        let ptr = self.0.as_ptr();
124        unsafe {
125            let body = nng_msg_body(ptr);
126            let len = nng_msg_len(ptr);
127            slice::from_raw_parts(body as *const u8, len)
128        }
129    }
130
131    #[inline(always)]
132    ///Returns reference to the header content
133    pub fn header(&self) -> &[u8] {
134        let ptr = self.0.as_ptr();
135        unsafe {
136            let body = nng_msg_header(ptr);
137            let len = nng_msg_header_len(ptr);
138            slice::from_raw_parts(body as *const u8, len)
139        }
140    }
141
142    fn push_inner<T: Copy>(&mut self, value: T, insertor: unsafe extern "C" fn(*mut nng_msg, T) -> core::ffi::c_int) -> Result<(), ErrorCode> {
143        let result = unsafe {
144            (insertor)(self.0.as_ptr(), value)
145        };
146        match result {
147            0 => Ok(()),
148            code => Err(error(code)),
149        }
150    }
151
152    fn pop_inner<T: Copy>(&mut self, extractor: unsafe extern "C" fn(*mut nng_msg, *mut T) -> core::ffi::c_int) -> Option<T> {
153        let mut out = mem::MaybeUninit::uninit();
154        let result = unsafe {
155            (extractor)(self.0.as_ptr(), out.as_mut_ptr())
156        };
157        match result {
158            0 => Some(unsafe {
159                out.assume_init()
160            }),
161            _ => None
162        }
163    }
164
165    //pop
166    #[inline(always)]
167    ///Extracts u16 from the end of body, encoding it into native byte order
168    ///
169    ///Returns `None` if there is not enough space
170    pub fn pop_u16(&mut self) -> Option<u16> {
171        self.pop_inner(nng_msg_chop_u16)
172    }
173
174    #[inline(always)]
175    ///Extracts u32 from the end of body, encoding it into native byte order
176    ///
177    ///Returns `None` if there is not enough space
178    pub fn pop_u32(&mut self) -> Option<u32> {
179        self.pop_inner(nng_msg_chop_u32)
180    }
181
182    #[inline(always)]
183    ///Extracts u64 from the end of body, encoding it into native byte order
184    ///
185    ///Returns `None` if there is not enough space
186    pub fn pop_u64(&mut self) -> Option<u64> {
187        self.pop_inner(nng_msg_chop_u64)
188    }
189
190    #[inline(always)]
191    ///Extracts u16 from the start of body, encoding it into native byte order
192    ///
193    ///Returns `None` if there is not enough space
194    pub fn pop_front_u16(&mut self) -> Option<u16> {
195        self.pop_inner(nng_msg_trim_u16)
196    }
197
198    #[inline(always)]
199    ///Extracts u32 from the start of body, encoding it into native byte order
200    ///
201    ///Returns `None` if there is not enough space
202    pub fn pop_front_u32(&mut self) -> Option<u32> {
203        self.pop_inner(nng_msg_trim_u32)
204    }
205
206    #[inline(always)]
207    ///Extracts u64 from the start of body, encoding it into native byte order
208    ///
209    ///Returns `None` if there is not enough space
210    pub fn pop_front_u64(&mut self) -> Option<u64> {
211        self.pop_inner(nng_msg_trim_u64)
212    }
213
214    //push
215    #[inline(always)]
216    ///Appends u16 to the end of body, encoding it into network byte order
217    ///
218    ///Returns `Err` if there is not enough space
219    pub fn append_u16(&mut self, value: u16) -> Result<(), ErrorCode> {
220        self.push_inner(value, nng_msg_append_u16)
221    }
222
223    #[inline(always)]
224    ///Appends u32 to the end of body, encoding it into network byte order
225    ///
226    ///Returns `Err` if there is not enough space
227    pub fn append_u32(&mut self, value: u32) -> Result<(), ErrorCode> {
228        self.push_inner(value, nng_msg_append_u32)
229    }
230
231    #[inline(always)]
232    ///Appends u64 to the end of body, encoding it into network byte order
233    ///
234    ///Returns `Err` if there is not enough space
235    pub fn append_u64(&mut self, value: u64) -> Result<(), ErrorCode> {
236        self.push_inner(value, nng_msg_append_u64)
237    }
238
239    ///Appends `bytes` to the message body.
240    pub fn append(&mut self, bytes: &[u8]) -> Result<(), ErrorCode> {
241        let result = unsafe {
242            nng_msg_append(self.0.as_ptr(), bytes.as_ptr() as _, bytes.len())
243        };
244
245        match result {
246            0 => Ok(()),
247            code => Err(error(code)),
248        }
249    }
250
251    #[inline(always)]
252    ///Inserts u16 at the start of body, encoding it into network byte order
253    ///
254    ///Returns `Err` if there is not enough space
255    pub fn insert_u16(&mut self, value: u16) -> Result<(), ErrorCode> {
256        self.push_inner(value, nng_msg_insert_u16)
257    }
258
259    #[inline(always)]
260    ///Inserts u32 at the start of body, encoding it into network byte order
261    ///
262    ///Returns `Err` if there is not enough space
263    pub fn insert_u32(&mut self, value: u32) -> Result<(), ErrorCode> {
264        self.push_inner(value, nng_msg_insert_u32)
265    }
266
267    #[inline(always)]
268    ///Inserts u64 at the start of body, encoding it into network byte order
269    ///
270    ///Returns `Err` if there is not enough space
271    pub fn insert_u64(&mut self, value: u64) -> Result<(), ErrorCode> {
272        self.push_inner(value, nng_msg_insert_u64)
273    }
274
275    ///Inserts `bytes` at the start of the body.
276    pub fn insert(&mut self, bytes: &[u8]) -> Result<(), ErrorCode> {
277        let result = unsafe {
278            nng_msg_insert(self.0.as_ptr(), bytes.as_ptr() as _, bytes.len())
279        };
280
281        match result {
282            0 => Ok(()),
283            code => Err(error(code)),
284        }
285    }
286}
287
288impl Clone for Message {
289    #[inline]
290    fn clone(&self) -> Self {
291        self.dup().unwrap()
292    }
293}
294
295impl ops::Deref for Message {
296    type Target = ptr::NonNull<nng_msg>;
297
298    #[inline(always)]
299    fn deref(&self) -> &Self::Target {
300        &self.0
301    }
302}
303
304impl ops::DerefMut for Message {
305    #[inline(always)]
306    fn deref_mut(&mut self) -> &mut Self::Target {
307        &mut self.0
308    }
309}
310
311impl fmt::Debug for Message {
312    #[inline]
313    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
314        fmt.debug_struct("Message").field("len", &self.len()).finish()
315    }
316}
317
318impl Drop for Message {
319    #[inline(always)]
320    fn drop(&mut self) {
321        unsafe {
322            nng_msg_free(self.0.as_ptr())
323        }
324    }
325}