use std::io::{self, Read};
use std::os::unix::io::AsRawFd;
use std::time::Duration;
pub struct RawInputReader {
stdin: io::Stdin,
}
impl RawInputReader {
pub fn new() -> Self {
Self { stdin: io::stdin() }
}
pub fn poll(&self, timeout: Duration) -> io::Result<bool> {
use nix::poll::{PollFd, PollFlags, PollTimeout, poll};
use std::os::unix::io::BorrowedFd;
let fd = self.stdin.as_raw_fd();
let borrowed_fd = unsafe { BorrowedFd::borrow_raw(fd) };
let mut poll_fds = [PollFd::new(borrowed_fd, PollFlags::POLLIN)];
let timeout_ms = timeout.as_millis().min(u16::MAX as u128) as u16;
let poll_timeout = PollTimeout::from(timeout_ms);
match poll(&mut poll_fds, poll_timeout) {
Ok(n) => Ok(n > 0),
Err(nix::errno::Errno::EINTR) => Ok(false), Err(e) => Err(io::Error::from_raw_os_error(e as i32)),
}
}
pub fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
self.stdin.read(buffer)
}
}
impl Default for RawInputReader {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_raw_input_reader_creation() {
let _reader = RawInputReader::new();
}
#[test]
fn test_default() {
let _reader = RawInputReader::default();
}
#[test]
fn test_poll_timeout() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_millis(10));
assert!(result.is_ok());
}
#[test]
fn test_poll_timeout_clamping_at_u16_max() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_millis(70000));
assert!(result.is_ok());
}
#[test]
fn test_poll_timeout_very_large_duration() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_secs(3600));
assert!(result.is_ok());
}
#[test]
fn test_poll_zero_timeout() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::ZERO);
assert!(result.is_ok());
}
#[test]
fn test_poll_one_millisecond_timeout() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_millis(1));
assert!(result.is_ok());
}
#[test]
fn test_poll_exactly_u16_max() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_millis(u16::MAX as u64));
assert!(result.is_ok());
}
#[test]
fn test_poll_just_over_u16_max() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_millis(u16::MAX as u64 + 1));
assert!(result.is_ok());
}
#[test]
fn test_multiple_sequential_polls() {
let reader = RawInputReader::new();
for _ in 0..5 {
let result = reader.poll(Duration::from_millis(1));
assert!(result.is_ok());
}
}
#[test]
fn test_poll_with_nanoseconds() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_nanos(1_500_000)); assert!(result.is_ok());
}
#[test]
fn test_poll_sub_millisecond() {
let reader = RawInputReader::new();
let result = reader.poll(Duration::from_micros(500)); assert!(result.is_ok());
}
}