use nix::libc::c_int;
use nix::poll::PollFlags;
use std::io::Result;
use std::io::Seek;
use std::io::SeekFrom;
use std::io::Write;
use std::os::fd::AsFd;
use std::os::fd::BorrowedFd;
use std::time::Duration;
use super::utils;
pub struct TimeoutWriter<H>
where
H: Write + AsFd,
{
timeout: Option<c_int>,
handle: H,
}
impl<H> Write for TimeoutWriter<H>
where
H: Write + AsFd,
{
fn write(&mut self, buf: &[u8]) -> Result<usize> {
utils::wait_until_ready(self.timeout, &self.handle, PollFlags::POLLOUT)?;
self.handle.write(buf)
}
fn flush(&mut self) -> Result<()> {
utils::wait_until_ready(self.timeout, &self.handle, PollFlags::POLLOUT)?;
self.handle.flush()
}
}
impl<H> Seek for TimeoutWriter<H>
where
H: Write + AsFd + Seek,
{
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
self.handle.seek(pos)
}
}
impl<H> AsFd for TimeoutWriter<H>
where
H: Write + AsFd,
{
fn as_fd(&self) -> BorrowedFd<'_> {
self.handle.as_fd()
}
}
impl<H> Clone for TimeoutWriter<H>
where
H: Write + AsFd + Clone,
{
fn clone(&self) -> TimeoutWriter<H> {
TimeoutWriter {
handle: self.handle.clone(),
..*self
}
}
}
impl<H> TimeoutWriter<H>
where
H: Write + AsFd,
{
pub fn new<T: Into<Option<Duration>>>(handle: H, timeout: T) -> TimeoutWriter<H> {
TimeoutWriter {
timeout: timeout.into().map(utils::duration_to_ms),
handle,
}
}
}
pub trait TimeoutWriteExt<H>
where
H: Write + AsFd,
{
fn with_timeout<T: Into<Option<Duration>>>(self, timeout: T) -> TimeoutWriter<H>;
}
impl<H> TimeoutWriteExt<H> for H
where
H: Write + AsFd,
{
fn with_timeout<T: Into<Option<Duration>>>(self, timeout: T) -> TimeoutWriter<H> {
TimeoutWriter::new(self, timeout)
}
}