1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
use crate::model::io::*; use crate::model::smtp::SmtpReply; use crate::model::{Error, Result}; use crate::service::mail::*; use crate::service::session::*; use futures::prelude::*; use pin_project::pin_project; use std::pin::Pin; use std::task::{Context, Poll}; #[derive(Clone)] pub struct DummySessionService<S> { mail_service: S, } impl<S> DummySessionService<S> { pub fn new(mail_service: S) -> Self { Self { mail_service } } } impl<S, TIn> SessionService<TIn> for DummySessionService<S> where S: NamedService, { type Session = DummySessionHandler; type StartFuture = future::Ready<Self::Session>; fn start(&self, _input: TIn) -> Self::StartFuture { let name = self.mail_service.name(); future::ready(DummySessionHandler::new(name)) } } #[pin_project(project=HandlerProjection)] #[must_use = "streams and sinks do nothing unless polled"] pub struct DummySessionHandler { name: String, state: u8, closed: bool, } impl DummySessionHandler { pub fn new(name: impl ToString) -> Self { Self { name: name.to_string(), state: 0, closed: false, } } } impl Sink<ReadControl> for DummySessionHandler { type Error = Error; fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { trace!("Polling flush"); assert!(self.closed == false, "called poll_flush() on closed sink"); self.poll_ready(cx) } fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { trace!("Polling close"); assert!(self.closed == false, "called poll_close() on closed sink"); let res = self.as_mut().poll_flush(cx); self.closed = true; res } fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>> { trace!("Polling ready"); assert!(self.closed == false, "called poll_ready() on closed sink"); Poll::Ready(Ok(())) } fn start_send(mut self: Pin<&mut Self>, item: ReadControl) -> Result<()> { trace!("Sink item: {:?}", item); assert!(self.closed == false, "called start_send() on closed sink"); self.state += 1; Ok(()) } } impl Stream for DummySessionHandler { type Item = Result<WriteControl>; fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { trace!("Polling next session answer. pending {}", self.state); if self.state != 0 { self.state -= 1; Poll::Ready(Some(Ok(WriteControl::Reply(SmtpReply::ServiceReadyInfo( self.name.clone(), ))))) } else if self.closed { Poll::Ready(None) } else { Poll::Pending } } }