fire_postgres/time/
timeout.rs

1use crate::table::column::{ColumnData, ColumnKind, ColumnType, FromDataError};
2use std::time::{Duration, SystemTime};
3
4use serde::de::{Deserializer, Error};
5use serde::ser::Serializer;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone)]
9pub struct Timeout {
10	inner: SystemTime,
11}
12
13impl Timeout {
14	pub fn new(dur: Duration) -> Self {
15		Self {
16			inner: SystemTime::now() + dur,
17		}
18	}
19
20	pub fn now() -> Self {
21		Self {
22			inner: SystemTime::now(),
23		}
24	}
25
26	pub fn has_elapsed(&self) -> bool {
27		SystemTime::now() > self.inner
28	}
29
30	/// Returns None if the Duration is negative
31	pub fn remaining(&self) -> Option<Duration> {
32		self.inner.duration_since(SystemTime::now()).ok()
33	}
34
35	/// returns the time from UNIX_EPOCH
36	pub fn as_secs(&self) -> u64 {
37		self.inner
38			.duration_since(SystemTime::UNIX_EPOCH)
39			.expect("Welcome to the past!")
40			.as_secs()
41	}
42
43	pub fn from_secs(s: u64) -> Option<Self> {
44		SystemTime::UNIX_EPOCH
45			.checked_add(Duration::from_secs(s))
46			.map(|c| Timeout { inner: c })
47	}
48}
49
50impl Serialize for Timeout {
51	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52	where
53		S: Serializer,
54	{
55		serializer.serialize_u64(self.as_secs())
56	}
57}
58
59impl<'de> Deserialize<'de> for Timeout {
60	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
61	where
62		D: Deserializer<'de>,
63	{
64		let num: u64 = Deserialize::deserialize(deserializer)?;
65		Self::from_secs(num).ok_or(D::Error::custom("timeout to big"))
66	}
67}
68
69impl ColumnType for Timeout {
70	fn column_kind() -> ColumnKind {
71		ColumnKind::I64
72	}
73
74	fn to_data(&self) -> ColumnData<'static> {
75		ColumnData::I64(self.as_secs().try_into().expect("timeout to large"))
76	}
77
78	fn from_data(data: ColumnData) -> Result<Self, FromDataError> {
79		match data {
80			ColumnData::I64(u) => match u64::try_from(u) {
81				Ok(u) => Self::from_secs(u)
82					.ok_or(FromDataError::Custom("timeout to large")),
83				Err(e) => Err(FromDataError::CustomString(e.to_string())),
84			},
85			_ => Err(FromDataError::ExpectedType("expected i64 for u64")),
86		}
87	}
88}