use std::cmp::min;
use std::ffi::c_int;
use std::fmt;
use std::time::Duration;
use crate::{OptRMarker, OptWMarker, SockOptMarker};
use crate::
{
SO_RCVTIMEO, SOL_SOCKET, timeval, time_t, suseconds_t
};
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct SoRcvTimeout(timeval);
#[cfg(unix)]
impl fmt::Debug for SoRcvTimeout
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.debug_tuple("SoRcvTimeout").field(&self.0).finish()
}
}
#[cfg(windows)]
impl fmt::Debug for SoRcvTimeout
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.debug_tuple("SoRcvTimeout").finish()
}
}
impl SockOptMarker for SoRcvTimeout
{
const SO_LEVEL: c_int = SOL_SOCKET;
const SO_OPTNAME: c_int = SO_RCVTIMEO;
type DataType = Option<Duration>;
type InputType = timeval;
#[inline]
fn from(value: Self::InputType) -> Self
{
return Self(value);
}
#[inline]
fn get(self) -> Self::DataType
{
if self.0.tv_sec == 0 && self.0.tv_usec == 0
{
return None;
}
else
{
let sec = self.0.tv_sec as u64;
let nsec = (self.0.tv_usec as u32) * 1000;
return Some(Duration::new(sec, nsec));
}
}
fn from_user(sz: Self::DataType) -> Self where Self: Sized
{
return Self(
sz
.map_or(
timeval{ tv_sec: 0, tv_usec: 0 },
|v|
timeval
{
tv_sec: min(v.as_secs(), time_t::MAX as u64) as time_t,
tv_usec: v.subsec_micros() as suseconds_t,
}
)
);
}
}
impl OptRMarker for SoRcvTimeout {}
impl OptWMarker for SoRcvTimeout {}