use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::{ TcpListener, TcpStream, tcp::{OwnedReadHalf, OwnedWriteHalf}, }, }; #[derive(Default)] pub struct State; pub struct Bind(TcpListener); pub struct Wire(String); pub enum Rx { Wait(Rx1), Bind(Rx1), Wire(Rx1), } pub enum Tx { Wait(Tx1), Bind(Tx1), Wire(Tx1), } pub struct Rx1(OwnedReadHalf); pub struct Tx1(OwnedWriteHalf); impl crate::Bind for Bind { type R = Rx1; type T = Tx1; async fn wait(&self) -> Result<(::R, ::T), String> { let (con, _) = self .0 .accept() .await .map_err(|e| format!("[tcp] accepting a new connection failed: {e}"))?; let (rx, tx) = con.into_split(); Ok((Rx1(rx), Tx1(tx))) } } impl crate::Wire for Bind { type R = Rx1; type T = Tx1; async fn parse(arg: &str) -> Result { let addr = arg; Ok(Self(TcpListener::bind(addr).await.map_err(|e| { format!("[tcp] binding to `{addr}` failed: {e}") })?)) } async fn open(&self) -> Result<(Self::R, Self::T), String> { Err("using binds as wires is not (yet) supported for tcp".to_owned()) } } impl crate::Wire for Wire { type R = Rx1; type T = Tx1; async fn parse(arg: &str) -> Result { Ok(Self(arg.to_owned())) } async fn open(&self) -> Result<(Self::R, Self::T), String> { let (rx, tx) = TcpStream::connect(&self.0) .await .map_err(|e| format!("[tcp] connecting to `{}` failed: {e}", &self.0))? .into_split(); Ok((Rx1(rx), Tx1(tx))) } } impl crate::Rx for Rx1 { type T<'a> = &'a [u8]; async fn rx<'a>(&mut self, buf: &'a mut [u8]) -> Result, String> { let i = self .0 .read(buf) .await .map_err(|e| format!("[tcp] reading bytes failed: {e}"))?; Ok(&buf[..i]) } } impl crate::Tx for Tx1 { async fn tx(&mut self, buf: &[u8]) -> Result<(), String> { self.0 .write_all(buf) .await .map_err(|e| format!("[tcp] writing bytes failed: {e}")) } }