rama_net/stream/service/
echo.rs

1//! An async service which echoes the incoming bytes back on the same stream.
2
3use crate::stream::Stream;
4use rama_core::{Context, Service, error::BoxError};
5
6/// An async service which echoes the incoming bytes back on the same stream.
7///
8/// # Example
9///
10/// ```rust
11/// use rama_core::{error::BoxError, Context, Service};
12/// use rama_net::stream::service::EchoService;
13///
14/// # #[tokio::main]
15/// # async fn main() -> Result<(), BoxError> {
16/// # let stream = tokio_test::io::Builder::new().read(b"hello world").write(b"hello world").build();
17/// let service = EchoService::new();
18///
19/// let bytes_copied = service.serve(Context::default(), stream).await?;
20/// # assert_eq!(bytes_copied, 11);
21/// # Ok(())
22/// # }
23/// ```
24#[derive(Debug, Clone)]
25pub struct EchoService {
26    _phantom: (),
27}
28
29impl EchoService {
30    /// Creates a new [`EchoService`],
31    pub const fn new() -> Self {
32        Self { _phantom: () }
33    }
34}
35
36impl Default for EchoService {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl<T, S> Service<T, S> for EchoService
43where
44    T: Send + Sync + 'static,
45    S: Stream + 'static,
46{
47    type Response = u64;
48    type Error = BoxError;
49
50    async fn serve(&self, _ctx: Context<T>, stream: S) -> Result<Self::Response, Self::Error> {
51        let (mut reader, mut writer) = tokio::io::split(stream);
52        tokio::io::copy(&mut reader, &mut writer)
53            .await
54            .map_err(Into::into)
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    use tokio_test::io::Builder;
63
64    #[tokio::test]
65    async fn test_echo() {
66        let stream = Builder::new()
67            .read(b"one")
68            .write(b"one")
69            .read(b"two")
70            .write(b"two")
71            .build();
72
73        EchoService::new()
74            .serve(Context::default(), stream)
75            .await
76            .unwrap();
77    }
78}