Skip to main content

c_ares/channel/
sockets.rs

1use crate::types::Socket;
2
3/// Information about the set of sockets that `c-ares` is interested in, as returned by
4/// `sockets()`.
5#[derive(Clone, Copy, Debug)]
6pub struct Sockets {
7    sockets: [c_ares_sys::ares_socket_t; c_ares_sys::ARES_GETSOCK_MAXNUM],
8    bitmask: u32,
9}
10
11impl Sockets {
12    pub(super) fn new(
13        socks: [c_ares_sys::ares_socket_t; c_ares_sys::ARES_GETSOCK_MAXNUM],
14        bitmask: u32,
15    ) -> Self {
16        Sockets {
17            sockets: socks,
18            bitmask,
19        }
20    }
21
22    /// Returns an iterator over the sockets that `c-ares` is interested in.
23    pub fn iter(&self) -> SocketsIter<'_> {
24        SocketsIter {
25            next: 0,
26            sockets: self,
27        }
28    }
29}
30
31/// Iterator for sockets of interest to `c-ares`.
32///
33/// Iterator items are `(socket, readable, writable)`.
34#[derive(Clone, Debug)]
35pub struct SocketsIter<'a> {
36    next: usize,
37    sockets: &'a Sockets,
38}
39
40impl Iterator for SocketsIter<'_> {
41    type Item = (Socket, bool, bool);
42    fn next(&mut self) -> Option<Self::Item> {
43        let index = self.next;
44        self.next += 1;
45        if index >= c_ares_sys::ARES_GETSOCK_MAXNUM {
46            None
47        } else {
48            let bit = 1 << index;
49            let readable = (self.sockets.bitmask & bit) != 0;
50            let bit = bit << c_ares_sys::ARES_GETSOCK_MAXNUM;
51            let writable = (self.sockets.bitmask & bit) != 0;
52            if readable || writable {
53                let fd = self.sockets.sockets[index];
54                Some((fd, readable, writable))
55            } else {
56                None
57            }
58        }
59    }
60}
61
62impl<'a> IntoIterator for &'a Sockets {
63    type Item = (Socket, bool, bool);
64    type IntoIter = SocketsIter<'a>;
65
66    fn into_iter(self) -> Self::IntoIter {
67        self.iter()
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::super::Channel;
74    use super::*;
75
76    #[test]
77    fn sockets_iter_empty() {
78        let channel = Channel::new().unwrap();
79        let sockets = channel.sockets();
80        let mut iter = sockets.iter();
81        assert!(iter.next().is_none());
82    }
83
84    #[test]
85    fn sockets_iter_clone() {
86        let channel = Channel::new().unwrap();
87        let sockets = channel.sockets();
88        let iter = sockets.iter();
89        let _cloned = iter.clone();
90    }
91
92    #[test]
93    fn sockets_is_send() {
94        fn assert_send<T: Send>() {}
95        assert_send::<Sockets>();
96    }
97
98    #[test]
99    fn sockets_is_sync() {
100        fn assert_sync<T: Sync>() {}
101        assert_sync::<Sockets>();
102    }
103
104    #[test]
105    fn sockets_iter_is_send() {
106        fn assert_send<T: Send>() {}
107        assert_send::<SocketsIter<'_>>();
108    }
109
110    #[test]
111    fn sockets_iter_is_sync() {
112        fn assert_sync<T: Sync>() {}
113        assert_sync::<SocketsIter<'_>>();
114    }
115
116    #[test]
117    fn sockets_into_iter() {
118        let channel = Channel::new().unwrap();
119        let sockets = channel.sockets();
120        // Use the IntoIterator implementation - empty channel should have no sockets
121        assert_eq!(sockets.into_iter().count(), 0);
122    }
123
124    #[test]
125    fn sockets_iter_exhausted() {
126        // Test that GetSockIter returns None when index >= ARES_GETSOCK_MAXNUM
127        let channel = Channel::new().unwrap();
128        let sockets = channel.sockets();
129        let mut iter = sockets.iter();
130        // Exhaust the iterator
131        while iter.next().is_some() {}
132        // After exhaustion, should continue returning None
133        assert!(iter.next().is_none());
134        assert!(iter.next().is_none());
135    }
136
137    #[test]
138    fn sockets_debug() {
139        let channel = Channel::new().unwrap();
140        let sockets = channel.sockets();
141        let debug_str = format!("{sockets:?}");
142        assert!(debug_str.contains("Sockets"));
143    }
144
145    #[test]
146    fn sockets_iter_debug() {
147        let channel = Channel::new().unwrap();
148        let sockets = channel.sockets();
149        let iter = sockets.iter();
150        let debug_str = format!("{iter:?}");
151        assert!(debug_str.contains("SocketsIter"));
152    }
153
154    #[test]
155    #[allow(clippy::clone_on_copy)]
156    fn sockets_clone() {
157        let channel = Channel::new().unwrap();
158        let sockets = channel.sockets();
159        let _cloned = sockets.clone();
160    }
161
162    #[test]
163    fn sockets_copy() {
164        let channel = Channel::new().unwrap();
165        let sockets = channel.sockets();
166        let copied: Sockets = sockets;
167        let _ = copied;
168    }
169}