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
16pub struct Message(pub(crate) ptr::NonNull<nng_msg>);
18
19impl Message {
20 #[inline(always)]
21 pub fn new() -> Option<Self> {
25 Self::with_capaicty(0)
26 }
27
28 #[inline]
29 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 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 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 pub fn len(&self) -> usize {
74 unsafe {
75 nng_msg_len(self.0.as_ptr())
76 }
77 }
78
79 #[inline(always)]
80 pub fn capaciy(&self) -> usize {
82 unsafe {
83 nng_msg_capacity(self.0.as_ptr())
84 }
85 }
86
87 #[inline(always)]
88 pub fn clear(&mut self) {
93 unsafe {
94 nng_msg_clear(self.0.as_ptr())
95 }
96 }
97
98 #[inline(always)]
99 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 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 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 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 #[inline(always)]
167 pub fn pop_u16(&mut self) -> Option<u16> {
171 self.pop_inner(nng_msg_chop_u16)
172 }
173
174 #[inline(always)]
175 pub fn pop_u32(&mut self) -> Option<u32> {
179 self.pop_inner(nng_msg_chop_u32)
180 }
181
182 #[inline(always)]
183 pub fn pop_u64(&mut self) -> Option<u64> {
187 self.pop_inner(nng_msg_chop_u64)
188 }
189
190 #[inline(always)]
191 pub fn pop_front_u16(&mut self) -> Option<u16> {
195 self.pop_inner(nng_msg_trim_u16)
196 }
197
198 #[inline(always)]
199 pub fn pop_front_u32(&mut self) -> Option<u32> {
203 self.pop_inner(nng_msg_trim_u32)
204 }
205
206 #[inline(always)]
207 pub fn pop_front_u64(&mut self) -> Option<u64> {
211 self.pop_inner(nng_msg_trim_u64)
212 }
213
214 #[inline(always)]
216 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 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 pub fn append_u64(&mut self, value: u64) -> Result<(), ErrorCode> {
236 self.push_inner(value, nng_msg_append_u64)
237 }
238
239 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 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 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 pub fn insert_u64(&mut self, value: u64) -> Result<(), ErrorCode> {
272 self.push_inner(value, nng_msg_insert_u64)
273 }
274
275 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}