Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

144
vendor/web-time/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,144 @@
//! # Description
//!
//! Complete drop-in replacement for [`std::time`] that works in browsers.
//!
//! Currently [`Instant::now()`] and [`SystemTime::now()`] will simply panic
//! when using the `wasm32-unknown-unknown` target. This implementation uses
//! [`Performance.now()`] for [`Instant`] and [`Date.now()`] for [`SystemTime`]
//! to offer a drop-in replacement that works in browsers.
//!
//! At the same time the library will simply re-export [`std::time`] when not
//! using the `wasm32-unknown-unknown` target and will not pull in any
//! dependencies.
//!
//! Additionally, if compiled with `target-feature = "atomics"` it will
//! synchronize the timestamps to account for different context's, like web
//! workers. See [`Performance.timeOrigin`] for more information.
//!
//! Using `-Ctarget-feature=+nontrapping-fptoint` will improve the performance
//! of [`Instant::now()`] and [`SystemTime::now()`], but the vast majority of
//! the time is still spent going through JS.
//!
//! # Target
//!
//! This library specifically targets browsers, that support
//! [`Performance.now()`], with the `wasm32-unknown-unknown` target. Emscripten
//! is not supported. WASI doesn't require support as it has it's own native API
//! to deal with [`std::time`].
//!
//! Furthermore it depends on [`wasm-bindgen`], which is required. This library
//! will continue to depend on it until a viable alternative presents itself, in
//! which case multiple ecosystems could be supported.
//!
//! # Note
//!
//! ## Ticking during sleep
//!
//! Currently a known bug is affecting browsers on operating system other then
//! Windows. This bug prevents [`Instant`] from continuing to tick when the
//! context is asleep. This doesn't necessarily conflict with Rusts requirements
//! of [`Instant`], but might still be unexpected.
//!
//! See [the MDN documentation on this](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now#ticking_during_sleep) for more information.
//!
//! ## Context support
//!
//! The implementation of [`Instant::now()`] relies on the availability of the
//! [`Performance` object], a lack thereof will cause a panic. This can happen
//! if called from a [worklet].
//!
//! # Usage
//!
//! You can simply import the types you need:
//! ```rust
//! use web_time::{Instant, SystemTime};
//!
//! let now = Instant::now();
//! let time = SystemTime::now();
//! ```
//!
//! # Features
//!
//! ## `serde`
//!
//! Implements [`serde::Deserialize`] and [`serde::Serialize`] for
//! [`SystemTime`].
//!
//! # MSRV
//!
//! As this library heavily relies on [`wasm-bindgen`] the MSRV depends on it.
//! At the point of time this was written the MSRV is 1.60.
//!
//! # Alternatives
//!
//! [instant](https://crates.io/crates/instant) [![Crates.io](https://img.shields.io/crates/v/instant.svg)](https://crates.io/crates/instant) is a popular alternative! However the API it implements doesn't match [`std::time`] exactly.
//!
//! # Contributing
//!
//! See the [CONTRIBUTING] file for details.
//!
//! # Attribution
//!
//! Inspiration was taken from the [instant](https://github.com/sebcrozet/instant/tree/v0.1.12) project.
//!
//! Additional insight was taken from the [time](https://github.com/time-rs/time/tree/v0.3.20) project.
//!
//! # Changelog
//!
//! See the [CHANGELOG] file for details.
//!
//! # License
//!
//! Licensed under either of
//!
//! - Apache License, Version 2.0 ([LICENSE-APACHE] or <http://www.apache.org/licenses/LICENSE-2.0>)
//! - MIT license ([LICENSE-MIT] or <http://opensource.org/licenses/MIT>)
//!
//! at your option.
//!
//! ## Copyright
//!
//! A majority of the code and documentation was taken from [`std::time`]. For
//! license information see [#License](https://github.com/rust-lang/rust/tree/1.68.1#license).
//!
//! ## Contribution
//!
//! Unless you explicitly state otherwise, any contribution intentionally
//! submitted for inclusion in the work by you, as defined in the Apache-2.0
//! license, shall be dual licensed as above, without any additional terms or
//! conditions.
//!
//! [CHANGELOG]: https://github.com/daxpedda/web-time/blob/v1.1.0/CHANGELOG.md
//! [CONTRIBUTING]: https://github.com/daxpedda/web-time/blob/v1.1.0/CONTRIBUTING.md
//! [LICENSE-MIT]: https://github.com/daxpedda/web-time/blob/v1.1.0/LICENSE-MIT
//! [LICENSE-APACHE]: https://github.com/daxpedda/web-time/blob/v1.1.0/LICENSE-APACHE
//! [worklet]: https://developer.mozilla.org/en-US/docs/Web/API/Worklet
//! [`Date.now()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now
//! [`Instant`]: https://doc.rust-lang.org/std/time/struct.Instant.html
//! [`Instant::now()`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now
//! [`SystemTime`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html
//! [`SystemTime::now()`]: https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.now
//! [`std::time`]: https://doc.rust-lang.org/stable/std/time/
//! [`performance.now()`]: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
//! [`Performance.timeOrigin`]: https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin
//! [`Performance` object]: https://developer.mozilla.org/en-US/docs/Web/API/performance_property
#![cfg_attr(
any(not(feature = "serde"), not(target_family = "wasm")),
doc = "[`serde::Deserialize`]: https://docs.rs/serde/1/serde/trait.Deserialize.html",
doc = "[`serde::Serialize`]: https://docs.rs/serde/1/serde/trait.Serialize.html"
)]
//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
mod time;
#[cfg(any(all(target_family = "wasm", target_os = "unknown"), docsrs))]
#[cfg_attr(docsrs, doc(cfg(Web)))]
pub mod web;
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
pub use std::time::*;
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
pub use self::time::*;

