Skip to main content

ntex_io/
seal.rs

1use std::{any::Any, any::TypeId, fmt, io, ops, task::Context, task::Poll};
2
3use crate::{Filter, FilterCtx, Io, Readiness};
4
5/// Sealed filter type
6pub struct Sealed(pub(crate) Box<dyn Filter>);
7
8impl fmt::Debug for Sealed {
9    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10        f.debug_struct("Sealed").finish()
11    }
12}
13
14impl Filter for Sealed {
15    #[inline]
16    fn query(&self, id: TypeId) -> Option<Box<dyn Any>> {
17        self.0.query(id)
18    }
19
20    #[inline]
21    fn process_read_buf(&self, ctx: &mut FilterCtx<'_>) -> io::Result<()> {
22        self.0.process_read_buf(ctx)
23    }
24
25    #[inline]
26    fn process_write_buf(&self, ctx: &mut FilterCtx<'_>) -> io::Result<()> {
27        self.0.process_write_buf(ctx)
28    }
29
30    #[inline]
31    fn shutdown(&self, ctx: &mut FilterCtx<'_>) -> io::Result<Poll<()>> {
32        self.0.shutdown(ctx)
33    }
34
35    #[inline]
36    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness> {
37        self.0.poll_read_ready(cx)
38    }
39
40    #[inline]
41    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Readiness> {
42        self.0.poll_write_ready(cx)
43    }
44}
45
46#[derive(Debug)]
47/// Boxed `Io` object with erased filter type
48pub struct IoBoxed(Io<Sealed>);
49
50impl IoBoxed {
51    #[inline]
52    #[must_use]
53    /// Clone current io object.
54    ///
55    /// Current io object becomes closed.
56    pub fn take(&mut self) -> Self {
57        IoBoxed(self.0.take())
58    }
59}
60
61impl<F: Filter> From<Io<F>> for IoBoxed {
62    fn from(io: Io<F>) -> Self {
63        Self(io.seal())
64    }
65}
66
67impl ops::Deref for IoBoxed {
68    type Target = Io<Sealed>;
69
70    #[inline]
71    fn deref(&self) -> &Self::Target {
72        &self.0
73    }
74}
75
76impl From<IoBoxed> for Io<Sealed> {
77    fn from(value: IoBoxed) -> Self {
78        value.0
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use ntex_bytes::Bytes;
85    use ntex_codec::BytesCodec;
86    use ntex_service::{ServiceFactory, cfg::SharedCfg, fn_service};
87
88    use super::*;
89    use crate::{testing::IoTest, utils::seal};
90
91    #[ntex::test]
92    async fn test_seal() {
93        let (client, server) = IoTest::create();
94        client.remote_buffer_cap(1024);
95        client.write("REQ");
96
97        let svc = seal(fn_service(|io: IoBoxed| async move {
98            let t = io.recv(&BytesCodec).await.unwrap().unwrap();
99            assert_eq!(t, b"REQ".as_ref());
100            io.send(Bytes::from_static(b"RES"), &BytesCodec)
101                .await
102                .unwrap();
103            Ok::<_, ()>(())
104        }))
105        .pipeline(())
106        .await
107        .unwrap();
108
109        let srv: Io<Sealed> = Io::new(server, SharedCfg::default()).boxed().into();
110        let _ = svc.call(srv).await;
111
112        let buf = client.read().await.unwrap();
113        assert_eq!(buf, b"RES".as_ref());
114    }
115}