Skip to main content

hiver_runtime/driver/
interest.rs

1//! Interest types for file descriptor registration
2//! 文件描述符注册的兴趣类型
3
4#[allow(unused_imports)]
5use std::os::fd::RawFd;
6
7/// Interest types for file descriptor registration
8/// 文件描述符注册的兴趣类型
9///
10/// Specifies which events the driver should monitor for a file descriptor.
11/// 指定driver应监控文件描述符的哪些事件。
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13pub struct Interest {
14    /// Monitor for readability / 监控可读性
15    pub readable: bool,
16    /// Monitor for writability / 监控可写性
17    pub writable: bool,
18    /// Priority hint for edge-triggered mode / 边缘触发模式的优先级提示
19    pub priority: bool,
20    /// One-shot mode: auto-deregister after one event / 单次模式:事件后自动取消注册
21    pub oneshot: bool,
22    /// Edge-triggered mode vs level-triggered / 边缘触发模式 vs 水平触发
23    pub edge: bool,
24}
25
26impl Interest {
27    /// Create a new empty interest
28    /// 创建一个新的空兴趣
29    #[must_use]
30    pub const fn new() -> Self {
31        Self {
32            readable: false,
33            writable: false,
34            priority: false,
35            oneshot: false,
36            edge: false,
37        }
38    }
39
40    /// Create interest for readable events
41    /// 创建可读事件兴趣
42    #[must_use]
43    pub const fn readable() -> Self {
44        Self {
45            readable: true,
46            writable: false,
47            priority: false,
48            oneshot: false,
49            edge: false,
50        }
51    }
52
53    /// Create interest for writable events
54    /// 创建可写事件兴趣
55    #[must_use]
56    pub const fn writable() -> Self {
57        Self {
58            readable: false,
59            writable: true,
60            priority: false,
61            oneshot: false,
62            edge: false,
63        }
64    }
65
66    /// Create interest for both readable and writable events
67    /// 创建可读和可写事件兴趣
68    #[must_use]
69    pub const fn both() -> Self {
70        Self {
71            readable: true,
72            writable: true,
73            priority: false,
74            oneshot: false,
75            edge: false,
76        }
77    }
78
79    /// Add readability to the interest
80    /// 添加可读性到兴趣
81    #[must_use]
82    pub const fn with_readable(mut self) -> Self {
83        self.readable = true;
84        self
85    }
86
87    /// Add writability to the interest
88    /// 添加可写性到兴趣
89    #[must_use]
90    pub const fn with_writable(mut self) -> Self {
91        self.writable = true;
92        self
93    }
94
95    /// Enable priority mode
96    /// 启用优先级模式
97    #[must_use]
98    pub const fn with_priority(mut self) -> Self {
99        self.priority = true;
100        self
101    }
102
103    /// Enable one-shot mode
104    /// 启用单次模式
105    #[must_use]
106    pub const fn with_oneshot(mut self) -> Self {
107        self.oneshot = true;
108        self
109    }
110
111    /// Enable edge-triggered mode
112    /// 启用边缘触发模式
113    #[must_use]
114    pub const fn with_edge(mut self) -> Self {
115        self.edge = true;
116        self
117    }
118
119    /// Convert to epoll event flags
120    /// 转换为epoll事件标志
121    #[cfg(target_os = "linux")]
122    pub const fn to_epoll_flags(self) -> u32 {
123        let mut flags = 0u32;
124
125        if self.readable {
126            flags |= libc::EPOLLIN as u32;
127        }
128        if self.writable {
129            flags |= libc::EPOLLOUT as u32;
130        }
131        if self.priority {
132            flags |= libc::EPOLLPRI as u32;
133        }
134        if self.oneshot {
135            flags |= libc::EPOLLONESHOT as u32;
136        }
137        if self.edge {
138            flags |= libc::EPOLLET as u32;
139        }
140
141        flags
142    }
143
144    /// Convert from epoll event flags
145    /// 从epoll事件标志转换
146    #[cfg(target_os = "linux")]
147    pub fn from_epoll_flags(flags: u32) -> Self {
148        Self {
149            readable: (flags & libc::EPOLLIN as u32) != 0,
150            writable: (flags & libc::EPOLLOUT as u32) != 0,
151            priority: (flags & libc::EPOLLPRI as u32) != 0,
152            oneshot: (flags & libc::EPOLLONESHOT as u32) != 0,
153            edge: (flags & libc::EPOLLET as u32) != 0,
154        }
155    }
156
157    /// Convert to kqueue event flags
158    /// 转换为kqueue事件标志
159    #[cfg(any(
160        target_os = "macos",
161        target_os = "freebsd",
162        target_os = "netbsd",
163        target_os = "openbsd",
164        target_os = "dragonfly"
165    ))]
166    #[allow(dead_code)]
167    pub fn to_kqueue_filters(&self, fd: RawFd) -> (Vec<libc::kevent>, Vec<libc::kevent>) {
168        use std::mem::zeroed;
169
170        let mut add_events = Vec::with_capacity(2);
171        let remove_events = Vec::new();
172
173        if self.readable {
174            let mut event = unsafe { zeroed::<libc::kevent>() };
175            event.ident = fd as libc::uintptr_t;
176            event.filter = libc::EVFILT_READ;
177            event.flags = libc::EV_ADD | libc::EV_RECEIPT;
178            if self.edge {
179                event.flags |= libc::EV_CLEAR;
180            }
181            if self.oneshot {
182                event.flags |= libc::EV_ONESHOT;
183            }
184            add_events.push(event);
185        }
186
187        if self.writable {
188            let mut event = unsafe { zeroed::<libc::kevent>() };
189            event.ident = fd as libc::uintptr_t;
190            event.filter = libc::EVFILT_WRITE;
191            event.flags = libc::EV_ADD | libc::EV_RECEIPT;
192            if self.edge {
193                event.flags |= libc::EV_CLEAR;
194            }
195            if self.oneshot {
196                event.flags |= libc::EV_ONESHOT;
197            }
198            add_events.push(event);
199        }
200
201        (add_events, remove_events)
202    }
203}
204
205#[cfg(test)]
206mod tests {
207    use super::*;
208
209    #[test]
210    fn test_interest_builder() {
211        let interest = Interest::readable().with_writable().with_edge();
212
213        assert!(interest.readable);
214        assert!(interest.writable);
215        assert!(interest.edge);
216        assert!(!interest.priority);
217    }
218
219    #[test]
220    fn test_interest_both() {
221        let interest = Interest::both();
222        assert!(interest.readable);
223        assert!(interest.writable);
224    }
225}