242
vendor/web-time/src/time/instant.rs vendored Normal file
View File

@@ -0,0 +1,242 @@
//! Re-implementation of [`std::time::Instant`].
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::Duration;
use super::js::PERFORMANCE;
#[cfg(target_feature = "atomics")]
thread_local! {
static ORIGIN: f64 = PERFORMANCE.with(super::js::Performance::time_origin);
}
/// See [`std::time::Instant`].
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Instant(Duration);
impl Instant {
/// See [`std::time::Instant::now()`].
///
/// # Panics
///
/// This call will panic if the [`Performance` object] was not found, e.g.
/// calling from a [worklet].
///
/// [`Performance` object]: https://developer.mozilla.org/en-US/docs/Web/API/performance_property
/// [worklet]: https://developer.mozilla.org/en-US/docs/Web/API/Worklet
#[must_use]
pub fn now() -> Self {
let now = PERFORMANCE.with(|performance| {
#[cfg(target_feature = "atomics")]
return ORIGIN.with(|origin| performance.now() + origin);
#[cfg(not(target_feature = "atomics"))]
performance.now()
});
Self(time_stamp_to_duration(now))
}
/// See [`std::time::Instant::duration_since()`].
#[must_use]
pub fn duration_since(&self, earlier: Self) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
}
/// See [`std::time::Instant::checked_duration_since()`].
#[must_use]
#[allow(clippy::missing_const_for_fn)]
pub fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
self.0.checked_sub(earlier.0)
}
/// See [`std::time::Instant::saturating_duration_since()`].
#[must_use]
pub fn saturating_duration_since(&self, earlier: Self) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
}
/// See [`std::time::Instant::elapsed()`].
#[must_use]
pub fn elapsed(&self) -> Duration {
Self::now() - *self
}
/// See [`std::time::Instant::checked_add()`].
pub fn checked_add(&self, duration: Duration) -> Option<Self> {
self.0.checked_add(duration).map(Instant)
}
/// See [`std::time::Instant::checked_sub()`].
pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
self.0.checked_sub(duration).map(Instant)
}
}
impl Add<Duration> for Instant {
type Output = Self;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be
/// represented by the underlying data structure. See
/// [`Instant::checked_add`] for a version without panic.
fn add(self, other: Duration) -> Self {
self.checked_add(other)
.expect("overflow when adding duration to instant")
}
}
impl AddAssign<Duration> for Instant {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}
impl Sub<Duration> for Instant {
type Output = Self;
fn sub(self, other: Duration) -> Self {
self.checked_sub(other)
.expect("overflow when subtracting duration from instant")
}
}
impl Sub<Self> for Instant {
type Output = Duration;
/// Returns the amount of time elapsed from another instant to this one,
/// or zero duration if that instant is later than this one.
fn sub(self, other: Self) -> Duration {
self.duration_since(other)
}
}
impl SubAssign<Duration> for Instant {
fn sub_assign(&mut self, other: Duration) {
*self = *self - other;
}
}
/// Converts a `DOMHighResTimeStamp` to a [`Duration`].
///
/// # Note
///
/// Keep in mind that like [`Duration::from_secs_f64()`] this doesn't do perfect
/// rounding.
#[allow(
clippy::as_conversions,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
fn time_stamp_to_duration(time_stamp: f64) -> Duration {
Duration::from_millis(time_stamp.trunc() as u64)
+ Duration::from_nanos((time_stamp.fract() * 1.0e6).round() as u64)
}
#[cfg(test)]
mod test {
use std::time::Duration;
use rand::distributions::Uniform;
use rand::Rng;
use wasm_bindgen_test::wasm_bindgen_test;
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
// According to <https://www.w3.org/TR/2023/WD-hr-time-3-20230719/#introduction>.
const MAXIMUM_ACCURATE_SECS: u64 = 285_616 * 365 * 24 * 60 * 60;
#[allow(clippy::as_conversions, clippy::cast_precision_loss)]
const MAXIMUM_ACCURATE_MILLIS: f64 = MAXIMUM_ACCURATE_SECS as f64 * 1_000.;
#[derive(Debug)]
struct ControlDuration(Duration);
impl ControlDuration {
fn new(time_stamp: f64) -> Self {
// See <https://doc.rust-lang.org/1.73.0/src/core/time.rs.html#657-668>.
let time_stamp = Duration::from_secs_f64(time_stamp);
let secs = time_stamp.as_secs() / 1000;
let carry = time_stamp.as_secs() - secs * 1000;
#[allow(clippy::as_conversions, clippy::cast_possible_truncation)]
let extra_nanos = (carry * 1_000_000_000 / 1000) as u32;
// CHANGED: Added rounding.
let nanos = time_stamp.subsec_micros()
+ u32::from(time_stamp.subsec_nanos() % 1000 > 499)
+ extra_nanos;
// CHANGED: Removed check that would fail because of the additional time added
// by rounding.
Self(Duration::new(secs, nanos))
}
}
impl PartialEq<Duration> for ControlDuration {
fn eq(&self, duration: &Duration) -> bool {
// Our control `Duration` has perfect accuracy, unlike
// [`super::time_stamp_to_duration()`].
if self.0 == *duration {
true
} else if let Some(diff) = self.0.checked_sub(*duration) {
diff == Duration::from_nanos(1)
} else {
false
}
}
}
#[wasm_bindgen_test]
fn sanity() {
#[track_caller]
fn assert(time_stamp: f64, result: Duration) {
let control = ControlDuration::new(time_stamp);
let duration = super::time_stamp_to_duration(time_stamp);
assert_eq!(control, result, "control and expected result are different");
assert_eq!(control, duration);
}
assert(0.000_000, Duration::ZERO);
assert(0.000_000_4, Duration::ZERO);
assert(0.000_000_5, Duration::from_nanos(1));
assert(0.000_001, Duration::from_nanos(1));
assert(0.000_001_4, Duration::from_nanos(1));
assert(0.000_001_5, Duration::from_nanos(2));
assert(0.999_999, Duration::from_nanos(999_999));
assert(0.999_999_4, Duration::from_nanos(999_999));
assert(0.999_999_5, Duration::from_millis(1));
assert(1., Duration::from_millis(1));
assert(1.000_000_4, Duration::from_millis(1));
assert(1.000_000_5, Duration::from_nanos(1_000_001));
assert(1.000_001, Duration::from_nanos(1_000_001));
assert(1.000_001_4, Duration::from_nanos(1_000_001));
assert(1.000_001_5, Duration::from_nanos(1_000_002));
assert(999.999_999, Duration::from_nanos(999_999_999));
assert(999.999_999_4, Duration::from_nanos(999_999_999));
assert(999.999_999_5, Duration::from_secs(1));
assert(1000., Duration::from_secs(1));
assert(1_000.000_000_4, Duration::from_secs(1));
assert(1_000.000_000_5, Duration::from_nanos(1_000_000_001));
assert(1_000.000_001, Duration::from_nanos(1_000_000_001));
assert(1_000.000_001_4, Duration::from_nanos(1_000_000_001));
assert(1_000.000_001_5, Duration::from_nanos(1_000_000_002));
assert(
MAXIMUM_ACCURATE_MILLIS,
Duration::from_secs(MAXIMUM_ACCURATE_SECS),
);
}
#[wasm_bindgen_test]
fn fuzzing() {
let mut random =
rand::thread_rng().sample_iter(Uniform::new_inclusive(0., MAXIMUM_ACCURATE_MILLIS));
for _ in 0..10_000_000 {
let time_stamp = random.next().unwrap();
let control = ControlDuration::new(time_stamp);
let duration = super::time_stamp_to_duration(time_stamp);
assert_eq!(control, duration);
}
}
}

