use crate::error::{Error, Result};
use crate::io::runtime::AsyncConn;
use crate::io::Machine;
pub(crate) async fn drive<M, C>(machine: &mut M, conn: &mut C) -> Result<Vec<M::Event>>
where
M: Machine,
C: AsyncConn,
{
let mut events = Vec::new();
let mut scratch = [0u8; 16 * 1024];
let mut out = Vec::new();
let mut eof_seen = false;
loop {
out.clear();
while machine.poll_transmit(&mut out) {}
if !out.is_empty() {
conn.write_all(&out).await.map_err(Error::Io)?;
conn.flush().await.map_err(Error::Io)?;
}
while let Some(ev) = machine.poll_event() {
events.push(ev);
}
if machine.is_finished() {
return Ok(events);
}
if eof_seen {
return Err(Error::UnexpectedEof);
}
let n = conn.read(&mut scratch).await.map_err(Error::Io)?;
if n == 0 {
eof_seen = true;
machine.handle_eof()?;
} else {
machine.handle_input(&scratch[..n])?;
}
}
}