use crate::prelude::*; pub(crate) struct App { outbox: VecDeque, stream: Framed, timer: Interval, } impl App { pub(crate) async fn new() -> Result { let stream = TcpStream::connect("127.0.0.1:9000").await?; let stream = Framed::new(stream, BytesCodec::new()); let mut timer = tokio::time::interval(Duration::from_millis(1000)); timer.set_missed_tick_behavior(MissedTickBehavior::Skip); Ok(Self { outbox: Default::default(), stream, timer, }) } pub(crate) fn poll_run(&mut self, cx: &mut Context<'_>) -> Poll> { { let mut stream = pin!(&mut self.stream); match <_ as futures_sink::Sink>::poll_flush(stream.as_mut(), cx) { Poll::Pending => {} Poll::Ready(Err(err)) => return Poll::Ready(Err(err).context("poll_flush")), Poll::Ready(Ok(())) => {} } } if ! self.outbox.is_empty() { let mut stream = pin!(&mut self.stream); match <_ as futures_sink::Sink>::poll_ready(stream.as_mut(), cx) { Poll::Pending => {} Poll::Ready(Err(err)) => { return Poll::Ready( Err(err).context("Can't check network write half for readiness"), ); } Poll::Ready(Ok(())) => { cx.waker().wake_by_ref(); let frame = rmp_serde::to_vec(&self.outbox.pop_front())?; if let Err(err) = stream.start_send(Bytes::from(frame)) { return Poll::Ready(Err(err).context("start_send")); } tracing::debug!("Started send"); } } } let stream = pin!(&mut self.stream); match stream.poll_next(cx) { Poll::Pending => {} Poll::Ready(None) => return Poll::Ready(Err(anyhow!("Server closed cxn"))), Poll::Ready(Some(frame)) => { cx.waker().wake_by_ref(); let frame = frame.context("network framing decode")?; match rmp_serde::from_slice(&frame)? { ToClient::ChatLine { id, line } => { tracing::info!(?id, ?line); } } } } if self.timer.poll_tick(cx).is_ready() { cx.waker().wake_by_ref(); if self.outbox.is_empty() { self.outbox.push_back(ToServer::ChatLine { line: "tick".to_string(), }); } } Poll::Pending } }