Skip to content

Instantly share code, notes, and snippets.

@andy0130tw
Last active June 14, 2025 06:59
Show Gist options
  • Save andy0130tw/af009916428c9ca31b291943beb8910b to your computer and use it in GitHub Desktop.
Save andy0130tw/af009916428c9ca31b291943beb8910b to your computer and use it in GitHub Desktop.
I just found the argubly very first complete Rust program I wrote from scratch. And there were no LLMs involved at that time of writing. Anyway.
use std::task::{Poll, Context};
use std::future::Future;
use std::pin::Pin;
use tokio::io::{Error, Interest, unix::AsyncFd};
struct PollTarget {
inner: AsyncFd<i32>,
}
impl PollTarget {
fn new<'a>(inner: AsyncFd<i32>) -> Self {
Self { inner }
}
}
impl Future for PollTarget {
type Output = Result<Vec::<u8>, Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let ready = self.inner.poll_read_ready(cx);
let mut ready = match ready {
Poll::Pending => {
println!("pending...");
return Poll::Pending;
}
Poll::Ready(Ok(guard)) => guard,
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
};
println!("ready!");
let mut buf = Vec::<u8>::with_capacity(128);
let read_ptr = buf.as_mut_ptr();
let nread = unsafe { libc::read(libc::STDIN_FILENO, read_ptr as *mut libc::c_void, 128) };
if nread < 0 {
let err = std::io::Error::last_os_error();
if err.kind() == std::io::ErrorKind::WouldBlock {
println!("EAGAIN!");
// no more data to consume
ready.clear_ready();
// the key is this line
cx.waker().wake_by_ref();
return Poll::Pending;
} else {
return Poll::Ready(Err(Error::from(err)));
}
} else {
unsafe { buf.set_len(nread as usize); }
return Poll::Ready(Ok(buf));
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// force stdin to be non-blocking
let fcntl_flags = unsafe { libc::fcntl(0, libc::F_GETFL) };
if fcntl_flags < 0 {
panic!("Failed to get fcntl flags on stdin");
}
let ret = unsafe { libc::fcntl(0, libc::F_SETFL, fcntl_flags | libc::O_NONBLOCK) };
if ret < 0 {
panic!("Failed to set fcntl flag to nonblock on stdin");
}
let afd = AsyncFd::with_interest(libc::STDIN_FILENO, Interest::READABLE).unwrap();
let mut stdin_poll = PollTarget::new(afd);
loop {
println!("enter loop");
tokio::select! {
res = &mut stdin_poll => {
match res {
Ok(buf) => {
if buf.is_empty() { break; }
let s = String::from_utf8(buf).unwrap();
println!("Got [{}]!", s);
}
Err(err) => {
println!("Error: {:?}", err);
},
}
},
// _ = sleep(Duration::from_millis(1000)) => {
// println!("slept for 1s");
// },
}
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment