79 lines
2.7 KiB
Rust
79 lines
2.7 KiB
Rust
use crate::prelude::*;
|
|
|
|
pub(crate) struct App {
|
|
outbox: VecDeque<ToServer>,
|
|
stream: Framed<TcpStream, BytesCodec>,
|
|
timer: Interval,
|
|
}
|
|
|
|
impl App {
|
|
pub(crate) async fn new() -> Result<Self> {
|
|
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<Result<()>> {
|
|
{
|
|
let mut stream = pin!(&mut self.stream);
|
|
match <_ as futures_sink::Sink<Bytes>>::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<Bytes>>::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
|
|
}
|
|
}
|