1use std::io;
2use crate::sys;
3
4pub(crate) const STRING_BUFFER_LENGTH: usize = 0x200;
5
6pub(crate) fn convert_error(e: sys::Error) -> io::Error {
7 e.into()
8}
9
10macro_rules! impl_iterable {
11 (@impliter $name: ident($start:expr, $count:expr)) => {
12 impl crate::bitmask::BitmaskTrait for $name {
13 type Array = [u8; (Self::COUNT + 7) / 8];
14 type Index = $name;
15 const ZERO: Self::Array = [0u8; (Self::COUNT + 7) / 8];
16
17 fn array_default() -> Self::Array { unsafe {std::mem::zeroed() } }
18 fn array_slice(array: &Self::Array) -> &[u8] { array }
19 fn array_slice_mut(array: &mut Self::Array) -> &mut [u8] { array }
20 fn index(index: Self::Index) -> usize { index as usize }
21 }
22
23 impl crate::enum_iterator::IterableEnum for $name {
24 fn iter_next(v: usize) -> Option<(usize, Self)> {
25 if v < Self::COUNT {
26 unsafe {
27 Some((v + 1, std::mem::transmute(v as u16)))
28 }
29 } else {
30 None
31 }
32 }
33
34 fn iter() -> crate::enum_iterator::EnumIterator<Self> {
35 crate::enum_iterator::EnumIterator::new($start)
36 }
37 }
38
39 impl $name {
40 pub const COUNT: usize = $count as usize;
42
43 pub fn iter() -> crate::enum_iterator::EnumIterator<Self> {
45 crate::enum_iterator::IterableEnum::iter()
46 }
47
48 pub fn bitmask() -> crate::bitmask::Bitmask<Self> {
50 Default::default()
51 }
52
53 pub const fn code(&self) -> u16 {
55 *self as _
56 }
57 }
58
59 impl From<$name> for u16 {
60 fn from(v: $name) -> Self {
61 v.code()
62 }
63 }
64 };
65 (@implcode $name: ident($start:expr, $count:expr)) => {
66 impl $name {
67 pub fn from_code(code: u16) -> Result<Self, crate::kinds::RangeError> {
69 use std::mem;
70
71 if code < Self::COUNT as u16 {
72 Ok(unsafe { mem::transmute(code) })
73 } else {
74 Err(crate::kinds::RangeError)
75 }
76 }
77 }
78
79 impl std::convert::TryFrom<u16> for $name {
80 type Error = crate::kinds::RangeError;
81
82 fn try_from(code: u16) -> Result<Self, Self::Error> {
83 Self::from_code(code)
84 }
85 }
86 };
87 ($name: ident($start:expr, $count:expr)) => {
88 impl_iterable! { @impliter $name($start, $count) }
89 impl_iterable! { @implcode $name($start, $count) }
90 };
91 (@nofromcode $name: ident($start:expr, $count:expr)) => {
92 impl_iterable! { @impliter $name($start, $count) }
93 };
94}
95
96macro_rules! ioctl_impl {
97 ($(#[$attr:meta])* @get $f:ident = $ev:ident -> $ret:ty) => {
98 $(#[$attr])*
99 pub fn $f(&self) -> io::Result<$ret> {
100 unsafe {
101 let mut v = std::mem::MaybeUninit::uninit();
102 sys::$ev(self.fd(), &mut *v.as_mut_ptr())
103 .map(|_| v.assume_init().into())
104 .map_err(crate::macros::convert_error)
105 }
106 }
107 };
108 ($(#[$attr:meta])* @call $f:ident = $ev:ident) => {
109 $(#[$attr])*
110 pub fn $f(&self) -> io::Result<()> {
111 unsafe {
112 sys::$ev(self.fd())
113 .map(drop)
114 .map_err(crate::macros::convert_error)
115 }
116 }
117 };
118 ($(#[$attr:meta])* @get_buf $f:ident($ty:ty) = $ev:ident) => {
119 $(#[$attr])*
120 pub fn $f(&self, buffer: &mut [$ty]) -> io::Result<usize> {
121 unsafe {
122 sys::$ev(self.fd(), &mut *(buffer as *mut [$ty] as *mut [_]))
123 .map(|len| len as _)
124 .map_err(crate::macros::convert_error)
125 }
126 }
127 };
128 ($(#[$attr:meta])* @get_str $f:ident, $fbuf:ident = $ev:ident) => {
129 ioctl_impl! {
130 $(#[$attr])*
131 @get_buf $fbuf(u8) = $ev
132 }
133
134 $(#[$attr])*
135 pub fn $f(&self) -> io::Result<Vec<u8>> {
136 let mut buf = vec![0; crate::macros::STRING_BUFFER_LENGTH];
137 self.$fbuf(&mut buf[..]).map(move |len| {
138 buf.truncate(len as _);
139 buf
140 })
141 }
142 };
143 ($(#[$attr:meta])* @set_str $f:ident = $ev:ident) => {
144 $(#[$attr])*
145 pub fn $f(&self, value: &::std::ffi::CStr) -> io::Result<()> {
146 unsafe {
147 sys::$ev(self.fd(), value.as_ptr())
148 .map(drop)
149 .map_err(crate::macros::convert_error)
150 }
151 }
152 };
153 ($(#[$attr:meta])* @set $f:ident($in:ty) = $ev:ident) => {
154 $(#[$attr])*
155 pub fn $f(&self, value: $in) -> io::Result<()> {
156 unsafe {
157 sys::$ev(self.fd(), value as _)
158 .map(drop)
159 .map_err(crate::macros::convert_error)
160 }
161 }
162 };
163 ($({ $($tt:tt)* })*) => {
164 $(
165 ioctl_impl! {$($tt)*}
166 )*
167 };
168}
169
170macro_rules! impl_bitmasks {
171 { $kind:path, $event: expr, $name_mask:ident, $name_mask_set:ident, $name_bits:ident } => {
172 pub fn $name_mask(&self) -> io::Result<crate::bitmask::Bitmask<$kind>> {
174 let mut bitmask = crate::bitmask::Bitmask::default();
175 self.event_mask_raw($event, &mut bitmask).map(|_| bitmask)
176 }
177
178 pub fn $name_mask_set(&self, bitmask: &crate::bitmask::Bitmask<$kind>) -> io::Result<()> {
180 self.set_event_mask_raw($event, bitmask)
181 }
182
183 pub fn $name_bits(&self) -> io::Result<crate::bitmask::Bitmask<$kind>> {
185 let mut bitmask = crate::bitmask::Bitmask::default();
186 self.event_bits_raw($event, &mut bitmask).map(|_| bitmask)
187 }
188 };
189}