1use std::{
2 io,
3 marker::PhantomData,
4 sync::atomic::{AtomicUsize, Ordering},
5};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct Token(pub usize);
10
11pub trait TokenGenerator {
12 fn next() -> Token {
14 static NEXT: AtomicUsize = AtomicUsize::new(0);
15
16 Token(NEXT.fetch_add(1, Ordering::SeqCst))
17 }
18}
19
20impl TokenGenerator for Token {}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub enum Description {
25 File,
27 TcpListener,
29 TcpStream,
31 UdpSocket,
33 Timeout,
35 Poller,
37 External(usize),
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43pub struct Handle {
44 pub token: Token,
46 pub desc: Description,
48 pub user_defined_desc: Option<*const ()>,
50 pub data: *const (),
52}
53
54unsafe impl Send for Handle {}
55unsafe impl Sync for Handle {}
56
57impl Handle {
58 pub fn new(
60 desc: Description,
61 user_defined_desc: Option<*const ()>,
62 token: Option<Token>,
63 data: *const (),
64 ) -> Self {
65 Self {
66 token: token.unwrap_or(Token::next()),
67 desc,
68 user_defined_desc,
69 data,
70 }
71 }
72
73 pub fn drop_as<T>(self) {
75 let boxed: Box<T> = unsafe { Box::from_raw(self.data as *mut T) };
76
77 drop(boxed);
78 }
79
80 pub fn expect(&self, desc: Description) -> io::Result<()> {
81 if self.desc != desc {
82 return Err(io::Error::new(
83 io::ErrorKind::InvalidInput,
84 format!(
85 "Expect file handle type {:?}, but got {:?}",
86 desc, self.desc
87 ),
88 ));
89 }
90
91 Ok(())
92 }
93}
94
95impl<T> From<(Description, T)> for Handle {
96 fn from(value: (Description, T)) -> Self {
97 let data = Box::into_raw(Box::new(value.1)) as *const ();
98
99 Self::new(value.0, None, None, data)
100 }
101}
102
103impl<UDDESC, T> From<(Description, UDDESC, T)> for Handle {
104 fn from(value: (Description, UDDESC, T)) -> Self {
105 let user_defined_desc = Box::into_raw(Box::new(value.1)) as *const ();
106 let data: *const () = Box::into_raw(Box::new(value.2)) as *const ();
107
108 Self::new(value.0, Some(user_defined_desc), None, data)
109 }
110}
111
112impl<UDDESC, T> From<(Description, UDDESC, Token, T)> for Handle {
113 fn from(value: (Description, UDDESC, Token, T)) -> Self {
114 let user_defined_desc = Box::into_raw(Box::new(value.1)) as *const ();
115 let data: *const () = Box::into_raw(Box::new(value.3)) as *const ();
116
117 Self::new(value.0, Some(user_defined_desc), Some(value.2), data)
118 }
119}
120
121pub struct TypedHandle<T> {
123 inner: Handle,
124 _marked: PhantomData<T>,
125}
126
127impl<T> From<Handle> for TypedHandle<T> {
128 fn from(value: Handle) -> Self {
129 Self::new(value)
130 }
131}
132
133impl<T> TypedHandle<T> {
134 pub fn new(inner: Handle) -> Self {
135 Self {
136 inner,
137 _marked: Default::default(),
138 }
139 }
140
141 #[inline]
147 pub fn with<F, R>(&self, f: F) -> R
148 where
149 F: FnOnce(&T) -> R,
150 {
151 let boxed = unsafe { Box::from_raw(self.inner.data as *mut T) };
152
153 let r = f(boxed.as_ref());
154
155 Box::into_raw(boxed);
156
157 r
158 }
159
160 #[inline]
166 pub fn with_mut<F, R>(&self, f: F) -> R
167 where
168 F: FnOnce(&mut T) -> R,
169 {
170 let mut boxed = unsafe { Box::from_raw(self.inner.data as *mut T) };
171
172 let r = f(boxed.as_mut());
173
174 Box::into_raw(boxed);
175
176 r
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use crate::*;
183
184 #[test]
185 fn test_typed_handle() {
186 let handle = Handle::from((Description::File, 100i32));
187
188 let typed_handle: TypedHandle<i32> = handle.into();
189
190 typed_handle.with(|v| assert_eq!(*v, 100));
191
192 typed_handle.with_mut(|v| *v = 10);
193
194 typed_handle.with(|v| assert_eq!(*v, 10));
195 }
196}