surrealdb/api/engine/remote/
mod.rs

1//! Protocols for communicating with the server
2
3#[cfg(feature = "protocol-http")]
4#[cfg_attr(docsrs, doc(cfg(feature = "protocol-http")))]
5pub mod http;
6
7#[cfg(feature = "protocol-ws")]
8#[cfg_attr(docsrs, doc(cfg(feature = "protocol-ws")))]
9pub mod ws;
10
11use rust_decimal::prelude::ToPrimitive;
12use rust_decimal::Decimal;
13use std::time::Duration;
14
15const NANOS_PER_SEC: i64 = 1_000_000_000;
16const NANOS_PER_MILLI: i64 = 1_000_000;
17const NANOS_PER_MICRO: i64 = 1_000;
18
19// Converts a debug representation of `std::time::Duration` back
20fn duration_from_str(duration: &str) -> Option<std::time::Duration> {
21	let nanos = if let Some(duration) = duration.strip_suffix("ns") {
22		duration.parse().ok()?
23	} else if let Some(duration) = duration.strip_suffix("µs") {
24		let micros = duration.parse::<Decimal>().ok()?;
25		let multiplier = Decimal::try_new(NANOS_PER_MICRO, 0).ok()?;
26		micros.checked_mul(multiplier)?.to_u128()?
27	} else if let Some(duration) = duration.strip_suffix("ms") {
28		let millis = duration.parse::<Decimal>().ok()?;
29		let multiplier = Decimal::try_new(NANOS_PER_MILLI, 0).ok()?;
30		millis.checked_mul(multiplier)?.to_u128()?
31	} else {
32		let duration = duration.strip_suffix('s')?;
33		let secs = duration.parse::<Decimal>().ok()?;
34		let multiplier = Decimal::try_new(NANOS_PER_SEC, 0).ok()?;
35		secs.checked_mul(multiplier)?.to_u128()?
36	};
37	let secs = nanos.checked_div(NANOS_PER_SEC as u128)?;
38	let nanos = nanos % (NANOS_PER_SEC as u128);
39	Some(Duration::new(secs.try_into().ok()?, nanos.try_into().ok()?))
40}
41
42#[cfg(test)]
43mod tests {
44	use std::time::Duration;
45
46	#[test]
47	fn duration_from_str() {
48		let durations = vec![
49			Duration::ZERO,
50			Duration::from_nanos(1),
51			Duration::from_nanos(u64::MAX),
52			Duration::from_micros(1),
53			Duration::from_micros(u64::MAX),
54			Duration::from_millis(1),
55			Duration::from_millis(u64::MAX),
56			Duration::from_secs(1),
57			Duration::from_secs(u64::MAX),
58			Duration::MAX,
59		];
60
61		for duration in durations {
62			let string = format!("{duration:?}");
63			let parsed = super::duration_from_str(&string)
64				.unwrap_or_else(|| panic!("Duration {string} failed to parse"));
65			assert_eq!(duration, parsed, "Duration {string} not parsed correctly");
66		}
67	}
68}