Add more from the std
This commit is contained in:
4
crates/std/src/error.rs
Normal file
4
crates/std/src/error.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::error::Error;
|
||||
#[unstable(feature = "error_generic_member_access", issue = "99301")]
|
||||
pub use core::error::{Request, request_ref, request_value};
|
||||
3532
crates/std/src/fs.rs
Normal file
3532
crates/std/src/fs.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ pub fn stdin() -> Stdin {
|
||||
Stdin
|
||||
}
|
||||
|
||||
pub type Result<T> = core::result::Result<T, ()>;
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
pub(super) struct Repr();
|
||||
|
||||
@@ -30,10 +30,42 @@ pub(super) struct Repr();
|
||||
#[unstable(feature = "io_const_error", issue = "133448")]
|
||||
#[allow_internal_unstable(hint_must_use, io_const_error_internals)]
|
||||
pub macro const_error($kind:expr, $message:expr $(,)?) {
|
||||
()
|
||||
crate::io::Error::new()
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Error {
|
||||
repr: Repr,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub const fn new() -> Self {
|
||||
Self { repr: Repr() }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Error {
|
||||
pub(crate) const INVALID_UTF8: Self =
|
||||
const_error!(ErrorKind::InvalidData, "stream did not contain valid UTF-8");
|
||||
|
||||
pub(crate) const READ_EXACT_EOF: Self =
|
||||
const_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer");
|
||||
|
||||
pub(crate) const UNKNOWN_THREAD_COUNT: Self = const_error!(
|
||||
ErrorKind::NotFound,
|
||||
"the number of hardware threads is not known for the target platform",
|
||||
);
|
||||
|
||||
pub(crate) const UNSUPPORTED_PLATFORM: Self =
|
||||
const_error!(ErrorKind::Unsupported, "operation not supported on this platform");
|
||||
|
||||
pub(crate) const WRITE_ALL_EOF: Self =
|
||||
const_error!(ErrorKind::WriteZero, "failed to write whole buffer");
|
||||
|
||||
pub(crate) const ZERO_TIMEOUT: Self =
|
||||
const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout");
|
||||
|
||||
pub(crate) const NO_ADDRESSES: Self =
|
||||
const_error!(ErrorKind::InvalidInput, "could not resolve to any addresses");
|
||||
}
|
||||
|
||||
@@ -181,10 +181,9 @@
|
||||
#![feature(io_const_error)]
|
||||
// tidy-alphabetical-end
|
||||
//
|
||||
|
||||
#![feature(c_size_t, unsafe_binders)]
|
||||
#![allow(clippy::doc_lazy_continuation, clippy::all)]
|
||||
#![allow(stable_features, incomplete_features)]
|
||||
#![allow(stable_features, incomplete_features, unexpected_cfgs)]
|
||||
#![allow(unused)]
|
||||
|
||||
extern crate alloc;
|
||||
@@ -246,12 +245,25 @@ pub use alloc::str;
|
||||
pub use alloc::string;
|
||||
pub use alloc::vec;
|
||||
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
pub use core::{
|
||||
assert, cfg, column, compile_error, concat, const_format_args, env, file, format_args,
|
||||
format_args_nl, include, include_bytes, include_str, line, log_syntax, module_path, option_env,
|
||||
stringify, trace_macros,
|
||||
};
|
||||
|
||||
pub mod ffi;
|
||||
pub mod hash;
|
||||
pub mod io;
|
||||
// pub mod fs;
|
||||
pub mod error;
|
||||
pub mod num;
|
||||
pub mod path;
|
||||
pub mod prelude;
|
||||
pub mod process;
|
||||
pub mod sys;
|
||||
pub mod time;
|
||||
pub mod thread;
|
||||
|
||||
#[prelude_import]
|
||||
#[allow(unused_imports)]
|
||||
|
||||
28
crates/std/src/num/mod.rs
Normal file
28
crates/std/src/num/mod.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
//! Additional functionality for numerics.
|
||||
//!
|
||||
//! This module provides some extra types that are useful when doing numerical
|
||||
//! work. See the individual documentation for each piece for more information.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
#[stable(feature = "int_error_matching", since = "1.55.0")]
|
||||
pub use core::num::IntErrorKind;
|
||||
#[stable(feature = "generic_nonzero", since = "1.79.0")]
|
||||
pub use core::num::NonZero;
|
||||
#[stable(feature = "saturating_int_impl", since = "1.74.0")]
|
||||
pub use core::num::Saturating;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::num::Wrapping;
|
||||
#[unstable(
|
||||
feature = "nonzero_internals",
|
||||
reason = "implementation detail which may disappear or be replaced at any time",
|
||||
issue = "none"
|
||||
)]
|
||||
pub use core::num::ZeroablePrimitive;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")]
|
||||
pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize};
|
||||
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||
pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
|
||||
4047
crates/std/src/path.rs
Normal file
4047
crates/std/src/path.rs
Normal file
File diff suppressed because it is too large
Load Diff
114
crates/std/src/sys/cmath.rs
Normal file
114
crates/std/src/sys/cmath.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
#![cfg(not(test))]
|
||||
|
||||
// These symbols are all defined by `libm`,
|
||||
// or by `compiler-builtins` on unsupported platforms.
|
||||
unsafe extern "C" {
|
||||
pub safe fn acos(n: f64) -> f64;
|
||||
pub safe fn asin(n: f64) -> f64;
|
||||
pub safe fn atan(n: f64) -> f64;
|
||||
pub safe fn atan2(a: f64, b: f64) -> f64;
|
||||
pub safe fn cosh(n: f64) -> f64;
|
||||
pub safe fn expm1(n: f64) -> f64;
|
||||
pub safe fn expm1f(n: f32) -> f32;
|
||||
#[cfg_attr(target_env = "msvc", link_name = "_hypot")]
|
||||
pub safe fn hypot(x: f64, y: f64) -> f64;
|
||||
#[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
|
||||
pub safe fn hypotf(x: f32, y: f32) -> f32;
|
||||
pub safe fn log1p(n: f64) -> f64;
|
||||
pub safe fn log1pf(n: f32) -> f32;
|
||||
pub safe fn sinh(n: f64) -> f64;
|
||||
pub safe fn tan(n: f64) -> f64;
|
||||
pub safe fn tanh(n: f64) -> f64;
|
||||
pub safe fn tgamma(n: f64) -> f64;
|
||||
pub safe fn tgammaf(n: f32) -> f32;
|
||||
pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64;
|
||||
#[cfg(not(target_os = "aix"))]
|
||||
pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32;
|
||||
pub safe fn erf(n: f64) -> f64;
|
||||
pub safe fn erff(n: f32) -> f32;
|
||||
pub safe fn erfc(n: f64) -> f64;
|
||||
pub safe fn erfcf(n: f32) -> f32;
|
||||
|
||||
pub safe fn acosf128(n: f128) -> f128;
|
||||
pub safe fn asinf128(n: f128) -> f128;
|
||||
pub safe fn atanf128(n: f128) -> f128;
|
||||
pub safe fn atan2f128(a: f128, b: f128) -> f128;
|
||||
pub safe fn cbrtf128(n: f128) -> f128;
|
||||
pub safe fn coshf128(n: f128) -> f128;
|
||||
pub safe fn expm1f128(n: f128) -> f128;
|
||||
pub safe fn hypotf128(x: f128, y: f128) -> f128;
|
||||
pub safe fn log1pf128(n: f128) -> f128;
|
||||
pub safe fn sinhf128(n: f128) -> f128;
|
||||
pub safe fn tanf128(n: f128) -> f128;
|
||||
pub safe fn tanhf128(n: f128) -> f128;
|
||||
pub safe fn tgammaf128(n: f128) -> f128;
|
||||
pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
|
||||
pub safe fn erff128(n: f128) -> f128;
|
||||
pub safe fn erfcf128(n: f128) -> f128;
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
all(target_os = "windows", target_env = "msvc", target_arch = "x86") => {
|
||||
// On 32-bit x86 MSVC these functions aren't defined, so we just define shims
|
||||
// which promote everything to f64, perform the calculation, and then demote
|
||||
// back to f32. While not precisely correct should be "correct enough" for now.
|
||||
#[inline]
|
||||
pub fn acosf(n: f32) -> f32 {
|
||||
f64::acos(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn asinf(n: f32) -> f32 {
|
||||
f64::asin(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn atan2f(n: f32, b: f32) -> f32 {
|
||||
f64::atan2(n as f64, b as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn atanf(n: f32) -> f32 {
|
||||
f64::atan(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn coshf(n: f32) -> f32 {
|
||||
f64::cosh(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sinhf(n: f32) -> f32 {
|
||||
f64::sinh(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tanf(n: f32) -> f32 {
|
||||
f64::tan(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tanhf(n: f32) -> f32 {
|
||||
f64::tanh(n as f64) as f32
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unsafe extern "C" {
|
||||
pub safe fn acosf(n: f32) -> f32;
|
||||
pub safe fn asinf(n: f32) -> f32;
|
||||
pub safe fn atan2f(a: f32, b: f32) -> f32;
|
||||
pub safe fn atanf(n: f32) -> f32;
|
||||
pub safe fn coshf(n: f32) -> f32;
|
||||
pub safe fn sinhf(n: f32) -> f32;
|
||||
pub safe fn tanf(n: f32) -> f32;
|
||||
pub safe fn tanhf(n: f32) -> f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On AIX, we don't have lgammaf_r only the f64 version, so we can
|
||||
// use the f64 version lgamma_r
|
||||
#[cfg(target_os = "aix")]
|
||||
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 {
|
||||
lgamma_r(n.into(), s) as f32
|
||||
}
|
||||
62
crates/std/src/sys/configure_builtins.rs
Normal file
62
crates/std/src/sys/configure_builtins.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
//! The configure builtins provides runtime support compiler-builtin features
|
||||
//! which require dynamic initialization to work as expected, e.g. aarch64
|
||||
//! outline-atomics.
|
||||
|
||||
/// Enable LSE atomic operations at startup, if supported.
|
||||
///
|
||||
/// Linker sections are based on what [`ctor`] does, with priorities to run slightly before user
|
||||
/// code:
|
||||
///
|
||||
/// - Apple uses the section `__mod_init_func`, `mod_init_funcs` is needed to set
|
||||
/// `S_MOD_INIT_FUNC_POINTERS`. There doesn't seem to be a way to indicate priorities.
|
||||
/// - Windows uses `.CRT$XCT`, which is run before user constructors (these should use `.CRT$XCU`).
|
||||
/// - ELF uses `.init_array` with a priority of 90, which runs before our `ARGV_INIT_ARRAY`
|
||||
/// initializer (priority 99). Both are within the 0-100 implementation-reserved range, per docs
|
||||
/// for the [`prio-ctor-dtor`] warning, and this matches compiler-rt's `CONSTRUCTOR_PRIORITY`.
|
||||
///
|
||||
/// To save startup time, the initializer is only run if outline atomic routines from
|
||||
/// compiler-builtins may be used. If LSE is known to be available then the calls are never
|
||||
/// emitted, and if we build the C intrinsics then it has its own initializer using the symbol
|
||||
/// `__aarch64_have_lse_atomics`.
|
||||
///
|
||||
/// Initialization is done in a global constructor to so we get the same behavior regardless of
|
||||
/// whether Rust's `init` is used, or if we are in a `dylib` or `no_main` situation (as opposed
|
||||
/// to doing it as part of pre-main startup). This also matches C implementations.
|
||||
///
|
||||
/// Ideally `core` would have something similar, but detecting the CPU features requires the
|
||||
/// auxiliary vector from the OS. We do the initialization in `std` rather than as part of
|
||||
/// `compiler-builtins` because a builtins->std dependency isn't possible, and inlining parts of
|
||||
/// `std-detect` would be much messier.
|
||||
///
|
||||
/// [`ctor`]: https://github.com/mmastrac/rust-ctor/blob/63382b833ddcbfb8b064f4e86bfa1ed4026ff356/shared/src/macros/mod.rs#L522-L534
|
||||
/// [`prio-ctor-dtor`]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
|
||||
#[cfg(all(
|
||||
target_arch = "aarch64",
|
||||
target_feature = "outline-atomics",
|
||||
not(target_feature = "lse"),
|
||||
not(feature = "compiler-builtins-c"),
|
||||
))]
|
||||
#[used]
|
||||
#[cfg_attr(target_vendor = "apple", unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs"))]
|
||||
#[cfg_attr(target_os = "windows", unsafe(link_section = ".CRT$XCT"))]
|
||||
#[cfg_attr(
|
||||
not(any(target_vendor = "apple", target_os = "windows")),
|
||||
unsafe(link_section = ".init_array.90")
|
||||
)]
|
||||
static RUST_LSE_INIT: extern "C" fn() = {
|
||||
extern "C" fn init_lse() {
|
||||
use crate::arch;
|
||||
|
||||
// This is provided by compiler-builtins::aarch64_outline_atomics.
|
||||
unsafe extern "C" {
|
||||
fn __rust_enable_lse();
|
||||
}
|
||||
|
||||
if arch::is_aarch64_feature_detected!("lse") {
|
||||
unsafe {
|
||||
__rust_enable_lse();
|
||||
}
|
||||
}
|
||||
}
|
||||
init_lse
|
||||
};
|
||||
31
crates/std/src/sys/env/common.rs
vendored
Normal file
31
crates/std/src/sys/env/common.rs
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
|
||||
Env { iter: env.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().entries(self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Env {}
|
||||
impl !Sync for Env {}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
1
crates/std/src/sys/env/mod.rs
vendored
1
crates/std/src/sys/env/mod.rs
vendored
@@ -11,6 +11,7 @@
|
||||
target_os = "uefi",
|
||||
target_os = "wasi",
|
||||
target_os = "xous",
|
||||
target_os = "survos",
|
||||
))]
|
||||
mod common;
|
||||
|
||||
|
||||
426
crates/std/src/sys/env_consts.rs
Normal file
426
crates/std/src/sys/env_consts.rs
Normal file
@@ -0,0 +1,426 @@
|
||||
//! Constants associated with each target.
|
||||
|
||||
// Replaces the #[else] gate with #[cfg(not(any(…)))] of all the other gates.
|
||||
// This ensures that they must be mutually exclusive and do not have precedence
|
||||
// like cfg_select!.
|
||||
macro cfg_unordered(
|
||||
$(#[cfg($cfg:meta)] $os:item)*
|
||||
#[else] $fallback:item
|
||||
) {
|
||||
$(#[cfg($cfg)] $os)*
|
||||
#[cfg(not(any($($cfg),*)))] $fallback
|
||||
}
|
||||
|
||||
// Keep entries sorted alphabetically and mutually exclusive.
|
||||
|
||||
cfg_unordered! {
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "aix";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".a";
|
||||
pub const DLL_EXTENSION: &str = "a";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "android";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "cygwin")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "cygwin";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".dll";
|
||||
pub const DLL_EXTENSION: &str = "dll";
|
||||
pub const EXE_SUFFIX: &str = ".exe";
|
||||
pub const EXE_EXTENSION: &str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "dragonfly";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "emscripten";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".js";
|
||||
pub const EXE_EXTENSION: &str = "js";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "espidf")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "espidf";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "freebsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "fuchsia";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "haiku")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "haiku";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "hermit";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "horizon")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "horizon";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hurd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "hurd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "illumos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "ios";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "l4re")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "l4re";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "linux";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "macos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "netbsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nto";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nuttx")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nuttx";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "openbsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "redox";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "rtems")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "rtems";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".sgxs";
|
||||
pub const DLL_EXTENSION: &str = "sgxs";
|
||||
pub const EXE_SUFFIX: &str = ".sgxs";
|
||||
pub const EXE_EXTENSION: &str = "sgxs";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solaris")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "solaris";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solid_asp3")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "itron";
|
||||
pub const OS: &str = "solid";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "tvos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "tvos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "uefi")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "uefi";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = ".efi";
|
||||
pub const EXE_EXTENSION: &str = "efi";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vexos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "vexos";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = ".bin";
|
||||
pub const EXE_EXTENSION: &str = "bin";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "visionos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "visionos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vita")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "vita";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "vxworks";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "wasm", not(any(target_os = "emscripten", target_os = "linux"))))]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".wasm";
|
||||
pub const DLL_EXTENSION: &str = "wasm";
|
||||
pub const EXE_SUFFIX: &str = ".wasm";
|
||||
pub const EXE_EXTENSION: &str = "wasm";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "watchos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "watchos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "windows";
|
||||
pub const OS: &str = "windows";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".dll";
|
||||
pub const DLL_EXTENSION: &str = "dll";
|
||||
pub const EXE_SUFFIX: &str = ".exe";
|
||||
pub const EXE_EXTENSION: &str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "zkvm")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".elf";
|
||||
pub const DLL_EXTENSION: &str = "elf";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
// The fallback when none of the other gates match.
|
||||
#[else]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
}
|
||||
143
crates/std/src/sys/exit.rs
Normal file
143
crates/std/src/sys/exit.rs
Normal file
@@ -0,0 +1,143 @@
|
||||
cfg_select! {
|
||||
target_os = "linux" => {
|
||||
/// Mitigation for <https://github.com/rust-lang/rust/issues/126600>
|
||||
///
|
||||
/// On glibc, `libc::exit` has been observed to not always be thread-safe.
|
||||
/// It is currently unclear whether that is a glibc bug or allowed by the standard.
|
||||
/// To mitigate this problem, we ensure that only one
|
||||
/// Rust thread calls `libc::exit` (or returns from `main`) by calling this function before
|
||||
/// calling `libc::exit` (or returning from `main`).
|
||||
///
|
||||
/// Technically, this is not enough to ensure soundness, since other code directly calling
|
||||
/// `libc::exit` will still race with this.
|
||||
///
|
||||
/// *This function does not itself call `libc::exit`.* This is so it can also be used
|
||||
/// to guard returning from `main`.
|
||||
///
|
||||
/// This function will return only the first time it is called in a process.
|
||||
///
|
||||
/// * If it is called again on the same thread as the first call, it will abort.
|
||||
/// * If it is called again on a different thread, it will wait in a loop
|
||||
/// (waiting for the process to exit).
|
||||
pub fn unique_thread_exit() {
|
||||
use crate::ffi::c_int;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::AtomicPtr;
|
||||
use crate::sync::atomic::Ordering::{Acquire, Relaxed};
|
||||
|
||||
static EXITING_THREAD_ID: AtomicPtr<c_int> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
// We use the address of `errno` as a cheap and safe way to identify
|
||||
// threads. As the C standard mandates that `errno` must have thread
|
||||
// storage duration, we can rely on its address not changing over the
|
||||
// lifetime of the thread. Additionally, accesses to `errno` are
|
||||
// async-signal-safe, so this function is available in all imaginable
|
||||
// circumstances.
|
||||
let this_thread_id = crate::sys::io::errno_location();
|
||||
match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) {
|
||||
Ok(_) => {
|
||||
// This is the first thread to call `unique_thread_exit`,
|
||||
// and this is the first time it is called. Continue exiting.
|
||||
}
|
||||
Err(exiting_thread_id) if exiting_thread_id == this_thread_id => {
|
||||
// This is the first thread to call `unique_thread_exit`,
|
||||
// but this is the second time it is called.
|
||||
// Abort the process.
|
||||
core::panicking::panic_nounwind("std::process::exit called re-entrantly")
|
||||
}
|
||||
Err(_) => {
|
||||
// This is not the first thread to call `unique_thread_exit`.
|
||||
// Pause until the process exits.
|
||||
loop {
|
||||
// Safety: libc::pause is safe to call.
|
||||
unsafe { libc::pause(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
/// Mitigation for <https://github.com/rust-lang/rust/issues/126600>
|
||||
///
|
||||
/// Mitigation is ***NOT*** implemented on this platform, either because this platform
|
||||
/// is not affected, or because mitigation is not yet implemented for this platform.
|
||||
#[cfg_attr(any(test, doctest), expect(dead_code))]
|
||||
pub fn unique_thread_exit() {
|
||||
// Mitigation not required on platforms where `exit` is thread-safe.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(code: i32) -> ! {
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
unsafe { hermit_abi::exit(code) }
|
||||
}
|
||||
target_os = "linux" => {
|
||||
unsafe {
|
||||
unique_thread_exit();
|
||||
libc::exit(code)
|
||||
}
|
||||
}
|
||||
target_os = "motor" => {
|
||||
moto_rt::process::exit(code)
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
crate::sys::pal::abi::exit_with_code(code as _)
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
rtabort!("exit({}) called", code)
|
||||
}
|
||||
target_os = "teeos" => {
|
||||
let _ = code;
|
||||
panic!("TA should not call `exit`")
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
use r_efi::base::Status;
|
||||
|
||||
use crate::os::uefi::env;
|
||||
|
||||
if let (Some(boot_services), Some(handle)) =
|
||||
(env::boot_services(), env::try_image_handle())
|
||||
{
|
||||
let boot_services = boot_services.cast::<r_efi::efi::BootServices>();
|
||||
let _ = unsafe {
|
||||
((*boot_services.as_ptr()).exit)(
|
||||
handle.as_ptr(),
|
||||
Status::from_usize(code as usize),
|
||||
0,
|
||||
crate::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
}
|
||||
crate::intrinsics::abort()
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "wasi",
|
||||
) => {
|
||||
unsafe { libc::exit(code as crate::ffi::c_int) }
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
let _ = code;
|
||||
|
||||
unsafe {
|
||||
vex_sdk::vexSystemExitRequest();
|
||||
|
||||
loop {
|
||||
vex_sdk::vexTasksRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
target_os = "windows" => {
|
||||
unsafe { crate::sys::pal::c::ExitProcess(code as u32) }
|
||||
}
|
||||
target_os = "xous" => {
|
||||
crate::os::xous::ffi::exit(code as u32)
|
||||
}
|
||||
_ => {
|
||||
let _ = code;
|
||||
crate::intrinsics::abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
81
crates/std/src/sys/fs/common.rs
Normal file
81
crates/std/src/sys/fs/common.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
#![allow(dead_code)] // not used on all platforms
|
||||
|
||||
use crate::io::{self, Error, ErrorKind};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::fs::{File, OpenOptions};
|
||||
use crate::sys::helpers::ignore_notfound;
|
||||
use crate::{fmt, fs};
|
||||
|
||||
pub(crate) const NOT_FILE_ERROR: Error = io::const_error!(
|
||||
ErrorKind::InvalidInput,
|
||||
"the source path is neither a regular file nor a symlink to a regular file",
|
||||
);
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
let mut reader = fs::File::open(from)?;
|
||||
let metadata = reader.metadata()?;
|
||||
|
||||
if !metadata.is_file() {
|
||||
return Err(NOT_FILE_ERROR);
|
||||
}
|
||||
|
||||
let mut writer = fs::File::create(to)?;
|
||||
let perm = metadata.permissions();
|
||||
|
||||
let ret = io::copy(&mut reader, &mut writer)?;
|
||||
writer.set_permissions(perm)?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
let filetype = fs::symlink_metadata(path)?.file_type();
|
||||
if filetype.is_symlink() { fs::remove_file(path) } else { remove_dir_all_recursive(path) }
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
|
||||
for child in fs::read_dir(path)? {
|
||||
let result: io::Result<()> = try {
|
||||
let child = child?;
|
||||
if child.file_type()?.is_dir() {
|
||||
remove_dir_all_recursive(&child.path())?;
|
||||
} else {
|
||||
fs::remove_file(&child.path())?;
|
||||
}
|
||||
};
|
||||
// ignore internal NotFound errors to prevent race conditions
|
||||
if let Err(err) = &result
|
||||
&& err.kind() != io::ErrorKind::NotFound
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
ignore_notfound(fs::remove_dir(path))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
match fs::metadata(path) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dir {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
pub fn open(path: &Path, _opts: &OpenOptions) -> io::Result<Self> {
|
||||
path.canonicalize().map(|path| Self { path })
|
||||
}
|
||||
|
||||
pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||
File::open(&self.path.join(path), &opts)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Dir {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Dir").field("path", &self.path).finish()
|
||||
}
|
||||
}
|
||||
173
crates/std/src/sys/fs/mod.rs
Normal file
173
crates/std/src/sys/fs/mod.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::io;
|
||||
use crate::path::{Path, PathBuf};
|
||||
|
||||
pub mod common;
|
||||
|
||||
cfg_select! {
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub use unix::{chown, fchown, lchown, mkfifo};
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
pub use unix::chroot;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) use unix::debug_assert_fd_is_open;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub(super) use unix::CachedFileMetadata;
|
||||
use crate::sys::helpers::run_path_with_cstr as with_native_path;
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
pub use windows::{symlink_inner, junction_point};
|
||||
use crate::sys::path::with_native_path;
|
||||
}
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
use hermit as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
use motor as imp;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
use solid as imp;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
use uefi as imp;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
use vexos as imp;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Replace this with platform-specific path conversion functions.
|
||||
#[cfg(not(any(target_family = "unix", target_os = "windows", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
|
||||
f(path)
|
||||
}
|
||||
|
||||
pub use imp::{
|
||||
Dir, DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
|
||||
ReadDir,
|
||||
};
|
||||
|
||||
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
imp::readdir(path)
|
||||
}
|
||||
|
||||
pub fn remove_file(path: &Path) -> io::Result<()> {
|
||||
with_native_path(path, &imp::unlink)
|
||||
}
|
||||
|
||||
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
|
||||
}
|
||||
|
||||
pub fn remove_dir(path: &Path) -> io::Result<()> {
|
||||
with_native_path(path, &imp::rmdir)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::remove_dir_all(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::remove_dir_all)
|
||||
}
|
||||
|
||||
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
|
||||
with_native_path(path, &imp::readlink)
|
||||
}
|
||||
|
||||
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(windows)]
|
||||
return imp::symlink(original, link);
|
||||
#[cfg(not(windows))]
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::symlink(original, link))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::link(original, link))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
with_native_path(path, &imp::stat)
|
||||
}
|
||||
|
||||
pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
with_native_path(path, &imp::lstat)
|
||||
}
|
||||
|
||||
pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "vxworks")))]
|
||||
pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
use crate::fs::OpenOptions;
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
|
||||
// ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
|
||||
// Their filesystems do not have symbolic links, so no special handling is required.
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
|
||||
{
|
||||
use crate::os::unix::fs::OpenOptionsExt;
|
||||
options.custom_flags(libc::O_NOFOLLOW);
|
||||
}
|
||||
|
||||
options.open(path)?.set_permissions(perm)
|
||||
}
|
||||
|
||||
#[cfg(any(not(unix), target_os = "vxworks"))]
|
||||
pub fn set_permissions_nofollow(_path: &Path, _perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
crate::unimplemented!(
|
||||
"`set_permissions_nofollow` is currently only implemented on Unix platforms"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
||||
with_native_path(path, &imp::canonicalize)
|
||||
}
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::copy(from, to);
|
||||
#[cfg(windows)]
|
||||
with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to)))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::exists(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::exists)
|
||||
}
|
||||
|
||||
pub fn set_times(path: &Path, times: FileTimes) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_times(path, times.clone()))
|
||||
}
|
||||
|
||||
pub fn set_times_nofollow(path: &Path, times: FileTimes) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_times_nofollow(path, times.clone()))
|
||||
}
|
||||
362
crates/std/src/sys/fs/unsupported.rs
Normal file
362
crates/std/src/sys/fs/unsupported.rs
Normal file
@@ -0,0 +1,362 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::fs::TryLockError;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::path::{Path, PathBuf};
|
||||
pub use crate::sys::fs::common::Dir;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::unsupported;
|
||||
|
||||
pub struct File(!);
|
||||
|
||||
pub struct FileAttr(!);
|
||||
|
||||
pub struct ReadDir(!);
|
||||
|
||||
pub struct DirEntry(!);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct FileTimes {}
|
||||
|
||||
pub struct FilePermissions(!);
|
||||
|
||||
pub struct FileType(!);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> FileAttr {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FileTimes {
|
||||
pub fn set_accessed(&mut self, _t: SystemTime) {}
|
||||
pub fn set_modified(&mut self, _t: SystemTime) {}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileType {
|
||||
fn clone(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for FileType {}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
fn eq(&self, _other: &FileType) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FileType {}
|
||||
|
||||
impl Hash for FileType {
|
||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenOptions {
|
||||
pub fn new() -> OpenOptions {
|
||||
OpenOptions {}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, _read: bool) {}
|
||||
pub fn write(&mut self, _write: bool) {}
|
||||
pub fn append(&mut self, _append: bool) {}
|
||||
pub fn truncate(&mut self, _truncate: bool) {}
|
||||
pub fn create(&mut self, _create: bool) {}
|
||||
pub fn create_new(&mut self, _create_new: bool) {}
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> Result<(), TryLockError> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<io::Result<u64>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn tell(&self) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
pub fn new() -> DirBuilder {
|
||||
DirBuilder {}
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn unlink(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
match perm.0 {}
|
||||
}
|
||||
|
||||
pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn exists(_path: &Path) -> io::Result<bool> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
|
||||
unsupported()
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
pub mod cmath;
|
||||
pub mod configure_builtins;
|
||||
pub mod env;
|
||||
pub mod env_consts;
|
||||
pub mod exit;
|
||||
pub mod os_str;
|
||||
pub mod path;
|
||||
pub mod sync;
|
||||
pub mod thread;
|
||||
pub mod time;
|
||||
// pub mod fs;
|
||||
|
||||
/// A trait for viewing representations from std types.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))]
|
||||
|
||||
28
crates/std/src/sys/path/mod.rs
Normal file
28
crates/std/src/sys/path/mod.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
cfg_select! {
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
mod windows_prefix;
|
||||
pub use windows::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod unsupported_backslash;
|
||||
pub use unsupported_backslash::*;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
}
|
||||
target_os = "cygwin" => {
|
||||
mod cygwin;
|
||||
mod windows_prefix;
|
||||
pub use cygwin::*;
|
||||
}
|
||||
_ => {
|
||||
mod unix;
|
||||
pub use unix::*;
|
||||
}
|
||||
}
|
||||
72
crates/std/src/sys/path/unix.rs
Normal file
72
crates/std/src/sys/path/unix.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use crate::ffi::OsStr;
|
||||
use crate::path::{Path, PathBuf, Prefix};
|
||||
use crate::{env, io};
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_verbatim_sep(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub const HAS_PREFIXES: bool = false;
|
||||
pub const MAIN_SEP_STR: &str = "/";
|
||||
pub const MAIN_SEP: char = '/';
|
||||
|
||||
/// Make a POSIX path absolute without changing its semantics.
|
||||
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
|
||||
// This is mostly a wrapper around collecting `Path::components`, with
|
||||
// exceptions made where this conflicts with the POSIX specification.
|
||||
// See 4.13 Pathname Resolution, IEEE Std 1003.1-2017
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
|
||||
|
||||
// Get the components, skipping the redundant leading "." component if it exists.
|
||||
let mut components = path.strip_prefix(".").unwrap_or(path).components();
|
||||
let path_os = path.as_os_str().as_encoded_bytes();
|
||||
|
||||
let mut normalized = if path.is_absolute() {
|
||||
// "If a pathname begins with two successive <slash> characters, the
|
||||
// first component following the leading <slash> characters may be
|
||||
// interpreted in an implementation-defined manner, although more than
|
||||
// two leading <slash> characters shall be treated as a single <slash>
|
||||
// character."
|
||||
if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
|
||||
components.next();
|
||||
PathBuf::from("//")
|
||||
} else {
|
||||
PathBuf::new()
|
||||
}
|
||||
} else {
|
||||
// env::current_dir()?
|
||||
todo!()
|
||||
};
|
||||
normalized.extend(components);
|
||||
|
||||
// "Interfaces using pathname resolution may specify additional constraints
|
||||
// when a pathname that does not name an existing directory contains at
|
||||
// least one non- <slash> character and contains one or more trailing
|
||||
// <slash> characters".
|
||||
// A trailing <slash> is also meaningful if "a symbolic link is
|
||||
// encountered during pathname resolution".
|
||||
if path_os.ends_with(b"/") {
|
||||
normalized.push("");
|
||||
}
|
||||
|
||||
Ok(normalized)
|
||||
}
|
||||
|
||||
pub(crate) fn is_absolute(path: &Path) -> bool {
|
||||
if cfg!(any(unix, target_os = "hermit", target_os = "wasi", target_os = "motor")) {
|
||||
path.has_root()
|
||||
} else {
|
||||
path.has_root() && path.prefix().is_some()
|
||||
}
|
||||
}
|
||||
44
crates/std/src/sys/sync/condvar/mod.rs
Normal file
44
crates/std/src/sys/sync/condvar/mod.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
cfg_select! {
|
||||
any(
|
||||
all(target_os = "windows", not(target_vendor="win7")),
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "motor",
|
||||
target_os = "fuchsia",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
) => {
|
||||
mod futex;
|
||||
pub use futex::Condvar;
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "teeos",
|
||||
) => {
|
||||
mod pthread;
|
||||
pub use pthread::Condvar;
|
||||
}
|
||||
all(target_os = "windows", target_vendor = "win7") => {
|
||||
mod windows7;
|
||||
pub use windows7::Condvar;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::Condvar;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod itron;
|
||||
pub use itron::Condvar;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::Condvar;
|
||||
}
|
||||
_ => {
|
||||
mod no_threads;
|
||||
pub use no_threads::Condvar;
|
||||
}
|
||||
}
|
||||
27
crates/std/src/sys/sync/condvar/no_threads.rs
Normal file
27
crates/std/src/sys/sync/condvar/no_threads.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use crate::sys::sync::Mutex;
|
||||
use crate::thread::sleep;
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct Condvar {}
|
||||
|
||||
impl Condvar {
|
||||
#[inline]
|
||||
pub const fn new() -> Condvar {
|
||||
Condvar {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn notify_one(&self) {}
|
||||
|
||||
#[inline]
|
||||
pub fn notify_all(&self) {}
|
||||
|
||||
pub unsafe fn wait(&self, _mutex: &Mutex) {
|
||||
panic!("condvar wait not supported")
|
||||
}
|
||||
|
||||
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, dur: Duration) -> bool {
|
||||
sleep(dur);
|
||||
false
|
||||
}
|
||||
}
|
||||
5
crates/std/src/sys/sync/mod.rs
Normal file
5
crates/std/src/sys/sync/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod condvar;
|
||||
mod mutex;
|
||||
|
||||
pub use condvar::Condvar;
|
||||
pub use mutex::Mutex;
|
||||
47
crates/std/src/sys/sync/mutex/mod.rs
Normal file
47
crates/std/src/sys/sync/mutex/mod.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
cfg_select! {
|
||||
any(
|
||||
all(target_os = "windows", not(target_vendor = "win7")),
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "motor",
|
||||
target_os = "dragonfly",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
) => {
|
||||
mod futex;
|
||||
pub use futex::Mutex;
|
||||
}
|
||||
target_os = "fuchsia" => {
|
||||
mod fuchsia;
|
||||
pub use fuchsia::Mutex;
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "teeos",
|
||||
) => {
|
||||
mod pthread;
|
||||
pub use pthread::Mutex;
|
||||
}
|
||||
all(target_os = "windows", target_vendor = "win7") => {
|
||||
mod windows7;
|
||||
pub use windows7::{Mutex, raw};
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::Mutex;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod itron;
|
||||
pub use itron::Mutex;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::Mutex;
|
||||
}
|
||||
_ => {
|
||||
mod no_threads;
|
||||
pub use no_threads::Mutex;
|
||||
}
|
||||
}
|
||||
31
crates/std/src/sys/sync/mutex/no_threads.rs
Normal file
31
crates/std/src/sys/sync/mutex/no_threads.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use crate::cell::Cell;
|
||||
|
||||
pub struct Mutex {
|
||||
// This platform has no threads, so we can use a Cell here.
|
||||
locked: Cell<bool>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Mutex {}
|
||||
unsafe impl Sync for Mutex {} // no threads on this platform
|
||||
|
||||
impl Mutex {
|
||||
#[inline]
|
||||
pub const fn new() -> Mutex {
|
||||
Mutex { locked: Cell::new(false) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn lock(&self) {
|
||||
assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn unlock(&self) {
|
||||
self.locked.set(false);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_lock(&self) -> bool {
|
||||
self.locked.replace(true) == false
|
||||
}
|
||||
}
|
||||
154
crates/std/src/sys/thread/mod.rs
Normal file
154
crates/std/src/sys/thread/mod.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
pub use hermit::{Thread, available_parallelism, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{current_os_id, set_name};
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::{Thread, current_os_id, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
|
||||
// SGX should protect in-enclave data from outside attackers, so there
|
||||
// must not be any data leakage to the OS, particularly no 1-1 mapping
|
||||
// between SGX thread names and OS thread names. Hence `set_name` is
|
||||
// intentionally a no-op.
|
||||
//
|
||||
// Note that the internally visible SGX thread name is already provided
|
||||
// by the platform-agnostic Rust thread code. This can be observed in
|
||||
// the [`std::thread::tests::test_named_thread`] test, which succeeds
|
||||
// as-is with the SGX target.
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{available_parallelism, set_name};
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
pub use solid::{Thread, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{available_parallelism, current_os_id, set_name};
|
||||
}
|
||||
target_os = "teeos" => {
|
||||
mod teeos;
|
||||
pub use teeos::{Thread, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{available_parallelism, current_os_id, set_name};
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::{available_parallelism, sleep};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, current_os_id, set_name, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod unix;
|
||||
pub use unix::{Thread, available_parallelism, current_os_id, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[cfg(not(any(
|
||||
target_env = "newlib",
|
||||
target_os = "l4re",
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "hurd",
|
||||
target_os = "aix",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub use unix::set_name;
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "dragonfly",
|
||||
target_os = "hurd",
|
||||
target_os = "vxworks",
|
||||
target_os = "wasi",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub use unix::sleep_until;
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
#[cfg(any(
|
||||
target_env = "newlib",
|
||||
target_os = "l4re",
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "hurd",
|
||||
target_os = "aix",
|
||||
target_os = "wasi",
|
||||
))]
|
||||
pub use unsupported::set_name;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
pub use vexos::{sleep, sleep_until, yield_now};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
all(target_family = "wasm", target_feature = "atomics") => {
|
||||
mod wasm;
|
||||
pub use wasm::sleep;
|
||||
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
pub use windows::{Thread, available_parallelism, current_os_id, set_name, set_name_wide, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::{Thread, available_parallelism, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{current_os_id, set_name};
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "dragonfly",
|
||||
target_os = "hurd",
|
||||
target_os = "vxworks",
|
||||
target_os = "wasi",
|
||||
target_vendor = "apple",
|
||||
target_os = "motor",
|
||||
target_os = "vexos"
|
||||
)))]
|
||||
pub fn sleep_until(deadline: crate::time::Instant) {
|
||||
use crate::time::Instant;
|
||||
|
||||
// The clock source used for `sleep` might not be the same used for `Instant`.
|
||||
// Since this function *must not* return before the deadline, we recheck the
|
||||
// time after every call to `sleep`. See #149935 for an example of this
|
||||
// occurring on older Windows systems.
|
||||
while let Some(delay) = deadline.checked_duration_since(Instant::now()) {
|
||||
// Sleep for the estimated time remaining until the deadline.
|
||||
//
|
||||
// If your system has a better way of estimating the delay time or
|
||||
// provides a way to sleep until an absolute time, specialize this
|
||||
// function for your system.
|
||||
sleep(delay);
|
||||
}
|
||||
}
|
||||
46
crates/std/src/sys/thread/unsupported.rs
Normal file
46
crates/std/src/sys/thread/unsupported.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::num::NonZero;
|
||||
use crate::thread::ThreadInit;
|
||||
use crate::time::Duration;
|
||||
|
||||
// Silence dead code warnings for the otherwise unused ThreadInit::init() call.
|
||||
#[expect(dead_code)]
|
||||
fn dummy_init_call(init: Box<ThreadInit>) {
|
||||
drop(init.init());
|
||||
}
|
||||
|
||||
pub struct Thread(!);
|
||||
|
||||
pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
|
||||
|
||||
impl Thread {
|
||||
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
||||
pub unsafe fn new(_stack: usize, _init: Box<ThreadInit>) -> io::Result<Thread> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
|
||||
pub fn join(self) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||
Err(io::Error::UNKNOWN_THREAD_COUNT)
|
||||
}
|
||||
|
||||
pub fn current_os_id() -> Option<u64> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn yield_now() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
pub fn set_name(_name: &CStr) {
|
||||
// nope
|
||||
}
|
||||
|
||||
pub fn sleep(_dur: Duration) {
|
||||
panic!("can't sleep");
|
||||
}
|
||||
53
crates/std/src/sys/time/mod.rs
Normal file
53
crates/std/src/sys/time/mod.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
use hermit as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
use moto_rt::time as imp;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
use sgx as imp;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
use solid as imp;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
use uefi as imp;
|
||||
}
|
||||
any(
|
||||
target_os = "teeos",
|
||||
target_family = "unix",
|
||||
target_os = "wasi",
|
||||
) => {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
#[expect(unused)]
|
||||
mod unsupported;
|
||||
|
||||
mod imp {
|
||||
pub use super::vexos::Instant;
|
||||
pub use super::unsupported::{SystemTime, UNIX_EPOCH};
|
||||
}
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
use xous as imp;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
}
|
||||
}
|
||||
|
||||
pub use imp::{Instant, SystemTime, UNIX_EPOCH};
|
||||
49
crates/std/src/sys/time/unsupported.rs
Normal file
49
crates/std/src/sys/time/unsupported.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use crate::time::Duration;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct Instant(Duration);
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct SystemTime(Duration);
|
||||
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
|
||||
|
||||
impl Instant {
|
||||
pub fn now() -> Instant {
|
||||
panic!("time not implemented on this platform")
|
||||
}
|
||||
|
||||
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
|
||||
self.0.checked_sub(other.0)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime(Duration::MAX);
|
||||
|
||||
pub const MIN: SystemTime = SystemTime(Duration::ZERO);
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
panic!("time not implemented on this platform")
|
||||
}
|
||||
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
13
crates/std/src/thread.rs
Normal file
13
crates/std/src/thread.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
pub use crate::sys::thread::*;
|
||||
|
||||
pub struct ThreadInit {
|
||||
pub handle: Thread,
|
||||
pub rust_start: Box<dyn FnOnce() + Send>,
|
||||
}
|
||||
impl ThreadInit {
|
||||
/// Initialize the 'current thread' mechanism on this thread, returning the
|
||||
/// Rust entry point.
|
||||
pub fn init(self: Box<Self>) -> Box<dyn FnOnce() + Send> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
859
crates/std/src/time.rs
Normal file
859
crates/std/src/time.rs
Normal file
@@ -0,0 +1,859 @@
|
||||
//! Temporal quantification.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! There are multiple ways to create a new [`Duration`]:
|
||||
//!
|
||||
//! ```
|
||||
//! # use std::time::Duration;
|
||||
//! let five_seconds = Duration::from_secs(5);
|
||||
//! assert_eq!(five_seconds, Duration::from_millis(5_000));
|
||||
//! assert_eq!(five_seconds, Duration::from_micros(5_000_000));
|
||||
//! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000));
|
||||
//!
|
||||
//! let ten_seconds = Duration::from_secs(10);
|
||||
//! let seven_nanos = Duration::from_nanos(7);
|
||||
//! let total = ten_seconds + seven_nanos;
|
||||
//! assert_eq!(total, Duration::new(10, 7));
|
||||
//! ```
|
||||
//!
|
||||
//! Using [`Instant`] to calculate how long a function took to run:
|
||||
//!
|
||||
//! ```ignore (incomplete)
|
||||
//! let now = Instant::now();
|
||||
//!
|
||||
//! // Calling a slow function, it may take a while
|
||||
//! slow_function();
|
||||
//!
|
||||
//! let elapsed_time = now.elapsed();
|
||||
//! println!("Running slow_function() took {} seconds.", elapsed_time.as_secs());
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "time", since = "1.3.0")]
|
||||
|
||||
#[stable(feature = "time", since = "1.3.0")]
|
||||
pub use core::time::Duration;
|
||||
#[stable(feature = "duration_checked_float", since = "1.66.0")]
|
||||
pub use core::time::TryFromFloatSecsError;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::ops::{Add, AddAssign, Sub, SubAssign};
|
||||
use crate::sys::{FromInner, IntoInner, time};
|
||||
|
||||
/// A measurement of a monotonically nondecreasing clock.
|
||||
/// Opaque and useful only with [`Duration`].
|
||||
///
|
||||
/// Instants are always guaranteed, barring [platform bugs], to be no less than any previously
|
||||
/// measured instant when created, and are often useful for tasks such as measuring
|
||||
/// benchmarks or timing how long an operation takes.
|
||||
///
|
||||
/// Note, however, that instants are **not** guaranteed to be **steady**. In other
|
||||
/// words, each tick of the underlying clock might not be the same length (e.g.
|
||||
/// some seconds may be longer than others). An instant may jump forwards or
|
||||
/// experience time dilation (slow down or speed up), but it will never go
|
||||
/// backwards.
|
||||
/// As part of this non-guarantee it is also not specified whether system suspends count as
|
||||
/// elapsed time or not. The behavior varies across platforms and Rust versions.
|
||||
///
|
||||
/// Instants are opaque types that can only be compared to one another. There is
|
||||
/// no method to get "the number of seconds" from an instant. Instead, it only
|
||||
/// allows measuring the duration between two instants (or comparing two
|
||||
/// instants).
|
||||
///
|
||||
/// The size of an `Instant` struct may vary depending on the target operating
|
||||
/// system.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, Instant};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let now = Instant::now();
|
||||
///
|
||||
/// // we sleep for 2 seconds
|
||||
/// sleep(Duration::new(2, 0));
|
||||
/// // it prints '2'
|
||||
/// println!("{}", now.elapsed().as_secs());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [platform bugs]: Instant#monotonicity
|
||||
///
|
||||
/// # OS-specific behaviors
|
||||
///
|
||||
/// An `Instant` is a wrapper around system-specific types and it may behave
|
||||
/// differently depending on the underlying operating system. For example,
|
||||
/// the following snippet is fine on Linux but panics on macOS:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Instant, Duration};
|
||||
///
|
||||
/// let now = Instant::now();
|
||||
/// let days_per_10_millennia = 365_2425;
|
||||
/// let solar_seconds_per_day = 60 * 60 * 24;
|
||||
/// let millennium_in_solar_seconds = 31_556_952_000;
|
||||
/// assert_eq!(millennium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10);
|
||||
///
|
||||
/// let duration = Duration::new(millennium_in_solar_seconds, 0);
|
||||
/// println!("{:?}", now + duration);
|
||||
/// ```
|
||||
///
|
||||
/// For cross-platform code, you can comfortably use durations of up to around one hundred years.
|
||||
///
|
||||
/// # Underlying System calls
|
||||
///
|
||||
/// The following system calls are [currently] being used by `now()` to find out
|
||||
/// the current time:
|
||||
///
|
||||
/// | Platform | System call |
|
||||
/// |-----------|----------------------------------------------------------------------|
|
||||
/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
|
||||
/// | UNIX | [clock_gettime] with `CLOCK_MONOTONIC` |
|
||||
/// | Darwin | [clock_gettime] with `CLOCK_UPTIME_RAW` |
|
||||
/// | VXWorks | [clock_gettime] with `CLOCK_MONOTONIC` |
|
||||
/// | SOLID | `get_tim` |
|
||||
/// | WASI | [__wasi_clock_time_get] with `monotonic` |
|
||||
/// | Windows | [QueryPerformanceCounter] |
|
||||
///
|
||||
/// [currently]: crate::io#platform-specific-behavior
|
||||
/// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
|
||||
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
|
||||
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
|
||||
/// [__wasi_clock_time_get]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get
|
||||
/// [clock_gettime]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getres.html
|
||||
///
|
||||
/// **Disclaimer:** These system calls might change over time.
|
||||
///
|
||||
/// > Note: mathematical operations like [`add`] may panic if the underlying
|
||||
/// > structure cannot represent the new point in time.
|
||||
///
|
||||
/// [`add`]: Instant::add
|
||||
///
|
||||
/// ## Monotonicity
|
||||
///
|
||||
/// On all platforms `Instant` will try to use an OS API that guarantees monotonic behavior
|
||||
/// if available, which is the case for all [tier 1] platforms.
|
||||
/// In practice such guarantees are – under rare circumstances – broken by hardware, virtualization
|
||||
/// or operating system bugs. To work around these bugs and platforms not offering monotonic clocks
|
||||
/// [`duration_since`], [`elapsed`] and [`sub`] saturate to zero. In older Rust versions this
|
||||
/// lead to a panic instead. [`checked_duration_since`] can be used to detect and handle situations
|
||||
/// where monotonicity is violated, or `Instant`s are subtracted in the wrong order.
|
||||
///
|
||||
/// This workaround obscures programming errors where earlier and later instants are accidentally
|
||||
/// swapped. For this reason future Rust versions may reintroduce panics.
|
||||
///
|
||||
/// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html
|
||||
/// [`duration_since`]: Instant::duration_since
|
||||
/// [`elapsed`]: Instant::elapsed
|
||||
/// [`sub`]: Instant::sub
|
||||
/// [`checked_duration_since`]: Instant::checked_duration_since
|
||||
///
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Instant")]
|
||||
pub struct Instant(time::Instant);
|
||||
|
||||
/// A measurement of the system clock, useful for talking to
|
||||
/// external entities like the file system or other processes.
|
||||
///
|
||||
/// Distinct from the [`Instant`] type, this time measurement **is not
|
||||
/// monotonic**. This means that you can save a file to the file system, then
|
||||
/// save another file to the file system, **and the second file has a
|
||||
/// `SystemTime` measurement earlier than the first**. In other words, an
|
||||
/// operation that happens after another operation in real time may have an
|
||||
/// earlier `SystemTime`!
|
||||
///
|
||||
/// Consequently, comparing two `SystemTime` instances to learn about the
|
||||
/// duration between them returns a [`Result`] instead of an infallible [`Duration`]
|
||||
/// to indicate that this sort of time drift may happen and needs to be handled.
|
||||
///
|
||||
/// Although a `SystemTime` cannot be directly inspected, the [`UNIX_EPOCH`]
|
||||
/// constant is provided in this module as an anchor in time to learn
|
||||
/// information about a `SystemTime`. By calculating the duration from this
|
||||
/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
|
||||
/// or perhaps some other string representation.
|
||||
///
|
||||
/// The size of a `SystemTime` struct may vary depending on the target operating
|
||||
/// system.
|
||||
///
|
||||
/// A `SystemTime` does not count leap seconds.
|
||||
/// `SystemTime::now()`'s behavior around a leap second
|
||||
/// is the same as the operating system's wall clock.
|
||||
/// The precise behavior near a leap second
|
||||
/// (e.g. whether the clock appears to run slow or fast, or stop, or jump)
|
||||
/// depends on platform and configuration,
|
||||
/// so should not be relied on.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let now = SystemTime::now();
|
||||
///
|
||||
/// // we sleep for 2 seconds
|
||||
/// sleep(Duration::new(2, 0));
|
||||
/// match now.elapsed() {
|
||||
/// Ok(elapsed) => {
|
||||
/// // it prints '2'
|
||||
/// println!("{}", elapsed.as_secs());
|
||||
/// }
|
||||
/// Err(e) => {
|
||||
/// // the system clock went backwards!
|
||||
/// println!("Great Scott! {e:?}");
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// The precision of `SystemTime` can depend on the underlying OS-specific time format.
|
||||
/// For example, on Windows the time is represented in 100 nanosecond intervals whereas Linux
|
||||
/// can represent nanosecond intervals.
|
||||
///
|
||||
/// The following system calls are [currently] being used by `now()` to find out
|
||||
/// the current time:
|
||||
///
|
||||
/// | Platform | System call |
|
||||
/// |-----------|----------------------------------------------------------------------|
|
||||
/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
|
||||
/// | UNIX | [clock_gettime (Realtime Clock)] |
|
||||
/// | Darwin | [clock_gettime (Realtime Clock)] |
|
||||
/// | VXWorks | [clock_gettime (Realtime Clock)] |
|
||||
/// | SOLID | `SOLID_RTC_ReadTime` |
|
||||
/// | WASI | [__wasi_clock_time_get (Realtime Clock)] |
|
||||
/// | Windows | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime] |
|
||||
///
|
||||
/// [currently]: crate::io#platform-specific-behavior
|
||||
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
|
||||
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
|
||||
/// [clock_gettime (Realtime Clock)]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getres.html
|
||||
/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get
|
||||
/// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
|
||||
/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime
|
||||
///
|
||||
/// **Disclaimer:** These system calls might change over time.
|
||||
///
|
||||
/// > Note: mathematical operations like [`add`] may panic if the underlying
|
||||
/// > structure cannot represent the new point in time.
|
||||
///
|
||||
/// [`add`]: SystemTime::add
|
||||
/// [`UNIX_EPOCH`]: SystemTime::UNIX_EPOCH
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub struct SystemTime(time::SystemTime);
|
||||
|
||||
/// An error returned from the `duration_since` and `elapsed` methods on
|
||||
/// `SystemTime`, used to learn how far in the opposite direction a system time
|
||||
/// lies.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread::sleep;
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// let sys_time = SystemTime::now();
|
||||
/// sleep(Duration::from_secs(1));
|
||||
/// let new_sys_time = SystemTime::now();
|
||||
/// match sys_time.duration_since(new_sys_time) {
|
||||
/// Ok(_) => {}
|
||||
/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub struct SystemTimeError(Duration);
|
||||
|
||||
impl Instant {
|
||||
/// Returns an instant corresponding to "now".
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::time::Instant;
|
||||
///
|
||||
/// let now = Instant::now();
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "instant_now")]
|
||||
pub fn now() -> Instant {
|
||||
Instant(time::Instant::now())
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or zero duration if that instant is later than this one.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Previous Rust versions panicked when `earlier` was later than `self`. Currently this
|
||||
/// method saturates. Future versions may reintroduce the panic in some circumstances.
|
||||
/// See [Monotonicity].
|
||||
///
|
||||
/// [Monotonicity]: Instant#monotonicity
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, Instant};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// let now = Instant::now();
|
||||
/// sleep(Duration::new(1, 0));
|
||||
/// let new_now = Instant::now();
|
||||
/// println!("{:?}", new_now.duration_since(now));
|
||||
/// println!("{:?}", now.duration_since(new_now)); // 0ns
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub fn duration_since(&self, earlier: Instant) -> Duration {
|
||||
self.checked_duration_since(earlier).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or None if that instant is later than this one.
|
||||
///
|
||||
/// Due to [monotonicity bugs], even under correct logical ordering of the passed `Instant`s,
|
||||
/// this method can return `None`.
|
||||
///
|
||||
/// [monotonicity bugs]: Instant#monotonicity
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, Instant};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// let now = Instant::now();
|
||||
/// sleep(Duration::new(1, 0));
|
||||
/// let new_now = Instant::now();
|
||||
/// println!("{:?}", new_now.checked_duration_since(now));
|
||||
/// println!("{:?}", now.checked_duration_since(new_now)); // None
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "checked_duration_since", since = "1.39.0")]
|
||||
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
|
||||
self.0.checked_sub_instant(&earlier.0)
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or zero duration if that instant is later than this one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{Duration, Instant};
|
||||
/// use std::thread::sleep;
|
||||
///
|
||||
/// let now = Instant::now();
|
||||
/// sleep(Duration::new(1, 0));
|
||||
/// let new_now = Instant::now();
|
||||
/// println!("{:?}", new_now.saturating_duration_since(now));
|
||||
/// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "checked_duration_since", since = "1.39.0")]
|
||||
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
|
||||
self.checked_duration_since(earlier).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed since this instant.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Previous Rust versions panicked when the current time was earlier than self. Currently this
|
||||
/// method returns a Duration of zero in that case. Future versions may reintroduce the panic.
|
||||
/// See [Monotonicity].
|
||||
///
|
||||
/// [Monotonicity]: Instant#monotonicity
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread::sleep;
|
||||
/// use std::time::{Duration, Instant};
|
||||
///
|
||||
/// let instant = Instant::now();
|
||||
/// let three_secs = Duration::from_secs(3);
|
||||
/// sleep(three_secs);
|
||||
/// assert!(instant.elapsed() >= three_secs);
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub fn elapsed(&self) -> Duration {
|
||||
Instant::now() - *self
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
|
||||
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
|
||||
self.0.checked_add_duration(&duration).map(Instant)
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
|
||||
self.0.checked_sub_duration(&duration).map(Instant)
|
||||
}
|
||||
|
||||
// Used by platform specific `sleep_until` implementations such as the one used on Linux.
|
||||
#[cfg_attr(
|
||||
not(target_os = "linux"),
|
||||
allow(unused, reason = "not every platform has a specific `sleep_until`")
|
||||
)]
|
||||
pub(crate) fn into_inner(self) -> time::Instant {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl Add<Duration> for Instant {
|
||||
type Output = Instant;
|
||||
|
||||
/// # 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) -> Instant {
|
||||
self.checked_add(other).expect("overflow when adding duration to instant")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
|
||||
impl AddAssign<Duration> for Instant {
|
||||
fn add_assign(&mut self, other: Duration) {
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl Sub<Duration> for Instant {
|
||||
type Output = Instant;
|
||||
|
||||
fn sub(self, other: Duration) -> Instant {
|
||||
self.checked_sub(other).expect("overflow when subtracting duration from instant")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
|
||||
impl SubAssign<Duration> for Instant {
|
||||
fn sub_assign(&mut self, other: Duration) {
|
||||
*self = *self - other;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl Sub<Instant> 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.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Previous Rust versions panicked when `other` was later than `self`. Currently this
|
||||
/// method saturates. Future versions may reintroduce the panic in some circumstances.
|
||||
/// See [Monotonicity].
|
||||
///
|
||||
/// [Monotonicity]: Instant#monotonicity
|
||||
fn sub(self, other: Instant) -> Duration {
|
||||
self.duration_since(other)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl fmt::Debug for Instant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemTime {
|
||||
/// An anchor in time which can be used to create new `SystemTime` instances or
|
||||
/// learn about where in time a `SystemTime` lies.
|
||||
//
|
||||
// NOTE! this documentation is duplicated, here and in std::time::UNIX_EPOCH.
|
||||
// The two copies are not quite identical, because of the difference in naming.
|
||||
///
|
||||
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
|
||||
/// respect to the system clock. Using `duration_since` on an existing
|
||||
/// `SystemTime` instance can tell how far away from this point in time a
|
||||
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
|
||||
/// `SystemTime` instance to represent another fixed point in time.
|
||||
///
|
||||
/// `duration_since(UNIX_EPOCH).unwrap().as_secs()` returns
|
||||
/// the number of non-leap seconds since the start of 1970 UTC.
|
||||
/// This is a POSIX `time_t` (as a `u64`),
|
||||
/// and is the same time representation as used in many Internet protocols.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::SystemTime;
|
||||
///
|
||||
/// match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
|
||||
/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
|
||||
/// Err(_) => panic!("SystemTime before UNIX EPOCH!"),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "assoc_unix_epoch", since = "1.28.0")]
|
||||
pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH;
|
||||
|
||||
/// Represents the maximum value representable by [`SystemTime`] on this platform.
|
||||
///
|
||||
/// This value differs a lot between platforms, but it is always the case
|
||||
/// that any positive addition of a [`Duration`], whose value is greater
|
||||
/// than or equal to the time precision of the operating system, to
|
||||
/// [`SystemTime::MAX`] will fail.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(time_systemtime_limits)]
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// // Adding zero will change nothing.
|
||||
/// assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX));
|
||||
///
|
||||
/// // But adding just one second will already fail ...
|
||||
/// //
|
||||
/// // Keep in mind that this in fact may succeed, if the Duration is
|
||||
/// // smaller than the time precision of the operating system, which
|
||||
/// // happens to be 1ns on most operating systems, with Windows being the
|
||||
/// // notable exception by using 100ns, hence why this example uses 1s.
|
||||
/// assert_eq!(SystemTime::MAX.checked_add(Duration::new(1, 0)), None);
|
||||
///
|
||||
/// // Utilize this for saturating arithmetic to improve error handling.
|
||||
/// // In this case, we will use a certificate with a timestamp in the
|
||||
/// // future as a practical example.
|
||||
/// let configured_offset = Duration::from_secs(60 * 60 * 24);
|
||||
/// let valid_after =
|
||||
/// SystemTime::now()
|
||||
/// .checked_add(configured_offset)
|
||||
/// .unwrap_or(SystemTime::MAX);
|
||||
/// ```
|
||||
#[unstable(feature = "time_systemtime_limits", issue = "149067")]
|
||||
pub const MAX: SystemTime = SystemTime(time::SystemTime::MAX);
|
||||
|
||||
/// Represents the minimum value representable by [`SystemTime`] on this platform.
|
||||
///
|
||||
/// This value differs a lot between platforms, but it is always the case
|
||||
/// that any positive subtraction of a [`Duration`] from, whose value is
|
||||
/// greater than or equal to the time precision of the operating system, to
|
||||
/// [`SystemTime::MIN`] will fail.
|
||||
///
|
||||
/// Depending on the platform, this may be either less than or equal to
|
||||
/// [`SystemTime::UNIX_EPOCH`], depending on whether the operating system
|
||||
/// supports the representation of timestamps before the Unix epoch or not.
|
||||
/// However, it is always guaranteed that a [`SystemTime::UNIX_EPOCH`] fits
|
||||
/// between a [`SystemTime::MIN`] and [`SystemTime::MAX`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(time_systemtime_limits)]
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// // Subtracting zero will change nothing.
|
||||
/// assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN));
|
||||
///
|
||||
/// // But subtracting just one second will already fail.
|
||||
/// //
|
||||
/// // Keep in mind that this in fact may succeed, if the Duration is
|
||||
/// // smaller than the time precision of the operating system, which
|
||||
/// // happens to be 1ns on most operating systems, with Windows being the
|
||||
/// // notable exception by using 100ns, hence why this example uses 1s.
|
||||
/// assert_eq!(SystemTime::MIN.checked_sub(Duration::new(1, 0)), None);
|
||||
///
|
||||
/// // Utilize this for saturating arithmetic to improve error handling.
|
||||
/// // In this case, we will use a cache expiry as a practical example.
|
||||
/// let configured_expiry = Duration::from_secs(60 * 3);
|
||||
/// let expiry_threshold =
|
||||
/// SystemTime::now()
|
||||
/// .checked_sub(configured_expiry)
|
||||
/// .unwrap_or(SystemTime::MIN);
|
||||
/// ```
|
||||
#[unstable(feature = "time_systemtime_limits", issue = "149067")]
|
||||
pub const MIN: SystemTime = SystemTime(time::SystemTime::MIN);
|
||||
|
||||
/// Returns the system time corresponding to "now".
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::time::SystemTime;
|
||||
///
|
||||
/// let sys_time = SystemTime::now();
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub fn now() -> SystemTime {
|
||||
SystemTime(time::SystemTime::now())
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from an earlier point in time.
|
||||
///
|
||||
/// This function may fail because measurements taken earlier are not
|
||||
/// guaranteed to always be before later measurements (due to anomalies such
|
||||
/// as the system clock being adjusted either forwards or backwards).
|
||||
/// [`Instant`] can be used to measure elapsed time without this risk of failure.
|
||||
///
|
||||
/// If successful, <code>[Ok]\([Duration])</code> is returned where the duration represents
|
||||
/// the amount of time elapsed from the specified measurement to this one.
|
||||
///
|
||||
/// Returns an [`Err`] if `earlier` is later than `self`, and the error
|
||||
/// contains how far from `self` the time is.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::SystemTime;
|
||||
///
|
||||
/// let sys_time = SystemTime::now();
|
||||
/// let new_sys_time = SystemTime::now();
|
||||
/// let difference = new_sys_time.duration_since(sys_time)
|
||||
/// .expect("Clock may have gone backwards");
|
||||
/// println!("{difference:?}");
|
||||
/// ```
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> {
|
||||
self.0.sub_time(&earlier.0).map_err(SystemTimeError)
|
||||
}
|
||||
|
||||
/// Returns the difference from this system time to the
|
||||
/// current clock time.
|
||||
///
|
||||
/// This function may fail as the underlying system clock is susceptible to
|
||||
/// drift and updates (e.g., the system clock could go backwards), so this
|
||||
/// function might not always succeed. If successful, <code>[Ok]\([Duration])</code> is
|
||||
/// returned where the duration represents the amount of time elapsed from
|
||||
/// this time measurement to the current time.
|
||||
///
|
||||
/// To measure elapsed time reliably, use [`Instant`] instead.
|
||||
///
|
||||
/// Returns an [`Err`] if `self` is later than the current system time, and
|
||||
/// the error contains how far from the current system time `self` is.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread::sleep;
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// let sys_time = SystemTime::now();
|
||||
/// let one_sec = Duration::from_secs(1);
|
||||
/// sleep(one_sec);
|
||||
/// assert!(sys_time.elapsed().unwrap() >= one_sec);
|
||||
/// ```
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
|
||||
SystemTime::now().duration_since(*self)
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
|
||||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
///
|
||||
/// In the case that the `duration` is smaller than the time precision of the operating
|
||||
/// system, `Some(self)` will be returned.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_add_duration(&duration).map(SystemTime)
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
///
|
||||
/// In the case that the `duration` is smaller than the time precision of the operating
|
||||
/// system, `Some(self)` will be returned.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_sub_duration(&duration).map(SystemTime)
|
||||
}
|
||||
|
||||
/// Saturating [`SystemTime`] addition, computing `self + duration`,
|
||||
/// returning [`SystemTime::MAX`] if overflow occurred.
|
||||
///
|
||||
/// In the case that the `duration` is smaller than the time precision of
|
||||
/// the operating system, `self` will be returned.
|
||||
#[unstable(feature = "time_saturating_systemtime", issue = "151199")]
|
||||
pub fn saturating_add(&self, duration: Duration) -> SystemTime {
|
||||
self.checked_add(duration).unwrap_or(SystemTime::MAX)
|
||||
}
|
||||
|
||||
/// Saturating [`SystemTime`] subtraction, computing `self - duration`,
|
||||
/// returning [`SystemTime::MIN`] if overflow occurred.
|
||||
///
|
||||
/// In the case that the `duration` is smaller than the time precision of
|
||||
/// the operating system, `self` will be returned.
|
||||
#[unstable(feature = "time_saturating_systemtime", issue = "151199")]
|
||||
pub fn saturating_sub(&self, duration: Duration) -> SystemTime {
|
||||
self.checked_sub(duration).unwrap_or(SystemTime::MIN)
|
||||
}
|
||||
|
||||
/// Saturating computation of time elapsed from an earlier point in time,
|
||||
/// returning [`Duration::ZERO`] in the case that `earlier` is later or
|
||||
/// equal to `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(time_saturating_systemtime)]
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// let now = SystemTime::now();
|
||||
/// let prev = now.saturating_sub(Duration::new(1, 0));
|
||||
///
|
||||
/// // now - prev should return non-zero.
|
||||
/// assert_eq!(now.saturating_duration_since(prev), Duration::new(1, 0));
|
||||
/// assert!(now.duration_since(prev).is_ok());
|
||||
///
|
||||
/// // prev - now should return zero (and fail with the non-saturating).
|
||||
/// assert_eq!(prev.saturating_duration_since(now), Duration::ZERO);
|
||||
/// assert!(prev.duration_since(now).is_err());
|
||||
///
|
||||
/// // now - now should return zero (and work with the non-saturating).
|
||||
/// assert_eq!(now.saturating_duration_since(now), Duration::ZERO);
|
||||
/// assert!(now.duration_since(now).is_ok());
|
||||
/// ```
|
||||
#[unstable(feature = "time_saturating_systemtime", issue = "151199")]
|
||||
pub fn saturating_duration_since(&self, earlier: SystemTime) -> Duration {
|
||||
self.duration_since(earlier).unwrap_or(Duration::ZERO)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl Add<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
/// # 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) -> SystemTime {
|
||||
self.checked_add(dur).expect("overflow when adding duration to instant")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
|
||||
impl AddAssign<Duration> for SystemTime {
|
||||
fn add_assign(&mut self, other: Duration) {
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl Sub<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
fn sub(self, dur: Duration) -> SystemTime {
|
||||
self.checked_sub(dur).expect("overflow when subtracting duration from instant")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
|
||||
impl SubAssign<Duration> for SystemTime {
|
||||
fn sub_assign(&mut self, other: Duration) {
|
||||
*self = *self - other;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl fmt::Debug for SystemTime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// An anchor in time which can be used to create new `SystemTime` instances or
|
||||
/// learn about where in time a `SystemTime` lies.
|
||||
//
|
||||
// NOTE! this documentation is duplicated, here and in SystemTime::UNIX_EPOCH.
|
||||
// The two copies are not quite identical, because of the difference in naming.
|
||||
///
|
||||
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
|
||||
/// respect to the system clock. Using `duration_since` on an existing
|
||||
/// [`SystemTime`] instance can tell how far away from this point in time a
|
||||
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
|
||||
/// [`SystemTime`] instance to represent another fixed point in time.
|
||||
///
|
||||
/// `duration_since(UNIX_EPOCH).unwrap().as_secs()` returns
|
||||
/// the number of non-leap seconds since the start of 1970 UTC.
|
||||
/// This is a POSIX `time_t` (as a `u64`),
|
||||
/// and is the same time representation as used in many Internet protocols.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::time::{SystemTime, UNIX_EPOCH};
|
||||
///
|
||||
/// match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
|
||||
/// Err(_) => panic!("SystemTime before UNIX EPOCH!"),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);
|
||||
|
||||
impl SystemTimeError {
|
||||
/// Returns the positive duration which represents how far forward the
|
||||
/// second system time was from the first.
|
||||
///
|
||||
/// A `SystemTimeError` is returned from the [`SystemTime::duration_since`]
|
||||
/// and [`SystemTime::elapsed`] methods whenever the second system time
|
||||
/// represents a point later in time than the `self` of the method call.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::thread::sleep;
|
||||
/// use std::time::{Duration, SystemTime};
|
||||
///
|
||||
/// let sys_time = SystemTime::now();
|
||||
/// sleep(Duration::from_secs(1));
|
||||
/// let new_sys_time = SystemTime::now();
|
||||
/// match sys_time.duration_since(new_sys_time) {
|
||||
/// Ok(_) => {}
|
||||
/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
pub fn duration(&self) -> Duration {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl Error for SystemTimeError {}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
impl fmt::Display for SystemTimeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "second time provided was later than self")
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<time::SystemTime> for SystemTime {
|
||||
fn from_inner(time: time::SystemTime) -> SystemTime {
|
||||
SystemTime(time)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<time::SystemTime> for SystemTime {
|
||||
fn into_inner(self) -> time::SystemTime {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
25
justfile
25
justfile
@@ -20,17 +20,40 @@ cp_std path:
|
||||
@sed -i -f patches.sed {{ "crates/std/src" / path }}
|
||||
|
||||
update_std:
|
||||
@# Not copied : sys/mod.rs, io.rs
|
||||
@# Not copied : sys/mod.rs, io.rs, error.rs, thread.rs
|
||||
# @just cp_std "process.rs"
|
||||
# @just cp_std "fs.rs"
|
||||
@just cp_std "time.rs"
|
||||
@just cp_std "num/mod.rs"
|
||||
@just cp_std "ffi/c_str.rs"
|
||||
@just cp_std "ffi/mod.rs"
|
||||
@just cp_std "ffi/os_str.rs"
|
||||
@just cp_std "ffi/os_str/tests.rs"
|
||||
@just cp_std "sys/exit.rs"
|
||||
@just cp_std "sys/env_consts.rs"
|
||||
@just cp_std "sys/configure_builtins.rs"
|
||||
@just cp_std "sys/cmath.rs"
|
||||
@just cp_std "sys/sync/condvar/mod.rs"
|
||||
@just cp_std "sys/sync/condvar/no_threads.rs"
|
||||
@just cp_std "sys/sync/mutex/mod.rs"
|
||||
@just cp_std "sys/sync/mutex/no_threads.rs"
|
||||
@just cp_std "sys/thread/mod.rs"
|
||||
@just cp_std "sys/thread/unsupported.rs"
|
||||
@just cp_std "sys/time/mod.rs"
|
||||
@just cp_std "sys/time/unsupported.rs"
|
||||
@just cp_std "sys/env/mod.rs"
|
||||
@just cp_std "sys/env/common.rs"
|
||||
@just cp_std "sys/env/unsupported.rs"
|
||||
@just cp_std "sys/os_str/mod.rs"
|
||||
@just cp_std "sys/os_str/bytes.rs"
|
||||
@just cp_std "sys/os_str/bytes/tests.rs"
|
||||
@just cp_std "sys/path/mod.rs"
|
||||
@just cp_std "sys/fs/mod.rs"
|
||||
@just cp_std "sys/fs/common.rs"
|
||||
@just cp_std "sys/fs/unsupported.rs"
|
||||
@# Copied but edited for the moment
|
||||
# @just cp_std "path.rs"
|
||||
# @just cp_std "sys/path/unix.rs"
|
||||
# @just cp_std "hash/mod.rs"
|
||||
|
||||
build_user_prog prog:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
s|crate::bstr::ByteStr|alloc::bstr::ByteStr|g
|
||||
s|crate::collections::TryReserveError|alloc::collections::TryReserveError|g
|
||||
s|crate::sync::Arc|alloc::sync::Arc|g
|
||||
/target_os = "xous",/a \ target_os = "survos",
|
||||
|
||||
# Ajouter d'autres modifications facilement ici :
|
||||
# s|ancien_texte|nouveau_texte|g
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": 64,
|
||||
"arch": "riscv64",
|
||||
"os": "none",
|
||||
"os": "survos",
|
||||
"vendor": "unknown",
|
||||
"env": "",
|
||||
"features": "+i,+m,+a,+zicsr",
|
||||
|
||||
Reference in New Issue
Block a user