39
vendor/web-time/src/time/js.rs vendored Normal file
View File

@@ -0,0 +1,39 @@
//! Bindings to the JS API.
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::{JsCast, JsValue};
#[wasm_bindgen]
extern "C" {
/// Type for the [global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object).
type Global;
/// Returns the [`Performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance) object.
#[wasm_bindgen(method, getter)]
fn performance(this: &Global) -> JsValue;
/// Type for the [`Performance` object](https://developer.mozilla.org/en-US/docs/Web/API/Performance).
pub(super) type Performance;
/// Binding to [`Performance.now()`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now).
#[wasm_bindgen(method)]
pub(super) fn now(this: &Performance) -> f64;
/// Binding to [`Performance.timeOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin).
#[cfg(target_feature = "atomics")]
#[wasm_bindgen(method, getter, js_name = timeOrigin)]
pub(super) fn time_origin(this: &Performance) -> f64;
}
thread_local! {
pub(super) static PERFORMANCE: Performance = {
let global: Global = js_sys::global().unchecked_into();
let performance = global.performance();
if performance.is_undefined() {
panic!("`Performance` object not found")
} else {
performance.unchecked_into()
}
};
}

15
vendor/web-time/src/time/mod.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
//! Re-implementation of [`std::time`].
mod instant;
mod js;
#[cfg(feature = "serde")]
mod serde;
mod system_time;
pub use std::time::*;
pub use self::instant::Instant;
pub use self::system_time::{SystemTime, SystemTimeError};
/// See [`std::time::UNIX_EPOCH`].
pub const UNIX_EPOCH: SystemTime = SystemTime::UNIX_EPOCH;

