Last active
June 14, 2025 06:59
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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