Skip to main content

ntex_io/
types.rs

1//! Values exposed through transport and filter queries.
2use std::{any, fmt, marker::PhantomData, net::SocketAddr};
3
4#[derive(Copy, Clone, PartialEq, Eq)]
5/// Peer socket address returned by [`IoRef::query`](crate::IoRef::query).
6pub struct PeerAddr(pub SocketAddr);
7
8impl PeerAddr {
9    /// Returns the contained socket address.
10    pub fn into_inner(self) -> SocketAddr {
11        self.0
12    }
13}
14
15impl From<SocketAddr> for PeerAddr {
16    fn from(addr: SocketAddr) -> Self {
17        Self(addr)
18    }
19}
20
21impl fmt::Debug for PeerAddr {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        self.0.fmt(f)
24    }
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
28/// HTTP protocol selected for an I/O stream.
29pub enum HttpProtocol {
30    /// HTTP/1.x.
31    Http1,
32    /// HTTP/2.
33    Http2,
34    /// The protocol has not been identified or is not HTTP.
35    Unknown,
36}
37
38/// Typed result of an [`IoRef::query`](crate::IoRef::query).
39///
40/// Query providers store values as `dyn Any`; this wrapper performs the
41/// requested downcast without exposing the erased representation.
42pub struct QueryItem<T> {
43    item: Option<Box<dyn any::Any>>,
44    _t: PhantomData<T>,
45}
46
47impl<T: any::Any> QueryItem<T> {
48    pub(crate) fn new(item: Option<Box<dyn any::Any>>) -> Self {
49        Self {
50            item,
51            _t: PhantomData,
52        }
53    }
54
55    /// Copies the queried value out of this item.
56    ///
57    /// Returns `None` if no provider returned a value of type `T`.
58    pub fn get(&self) -> Option<T>
59    where
60        T: Copy,
61    {
62        self.item.as_ref().and_then(|v| v.downcast_ref().copied())
63    }
64
65    /// Borrows the queried value.
66    ///
67    /// Returns `None` if no provider returned a value of type `T`.
68    pub fn as_ref(&self) -> Option<&T> {
69        if let Some(ref item) = self.item {
70            item.downcast_ref()
71        } else {
72            None
73        }
74    }
75}
76
77impl<T: any::Any + fmt::Debug> fmt::Debug for QueryItem<T> {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        if let Some(v) = self.as_ref() {
80            f.debug_tuple("QueryItem").field(v).finish()
81        } else {
82            f.debug_tuple("QueryItem").field(&None::<T>).finish()
83        }
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn peer_addr() {
93        let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
94        let peer = PeerAddr::from(addr);
95        assert_eq!(peer, PeerAddr(addr));
96        assert_eq!(format!("{peer:?}"), "127.0.0.1:8080");
97        assert_eq!(peer.into_inner(), addr);
98    }
99
100    #[test]
101    fn query_item() {
102        let item = QueryItem::<u32>::new(Some(Box::new(10u32)));
103        assert_eq!(item.get(), Some(10));
104        assert_eq!(item.as_ref(), Some(&10));
105        assert_eq!(format!("{item:?}"), "QueryItem(10)");
106
107        // a value of another type is not returned
108        let item = QueryItem::<u32>::new(Some(Box::new("str")));
109        assert_eq!(item.get(), None);
110        assert_eq!(item.as_ref(), None);
111
112        let item = QueryItem::<u32>::new(None);
113        assert_eq!(item.get(), None);
114        assert_eq!(item.as_ref(), None);
115        assert_eq!(format!("{item:?}"), "QueryItem(None)");
116    }
117}