177
vendor/web-time/src/time/serde.rs vendored Normal file
View File

@@ -0,0 +1,177 @@
//! Serde serialization and de-serialization for `SystemTime`. It aims to be
//! compatible with Serde's implementation for [`std::time::SystemTime`].
//!
//! This implementation was copied from Serde's
//! [`Deserialize`](https://github.com/serde-rs/serde/blob/5fa711d75d91173aafc6019e03cf8af6ac9ba7b2/serde/src/de/impls.rs#L2168-L2314),
//! and
//! [`Sserialize`](https://github.com/serde-rs/serde/blob/5fa711d75d91173aafc6019e03cf8af6ac9ba7b2/serde/src/ser/impls.rs#L730-L747)
//! implementation.
#![allow(warnings)]
// CHANGED: Replaced occurrences of `tri!` macro with `?`.
use std::fmt;
use std::time::Duration;
use serde::de::{Error, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::SystemTime;
impl<'de> Deserialize<'de> for SystemTime {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
// Reuse duration
enum Field {
Secs,
Nanos,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"secs_since_epoch" => Ok(Field::Secs),
"nanos_since_epoch" => Ok(Field::Nanos),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match value {
b"secs_since_epoch" => Ok(Field::Secs),
b"nanos_since_epoch" => Ok(Field::Nanos),
_ => {
let value = String::from_utf8_lossy(value);
Err(Error::unknown_field(&value, FIELDS))
}
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
fn check_overflow<E>(secs: u64, nanos: u32) -> Result<(), E>
where
E: Error,
{
static NANOS_PER_SEC: u32 = 1_000_000_000;
match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
Some(_) => Ok(()),
None => Err(E::custom("overflow deserializing SystemTime epoch offset")),
}
}
struct DurationVisitor;
impl<'de> Visitor<'de> for DurationVisitor {
type Value = Duration;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("struct SystemTime")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let secs: u64 = match seq.next_element()? {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let nanos: u32 = match seq.next_element()? {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
check_overflow(secs, nanos)?;
Ok(Duration::new(secs, nanos))
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None;
while let Some(key) = map.next_key()? {
match key {
Field::Secs => {
if secs.is_some() {
return Err(<A::Error as Error>::duplicate_field(
"secs_since_epoch",
));
}
secs = Some(map.next_value()?);
}
Field::Nanos => {
if nanos.is_some() {
return Err(<A::Error as Error>::duplicate_field(
"nanos_since_epoch",
));
}
nanos = Some(map.next_value()?);
}
}
}
let secs = match secs {
Some(secs) => secs,
None => return Err(<A::Error as Error>::missing_field("secs_since_epoch")),
};
let nanos = match nanos {
Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
};
check_overflow(secs, nanos)?;
Ok(Duration::new(secs, nanos))
}
}
const FIELDS: &[&str] = &["secs_since_epoch", "nanos_since_epoch"];
let duration = deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor)?;
// CHANGED: Insert `Duration` directly.
let ret = Ok(Self(duration));
ret
}
}
impl Serialize for SystemTime {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeStruct;
// CHANGED: Take `Duration` directly.
let duration_since_epoch = self.0;
let mut state = serializer.serialize_struct("SystemTime", 2)?;
state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())?;
state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos())?;
state.end()
}
}

