1use libc::size_t;
2
3use std::ffi;
4use std::fmt;
5use std::ops::{Deref, DerefMut};
6use std::os::raw::c_void;
7use std::{ptr, slice, str};
8
9use super::errno_to_error;
10
11pub struct Message {
22 msg: zmq_sys::zmq_msg_t,
23}
24
25impl Drop for Message {
26 fn drop(&mut self) {
27 unsafe {
28 let rc = zmq_sys::zmq_msg_close(&mut self.msg);
29 assert_eq!(rc, 0);
30 }
31 }
32}
33
34impl fmt::Debug for Message {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 write!(f, "{:?}", self.deref())
37 }
38}
39
40unsafe extern "C" fn drop_msg_data_box(data: *mut c_void, hint: *mut c_void) {
41 let _ = Box::from_raw(slice::from_raw_parts_mut(data as *mut u8, hint as usize));
42}
43
44impl Message {
45 unsafe fn alloc<F>(f: F) -> Message
46 where
47 F: FnOnce(&mut zmq_sys::zmq_msg_t) -> i32,
48 {
49 let mut msg = zmq_sys::zmq_msg_t::default();
50 let rc = f(&mut msg);
51 if rc == -1 {
52 panic!("{}", errno_to_error())
53 }
54 Message { msg }
55 }
56
57 pub fn new() -> Message {
59 unsafe { Self::alloc(|msg| zmq_sys::zmq_msg_init(msg)) }
60 }
61
62 #[deprecated(
77 since = "0.9.1",
78 note = "This method has an unintuitive name, and should not be needed."
79 )]
80 pub unsafe fn with_capacity_unallocated(len: usize) -> Message {
81 Self::alloc(|msg| zmq_sys::zmq_msg_init_size(msg, len as size_t))
82 }
83
84 unsafe fn with_size_uninit(len: usize) -> Message {
85 Self::alloc(|msg| zmq_sys::zmq_msg_init_size(msg, len as size_t))
86 }
87
88 pub fn with_size(len: usize) -> Message {
90 unsafe {
91 let mut msg = Message::with_size_uninit(len);
92 ptr::write_bytes(msg.as_mut_ptr(), 0, len);
93 msg
94 }
95 }
96
97 #[deprecated(
99 since = "0.9.1",
100 note = "This method has a name which does not match its semantics. Use `with_size` instead"
101 )]
102 pub fn with_capacity(len: usize) -> Message {
103 Self::with_size(len)
104 }
105
106 #[deprecated(since = "0.9.1", note = "Use the `From` trait instead.")]
110 pub fn from_slice(data: &[u8]) -> Message {
111 Self::from(data)
112 }
113
114 pub fn as_str(&self) -> Option<&str> {
116 str::from_utf8(self).ok()
117 }
118
119 pub fn get_more(&self) -> bool {
122 let rc = unsafe { zmq_sys::zmq_msg_more(&self.msg) };
123 rc != 0
124 }
125
126 pub fn gets<'a>(&'a mut self, property: &str) -> Option<&'a str> {
139 let c_str = ffi::CString::new(property.as_bytes()).unwrap();
140
141 let value = unsafe { zmq_sys::zmq_msg_gets(&self.msg, c_str.as_ptr()) };
142
143 if value.is_null() {
144 None
145 } else {
146 str::from_utf8(unsafe { ffi::CStr::from_ptr(value) }.to_bytes()).ok()
147 }
148 }
149}
150
151impl Deref for Message {
152 type Target = [u8];
153
154 fn deref(&self) -> &[u8] {
155 unsafe {
158 let ptr = &self.msg as *const _ as *mut _;
159 let data = zmq_sys::zmq_msg_data(ptr);
160 let len = zmq_sys::zmq_msg_size(ptr) as usize;
161 slice::from_raw_parts(data as *mut u8, len)
162 }
163 }
164}
165
166impl PartialEq for Message {
167 fn eq(&self, other: &Message) -> bool {
168 self[..] == other[..]
169 }
170}
171
172impl Eq for Message {}
173
174impl DerefMut for Message {
175 fn deref_mut(&mut self) -> &mut [u8] {
176 unsafe {
179 let data = zmq_sys::zmq_msg_data(&mut self.msg);
180 let len = zmq_sys::zmq_msg_size(&self.msg) as usize;
181 slice::from_raw_parts_mut(data as *mut u8, len)
182 }
183 }
184}
185
186impl<'a> From<&'a [u8]> for Message {
187 fn from(data: &'a [u8]) -> Self {
189 unsafe {
190 let mut msg = Message::with_size_uninit(data.len());
191 ptr::copy_nonoverlapping(data.as_ptr(), msg.as_mut_ptr(), data.len());
192 msg
193 }
194 }
195}
196
197impl From<Vec<u8>> for Message {
198 fn from(msg: Vec<u8>) -> Self {
200 Message::from(msg.into_boxed_slice())
201 }
202}
203
204impl From<Box<[u8]>> for Message {
205 fn from(data: Box<[u8]>) -> Self {
207 let len = data.len();
208 if len == 0 {
209 return Message::new();
210 }
211 let raw = Box::into_raw(data);
212 unsafe {
213 Self::alloc(|msg| {
214 zmq_sys::zmq_msg_init_data(
215 msg,
216 raw as *mut c_void,
217 len,
218 Some(drop_msg_data_box),
219 len as *mut c_void,
220 )
221 })
222 }
223 }
224}
225
226impl<'a> From<&'a str> for Message {
227 fn from(msg: &str) -> Self {
229 Message::from(msg.as_bytes())
230 }
231}
232
233impl<'a> From<&'a String> for Message {
234 fn from(msg: &String) -> Self {
236 Message::from(msg.as_bytes())
237 }
238}
239
240impl<'a, T> From<&'a T> for Message
241where
242 T: Into<Message> + Clone,
243{
244 fn from(v: &'a T) -> Self {
245 v.clone().into()
246 }
247}
248
249pub fn msg_ptr(msg: &mut Message) -> *mut zmq_sys::zmq_msg_t {
251 &mut msg.msg
252}