1use libc::{c_int, c_uint, size_t};
2use std::os::raw::c_void;
3use std::result;
4use std::string::FromUtf8Error;
5use std::{mem, ptr, str};
6
7use super::{PollEvents, Result};
8
9pub trait Getter
10where
11 Self: Sized,
12{
13 fn get(sock: *mut c_void, opt: c_int) -> Result<Self>;
14}
15
16pub trait Setter
17where
18 Self: Sized,
19{
20 fn set(sock: *mut c_void, opt: c_int, value: Self) -> Result<()>;
21}
22
23macro_rules! getsockopt_num(
24 ($c_ty:ty, $ty:ty) => (
25 impl Getter for $ty {
26 #[allow(trivial_casts)]
27 fn get(sock: *mut c_void, opt: c_int) -> Result<$ty> {
28 let mut value: $c_ty = 0;
29 let value_ptr = &mut value as *mut $c_ty;
30 let mut size = mem::size_of::<$c_ty>() as size_t;
31
32 zmq_try!(unsafe {
33 zmq_sys::zmq_getsockopt(
34 sock,
35 opt,
36 value_ptr as *mut c_void,
37 &mut size)
38 });
39 Ok(value as $ty)
40 }
41 }
42 )
43);
44
45getsockopt_num!(c_int, i32);
46getsockopt_num!(c_uint, u32);
47getsockopt_num!(i64, i64);
48getsockopt_num!(u64, u64);
49
50pub fn get_bytes(sock: *mut c_void, opt: c_int, size: size_t) -> Result<Vec<u8>> {
51 let mut size = size;
52 let mut value = vec![0u8; size];
53
54 zmq_try!(unsafe {
55 zmq_sys::zmq_getsockopt(sock, opt, value.as_mut_ptr() as *mut c_void, &mut size)
56 });
57 value.truncate(size);
58 Ok(value)
59}
60
61pub fn get_string(
62 sock: *mut c_void,
63 opt: c_int,
64 size: size_t,
65 remove_nulbyte: bool,
66) -> Result<result::Result<String, Vec<u8>>> {
67 let mut value = get_bytes(sock, opt, size)?;
68
69 if remove_nulbyte {
70 value.pop();
71 }
72 Ok(String::from_utf8(value).map_err(FromUtf8Error::into_bytes))
73}
74
75macro_rules! setsockopt_num(
76 ($ty:ty) => (
77 impl Setter for $ty {
78 #[allow(trivial_casts)]
79 fn set(sock: *mut c_void, opt: c_int, value: $ty) -> Result<()> {
80 let size = mem::size_of::<$ty>() as size_t;
81
82 zmq_try!(unsafe {
83 zmq_sys::zmq_setsockopt(
84 sock,
85 opt,
86 (&value as *const $ty) as *const c_void,
87 size)
88 });
89 Ok(())
90 }
91 }
92 )
93);
94
95setsockopt_num!(i32);
96setsockopt_num!(i64);
97setsockopt_num!(u64);
98
99fn setsockopt_null(sock: *mut c_void, opt: c_int) -> Result<()> {
100 zmq_try!(unsafe { zmq_sys::zmq_setsockopt(sock, opt, ptr::null(), 0) });
101 Ok(())
102}
103
104impl<'a> Setter for &'a str {
105 fn set(sock: *mut c_void, opt: c_int, value: Self) -> Result<()> {
106 set(sock, opt, value.as_bytes())
107 }
108}
109
110impl<'a> Setter for Option<&'a str> {
111 fn set(sock: *mut c_void, opt: c_int, value: Self) -> Result<()> {
112 if let Some(s) = value {
113 set(sock, opt, s.as_bytes())
114 } else {
115 setsockopt_null(sock, opt)
116 }
117 }
118}
119
120impl Getter for bool {
121 fn get(sock: *mut c_void, opt: c_int) -> Result<Self> {
122 let result: i32 = get(sock, opt)?;
123 Ok(result == 1)
124 }
125}
126
127impl Setter for bool {
128 fn set(sock: *mut c_void, opt: c_int, value: Self) -> Result<()> {
129 set(sock, opt, if value { 1i32 } else { 0i32 })
130 }
131}
132
133impl<'a> Setter for &'a [u8] {
134 fn set(sock: *mut c_void, opt: c_int, value: &'a [u8]) -> Result<()> {
135 zmq_try!(unsafe {
136 zmq_sys::zmq_setsockopt(
137 sock,
138 opt,
139 value.as_ptr() as *const c_void,
140 value.len() as size_t,
141 )
142 });
143 Ok(())
144 }
145}
146
147impl Getter for PollEvents {
148 fn get(sock: *mut c_void, opt: c_int) -> Result<Self> {
149 get::<c_int>(sock, opt).map(|bits| PollEvents::from_bits_truncate(bits as i16))
150 }
151}
152
153pub fn get<T: Getter>(sock: *mut c_void, opt: c_int) -> Result<T> {
154 T::get(sock, opt)
155}
156
157pub fn set<T: Setter>(sock: *mut c_void, opt: c_int, value: T) -> Result<()> {
158 T::set(sock, opt, value)
159}