111
vendor/web-time/src/time/system_time.rs vendored Normal file
View File

@@ -0,0 +1,111 @@
//! Re-implementation of [`std::time::SystemTime`].
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::Duration;
/// See [`std::time::SystemTime`].
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct SystemTime(pub(crate) Duration);
impl SystemTime {
/// See [`std::time::SystemTime::UNIX_EPOCH`].
pub const UNIX_EPOCH: Self = Self(Duration::ZERO);
/// See [`std::time::SystemTime::now()`].
#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn now() -> Self {
#[allow(clippy::as_conversions, clippy::cast_possible_truncation)]
let ms = js_sys::Date::now() as i64;
let ms = ms.try_into().expect("found negative timestamp");
Self(Duration::from_millis(ms))
}
/// See [`std::time::SystemTime::duration_since()`].
#[allow(clippy::missing_errors_doc, clippy::trivially_copy_pass_by_ref)]
pub fn duration_since(&self, earlier: Self) -> Result<Duration, SystemTimeError> {
if self.0 < earlier.0 {
Err(SystemTimeError(earlier.0 - self.0))
} else {
Ok(self.0 - earlier.0)
}
}
/// See [`std::time::SystemTime::elapsed()`].
#[allow(clippy::missing_errors_doc, clippy::trivially_copy_pass_by_ref)]
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
Self::now().duration_since(*self)
}
/// See [`std::time::SystemTime::checked_add()`].
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn checked_add(&self, duration: Duration) -> Option<Self> {
self.0.checked_add(duration).map(SystemTime)
}
/// See [`std::time::SystemTime::checked_sub()`].
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
self.0.checked_sub(duration).map(SystemTime)
}
}
impl Add<Duration> for SystemTime {
type Output = Self;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be
/// represented by the underlying data structure. See
/// [`SystemTime::checked_add`] for a version without panic.
fn add(self, dur: Duration) -> Self {
self.checked_add(dur)
.expect("overflow when adding duration to instant")
}
}
impl AddAssign<Duration> for SystemTime {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}
impl Sub<Duration> for SystemTime {
type Output = Self;
fn sub(self, dur: Duration) -> Self {
self.checked_sub(dur)
.expect("overflow when subtracting duration from instant")
}
}
impl SubAssign<Duration> for SystemTime {
fn sub_assign(&mut self, other: Duration) {
*self = *self - other;
}
}
/// See [`std::time::SystemTimeError`].
#[derive(Clone, Debug)]
#[allow(missing_copy_implementations)]
pub struct SystemTimeError(Duration);
impl SystemTimeError {
/// See [`std::time::SystemTimeError::duration()`].
#[must_use]
#[allow(clippy::missing_const_for_fn)]
pub fn duration(&self) -> Duration {
self.0
}
}
impl Display for SystemTimeError {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(formatter, "second time provided was later than self")
}
}
impl Error for SystemTimeError {}

49
vendor/web-time/src/web.rs vendored Normal file
View File

@@ -0,0 +1,49 @@
//! Platform-specific extensions to [`web-time`](crate) for the Web platform.
#![allow(clippy::absolute_paths)]
use std::time::SystemTime as StdSystemTime;
use crate::SystemTime;
/// Web-specific extension to [`web_time::SystemTime`](crate::SystemTime).
pub trait SystemTimeExt {
/// Convert [`web_time::SystemTime`](crate::SystemTime) to
/// [`std::time::SystemTime`].
///
/// # Note
///
/// This might give a misleading impression of compatibility!
///
/// Considering this functionality will probably be used to interact with
/// incompatible APIs of other dependencies, care should be taken that the
/// dependency in question doesn't call [`std::time::SystemTime::now()`]
/// internally, which would panic.
fn to_std(self) -> std::time::SystemTime;
/// Convert [`std::time::SystemTime`] to
/// [`web_time::SystemTime`](crate::SystemTime).
///
/// # Note
///
/// This might give a misleading impression of compatibility!
///
/// Considering this functionality will probably be used to interact with
/// incompatible APIs of other dependencies, care should be taken that the
/// dependency in question doesn't call [`std::time::SystemTime::now()`]
/// internally, which would panic.
fn from_std(time: std::time::SystemTime) -> SystemTime;
}
impl SystemTimeExt for SystemTime {
fn to_std(self) -> std::time::SystemTime {
StdSystemTime::UNIX_EPOCH + self.0
}
fn from_std(time: std::time::SystemTime) -> SystemTime {
Self::UNIX_EPOCH
+ time
.duration_since(StdSystemTime::UNIX_EPOCH)
.expect("found `SystemTime` earlier then unix epoch")
}
}