1use crate::sys;
4use crate::socket::Socket;
5use crate::error::{error, ErrorCode};
6
7use core::{fmt, time};
8use core::convert::TryInto;
9
10pub trait Property<T>: Sized {
12 fn get(target: &T) -> Result<Self, ErrorCode>;
14}
15
16pub trait Options<T> {
18 fn apply(&self, target: &T) -> Result<(), ErrorCode>;
20}
21
22impl<T> Options<T> for () {
23 #[inline(always)]
24 fn apply(&self, _: &T) -> Result<(), ErrorCode> {
25 Ok(())
26 }
27}
28
29macro_rules! set_bytes_option {
30 ($socket:expr, $name:expr, $bytes:expr) => {
31 unsafe {
32 let bytes = $bytes;
33 match sys::nng_socket_set($socket, $name.as_ptr() as _, bytes.as_ptr() as _, bytes.len()) {
34 0 => Ok(()),
35 code => Err(error(code)),
36 }
37 }
38 }
39}
40
41macro_rules! set_string_option {
42 ($socket:expr, $name:expr, $bytes:expr) => {
43 unsafe {
44 let bytes = $bytes;
45 match sys::nng_socket_set_string($socket, $name.as_ptr() as _, bytes.as_ptr() as _) {
46 0 => Ok(()),
47 code => Err(error(code)),
48 }
49 }
50 }
51}
52
53macro_rules! set_int_option {
54 ($socket:expr, $name:expr, $num:expr) => {
55 unsafe {
56 match sys::nng_socket_set_int($socket, $name.as_ptr() as _, $num as _) {
57 0 => Ok(()),
58 code => Err(error(code)),
59 }
60 }
61 }
62}
63
64macro_rules! set_size_t_option {
65 ($socket:expr, $name:expr, $num:expr) => {
66 unsafe {
67 match sys::nng_socket_set_size($socket, $name.as_ptr() as _, $num as _) {
68 0 => Ok(()),
69 code => Err(error(code)),
70 }
71 }
72 }
73}
74
75macro_rules! set_duration_option {
76 ($socket:expr, $name:expr, $duration:expr) => {
77 match $duration.as_millis().try_into() {
78 Ok(duration) => unsafe {
79 match sys::nng_socket_set_ms($socket, $name.as_ptr() as _, duration) {
80 0 => Ok(()),
81 code => Err(error(code)),
82 }
83 },
84 Err(_) => Err(error(sys::nng_errno_enum::NNG_EINVAL)),
85 }
86 }
87}
88
89#[derive(Copy, Clone, Debug)]
90pub struct Req {
92 pub resend_time: Option<time::Duration>,
95 pub resend_tick: Option<time::Duration>,
97}
98
99impl Options<Socket> for Req {
100 #[inline]
101 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
102 if let Some(resend_time) = self.resend_time {
103 set_duration_option!(**target, sys::NNG_OPT_REQ_RESENDTIME, resend_time)?;
104 }
105
106 if let Some(resend_tick) = self.resend_tick {
107 set_duration_option!(**target, sys::NNG_OPT_REQ_RESENDTICK, resend_tick)?;
108 }
109
110 Ok(())
111 }
112}
113
114#[derive(Copy, Clone, Debug)]
115pub struct Subscribe<'a>(pub &'a [u8]);
117
118impl Options<Socket> for Subscribe<'_> {
119 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
120 set_bytes_option!(**target, sys::NNG_OPT_SUB_SUBSCRIBE, self.0)
121 }
122}
123
124#[derive(Copy, Clone, Debug)]
125pub struct Unsubscribe<'a>(pub &'a [u8]);
127
128impl Options<Socket> for Unsubscribe<'_> {
129 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
130 set_bytes_option!(**target, sys::NNG_OPT_SUB_UNSUBSCRIBE, self.0)
131 }
132}
133
134#[derive(Copy, Clone, Debug)]
135pub struct MaxTtl(pub u8);
139
140impl Options<Socket> for MaxTtl {
141 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
142 set_int_option!(**target, sys::NNG_OPT_MAXTTL, self.0)
143 }
144}
145
146#[derive(Copy, Clone, Debug)]
147pub struct Reconnect {
149 pub min_time: Option<time::Duration>,
151 pub max_time: Option<time::Duration>,
155}
156
157impl Options<Socket> for Reconnect {
158 #[inline]
159 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
160 if let Some(min_time) = self.min_time {
161 set_duration_option!(**target, sys::NNG_OPT_RECONNMINT, min_time)?;
162 }
163
164 if let Some(max_time) = self.max_time {
165 set_duration_option!(**target, sys::NNG_OPT_RECONNMAXT, max_time)?;
166 }
167
168 Ok(())
169 }
170}
171
172#[derive(Copy, Clone, Debug)]
173pub struct RecvBuf(pub u16);
177
178impl Options<Socket> for RecvBuf {
179 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
180 set_int_option!(**target, sys::NNG_OPT_RECVBUF, self.0)
181 }
182}
183
184#[derive(Copy, Clone, Debug)]
185pub struct RecvMaxSize(pub usize);
189
190impl Options<Socket> for RecvMaxSize {
191 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
192 set_size_t_option!(**target, sys::NNG_OPT_RECVMAXSZ, self.0)
193 }
194}
195
196#[derive(Copy, Clone, Debug)]
197pub struct RecvTimeout(pub time::Duration);
201
202impl Options<Socket> for RecvTimeout {
203 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
204 set_duration_option!(**target, sys::NNG_OPT_RECVTIMEO, self.0)
205 }
206}
207
208#[derive(Copy, Clone, Debug)]
209pub struct SendBuf(pub u16);
213
214impl Options<Socket> for SendBuf {
215 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
216 set_int_option!(**target, sys::NNG_OPT_SENDBUF, self.0)
217 }
218}
219
220#[derive(Copy, Clone, Debug)]
221pub struct SendTimeout(pub time::Duration);
225
226impl Options<Socket> for SendTimeout {
227 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
228 set_duration_option!(**target, sys::NNG_OPT_SENDTIMEO, self.0)
229 }
230}
231
232#[derive(Copy, Clone, Eq)]
233pub struct SocketName(pub(crate) [u8; 64]);
237
238impl SocketName {
239 pub fn new(name: &str) -> Option<Self> {
241 let mut buf = [0; 64];
242 if name.len() < buf.len() {
243 buf[..name.len()].copy_from_slice(name.as_bytes());
244 Some(Self(buf))
245 } else {
246 None
247 }
248 }
249
250 pub fn as_bytes(&self) -> &[u8] {
252 if let Some(idx) = self.0.iter().position(|byt| *byt == 0) {
253 &self.0[..idx]
254 } else {
255 &self.0
256 }
257 }
258
259 pub fn as_str(&self) -> Option<&str> {
261 core::str::from_utf8(self.as_bytes()).ok()
262 }
263}
264
265impl Options<Socket> for SocketName {
266 fn apply(&self, target: &Socket) -> Result<(), ErrorCode> {
267 set_string_option!(**target, sys::NNG_OPT_SOCKNAME, self.0)
268 }
269}
270
271impl Property<Socket> for SocketName {
272 fn get(target: &Socket) -> Result<Self, ErrorCode> {
273 let mut buf = [0; 64];
274 let result = unsafe {
275 sys::nng_socket_get(**target, sys::NNG_OPT_SOCKNAME.as_ptr() as _, buf.as_mut_ptr() as _, &mut buf.len())
276 };
277
278 match result {
279 0 => Ok(Self(buf)),
280 code => Err(error(code))
281 }
282 }
283}
284
285impl PartialEq for SocketName {
286 #[inline]
287 fn eq(&self, other: &Self) -> bool {
288 self.as_bytes() == other.as_bytes()
289 }
290}
291
292impl PartialEq<PeerName> for SocketName {
293 #[inline]
294 fn eq(&self, other: &PeerName) -> bool {
295 self.as_bytes() == other.0.as_bytes()
296 }
297}
298
299impl PartialEq<str> for SocketName {
300 #[inline]
301 fn eq(&self, other: &str) -> bool {
302 self.as_bytes() == other.as_bytes()
303 }
304}
305
306impl PartialEq<&str> for SocketName {
307 #[inline]
308 fn eq(&self, other: &&str) -> bool {
309 self.as_bytes() == other.as_bytes()
310 }
311}
312
313impl PartialEq<SocketName> for str {
314 #[inline]
315 fn eq(&self, other: &SocketName) -> bool {
316 self.as_bytes() == other.as_bytes()
317 }
318}
319
320impl PartialEq<SocketName> for &str {
321 #[inline]
322 fn eq(&self, other: &SocketName) -> bool {
323 self.as_bytes() == other.as_bytes()
324 }
325}
326
327impl fmt::Debug for SocketName {
328 #[inline]
329 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
330 let mut fmt = fmt.debug_tuple("SocketName");
331 match self.as_str() {
332 Some(name) => fmt.field(&name).finish(),
333 None => fmt.field(&self.0).finish(),
334 }
335 }
336}
337
338impl fmt::Display for SocketName {
339 #[inline]
340 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
341 match self.as_str() {
342 Some(name) => fmt.write_str(name),
343 None => fmt.write_str("<non-utf-8>"),
344 }
345 }
346}
347
348#[derive(Copy, Clone, Eq)]
349#[repr(transparent)]
350pub struct PeerName(pub(crate) SocketName);
354
355impl Property<Socket> for PeerName {
356 fn get(target: &Socket) -> Result<Self, ErrorCode> {
357 let mut buf = [0; 64];
358 let result = unsafe {
359 sys::nng_socket_get(**target, sys::NNG_OPT_PEERNAME.as_ptr() as _, buf.as_mut_ptr() as _, &mut buf.len())
360 };
361
362 match result {
363 0 => Ok(Self(SocketName(buf))),
364 code => Err(error(code))
365 }
366 }
367}
368
369impl PartialEq<SocketName> for PeerName {
370 #[inline]
371 fn eq(&self, other: &SocketName) -> bool {
372 self.0.as_bytes() == other.as_bytes()
373 }
374}
375
376impl PartialEq for PeerName {
377 #[inline]
378 fn eq(&self, other: &Self) -> bool {
379 self.0.as_bytes() == other.0.as_bytes()
380 }
381}
382
383impl PartialEq<str> for PeerName {
384 #[inline]
385 fn eq(&self, other: &str) -> bool {
386 self.0.as_bytes() == other.as_bytes()
387 }
388}
389
390impl PartialEq<&str> for PeerName {
391 #[inline]
392 fn eq(&self, other: &&str) -> bool {
393 self.0.as_bytes() == other.as_bytes()
394 }
395}
396
397impl PartialEq<PeerName> for str {
398 #[inline]
399 fn eq(&self, other: &PeerName) -> bool {
400 self.as_bytes() == other.0.as_bytes()
401 }
402}
403
404impl PartialEq<PeerName> for &str {
405 #[inline]
406 fn eq(&self, other: &PeerName) -> bool {
407 self.as_bytes() == other.0.as_bytes()
408 }
409}
410
411impl fmt::Debug for PeerName {
412 #[inline]
413 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
414 let mut fmt = fmt.debug_tuple("PeerName");
415 match self.0.as_str() {
416 Some(name) => fmt.field(&name).finish(),
417 None => fmt.field(&self.0).finish(),
418 }
419 }
420}
421
422impl fmt::Display for PeerName {
423 #[inline]
424 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
425 match self.0.as_str() {
426 Some(name) => fmt.write_str(name),
427 None => fmt.write_str("<non-utf-8>"),
428 }
429 }
430}