Merge from rustc
This commit is contained in:
commit
6c2fa0bce7
221 changed files with 3217 additions and 2142 deletions
|
|
@ -1138,6 +1138,10 @@ pub(crate) mod builtin {
|
|||
issue = "29599",
|
||||
reason = "`concat_idents` is not stable enough for use and is subject to change"
|
||||
)]
|
||||
#[deprecated(
|
||||
since = "1.88.0",
|
||||
note = "use `${concat(...)}` with the `macro_metavar_expr_concat` feature instead"
|
||||
)]
|
||||
#[rustc_builtin_macro]
|
||||
#[macro_export]
|
||||
macro_rules! concat_idents {
|
||||
|
|
|
|||
|
|
@ -162,8 +162,14 @@
|
|||
//! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`]
|
||||
//! is [`Some`] or [`None`], respectively.
|
||||
//!
|
||||
//! The [`is_some_and`] and [`is_none_or`] methods apply the provided function
|
||||
//! to the contents of the [`Option`] to produce a boolean value.
|
||||
//! If this is [`None`] then a default result is returned instead without executing the function.
|
||||
//!
|
||||
//! [`is_none`]: Option::is_none
|
||||
//! [`is_some`]: Option::is_some
|
||||
//! [`is_some_and`]: Option::is_some_and
|
||||
//! [`is_none_or`]: Option::is_none_or
|
||||
//!
|
||||
//! ## Adapters for working with references
|
||||
//!
|
||||
|
|
@ -177,6 +183,10 @@
|
|||
//! <code>[Option]<[Pin]<[&]T>></code>
|
||||
//! * [`as_pin_mut`] converts from <code>[Pin]<[&mut] [Option]\<T>></code> to
|
||||
//! <code>[Option]<[Pin]<[&mut] T>></code>
|
||||
//! * [`as_slice`] returns a one-element slice of the contained value, if any.
|
||||
//! If this is [`None`], an empty slice is returned.
|
||||
//! * [`as_mut_slice`] returns a mutable one-element slice of the contained value, if any.
|
||||
//! If this is [`None`], an empty slice is returned.
|
||||
//!
|
||||
//! [&]: reference "shared reference"
|
||||
//! [&mut]: reference "mutable reference"
|
||||
|
|
@ -187,6 +197,8 @@
|
|||
//! [`as_pin_mut`]: Option::as_pin_mut
|
||||
//! [`as_pin_ref`]: Option::as_pin_ref
|
||||
//! [`as_ref`]: Option::as_ref
|
||||
//! [`as_slice`]: Option::as_slice
|
||||
//! [`as_mut_slice`]: Option::as_mut_slice
|
||||
//!
|
||||
//! ## Extracting the contained value
|
||||
//!
|
||||
|
|
@ -200,12 +212,15 @@
|
|||
//! (which must implement the [`Default`] trait)
|
||||
//! * [`unwrap_or_else`] returns the result of evaluating the provided
|
||||
//! function
|
||||
//! * [`unwrap_unchecked`] produces *[undefined behavior]*
|
||||
//!
|
||||
//! [`expect`]: Option::expect
|
||||
//! [`unwrap`]: Option::unwrap
|
||||
//! [`unwrap_or`]: Option::unwrap_or
|
||||
//! [`unwrap_or_default`]: Option::unwrap_or_default
|
||||
//! [`unwrap_or_else`]: Option::unwrap_or_else
|
||||
//! [`unwrap_unchecked`]: Option::unwrap_unchecked
|
||||
//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
|
||||
//!
|
||||
//! ## Transforming contained values
|
||||
//!
|
||||
|
|
@ -230,8 +245,9 @@
|
|||
//! * [`filter`] calls the provided predicate function on the contained
|
||||
//! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`]
|
||||
//! if the function returns `true`; otherwise, returns [`None`]
|
||||
//! * [`flatten`] removes one level of nesting from an
|
||||
//! [`Option<Option<T>>`]
|
||||
//! * [`flatten`] removes one level of nesting from an [`Option<Option<T>>`]
|
||||
//! * [`inspect`] method takes ownership of the [`Option`] and applies
|
||||
//! the provided function to the contained value by reference if [`Some`]
|
||||
//! * [`map`] transforms [`Option<T>`] to [`Option<U>`] by applying the
|
||||
//! provided function to the contained value of [`Some`] and leaving
|
||||
//! [`None`] values unchanged
|
||||
|
|
@ -239,6 +255,7 @@
|
|||
//! [`Some(t)`]: Some
|
||||
//! [`filter`]: Option::filter
|
||||
//! [`flatten`]: Option::flatten
|
||||
//! [`inspect`]: Option::inspect
|
||||
//! [`map`]: Option::map
|
||||
//!
|
||||
//! These methods transform [`Option<T>`] to a value of a possibly
|
||||
|
|
@ -621,6 +638,10 @@ impl<T> Option<T> {
|
|||
///
|
||||
/// let x: Option<u32> = None;
|
||||
/// assert_eq!(x.is_some_and(|x| x > 1), false);
|
||||
///
|
||||
/// let x: Option<String> = Some("ownership".to_string());
|
||||
/// assert_eq!(x.as_ref().is_some_and(|x| x.len() > 1), true);
|
||||
/// println!("still alive {:?}", x);
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
|
|
@ -665,6 +686,10 @@ impl<T> Option<T> {
|
|||
///
|
||||
/// let x: Option<u32> = None;
|
||||
/// assert_eq!(x.is_none_or(|x| x > 1), true);
|
||||
///
|
||||
/// let x: Option<String> = Some("ownership".to_string());
|
||||
/// assert_eq!(x.as_ref().is_none_or(|x| x.len() > 1), true);
|
||||
/// println!("still alive {:?}", x);
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ pub use crate::hash::macros::Hash;
|
|||
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow(deprecated)]
|
||||
#[cfg_attr(bootstrap, allow(deprecated_in_future))]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::{
|
||||
assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
|
||||
|
|
|
|||
|
|
@ -259,8 +259,14 @@
|
|||
//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`]
|
||||
//! is [`Ok`] or [`Err`], respectively.
|
||||
//!
|
||||
//! The [`is_ok_and`] and [`is_err_and`] methods apply the provided function
|
||||
//! to the contents of the [`Result`] to produce a boolean value. If the [`Result`] does not have the expected variant
|
||||
//! then [`false`] is returned instead without executing the function.
|
||||
//!
|
||||
//! [`is_err`]: Result::is_err
|
||||
//! [`is_ok`]: Result::is_ok
|
||||
//! [`is_ok_and`]: Result::is_ok_and
|
||||
//! [`is_err_and`]: Result::is_err_and
|
||||
//!
|
||||
//! ## Adapters for working with references
|
||||
//!
|
||||
|
|
@ -287,6 +293,7 @@
|
|||
//! (which must implement the [`Default`] trait)
|
||||
//! * [`unwrap_or_else`] returns the result of evaluating the provided
|
||||
//! function
|
||||
//! * [`unwrap_unchecked`] produces *[undefined behavior]*
|
||||
//!
|
||||
//! The panicking methods [`expect`] and [`unwrap`] require `E` to
|
||||
//! implement the [`Debug`] trait.
|
||||
|
|
@ -297,6 +304,8 @@
|
|||
//! [`unwrap_or`]: Result::unwrap_or
|
||||
//! [`unwrap_or_default`]: Result::unwrap_or_default
|
||||
//! [`unwrap_or_else`]: Result::unwrap_or_else
|
||||
//! [`unwrap_unchecked`]: Result::unwrap_unchecked
|
||||
//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
|
||||
//!
|
||||
//! These methods extract the contained value in a [`Result<T, E>`] when it
|
||||
//! is the [`Err`] variant. They require `T` to implement the [`Debug`]
|
||||
|
|
@ -304,10 +313,13 @@
|
|||
//!
|
||||
//! * [`expect_err`] panics with a provided custom message
|
||||
//! * [`unwrap_err`] panics with a generic message
|
||||
//! * [`unwrap_err_unchecked`] produces *[undefined behavior]*
|
||||
//!
|
||||
//! [`Debug`]: crate::fmt::Debug
|
||||
//! [`expect_err`]: Result::expect_err
|
||||
//! [`unwrap_err`]: Result::unwrap_err
|
||||
//! [`unwrap_err_unchecked`]: Result::unwrap_err_unchecked
|
||||
//! [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
|
||||
//!
|
||||
//! ## Transforming contained values
|
||||
//!
|
||||
|
|
@ -330,21 +342,29 @@
|
|||
//! [`Some(v)`]: Option::Some
|
||||
//! [`transpose`]: Result::transpose
|
||||
//!
|
||||
//! This method transforms the contained value of the [`Ok`] variant:
|
||||
//! These methods transform the contained value of the [`Ok`] variant:
|
||||
//!
|
||||
//! * [`map`] transforms [`Result<T, E>`] into [`Result<U, E>`] by applying
|
||||
//! the provided function to the contained value of [`Ok`] and leaving
|
||||
//! [`Err`] values unchanged
|
||||
//! * [`inspect`] takes ownership of the [`Result`], applies the
|
||||
//! provided function to the contained value by reference,
|
||||
//! and then returns the [`Result`]
|
||||
//!
|
||||
//! [`map`]: Result::map
|
||||
//! [`inspect`]: Result::inspect
|
||||
//!
|
||||
//! This method transforms the contained value of the [`Err`] variant:
|
||||
//! These methods transform the contained value of the [`Err`] variant:
|
||||
//!
|
||||
//! * [`map_err`] transforms [`Result<T, E>`] into [`Result<T, F>`] by
|
||||
//! applying the provided function to the contained value of [`Err`] and
|
||||
//! leaving [`Ok`] values unchanged
|
||||
//! * [`inspect_err`] takes ownership of the [`Result`], applies the
|
||||
//! provided function to the contained value of [`Err`] by reference,
|
||||
//! and then returns the [`Result`]
|
||||
//!
|
||||
//! [`map_err`]: Result::map_err
|
||||
//! [`inspect_err`]: Result::inspect_err
|
||||
//!
|
||||
//! These methods transform a [`Result<T, E>`] into a value of a possibly
|
||||
//! different type `U`:
|
||||
|
|
@ -578,6 +598,10 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// let x: Result<u32, &str> = Err("hey");
|
||||
/// assert_eq!(x.is_ok_and(|x| x > 1), false);
|
||||
///
|
||||
/// let x: Result<String, &str> = Ok("ownership".to_string());
|
||||
/// assert_eq!(x.as_ref().is_ok_and(|x| x.len() > 1), true);
|
||||
/// println!("still alive {:?}", x);
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
|
|
@ -623,6 +647,10 @@ impl<T, E> Result<T, E> {
|
|||
///
|
||||
/// let x: Result<u32, Error> = Ok(123);
|
||||
/// assert_eq!(x.is_err_and(|x| x.kind() == ErrorKind::NotFound), false);
|
||||
///
|
||||
/// let x: Result<u32, String> = Err("ownership".to_string());
|
||||
/// assert_eq!(x.as_ref().is_err_and(|x| x.len() > 1), true);
|
||||
/// println!("still alive {:?}", x);
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -163,4 +163,10 @@ check-cfg = [
|
|||
# and to the `backtrace` crate which messes-up with Cargo list
|
||||
# of declared features, we therefor expect any feature cfg
|
||||
'cfg(feature, values(any()))',
|
||||
# Internal features aren't marked known config by default, we use these to
|
||||
# gate tests.
|
||||
'cfg(target_has_reliable_f16)',
|
||||
'cfg(target_has_reliable_f16_math)',
|
||||
'cfg(target_has_reliable_f128)',
|
||||
'cfg(target_has_reliable_f128_math)',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,12 +7,6 @@ fn main() {
|
|||
let target_vendor =
|
||||
env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set");
|
||||
let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set");
|
||||
let target_abi = env::var("CARGO_CFG_TARGET_ABI").expect("CARGO_CFG_TARGET_ABI was not set");
|
||||
let target_pointer_width: u32 = env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
|
||||
.expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
|
||||
.parse()
|
||||
.unwrap();
|
||||
let is_miri = env::var_os("CARGO_CFG_MIRI").is_some();
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(netbsd10)");
|
||||
if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
|
||||
|
|
@ -80,108 +74,4 @@ fn main() {
|
|||
println!("cargo:rustc-cfg=backtrace_in_libstd");
|
||||
|
||||
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
|
||||
|
||||
// Emit these on platforms that have no known ABI bugs, LLVM selection bugs, lowering bugs,
|
||||
// missing symbols, or other problems, to determine when tests get run.
|
||||
// If more broken platforms are found, please update the tracking issue at
|
||||
// <https://github.com/rust-lang/rust/issues/116909>
|
||||
//
|
||||
// Some of these match arms are redundant; the goal is to separate reasons that the type is
|
||||
// unreliable, even when multiple reasons might fail the same platform.
|
||||
println!("cargo:rustc-check-cfg=cfg(reliable_f16)");
|
||||
println!("cargo:rustc-check-cfg=cfg(reliable_f128)");
|
||||
|
||||
// This is a step beyond only having the types and basic functions available. Math functions
|
||||
// aren't consistently available or correct.
|
||||
println!("cargo:rustc-check-cfg=cfg(reliable_f16_math)");
|
||||
println!("cargo:rustc-check-cfg=cfg(reliable_f128_math)");
|
||||
|
||||
let has_reliable_f16 = match (target_arch.as_str(), target_os.as_str()) {
|
||||
// We can always enable these in Miri as that is not affected by codegen bugs.
|
||||
_ if is_miri => true,
|
||||
// Selection failure <https://github.com/llvm/llvm-project/issues/50374>
|
||||
("s390x", _) => false,
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
("arm64ec", _) => false,
|
||||
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
|
||||
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
|
||||
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
|
||||
("csky", _) => false,
|
||||
("hexagon", _) => false,
|
||||
("powerpc" | "powerpc64", _) => false,
|
||||
("sparc" | "sparc64", _) => false,
|
||||
("wasm32" | "wasm64", _) => false,
|
||||
// `f16` support only requires that symbols converting to and from `f32` are available. We
|
||||
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
|
||||
// do not have other ABI issues or LLVM crashes.
|
||||
_ => true,
|
||||
};
|
||||
|
||||
let has_reliable_f128 = match (target_arch.as_str(), target_os.as_str()) {
|
||||
// We can always enable these in Miri as that is not affected by codegen bugs.
|
||||
_ if is_miri => true,
|
||||
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
|
||||
("arm64ec", _) => false,
|
||||
// Selection bug <https://github.com/llvm/llvm-project/issues/96432>
|
||||
("mips64" | "mips64r6", _) => false,
|
||||
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>
|
||||
("nvptx64", _) => false,
|
||||
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
|
||||
// list at <https://github.com/rust-lang/rust/issues/116909>)
|
||||
("powerpc" | "powerpc64", _) => false,
|
||||
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
|
||||
("sparc", _) => false,
|
||||
// Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
|
||||
// not fail if our compiler-builtins is linked.
|
||||
("x86", _) => false,
|
||||
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
|
||||
("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
|
||||
// There are no known problems on other platforms, so the only requirement is that symbols
|
||||
// are available. `compiler-builtins` provides all symbols required for core `f128`
|
||||
// support, so this should work for everything else.
|
||||
_ => true,
|
||||
};
|
||||
|
||||
// Configure platforms that have reliable basics but may have unreliable math.
|
||||
|
||||
// LLVM is currently adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
|
||||
let has_reliable_f16_math = has_reliable_f16
|
||||
&& match (target_arch.as_str(), target_os.as_str()) {
|
||||
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.
|
||||
_ if is_miri => false,
|
||||
// x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747>
|
||||
("x86" | "x86_64", _) => false,
|
||||
// Assume that working `f16` means working `f16` math for most platforms, since
|
||||
// operations just go through `f32`.
|
||||
_ => true,
|
||||
};
|
||||
|
||||
let has_reliable_f128_math = has_reliable_f128
|
||||
&& match (target_arch.as_str(), target_os.as_str()) {
|
||||
// FIXME: Disabled on Miri as the intrinsics are not implemented yet.
|
||||
_ if is_miri => false,
|
||||
// LLVM lowers `fp128` math to `long double` symbols even on platforms where
|
||||
// `long double` is not IEEE binary128. See
|
||||
// <https://github.com/llvm/llvm-project/issues/44744>.
|
||||
//
|
||||
// This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
|
||||
// (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
|
||||
// (ld is 80-bit extended precision).
|
||||
("x86_64", _) => false,
|
||||
(_, "linux") if target_pointer_width == 64 => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if has_reliable_f16 {
|
||||
println!("cargo:rustc-cfg=reliable_f16");
|
||||
}
|
||||
if has_reliable_f128 {
|
||||
println!("cargo:rustc-cfg=reliable_f128");
|
||||
}
|
||||
if has_reliable_f16_math {
|
||||
println!("cargo:rustc-cfg=reliable_f16_math");
|
||||
}
|
||||
if has_reliable_f128_math {
|
||||
println!("cargo:rustc-cfg=reliable_f128_math");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
use crate::error::Error;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::os as os_imp;
|
||||
use crate::sys::{env as env_imp, os as os_imp};
|
||||
use crate::{fmt, io, sys};
|
||||
|
||||
/// Returns the current working directory as a [`PathBuf`].
|
||||
|
|
@ -96,7 +96,7 @@ pub struct Vars {
|
|||
/// [`env::vars_os()`]: vars_os
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub struct VarsOs {
|
||||
inner: os_imp::Env,
|
||||
inner: env_imp::Env,
|
||||
}
|
||||
|
||||
/// Returns an iterator of (variable, value) pairs of strings, for all the
|
||||
|
|
@ -150,7 +150,7 @@ pub fn vars() -> Vars {
|
|||
#[must_use]
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub fn vars_os() -> VarsOs {
|
||||
VarsOs { inner: os_imp::env() }
|
||||
VarsOs { inner: env_imp::env() }
|
||||
}
|
||||
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
|
|
@ -259,7 +259,7 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
|
|||
}
|
||||
|
||||
fn _var_os(key: &OsStr) -> Option<OsString> {
|
||||
os_imp::getenv(key)
|
||||
env_imp::getenv(key)
|
||||
}
|
||||
|
||||
/// The error type for operations interacting with environment variables.
|
||||
|
|
@ -363,7 +363,7 @@ impl Error for VarError {
|
|||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
|
||||
let (key, value) = (key.as_ref(), value.as_ref());
|
||||
unsafe { os_imp::setenv(key, value) }.unwrap_or_else(|e| {
|
||||
unsafe { env_imp::setenv(key, value) }.unwrap_or_else(|e| {
|
||||
panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
|
||||
})
|
||||
}
|
||||
|
|
@ -434,7 +434,7 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
|
|||
#[stable(feature = "env", since = "1.0.0")]
|
||||
pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
|
||||
let key = key.as_ref();
|
||||
unsafe { os_imp::unsetenv(key) }
|
||||
unsafe { env_imp::unsetenv(key) }
|
||||
.unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.7_f128;
|
||||
/// let g = 3.0_f128;
|
||||
|
|
@ -49,7 +53,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.01_f128;
|
||||
/// let g = 4.0_f128;
|
||||
|
|
@ -76,7 +84,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.3_f128;
|
||||
/// let g = -3.3_f128;
|
||||
|
|
@ -108,7 +120,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.3_f128;
|
||||
/// let g = -3.3_f128;
|
||||
|
|
@ -138,7 +154,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.7_f128;
|
||||
/// let g = 3.0_f128;
|
||||
|
|
@ -166,7 +186,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 3.6_f128;
|
||||
/// let y = -3.6_f128;
|
||||
|
|
@ -203,7 +227,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let m = 10.0_f128;
|
||||
/// let x = 4.0_f128;
|
||||
|
|
@ -247,7 +275,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let a: f128 = 7.0;
|
||||
/// let b = 4.0;
|
||||
|
|
@ -289,7 +321,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let a: f128 = 7.0;
|
||||
/// let b = 4.0;
|
||||
|
|
@ -326,7 +362,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 2.0_f128;
|
||||
/// let abs_difference = (x.powi(2) - (x * x)).abs();
|
||||
|
|
@ -354,7 +394,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 2.0_f128;
|
||||
/// let abs_difference = (x.powf(2.0) - (x * x)).abs();
|
||||
|
|
@ -386,7 +430,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let positive = 4.0_f128;
|
||||
/// let negative = -4.0_f128;
|
||||
|
|
@ -417,7 +465,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let one = 1.0f128;
|
||||
/// // e^1
|
||||
|
|
@ -448,7 +500,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 2.0f128;
|
||||
///
|
||||
|
|
@ -479,7 +535,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let one = 1.0f128;
|
||||
/// // e^1
|
||||
|
|
@ -495,7 +555,11 @@ impl f128 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f128.ln(), f128::NEG_INFINITY);
|
||||
/// assert!((-42_f128).ln().is_nan());
|
||||
|
|
@ -526,7 +590,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let five = 5.0f128;
|
||||
///
|
||||
|
|
@ -540,7 +608,11 @@ impl f128 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f128.log(10.0), f128::NEG_INFINITY);
|
||||
/// assert!((-42_f128).log(10.0).is_nan());
|
||||
|
|
@ -567,7 +639,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let two = 2.0f128;
|
||||
///
|
||||
|
|
@ -581,7 +657,11 @@ impl f128 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f128.log2(), f128::NEG_INFINITY);
|
||||
/// assert!((-42_f128).log2().is_nan());
|
||||
|
|
@ -608,7 +688,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let ten = 10.0f128;
|
||||
///
|
||||
|
|
@ -622,7 +706,11 @@ impl f128 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f128.log10(), f128::NEG_INFINITY);
|
||||
/// assert!((-42_f128).log10().is_nan());
|
||||
|
|
@ -651,7 +739,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 8.0f128;
|
||||
///
|
||||
|
|
@ -687,7 +779,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 2.0f128;
|
||||
/// let y = 3.0f128;
|
||||
|
|
@ -717,7 +813,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = std::f128::consts::FRAC_PI_2;
|
||||
///
|
||||
|
|
@ -745,7 +845,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 2.0 * std::f128::consts::PI;
|
||||
///
|
||||
|
|
@ -776,7 +880,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = std::f128::consts::FRAC_PI_4;
|
||||
/// let abs_difference = (x.tan() - 1.0).abs();
|
||||
|
|
@ -808,7 +916,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = std::f128::consts::FRAC_PI_2;
|
||||
///
|
||||
|
|
@ -843,7 +955,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = std::f128::consts::FRAC_PI_4;
|
||||
///
|
||||
|
|
@ -877,7 +993,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 1.0f128;
|
||||
///
|
||||
|
|
@ -915,7 +1035,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// // Positive angles measured counter-clockwise
|
||||
/// // from positive x axis
|
||||
|
|
@ -957,7 +1081,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = std::f128::consts::FRAC_PI_4;
|
||||
/// let f = x.sin_cos();
|
||||
|
|
@ -992,7 +1120,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1e-8_f128;
|
||||
///
|
||||
|
|
@ -1028,7 +1160,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1e-8_f128;
|
||||
///
|
||||
|
|
@ -1043,7 +1179,11 @@ impl f128 {
|
|||
/// Out-of-range values:
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// assert_eq!((-1.0_f128).ln_1p(), f128::NEG_INFINITY);
|
||||
/// assert!((-2.0_f128).ln_1p().is_nan());
|
||||
|
|
@ -1072,7 +1212,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let e = std::f128::consts::E;
|
||||
/// let x = 1.0f128;
|
||||
|
|
@ -1107,7 +1251,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let e = std::f128::consts::E;
|
||||
/// let x = 1.0f128;
|
||||
|
|
@ -1142,7 +1290,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let e = std::f128::consts::E;
|
||||
/// let x = 1.0f128;
|
||||
|
|
@ -1174,7 +1326,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// let f = x.sinh().asinh();
|
||||
|
|
@ -1206,7 +1362,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 1.0f128;
|
||||
/// let f = x.cosh().acosh();
|
||||
|
|
@ -1240,7 +1400,11 @@ impl f128 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let e = std::f128::consts::E;
|
||||
/// let f = e.tanh().atanh();
|
||||
|
|
@ -1274,7 +1438,11 @@ impl f128 {
|
|||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(float_gamma)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 5.0f128;
|
||||
///
|
||||
|
|
@ -1309,7 +1477,11 @@ impl f128 {
|
|||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(float_gamma)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
///
|
||||
/// let x = 2.0f128;
|
||||
///
|
||||
|
|
@ -1344,7 +1516,11 @@ impl f128 {
|
|||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(float_erf)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
/// /// The error function relates what percent of a normal distribution lies
|
||||
/// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
|
||||
/// fn within_standard_deviations(x: f128) -> f128 {
|
||||
|
|
@ -1383,7 +1559,11 @@ impl f128 {
|
|||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// #![feature(float_erf)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f128_math)] {
|
||||
/// let x: f128 = 0.123;
|
||||
///
|
||||
/// let one = x.erf() + x.erfc();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.7_f16;
|
||||
/// let g = 3.0_f16;
|
||||
|
|
@ -49,7 +53,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.01_f16;
|
||||
/// let g = 4.0_f16;
|
||||
|
|
@ -76,7 +84,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.3_f16;
|
||||
/// let g = -3.3_f16;
|
||||
|
|
@ -108,7 +120,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.3_f16;
|
||||
/// let g = -3.3_f16;
|
||||
|
|
@ -138,7 +154,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.7_f16;
|
||||
/// let g = 3.0_f16;
|
||||
|
|
@ -166,7 +186,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 3.6_f16;
|
||||
/// let y = -3.6_f16;
|
||||
|
|
@ -203,7 +227,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let m = 10.0_f16;
|
||||
/// let x = 4.0_f16;
|
||||
|
|
@ -247,7 +275,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let a: f16 = 7.0;
|
||||
/// let b = 4.0;
|
||||
|
|
@ -289,7 +321,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let a: f16 = 7.0;
|
||||
/// let b = 4.0;
|
||||
|
|
@ -326,7 +362,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 2.0_f16;
|
||||
/// let abs_difference = (x.powi(2) - (x * x)).abs();
|
||||
|
|
@ -354,7 +394,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 2.0_f16;
|
||||
/// let abs_difference = (x.powf(2.0) - (x * x)).abs();
|
||||
|
|
@ -386,7 +430,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let positive = 4.0_f16;
|
||||
/// let negative = -4.0_f16;
|
||||
|
|
@ -417,7 +465,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let one = 1.0f16;
|
||||
/// // e^1
|
||||
|
|
@ -448,7 +500,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 2.0f16;
|
||||
///
|
||||
|
|
@ -479,7 +535,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let one = 1.0f16;
|
||||
/// // e^1
|
||||
|
|
@ -495,7 +555,11 @@ impl f16 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f16.ln(), f16::NEG_INFINITY);
|
||||
/// assert!((-42_f16).ln().is_nan());
|
||||
|
|
@ -526,7 +590,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let five = 5.0f16;
|
||||
///
|
||||
|
|
@ -540,7 +608,11 @@ impl f16 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY);
|
||||
/// assert!((-42_f16).log(10.0).is_nan());
|
||||
|
|
@ -567,7 +639,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let two = 2.0f16;
|
||||
///
|
||||
|
|
@ -581,7 +657,11 @@ impl f16 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f16.log2(), f16::NEG_INFINITY);
|
||||
/// assert!((-42_f16).log2().is_nan());
|
||||
|
|
@ -608,7 +688,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let ten = 10.0f16;
|
||||
///
|
||||
|
|
@ -622,7 +706,11 @@ impl f16 {
|
|||
/// Non-positive values:
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// assert_eq!(0_f16.log10(), f16::NEG_INFINITY);
|
||||
/// assert!((-42_f16).log10().is_nan());
|
||||
|
|
@ -650,7 +738,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 8.0f16;
|
||||
///
|
||||
|
|
@ -685,7 +777,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 2.0f16;
|
||||
/// let y = 3.0f16;
|
||||
|
|
@ -715,7 +811,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = std::f16::consts::FRAC_PI_2;
|
||||
///
|
||||
|
|
@ -743,7 +843,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 2.0 * std::f16::consts::PI;
|
||||
///
|
||||
|
|
@ -774,7 +878,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = std::f16::consts::FRAC_PI_4;
|
||||
/// let abs_difference = (x.tan() - 1.0).abs();
|
||||
|
|
@ -806,7 +914,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = std::f16::consts::FRAC_PI_2;
|
||||
///
|
||||
|
|
@ -841,7 +953,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = std::f16::consts::FRAC_PI_4;
|
||||
///
|
||||
|
|
@ -875,7 +991,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 1.0f16;
|
||||
///
|
||||
|
|
@ -913,7 +1033,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// // Positive angles measured counter-clockwise
|
||||
/// // from positive x axis
|
||||
|
|
@ -955,7 +1079,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = std::f16::consts::FRAC_PI_4;
|
||||
/// let f = x.sin_cos();
|
||||
|
|
@ -990,7 +1118,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 1e-4_f16;
|
||||
///
|
||||
|
|
@ -1026,7 +1158,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 1e-4_f16;
|
||||
///
|
||||
|
|
@ -1041,7 +1177,11 @@ impl f16 {
|
|||
/// Out-of-range values:
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY);
|
||||
/// assert!((-2.0_f16).ln_1p().is_nan());
|
||||
|
|
@ -1070,7 +1210,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let e = std::f16::consts::E;
|
||||
/// let x = 1.0f16;
|
||||
|
|
@ -1105,7 +1249,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let e = std::f16::consts::E;
|
||||
/// let x = 1.0f16;
|
||||
|
|
@ -1140,7 +1288,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let e = std::f16::consts::E;
|
||||
/// let x = 1.0f16;
|
||||
|
|
@ -1172,7 +1324,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 1.0f16;
|
||||
/// let f = x.sinh().asinh();
|
||||
|
|
@ -1204,7 +1360,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 1.0f16;
|
||||
/// let f = x.cosh().acosh();
|
||||
|
|
@ -1238,7 +1398,11 @@ impl f16 {
|
|||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let e = std::f16::consts::E;
|
||||
/// let f = e.tanh().atanh();
|
||||
|
|
@ -1272,7 +1436,11 @@ impl f16 {
|
|||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// #![feature(float_gamma)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 5.0f16;
|
||||
///
|
||||
|
|
@ -1307,7 +1475,11 @@ impl f16 {
|
|||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// #![feature(float_gamma)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
///
|
||||
/// let x = 2.0f16;
|
||||
///
|
||||
|
|
@ -1342,7 +1514,11 @@ impl f16 {
|
|||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// #![feature(float_erf)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
/// /// The error function relates what percent of a normal distribution lies
|
||||
/// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
|
||||
/// fn within_standard_deviations(x: f16) -> f16 {
|
||||
|
|
@ -1381,7 +1557,11 @@ impl f16 {
|
|||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// #![feature(float_erf)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
/// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
/// # #![cfg_attr(not(bootstrap), expect(internal_features))]
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # #[cfg(not(bootstrap))]
|
||||
/// # #[cfg(target_has_reliable_f16_math)] {
|
||||
/// let x: f16 = 0.123;
|
||||
///
|
||||
/// let one = x.erf() + x.erfc();
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ mod break_keyword {}
|
|||
|
||||
#[doc(keyword = "const")]
|
||||
//
|
||||
/// Compile-time constants, compile-time evaluable functions, and raw pointers.
|
||||
/// Compile-time constants, compile-time blocks, compile-time evaluable functions, and raw pointers.
|
||||
///
|
||||
/// ## Compile-time constants
|
||||
///
|
||||
|
|
@ -166,6 +166,12 @@ mod break_keyword {}
|
|||
///
|
||||
/// For more detail on `const`, see the [Rust Book] or the [Reference].
|
||||
///
|
||||
/// ## Compile-time blocks
|
||||
///
|
||||
/// The `const` keyword can also be used to define a block of code that is evaluated at compile time.
|
||||
/// This is useful for ensuring certain computations are completed before optimizations happen, as well as
|
||||
/// before runtime. For more details, see the [Reference][const-blocks].
|
||||
///
|
||||
/// ## Compile-time evaluable functions
|
||||
///
|
||||
/// The other main use of the `const` keyword is in `const fn`. This marks a function as being
|
||||
|
|
@ -184,6 +190,7 @@ mod break_keyword {}
|
|||
/// [pointer primitive]: pointer
|
||||
/// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#constants
|
||||
/// [Reference]: ../reference/items/constant-items.html
|
||||
/// [const-blocks]: ../reference/expressions/block-expr.html#const-blocks
|
||||
/// [const-eval]: ../reference/const_eval.html
|
||||
mod const_keyword {}
|
||||
|
||||
|
|
|
|||
|
|
@ -709,6 +709,7 @@ pub use core::primitive;
|
|||
// Re-export built-in macros defined through core.
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow(deprecated)]
|
||||
#[cfg_attr(bootstrap, allow(deprecated_in_future))]
|
||||
pub use core::{
|
||||
assert, assert_matches, cfg, column, compile_error, concat, concat_idents, const_format_args,
|
||||
env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ pub use crate::result::Result::{self, Err, Ok};
|
|||
// Re-exported built-in macros
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow(deprecated)]
|
||||
#[cfg_attr(bootstrap, allow(deprecated_in_future))]
|
||||
#[doc(no_inline)]
|
||||
pub use core::prelude::v1::{
|
||||
assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,16 @@
|
|||
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(any(
|
||||
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
|
||||
target_family = "windows",
|
||||
target_os = "hermit",
|
||||
target_os = "uefi",
|
||||
target_os = "wasi",
|
||||
target_os = "xous",
|
||||
))]
|
||||
mod common;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(
|
||||
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
use r_efi::protocols::loaded_image;
|
||||
|
||||
pub use super::common::Args;
|
||||
use crate::env::current_exe;
|
||||
use crate::ffi::OsString;
|
||||
use crate::iter::Iterator;
|
||||
use crate::sys::pal::helpers;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
pub fn args() -> Args {
|
||||
let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,16 +5,13 @@
|
|||
|
||||
#![allow(dead_code)] // runtime init functions not used during testing
|
||||
|
||||
pub use super::common::Args;
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(target_os = "hermit")]
|
||||
use crate::os::hermit::ffi::OsStringExt;
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use crate::os::unix::ffi::OsStringExt;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
/// One-time global initialization.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
unsafe { imp::init(argc, argv) }
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub use super::common::Args;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::os::wasi::ffi::OsStrExt;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
/// Returns the command line arguments
|
||||
pub fn args() -> Args {
|
||||
Args::new(maybe_args().unwrap_or(Vec::new()))
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use super::common::Args;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::num::NonZero;
|
||||
use crate::os::windows::prelude::*;
|
||||
|
|
@ -18,10 +19,6 @@ use crate::sys_common::AsInner;
|
|||
use crate::sys_common::wstr::WStrUnits;
|
||||
use crate::{io, iter, ptr};
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
pub fn args() -> Args {
|
||||
// SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
|
||||
// string so it's safe for `WStrUnits` to use.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
pub use super::common::Args;
|
||||
use crate::sys::pal::os::get_application_parameters;
|
||||
use crate::sys::pal::os::params::ArgumentList;
|
||||
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
pub use common::Args;
|
||||
|
||||
pub fn args() -> Args {
|
||||
let Some(params) = get_application_parameters() else {
|
||||
return Args::new(vec![]);
|
||||
|
|
|
|||
48
library/std/src/sys/env/common.rs
vendored
Normal file
48
library/std/src/sys/env/common.rs
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use crate::ffi::OsString;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
|
||||
Env { iter: env.into_iter() }
|
||||
}
|
||||
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
EnvStrDebug { slice: self.iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
72
library/std/src/sys/env/hermit.rs
vendored
Normal file
72
library/std/src/sys/env/hermit.rs
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use core::slice::memchr;
|
||||
|
||||
pub use super::common::Env;
|
||||
use crate::collections::HashMap;
|
||||
use crate::ffi::{CStr, OsStr, OsString, c_char};
|
||||
use crate::io;
|
||||
use crate::os::hermit::ffi::OsStringExt;
|
||||
use crate::sync::Mutex;
|
||||
|
||||
static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
|
||||
|
||||
pub fn init(env: *const *const c_char) {
|
||||
let mut guard = ENV.lock().unwrap();
|
||||
let map = guard.insert(HashMap::new());
|
||||
|
||||
if env.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut environ = env;
|
||||
while !(*environ).is_null() {
|
||||
if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
map.insert(key, value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
let guard = ENV.lock().unwrap();
|
||||
let env = guard.as_ref().unwrap();
|
||||
|
||||
let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect();
|
||||
|
||||
Env::new(result)
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
ENV.lock().unwrap().as_ref().unwrap().get(k).cloned()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
ENV.lock().unwrap().as_mut().unwrap().insert(k, v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
ENV.lock().unwrap().as_mut().unwrap().remove(k);
|
||||
Ok(())
|
||||
}
|
||||
48
library/std/src/sys/env/mod.rs
vendored
Normal file
48
library/std/src/sys/env/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//! Platform-dependent environment variables abstraction.
|
||||
|
||||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(any(
|
||||
target_family = "unix",
|
||||
target_os = "hermit",
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
target_os = "solid_asp3",
|
||||
target_os = "uefi",
|
||||
target_os = "wasi",
|
||||
target_os = "xous",
|
||||
))]
|
||||
mod common;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_family = "unix")] {
|
||||
mod unix;
|
||||
pub use unix::*;
|
||||
} else if #[cfg(target_family = "windows")] {
|
||||
mod windows;
|
||||
pub use windows::*;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
mod hermit;
|
||||
pub use hermit::*;
|
||||
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
} else if #[cfg(target_os = "solid_asp3")] {
|
||||
mod solid;
|
||||
pub use solid::*;
|
||||
} else if #[cfg(target_os = "uefi")] {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
} else if #[cfg(target_os = "wasi")] {
|
||||
mod wasi;
|
||||
pub use wasi::*;
|
||||
} else if #[cfg(target_os = "xous")] {
|
||||
mod xous;
|
||||
pub use xous::*;
|
||||
} else if #[cfg(target_os = "zkvm")] {
|
||||
mod zkvm;
|
||||
pub use zkvm::*;
|
||||
} else {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
}
|
||||
}
|
||||
55
library/std/src/sys/env/sgx.rs
vendored
Normal file
55
library/std/src/sys/env/sgx.rs
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers
|
||||
|
||||
pub use super::common::Env;
|
||||
use crate::collections::HashMap;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sync::{Mutex, Once};
|
||||
|
||||
// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
|
||||
#[cfg_attr(test, linkage = "available_externally")]
|
||||
#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")]
|
||||
static ENV: AtomicUsize = AtomicUsize::new(0);
|
||||
// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
|
||||
#[cfg_attr(test, linkage = "available_externally")]
|
||||
#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")]
|
||||
static ENV_INIT: Once = Once::new();
|
||||
type EnvStore = Mutex<HashMap<OsString, OsString>>;
|
||||
|
||||
fn get_env_store() -> Option<&'static EnvStore> {
|
||||
unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() }
|
||||
}
|
||||
|
||||
fn create_env_store() -> &'static EnvStore {
|
||||
ENV_INIT.call_once(|| {
|
||||
ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed)
|
||||
});
|
||||
unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) }
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
|
||||
map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
|
||||
};
|
||||
|
||||
let env = get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default();
|
||||
Env::new(env)
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned())
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
create_env_store().lock().unwrap().insert(k, v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
if let Some(env) = get_env_store() {
|
||||
env.lock().unwrap().remove(k);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
96
library/std/src/sys/env/solid.rs
vendored
Normal file
96
library/std/src/sys/env/solid.rs
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
use core::slice::memchr;
|
||||
|
||||
pub use super::common::Env;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::os::raw::{c_char, c_int};
|
||||
use crate::os::solid::ffi::{OsStrExt, OsStringExt};
|
||||
use crate::sync::{PoisonError, RwLock};
|
||||
use crate::sys::common::small_c_string::run_with_cstr;
|
||||
|
||||
static ENV_LOCK: RwLock<()> = RwLock::new(());
|
||||
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
unsafe extern "C" {
|
||||
static mut environ: *const *const c_char;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let _guard = env_read_lock();
|
||||
let mut result = Vec::new();
|
||||
if !environ.is_null() {
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
return Env::new(result);
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
let _guard = env_read_lock();
|
||||
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
|
||||
|
||||
if v.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
|
||||
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
|
||||
|
||||
Ok(Some(OsStringExt::from_vec(bytes)))
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
run_with_cstr(v.as_bytes(), &|v| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(n.as_bytes(), &|nbuf| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
|
||||
})
|
||||
}
|
||||
|
||||
/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this
|
||||
/// function just returns a generic error.
|
||||
fn cvt_env(t: c_int) -> io::Result<c_int> {
|
||||
if t == -1 { Err(io::const_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) }
|
||||
}
|
||||
102
library/std/src/sys/env/uefi.rs
vendored
Normal file
102
library/std/src/sys/env/uefi.rs
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
pub use super::common::Env;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::io;
|
||||
|
||||
pub fn env() -> Env {
|
||||
let env = uefi_env::get_all().expect("not supported on this platform");
|
||||
Env::new(env)
|
||||
}
|
||||
|
||||
pub fn getenv(key: &OsStr) -> Option<OsString> {
|
||||
uefi_env::get(key)
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
|
||||
uefi_env::set(key, val)
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
|
||||
uefi_env::unset(key)
|
||||
}
|
||||
|
||||
mod uefi_env {
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::os::uefi::ffi::OsStringExt;
|
||||
use crate::ptr::NonNull;
|
||||
use crate::sys::{helpers, unsupported_err};
|
||||
|
||||
pub(crate) fn get(key: &OsStr) -> Option<OsString> {
|
||||
let shell = helpers::open_shell()?;
|
||||
let mut key_ptr = helpers::os_string_to_raw(key)?;
|
||||
unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
|
||||
let mut key_ptr = helpers::os_string_to_raw(key)
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
|
||||
let mut val_ptr = helpers::os_string_to_raw(val)
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
|
||||
unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
|
||||
let mut key_ptr = helpers::os_string_to_raw(key)
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
|
||||
unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
|
||||
}
|
||||
|
||||
pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
|
||||
let shell = helpers::open_shell().ok_or(unsupported_err())?;
|
||||
|
||||
let mut vars = Vec::new();
|
||||
let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
|
||||
|
||||
if val.is_null() {
|
||||
return Ok(vars);
|
||||
}
|
||||
|
||||
let mut start = 0;
|
||||
|
||||
// UEFI Shell returns all keys separated by NULL.
|
||||
// End of string is denoted by two NULLs
|
||||
for i in 0.. {
|
||||
if unsafe { *val.add(i) } == 0 {
|
||||
// Two NULL signal end of string
|
||||
if i == start {
|
||||
break;
|
||||
}
|
||||
|
||||
let key = OsString::from_wide(unsafe {
|
||||
crate::slice::from_raw_parts(val.add(start), i - start)
|
||||
});
|
||||
// SAFETY: val.add(start) is always NULL terminated
|
||||
let val = unsafe { get_raw(shell, val.add(start)) }
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
|
||||
|
||||
vars.push((key, val));
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(vars)
|
||||
}
|
||||
|
||||
unsafe fn get_raw(
|
||||
shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
|
||||
key_ptr: *mut r_efi::efi::Char16,
|
||||
) -> Option<OsString> {
|
||||
let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
|
||||
helpers::os_string_from_raw(val)
|
||||
}
|
||||
|
||||
unsafe fn set_raw(
|
||||
key_ptr: *mut r_efi::efi::Char16,
|
||||
val_ptr: *mut r_efi::efi::Char16,
|
||||
) -> io::Result<()> {
|
||||
let shell = helpers::open_shell().ok_or(unsupported_err())?;
|
||||
let r =
|
||||
unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
|
||||
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
|
||||
}
|
||||
}
|
||||
126
library/std/src/sys/env/unix.rs
vendored
Normal file
126
library/std/src/sys/env/unix.rs
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
use core::slice::memchr;
|
||||
|
||||
use libc::c_char;
|
||||
|
||||
pub use super::common::Env;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::os::unix::prelude::*;
|
||||
use crate::sync::{PoisonError, RwLock};
|
||||
use crate::sys::common::small_c_string::run_with_cstr;
|
||||
use crate::sys::cvt;
|
||||
|
||||
// Use `_NSGetEnviron` on Apple platforms.
|
||||
//
|
||||
// `_NSGetEnviron` is the documented alternative (see `man environ`), and has
|
||||
// been available since the first versions of both macOS and iOS.
|
||||
//
|
||||
// Nowadays, specifically since macOS 10.8, `environ` has been exposed through
|
||||
// `libdyld.dylib`, which is linked via. `libSystem.dylib`:
|
||||
// <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913>
|
||||
//
|
||||
// So in the end, it likely doesn't really matter which option we use, but the
|
||||
// performance cost of using `_NSGetEnviron` is extremely miniscule, and it
|
||||
// might be ever so slightly more supported, so let's just use that.
|
||||
//
|
||||
// NOTE: The header where this is defined (`crt_externs.h`) was added to the
|
||||
// iOS 13.0 SDK, which has been the source of a great deal of confusion in the
|
||||
// past about the availability of this API.
|
||||
//
|
||||
// NOTE(madsmtm): Neither this nor using `environ` has been verified to not
|
||||
// cause App Store rejections; if this is found to be the case, an alternative
|
||||
// implementation of this is possible using `[NSProcessInfo environment]`
|
||||
// - which internally uses `_NSGetEnviron` and a system-wide lock on the
|
||||
// environment variables to protect against `setenv`, so using that might be
|
||||
// desirable anyhow? Though it also means that we have to link to Foundation.
|
||||
#[cfg(target_vendor = "apple")]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
unsafe { libc::_NSGetEnviron() as *mut *const *const c_char }
|
||||
}
|
||||
|
||||
// Use the `environ` static which is part of POSIX.
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
unsafe extern "C" {
|
||||
static mut environ: *const *const c_char;
|
||||
}
|
||||
&raw mut environ
|
||||
}
|
||||
|
||||
static ENV_LOCK: RwLock<()> = RwLock::new(());
|
||||
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let _guard = env_read_lock();
|
||||
let mut environ = *environ();
|
||||
let mut result = Vec::new();
|
||||
if !environ.is_null() {
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
return Env::new(result);
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
let _guard = env_read_lock();
|
||||
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
|
||||
|
||||
if v.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
|
||||
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
|
||||
|
||||
Ok(Some(OsStringExt::from_vec(bytes)))
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
run_with_cstr(v.as_bytes(), &|v| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(n.as_bytes(), &|nbuf| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
|
||||
})
|
||||
}
|
||||
40
library/std/src/sys/env/unsupported.rs
vendored
Normal file
40
library/std/src/sys/env/unsupported.rs
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::{fmt, io};
|
||||
|
||||
pub struct Env(!);
|
||||
|
||||
impl Env {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
panic!("not supported on this platform")
|
||||
}
|
||||
|
||||
pub fn getenv(_: &OsStr) -> Option<OsString> {
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
|
||||
}
|
||||
102
library/std/src/sys/env/wasi.rs
vendored
Normal file
102
library/std/src/sys/env/wasi.rs
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use core::slice::memchr;
|
||||
|
||||
pub use super::common::Env;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::os::wasi::prelude::*;
|
||||
use crate::sys::common::small_c_string::run_with_cstr;
|
||||
use crate::sys::pal::os::{cvt, libc};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_feature = "atomics")] {
|
||||
// Access to the environment must be protected by a lock in multi-threaded scenarios.
|
||||
use crate::sync::{PoisonError, RwLock};
|
||||
static ENV_LOCK: RwLock<()> = RwLock::new(());
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
pub fn env_write_lock() -> impl Drop {
|
||||
ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
} else {
|
||||
// No need for a lock if we are single-threaded.
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
Box::new(())
|
||||
}
|
||||
pub fn env_write_lock() -> impl Drop {
|
||||
Box::new(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let _guard = env_read_lock();
|
||||
|
||||
// Use `__wasilibc_get_environ` instead of `environ` here so that we
|
||||
// don't require wasi-libc to eagerly initialize the environment
|
||||
// variables.
|
||||
let mut environ = libc::__wasilibc_get_environ();
|
||||
|
||||
let mut result = Vec::new();
|
||||
if !environ.is_null() {
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
return Env::new(result);
|
||||
}
|
||||
|
||||
// See src/libstd/sys/pal/unix/os.rs, same as that
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
let _guard = env_read_lock();
|
||||
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
|
||||
|
||||
if v.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
|
||||
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
|
||||
|
||||
Ok(Some(OsStringExt::from_vec(bytes)))
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
run_with_cstr(v.as_bytes(), &|v| unsafe {
|
||||
let _guard = env_write_lock();
|
||||
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(n.as_bytes(), &|nbuf| unsafe {
|
||||
let _guard = env_write_lock();
|
||||
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
|
||||
})
|
||||
}
|
||||
133
library/std/src/sys/env/windows.rs
vendored
Normal file
133
library/std/src/sys/env/windows.rs
vendored
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::os::windows::prelude::*;
|
||||
use crate::sys::pal::{c, cvt, fill_utf16_buf, to_u16s};
|
||||
use crate::{fmt, io, ptr, slice};
|
||||
|
||||
pub struct Env {
|
||||
base: *mut c::WCHAR,
|
||||
iter: EnvIterator,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
iter: &'a EnvIterator,
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
let iter: EnvIterator = (*iter).clone();
|
||||
let mut list = f.debug_list();
|
||||
for (a, b) in iter {
|
||||
list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
|
||||
}
|
||||
list.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { base: _, iter } = self;
|
||||
EnvStrDebug { iter }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { base: _, iter } = self;
|
||||
f.debug_list().entries(iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
let Self { base: _, iter } = self;
|
||||
iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct EnvIterator(*mut c::WCHAR);
|
||||
|
||||
impl Iterator for EnvIterator {
|
||||
type Item = (OsString, OsString);
|
||||
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
let Self(cur) = self;
|
||||
loop {
|
||||
unsafe {
|
||||
if **cur == 0 {
|
||||
return None;
|
||||
}
|
||||
let p = *cur as *const u16;
|
||||
let mut len = 0;
|
||||
while *p.add(len) != 0 {
|
||||
len += 1;
|
||||
}
|
||||
let s = slice::from_raw_parts(p, len);
|
||||
*cur = cur.add(len + 1);
|
||||
|
||||
// Windows allows environment variables to start with an equals
|
||||
// symbol (in any other position, this is the separator between
|
||||
// variable name and value). Since`s` has at least length 1 at
|
||||
// this point (because the empty string terminates the array of
|
||||
// environment variables), we can safely slice.
|
||||
let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) {
|
||||
Some(p) => p,
|
||||
None => continue,
|
||||
};
|
||||
return Some((
|
||||
OsStringExt::from_wide(&s[..pos]),
|
||||
OsStringExt::from_wide(&s[pos + 1..]),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Env {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
c::FreeEnvironmentStringsW(self.base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let ch = c::GetEnvironmentStringsW();
|
||||
if ch.is_null() {
|
||||
panic!("failure getting env string from OS: {}", io::Error::last_os_error());
|
||||
}
|
||||
Env { base: ch, iter: EnvIterator(ch) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
let k = to_u16s(k).ok()?;
|
||||
fill_utf16_buf(
|
||||
|buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) },
|
||||
OsStringExt::from_wide,
|
||||
)
|
||||
.ok()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
// SAFETY: We ensure that k and v are null-terminated wide strings.
|
||||
unsafe {
|
||||
let k = to_u16s(k)?;
|
||||
let v = to_u16s(v)?;
|
||||
|
||||
cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
// SAFETY: We ensure that v is a null-terminated wide strings.
|
||||
unsafe {
|
||||
let v = to_u16s(n)?;
|
||||
cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
|
||||
}
|
||||
}
|
||||
54
library/std/src/sys/env/xous.rs
vendored
Normal file
54
library/std/src/sys/env/xous.rs
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
pub use super::common::Env;
|
||||
use crate::collections::HashMap;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sync::{Mutex, Once};
|
||||
use crate::sys::pal::os::{get_application_parameters, params};
|
||||
|
||||
static ENV: AtomicUsize = AtomicUsize::new(0);
|
||||
static ENV_INIT: Once = Once::new();
|
||||
type EnvStore = Mutex<HashMap<OsString, OsString>>;
|
||||
|
||||
fn get_env_store() -> &'static EnvStore {
|
||||
ENV_INIT.call_once(|| {
|
||||
let env_store = EnvStore::default();
|
||||
if let Some(params) = get_application_parameters() {
|
||||
for param in params {
|
||||
if let Ok(envs) = params::EnvironmentBlock::try_from(¶m) {
|
||||
let mut env_store = env_store.lock().unwrap();
|
||||
for env in envs {
|
||||
env_store.insert(env.key.into(), env.value.into());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed)
|
||||
});
|
||||
unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) }
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
|
||||
map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
|
||||
};
|
||||
|
||||
let env = clone_to_vec(&*get_env_store().lock().unwrap());
|
||||
Env::new(env)
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
get_env_store().lock().unwrap().get(k).cloned()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
get_env_store().lock().unwrap().insert(k, v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
get_env_store().lock().unwrap().remove(k);
|
||||
Ok(())
|
||||
}
|
||||
32
library/std/src/sys/env/zkvm.rs
vendored
Normal file
32
library/std/src/sys/env/zkvm.rs
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#[expect(dead_code)]
|
||||
#[path = "unsupported.rs"]
|
||||
mod unsupported_env;
|
||||
pub use unsupported_env::{Env, env, setenv, unsetenv};
|
||||
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::sys::os_str;
|
||||
use crate::sys::pal::{WORD_SIZE, abi};
|
||||
use crate::sys_common::FromInner;
|
||||
|
||||
pub fn getenv(varname: &OsStr) -> Option<OsString> {
|
||||
let varname = varname.as_encoded_bytes();
|
||||
let nbytes =
|
||||
unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) };
|
||||
if nbytes == usize::MAX {
|
||||
return None;
|
||||
}
|
||||
|
||||
let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE;
|
||||
let words = unsafe { abi::sys_alloc_words(nwords) };
|
||||
|
||||
let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) };
|
||||
debug_assert_eq!(nbytes, nbytes2);
|
||||
|
||||
// Convert to OsString.
|
||||
//
|
||||
// FIXME: We can probably get rid of the extra copy here if we
|
||||
// reimplement "os_str" instead of just using the generic unix
|
||||
// "os_str".
|
||||
let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) };
|
||||
Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() }))
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ pub mod anonymous_pipe;
|
|||
pub mod args;
|
||||
pub mod backtrace;
|
||||
pub mod cmath;
|
||||
pub mod env;
|
||||
pub mod env_consts;
|
||||
pub mod exit_guard;
|
||||
pub mod fd;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![allow(missing_docs, nonstandard_style)]
|
||||
|
||||
use crate::io::ErrorKind;
|
||||
use crate::os::hermit::hermit_abi;
|
||||
use crate::os::raw::c_char;
|
||||
use crate::sys::env;
|
||||
|
||||
pub mod futex;
|
||||
pub mod os;
|
||||
|
|
@ -25,9 +28,6 @@ pub mod pipe;
|
|||
pub mod thread;
|
||||
pub mod time;
|
||||
|
||||
use crate::io::ErrorKind;
|
||||
use crate::os::hermit::hermit_abi;
|
||||
|
||||
pub fn unsupported<T>() -> crate::io::Result<T> {
|
||||
Err(unsupported_err())
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ pub unsafe extern "C" fn runtime_entry(
|
|||
}
|
||||
|
||||
// initialize environment
|
||||
os::init_environment(env);
|
||||
env::init(env);
|
||||
|
||||
let result = unsafe { main(argc as isize, argv) };
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
use core::slice::memchr;
|
||||
|
||||
use super::hermit_abi;
|
||||
use crate::collections::HashMap;
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{CStr, OsStr, OsString, c_char};
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::marker::PhantomData;
|
||||
use crate::os::hermit::ffi::OsStringExt;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sync::Mutex;
|
||||
use crate::sys::unsupported;
|
||||
use crate::{fmt, io, str, vec};
|
||||
use crate::{fmt, io, str};
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
unsafe { hermit_abi::get_errno() }
|
||||
|
|
@ -68,115 +63,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
|
||||
|
||||
pub fn init_environment(env: *const *const c_char) {
|
||||
let mut guard = ENV.lock().unwrap();
|
||||
let map = guard.insert(HashMap::new());
|
||||
|
||||
if env.is_null() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut environ = env;
|
||||
while !(*environ).is_null() {
|
||||
if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
map.insert(key, value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { slice } = self;
|
||||
f.debug_list()
|
||||
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { iter } = self;
|
||||
EnvStrDebug { slice: iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
f.debug_list().entries(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()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
let guard = ENV.lock().unwrap();
|
||||
let env = guard.as_ref().unwrap();
|
||||
|
||||
let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect::<Vec<_>>();
|
||||
|
||||
Env { iter: result.into_iter() }
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
ENV.lock().unwrap().as_ref().unwrap().get(k).cloned()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
ENV.lock().unwrap().as_mut().unwrap().insert(k, v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
ENV.lock().unwrap().as_mut().unwrap().remove(k);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
PathBuf::from("/tmp")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
|
||||
|
||||
use crate::collections::HashMap;
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::marker::PhantomData;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::sync::{Mutex, Once};
|
||||
use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
|
||||
use crate::{fmt, io, str, vec};
|
||||
use crate::{fmt, io, str};
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
RESULT_SUCCESS
|
||||
|
|
@ -73,101 +70,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
|
||||
#[cfg_attr(test, linkage = "available_externally")]
|
||||
#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")]
|
||||
static ENV: AtomicUsize = AtomicUsize::new(0);
|
||||
// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests
|
||||
#[cfg_attr(test, linkage = "available_externally")]
|
||||
#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")]
|
||||
static ENV_INIT: Once = Once::new();
|
||||
type EnvStore = Mutex<HashMap<OsString, OsString>>;
|
||||
|
||||
fn get_env_store() -> Option<&'static EnvStore> {
|
||||
unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() }
|
||||
}
|
||||
|
||||
fn create_env_store() -> &'static EnvStore {
|
||||
ENV_INIT.call_once(|| {
|
||||
ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed)
|
||||
});
|
||||
unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) }
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { slice } = self;
|
||||
f.debug_list()
|
||||
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { iter } = self;
|
||||
EnvStrDebug { slice: iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
f.debug_list().entries(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()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
|
||||
map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
|
||||
};
|
||||
|
||||
let iter = get_env_store()
|
||||
.map(|env| clone_to_vec(&env.lock().unwrap()))
|
||||
.unwrap_or_default()
|
||||
.into_iter();
|
||||
Env { iter }
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned())
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
create_env_store().lock().unwrap().insert(k, v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
if let Some(env) = get_env_store() {
|
||||
env.lock().unwrap().remove(k);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem in SGX")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
use core::slice::memchr;
|
||||
|
||||
use super::{error, itron, unsupported};
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::os::raw::{c_char, c_int};
|
||||
use crate::os::solid::ffi::{OsStrExt, OsStringExt};
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sync::{PoisonError, RwLock};
|
||||
use crate::sys::common::small_c_string::run_with_cstr;
|
||||
use crate::{fmt, io, vec};
|
||||
use crate::{fmt, io};
|
||||
|
||||
// `solid` directly maps `errno`s to μITRON error codes.
|
||||
impl itron::error::ItronError {
|
||||
|
|
@ -75,138 +69,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
static ENV_LOCK: RwLock<()> = RwLock::new(());
|
||||
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { slice } = self;
|
||||
f.debug_list()
|
||||
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { iter } = self;
|
||||
EnvStrDebug { slice: iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
f.debug_list().entries(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()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
unsafe extern "C" {
|
||||
static mut environ: *const *const c_char;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let _guard = env_read_lock();
|
||||
let mut result = Vec::new();
|
||||
if !environ.is_null() {
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
return Env { iter: result.into_iter() };
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
let _guard = env_read_lock();
|
||||
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
|
||||
|
||||
if v.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
|
||||
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
|
||||
|
||||
Ok(Some(OsStringExt::from_vec(bytes)))
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
run_with_cstr(v.as_bytes(), &|v| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(n.as_bytes(), &|nbuf| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
|
||||
})
|
||||
}
|
||||
|
||||
/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this
|
||||
/// function just returns a generic error.
|
||||
fn cvt_env(t: c_int) -> io::Result<c_int> {
|
||||
if t == -1 { Err(io::const_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) }
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no standard temporary directory on this platform")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,47 +73,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
pub struct Env(!);
|
||||
|
||||
impl Env {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
panic!("not supported on this platform")
|
||||
}
|
||||
|
||||
pub fn getenv(_: &OsStr) -> Option<OsString> {
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem on this platform")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,60 +131,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
helpers::device_path_to_text(protocol).map(PathBuf::from)
|
||||
}
|
||||
|
||||
pub struct EnvStrDebug<'a> {
|
||||
iter: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut list = f.debug_list();
|
||||
for (a, b) in self.iter {
|
||||
list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
|
||||
}
|
||||
list.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);
|
||||
|
||||
impl Env {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
EnvStrDebug { iter: self.0.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
let env = uefi_env::get_all().expect("not supported on this platform");
|
||||
Env(env.into_iter())
|
||||
}
|
||||
|
||||
pub fn getenv(key: &OsStr) -> Option<OsString> {
|
||||
uefi_env::get(key)
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
|
||||
uefi_env::set(key, val)
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
|
||||
uefi_env::unset(key)
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem on this platform")
|
||||
}
|
||||
|
|
@ -213,85 +159,3 @@ pub fn exit(code: i32) -> ! {
|
|||
pub fn getpid() -> u32 {
|
||||
panic!("no pids on this platform")
|
||||
}
|
||||
|
||||
mod uefi_env {
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::io;
|
||||
use crate::os::uefi::ffi::OsStringExt;
|
||||
use crate::ptr::NonNull;
|
||||
use crate::sys::{helpers, unsupported_err};
|
||||
|
||||
pub(crate) fn get(key: &OsStr) -> Option<OsString> {
|
||||
let shell = helpers::open_shell()?;
|
||||
let mut key_ptr = helpers::os_string_to_raw(key)?;
|
||||
unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
|
||||
let mut key_ptr = helpers::os_string_to_raw(key)
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
|
||||
let mut val_ptr = helpers::os_string_to_raw(val)
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
|
||||
unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
|
||||
let mut key_ptr = helpers::os_string_to_raw(key)
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?;
|
||||
unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
|
||||
}
|
||||
|
||||
pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
|
||||
let shell = helpers::open_shell().ok_or(unsupported_err())?;
|
||||
|
||||
let mut vars = Vec::new();
|
||||
let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
|
||||
|
||||
if val.is_null() {
|
||||
return Ok(vars);
|
||||
}
|
||||
|
||||
let mut start = 0;
|
||||
|
||||
// UEFI Shell returns all keys separated by NULL.
|
||||
// End of string is denoted by two NULLs
|
||||
for i in 0.. {
|
||||
if unsafe { *val.add(i) } == 0 {
|
||||
// Two NULL signal end of string
|
||||
if i == start {
|
||||
break;
|
||||
}
|
||||
|
||||
let key = OsString::from_wide(unsafe {
|
||||
crate::slice::from_raw_parts(val.add(start), i - start)
|
||||
});
|
||||
// SAFETY: val.add(start) is always NULL terminated
|
||||
let val = unsafe { get_raw(shell, val.add(start)) }
|
||||
.ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?;
|
||||
|
||||
vars.push((key, val));
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(vars)
|
||||
}
|
||||
|
||||
unsafe fn get_raw(
|
||||
shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
|
||||
key_ptr: *mut r_efi::efi::Char16,
|
||||
) -> Option<OsString> {
|
||||
let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
|
||||
helpers::os_string_from_raw(val)
|
||||
}
|
||||
|
||||
unsafe fn set_raw(
|
||||
key_ptr: *mut r_efi::efi::Char16,
|
||||
val_ptr: *mut r_efi::efi::Char16,
|
||||
) -> io::Result<()> {
|
||||
let shell = helpers::open_shell().ok_or(unsupported_err())?;
|
||||
let r =
|
||||
unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
|
||||
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,15 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use core::slice::memchr;
|
||||
|
||||
use libc::{c_char, c_int, c_void};
|
||||
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{CStr, CString, OsStr, OsString};
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::os::unix::prelude::*;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sync::{PoisonError, RwLock};
|
||||
use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
|
||||
#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
|
||||
use crate::sys::weak::weak;
|
||||
use crate::sys::{cvt, fd};
|
||||
use crate::{fmt, io, iter, mem, ptr, slice, str, vec};
|
||||
use crate::sys::common::small_c_string::run_path_with_cstr;
|
||||
use crate::sys::cvt;
|
||||
use crate::{fmt, io, iter, mem, ptr, slice, str};
|
||||
|
||||
const TMPBUF_SZ: usize = 128;
|
||||
|
||||
|
|
@ -552,166 +547,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
if !path.is_absolute() { getcwd().map(|cwd| cwd.join(path)) } else { Ok(path) }
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { slice } = self;
|
||||
f.debug_list()
|
||||
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { iter } = self;
|
||||
EnvStrDebug { slice: iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
f.debug_list().entries(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()
|
||||
}
|
||||
}
|
||||
|
||||
// Use `_NSGetEnviron` on Apple platforms.
|
||||
//
|
||||
// `_NSGetEnviron` is the documented alternative (see `man environ`), and has
|
||||
// been available since the first versions of both macOS and iOS.
|
||||
//
|
||||
// Nowadays, specifically since macOS 10.8, `environ` has been exposed through
|
||||
// `libdyld.dylib`, which is linked via. `libSystem.dylib`:
|
||||
// <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913>
|
||||
//
|
||||
// So in the end, it likely doesn't really matter which option we use, but the
|
||||
// performance cost of using `_NSGetEnviron` is extremely miniscule, and it
|
||||
// might be ever so slightly more supported, so let's just use that.
|
||||
//
|
||||
// NOTE: The header where this is defined (`crt_externs.h`) was added to the
|
||||
// iOS 13.0 SDK, which has been the source of a great deal of confusion in the
|
||||
// past about the availability of this API.
|
||||
//
|
||||
// NOTE(madsmtm): Neither this nor using `environ` has been verified to not
|
||||
// cause App Store rejections; if this is found to be the case, an alternative
|
||||
// implementation of this is possible using `[NSProcessInfo environment]`
|
||||
// - which internally uses `_NSGetEnviron` and a system-wide lock on the
|
||||
// environment variables to protect against `setenv`, so using that might be
|
||||
// desirable anyhow? Though it also means that we have to link to Foundation.
|
||||
#[cfg(target_vendor = "apple")]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
libc::_NSGetEnviron() as *mut *const *const c_char
|
||||
}
|
||||
|
||||
// Use the `environ` static which is part of POSIX.
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
unsafe extern "C" {
|
||||
static mut environ: *const *const c_char;
|
||||
}
|
||||
&raw mut environ
|
||||
}
|
||||
|
||||
static ENV_LOCK: RwLock<()> = RwLock::new(());
|
||||
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let _guard = env_read_lock();
|
||||
let mut environ = *environ();
|
||||
let mut result = Vec::new();
|
||||
if !environ.is_null() {
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
return Env { iter: result.into_iter() };
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
let _guard = env_read_lock();
|
||||
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
|
||||
|
||||
if v.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
|
||||
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
|
||||
|
||||
Ok(Some(OsStringExt::from_vec(bytes)))
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
run_with_cstr(v.as_bytes(), &|v| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(n.as_bytes(), &|nbuf| {
|
||||
let _guard = ENV_LOCK.write();
|
||||
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
pub fn page_size() -> usize {
|
||||
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
|
||||
|
|
|
|||
|
|
@ -64,7 +64,10 @@ impl Condvar {
|
|||
// https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
|
||||
//
|
||||
// To work around this issue, the timeout is clamped to 1000 years.
|
||||
#[cfg(target_vendor = "apple")]
|
||||
//
|
||||
// Cygwin implementation is based on NT API and a super large timeout
|
||||
// makes the syscall block forever.
|
||||
#[cfg(any(target_vendor = "apple", target_os = "cygwin"))]
|
||||
let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
|
||||
|
||||
let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur);
|
||||
|
|
|
|||
|
|
@ -62,47 +62,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
pub struct Env(!);
|
||||
|
||||
impl Env {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
panic!("not supported on this platform")
|
||||
}
|
||||
|
||||
pub fn getenv(_: &OsStr) -> Option<OsString> {
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem on this platform")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use core::slice::memchr;
|
||||
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::marker::PhantomData;
|
||||
use crate::ops::Drop;
|
||||
use crate::os::wasi::prelude::*;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
|
||||
use crate::sys::common::small_c_string::run_path_with_cstr;
|
||||
use crate::sys::unsupported;
|
||||
use crate::{fmt, io, str, vec};
|
||||
use crate::{fmt, io, str};
|
||||
|
||||
// Add a few symbols not in upstream `libc` just yet.
|
||||
mod libc {
|
||||
pub mod libc {
|
||||
pub use libc::*;
|
||||
|
||||
unsafe extern "C" {
|
||||
|
|
@ -23,28 +20,6 @@ mod libc {
|
|||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_feature = "atomics")] {
|
||||
// Access to the environment must be protected by a lock in multi-threaded scenarios.
|
||||
use crate::sync::{PoisonError, RwLock};
|
||||
static ENV_LOCK: RwLock<()> = RwLock::new(());
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
pub fn env_write_lock() -> impl Drop {
|
||||
ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
} else {
|
||||
// No need for a lock if we are single-threaded.
|
||||
pub fn env_read_lock() -> impl Drop {
|
||||
Box::new(())
|
||||
}
|
||||
pub fn env_write_lock() -> impl Drop {
|
||||
Box::new(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
unsafe extern "C" {
|
||||
#[thread_local]
|
||||
|
|
@ -141,123 +116,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { slice } = self;
|
||||
f.debug_list()
|
||||
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { iter } = self;
|
||||
EnvStrDebug { slice: iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
f.debug_list().entries(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()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let _guard = env_read_lock();
|
||||
|
||||
// Use `__wasilibc_get_environ` instead of `environ` here so that we
|
||||
// don't require wasi-libc to eagerly initialize the environment
|
||||
// variables.
|
||||
let mut environ = libc::__wasilibc_get_environ();
|
||||
|
||||
let mut result = Vec::new();
|
||||
if !environ.is_null() {
|
||||
while !(*environ).is_null() {
|
||||
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
result.push(key_value);
|
||||
}
|
||||
environ = environ.add(1);
|
||||
}
|
||||
}
|
||||
return Env { iter: result.into_iter() };
|
||||
}
|
||||
|
||||
// See src/libstd/sys/pal/unix/os.rs, same as that
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| {
|
||||
(
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p + 1..].to_vec()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
// environment variables with a nul byte can't be set, so their value is
|
||||
// always None as well
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
let _guard = env_read_lock();
|
||||
let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
|
||||
|
||||
if v.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
// SAFETY: `v` cannot be mutated while executing this line since we've a read lock
|
||||
let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
|
||||
|
||||
Ok(Some(OsStringExt::from_vec(bytes)))
|
||||
}
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(k.as_bytes(), &|k| {
|
||||
run_with_cstr(v.as_bytes(), &|v| unsafe {
|
||||
let _guard = env_write_lock();
|
||||
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
run_with_cstr(n.as_bytes(), &|nbuf| unsafe {
|
||||
let _guard = env_write_lock();
|
||||
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn page_size() -> usize {
|
||||
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
|
||||
|
|
@ -294,6 +152,6 @@ macro_rules! impl_is_minus_one {
|
|||
|
||||
impl_is_minus_one! { i8 i16 i32 i64 isize }
|
||||
|
||||
fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
|
||||
pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
|
||||
if t.is_minus_one() { Err(io::Error::last_os_error()) } else { Ok(t) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use super::api;
|
||||
#[cfg(not(target_vendor = "uwp"))]
|
||||
use super::api::WinError;
|
||||
use super::{api, to_u16s};
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::os::windows::ffi::EncodeWide;
|
||||
use crate::os::windows::prelude::*;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sys::{c, cvt};
|
||||
use crate::{fmt, io, ptr, slice};
|
||||
use crate::sys::pal::{c, cvt};
|
||||
use crate::{fmt, io, ptr};
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
api::get_last_error().code as i32
|
||||
|
|
@ -76,108 +76,6 @@ pub fn error_string(mut errnum: i32) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
base: *mut c::WCHAR,
|
||||
iter: EnvIterator,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
iter: &'a EnvIterator,
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
let iter: EnvIterator = (*iter).clone();
|
||||
let mut list = f.debug_list();
|
||||
for (a, b) in iter {
|
||||
list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
|
||||
}
|
||||
list.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { base: _, iter } = self;
|
||||
EnvStrDebug { iter }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { base: _, iter } = self;
|
||||
f.debug_list().entries(iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
let Self { base: _, iter } = self;
|
||||
iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct EnvIterator(*mut c::WCHAR);
|
||||
|
||||
impl Iterator for EnvIterator {
|
||||
type Item = (OsString, OsString);
|
||||
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
let Self(cur) = self;
|
||||
loop {
|
||||
unsafe {
|
||||
if **cur == 0 {
|
||||
return None;
|
||||
}
|
||||
let p = *cur as *const u16;
|
||||
let mut len = 0;
|
||||
while *p.add(len) != 0 {
|
||||
len += 1;
|
||||
}
|
||||
let s = slice::from_raw_parts(p, len);
|
||||
*cur = cur.add(len + 1);
|
||||
|
||||
// Windows allows environment variables to start with an equals
|
||||
// symbol (in any other position, this is the separator between
|
||||
// variable name and value). Since`s` has at least length 1 at
|
||||
// this point (because the empty string terminates the array of
|
||||
// environment variables), we can safely slice.
|
||||
let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) {
|
||||
Some(p) => p,
|
||||
None => continue,
|
||||
};
|
||||
return Some((
|
||||
OsStringExt::from_wide(&s[..pos]),
|
||||
OsStringExt::from_wide(&s[pos + 1..]),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Env {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
c::FreeEnvironmentStringsW(self.base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let ch = c::GetEnvironmentStringsW();
|
||||
if ch.is_null() {
|
||||
panic!("failure getting env string from OS: {}", io::Error::last_os_error());
|
||||
}
|
||||
Env { base: ch, iter: EnvIterator(ch) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SplitPaths<'a> {
|
||||
data: EncodeWide<'a>,
|
||||
must_yield: bool,
|
||||
|
|
@ -290,33 +188,6 @@ pub fn chdir(p: &path::Path) -> io::Result<()> {
|
|||
cvt(unsafe { c::SetCurrentDirectoryW(p.as_ptr()) }).map(drop)
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
let k = to_u16s(k).ok()?;
|
||||
super::fill_utf16_buf(
|
||||
|buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) },
|
||||
OsStringExt::from_wide,
|
||||
)
|
||||
.ok()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
// SAFETY: We ensure that k and v are null-terminated wide strings.
|
||||
unsafe {
|
||||
let k = to_u16s(k)?;
|
||||
let v = to_u16s(v)?;
|
||||
|
||||
cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
|
||||
// SAFETY: We ensure that v is a null-terminated wide strings.
|
||||
unsafe {
|
||||
let v = to_u16s(n)?;
|
||||
cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
use super::unsupported;
|
||||
use crate::collections::HashMap;
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::marker::PhantomData;
|
||||
use crate::os::xous::ffi::Error as XousError;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
||||
use crate::sync::{Mutex, Once};
|
||||
use crate::{fmt, io, vec};
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||
use crate::{fmt, io};
|
||||
|
||||
pub(crate) mod params;
|
||||
|
||||
|
|
@ -136,100 +134,6 @@ pub(crate) fn get_application_parameters() -> Option<params::ApplicationParamete
|
|||
unsafe { params::ApplicationParameters::new_from_ptr(params_address) }
|
||||
}
|
||||
|
||||
// ---------- Environment handling ---------- //
|
||||
static ENV: AtomicUsize = AtomicUsize::new(0);
|
||||
static ENV_INIT: Once = Once::new();
|
||||
type EnvStore = Mutex<HashMap<OsString, OsString>>;
|
||||
|
||||
fn get_env_store() -> &'static EnvStore {
|
||||
ENV_INIT.call_once(|| {
|
||||
let env_store = EnvStore::default();
|
||||
if let Some(params) = get_application_parameters() {
|
||||
for param in params {
|
||||
if let Ok(envs) = params::EnvironmentBlock::try_from(¶m) {
|
||||
let mut env_store = env_store.lock().unwrap();
|
||||
for env in envs {
|
||||
env_store.insert(env.key.into(), env.value.into());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed)
|
||||
});
|
||||
unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) }
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { slice } = self;
|
||||
f.debug_list()
|
||||
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { iter } = self;
|
||||
EnvStrDebug { slice: iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
f.debug_list().entries(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()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> {
|
||||
map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
|
||||
};
|
||||
|
||||
let iter = clone_to_vec(&*get_env_store().lock().unwrap()).into_iter();
|
||||
Env { iter }
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
get_env_store().lock().unwrap().get(k).cloned()
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
get_env_store().lock().unwrap().insert(k, v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
get_env_store().lock().unwrap().remove(k);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem on this platform")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
use super::{WORD_SIZE, abi, unsupported};
|
||||
use super::unsupported;
|
||||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::marker::PhantomData;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::sys::os_str;
|
||||
use crate::sys_common::FromInner;
|
||||
use crate::{fmt, io};
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
|
|
@ -64,64 +62,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
unsupported()
|
||||
}
|
||||
|
||||
pub struct Env(!);
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
panic!("not supported on this platform")
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self(inner) = self;
|
||||
match *inner {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(varname: &OsStr) -> Option<OsString> {
|
||||
let varname = varname.as_encoded_bytes();
|
||||
let nbytes =
|
||||
unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) };
|
||||
if nbytes == usize::MAX {
|
||||
return None;
|
||||
}
|
||||
|
||||
let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE;
|
||||
let words = unsafe { abi::sys_alloc_words(nwords) };
|
||||
|
||||
let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) };
|
||||
debug_assert_eq!(nbytes, nbytes2);
|
||||
|
||||
// Convert to OsString.
|
||||
//
|
||||
// FIXME: We can probably get rid of the extra copy here if we
|
||||
// reimplement "os_str" instead of just using the generic unix
|
||||
// "os_str".
|
||||
let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) };
|
||||
Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() }))
|
||||
}
|
||||
|
||||
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
|
||||
}
|
||||
|
||||
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
|
||||
Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem on this platform")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ impl Command {
|
|||
// in its own process. Thus the parent drops the lock guard immediately.
|
||||
// The child calls `mem::forget` to leak the lock, which is crucial because
|
||||
// releasing a lock is not async-signal-safe.
|
||||
let env_lock = sys::os::env_read_lock();
|
||||
let env_lock = sys::env::env_read_lock();
|
||||
let pid = unsafe { self.do_fork()? };
|
||||
|
||||
if pid == 0 {
|
||||
|
|
@ -237,7 +237,7 @@ impl Command {
|
|||
// Similar to when forking, we want to ensure that access to
|
||||
// the environment is synchronized, so make sure to grab the
|
||||
// environment lock before we try to exec.
|
||||
let _lock = sys::os::env_read_lock();
|
||||
let _lock = sys::env::env_read_lock();
|
||||
|
||||
let Err(e) = self.do_exec(theirs, envp.as_ref());
|
||||
e
|
||||
|
|
@ -386,13 +386,13 @@ impl Command {
|
|||
impl Drop for Reset {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
*sys::os::environ() = self.0;
|
||||
*sys::env::environ() = self.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_reset = Some(Reset(*sys::os::environ()));
|
||||
*sys::os::environ() = envp.as_ptr();
|
||||
_reset = Some(Reset(*sys::env::environ()));
|
||||
*sys::env::environ() = envp.as_ptr();
|
||||
}
|
||||
|
||||
libc::execvp(self.get_program_cstr().as_ptr(), self.get_argv().as_ptr());
|
||||
|
|
@ -739,8 +739,8 @@ impl Command {
|
|||
cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
|
||||
|
||||
// Make sure we synchronize access to the global `environ` resource
|
||||
let _env_lock = sys::os::env_read_lock();
|
||||
let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
|
||||
let _env_lock = sys::env::env_read_lock();
|
||||
let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::env::environ() as *const _);
|
||||
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
let spawn_fn = libc::posix_spawnp;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ impl Command {
|
|||
let c_envp = envp
|
||||
.as_ref()
|
||||
.map(|c| c.as_ptr())
|
||||
.unwrap_or_else(|| *sys::os::environ() as *const _);
|
||||
.unwrap_or_else(|| *sys::env::environ() as *const _);
|
||||
let stack_size = crate::cmp::max(
|
||||
crate::env::var_os("RUST_MIN_STACK")
|
||||
.and_then(|s| s.to_str().and_then(|s| s.parse().ok()))
|
||||
|
|
@ -76,7 +76,7 @@ impl Command {
|
|||
);
|
||||
|
||||
// ensure that access to the environment is synchronized
|
||||
let _lock = sys::os::env_read_lock();
|
||||
let _lock = sys::env::env_read_lock();
|
||||
|
||||
let ret = libc::rtpSpawn(
|
||||
self.get_program_cstr().as_ptr(),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
|
||||
#![cfg(reliable_f128)]
|
||||
#![cfg(not(bootstrap))]
|
||||
#![cfg(target_has_reliable_f128)]
|
||||
|
||||
use std::f128::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
use std::ops::Rem;
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
|
|
@ -19,7 +22,9 @@ const TOL: f128 = 1e-12;
|
|||
|
||||
/// Tolerances for math that is allowed to be imprecise, usually due to multiple chained
|
||||
/// operations.
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
const TOL_IMPR: f128 = 1e-10;
|
||||
|
||||
/// Smallest number
|
||||
|
|
@ -66,8 +71,13 @@ fn test_num_f128() {
|
|||
assert_eq!(ten.div(two), ten / two);
|
||||
}
|
||||
|
||||
// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
|
||||
// the intrinsics.
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_num_f128_rem() {
|
||||
let ten = 10f128;
|
||||
let two = 2f128;
|
||||
|
|
@ -75,28 +85,36 @@ fn test_num_f128_rem() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_min_nan() {
|
||||
assert_eq!(f128::NAN.min(2.0), 2.0);
|
||||
assert_eq!(2.0f128.min(f128::NAN), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_max_nan() {
|
||||
assert_eq!(f128::NAN.max(2.0), 2.0);
|
||||
assert_eq!(2.0f128.max(f128::NAN), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_minimum() {
|
||||
assert!(f128::NAN.minimum(2.0).is_nan());
|
||||
assert!(2.0f128.minimum(f128::NAN).is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_maximum() {
|
||||
assert!(f128::NAN.maximum(2.0).is_nan());
|
||||
assert!(2.0f128.maximum(f128::NAN).is_nan());
|
||||
|
|
@ -253,7 +271,9 @@ fn test_classify() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_floor() {
|
||||
assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
|
||||
assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
|
||||
|
|
@ -268,7 +288,9 @@ fn test_floor() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_ceil() {
|
||||
assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
|
||||
assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
|
||||
|
|
@ -283,7 +305,9 @@ fn test_ceil() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_round() {
|
||||
assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
|
||||
assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
|
||||
|
|
@ -299,7 +323,9 @@ fn test_round() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_round_ties_even() {
|
||||
assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
|
||||
assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
|
||||
|
|
@ -315,7 +341,9 @@ fn test_round_ties_even() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_trunc() {
|
||||
assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
|
||||
assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
|
||||
|
|
@ -330,7 +358,9 @@ fn test_trunc() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_fract() {
|
||||
assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
|
||||
assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
|
||||
|
|
@ -345,7 +375,9 @@ fn test_fract() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_abs() {
|
||||
assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
|
||||
assert_eq!(1f128.abs(), 1f128);
|
||||
|
|
@ -445,7 +477,9 @@ fn test_next_down() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_mul_add() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -462,7 +496,9 @@ fn test_mul_add() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_recip() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -484,7 +520,9 @@ fn test_recip() {
|
|||
// Many math functions allow for less accurate results, so the next tolerance up is used
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_powi() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -499,7 +537,9 @@ fn test_powi() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_powf() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -516,7 +556,9 @@ fn test_powf() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_sqrt_domain() {
|
||||
assert!(f128::NAN.sqrt().is_nan());
|
||||
assert!(f128::NEG_INFINITY.sqrt().is_nan());
|
||||
|
|
@ -528,7 +570,9 @@ fn test_sqrt_domain() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_exp() {
|
||||
assert_eq!(1.0, 0.0f128.exp());
|
||||
assert_approx_eq!(consts::E, 1.0f128.exp(), TOL);
|
||||
|
|
@ -543,7 +587,9 @@ fn test_exp() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_exp2() {
|
||||
assert_eq!(32.0, 5.0f128.exp2());
|
||||
assert_eq!(1.0, 0.0f128.exp2());
|
||||
|
|
@ -557,7 +603,9 @@ fn test_exp2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_ln() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -573,7 +621,9 @@ fn test_ln() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_log() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -592,7 +642,9 @@ fn test_log() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_log2() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -609,7 +661,9 @@ fn test_log2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_log10() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
|
|
@ -659,7 +713,9 @@ fn test_to_radians() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_asinh() {
|
||||
// Lower accuracy results are allowed, use increased tolerances
|
||||
assert_eq!(0.0f128.asinh(), 0.0f128);
|
||||
|
|
@ -690,7 +746,9 @@ fn test_asinh() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f128.acosh(), 0.0f128);
|
||||
assert!(0.999f128.acosh().is_nan());
|
||||
|
|
@ -709,7 +767,9 @@ fn test_acosh() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f128.atanh(), 0.0f128);
|
||||
assert_eq!((-0.0f128).atanh(), -0.0f128);
|
||||
|
|
@ -729,7 +789,9 @@ fn test_atanh() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_gamma() {
|
||||
// precision can differ among platforms
|
||||
assert_approx_eq!(1.0f128.gamma(), 1.0f128, TOL_IMPR);
|
||||
|
|
@ -750,7 +812,9 @@ fn test_gamma() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_ln_gamma() {
|
||||
assert_approx_eq!(1.0f128.ln_gamma().0, 0.0f128, TOL_IMPR);
|
||||
assert_eq!(1.0f128.ln_gamma().1, 1);
|
||||
|
|
@ -781,7 +845,9 @@ fn test_real_consts() {
|
|||
assert_approx_eq!(frac_1_pi, 1f128 / pi, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_2_pi, 2f128 / pi, TOL_PRECISE);
|
||||
|
||||
#[cfg(reliable_f128_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
{
|
||||
let frac_2_sqrtpi: f128 = consts::FRAC_2_SQRT_PI;
|
||||
let sqrt2: f128 = consts::SQRT_2;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
|
||||
#![cfg(reliable_f16)]
|
||||
#![cfg(not(bootstrap))]
|
||||
#![cfg(target_has_reliable_f16)]
|
||||
|
||||
use std::f16::consts;
|
||||
use std::num::FpCategory as Fp;
|
||||
|
|
@ -57,29 +58,40 @@ fn test_num_f16() {
|
|||
crate::test_num(10f16, 2f16);
|
||||
}
|
||||
|
||||
// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
|
||||
// the intrinsics.
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_min_nan() {
|
||||
assert_eq!(f16::NAN.min(2.0), 2.0);
|
||||
assert_eq!(2.0f16.min(f16::NAN), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_max_nan() {
|
||||
assert_eq!(f16::NAN.max(2.0), 2.0);
|
||||
assert_eq!(2.0f16.max(f16::NAN), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_minimum() {
|
||||
assert!(f16::NAN.minimum(2.0).is_nan());
|
||||
assert!(2.0f16.minimum(f16::NAN).is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_maximum() {
|
||||
assert!(f16::NAN.maximum(2.0).is_nan());
|
||||
assert!(2.0f16.maximum(f16::NAN).is_nan());
|
||||
|
|
@ -236,7 +248,9 @@ fn test_classify() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_floor() {
|
||||
assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
|
||||
assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
|
||||
|
|
@ -251,7 +265,9 @@ fn test_floor() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_ceil() {
|
||||
assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
|
||||
assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
|
||||
|
|
@ -266,7 +282,9 @@ fn test_ceil() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_round() {
|
||||
assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
|
||||
assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
|
||||
|
|
@ -282,7 +300,9 @@ fn test_round() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_round_ties_even() {
|
||||
assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
|
||||
assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
|
||||
|
|
@ -298,7 +318,9 @@ fn test_round_ties_even() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_trunc() {
|
||||
assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
|
||||
assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
|
||||
|
|
@ -313,7 +335,9 @@ fn test_trunc() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_fract() {
|
||||
assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
|
||||
assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
|
||||
|
|
@ -328,7 +352,9 @@ fn test_fract() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_abs() {
|
||||
assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
|
||||
assert_eq!(1f16.abs(), 1f16);
|
||||
|
|
@ -428,7 +454,9 @@ fn test_next_down() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_mul_add() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -445,7 +473,9 @@ fn test_mul_add() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_recip() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -461,7 +491,9 @@ fn test_recip() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_powi() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -476,7 +508,9 @@ fn test_powi() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_powf() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -493,7 +527,9 @@ fn test_powf() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_sqrt_domain() {
|
||||
assert!(f16::NAN.sqrt().is_nan());
|
||||
assert!(f16::NEG_INFINITY.sqrt().is_nan());
|
||||
|
|
@ -505,7 +541,9 @@ fn test_sqrt_domain() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_exp() {
|
||||
assert_eq!(1.0, 0.0f16.exp());
|
||||
assert_approx_eq!(2.718282, 1.0f16.exp(), TOL_0);
|
||||
|
|
@ -520,7 +558,9 @@ fn test_exp() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_exp2() {
|
||||
assert_eq!(32.0, 5.0f16.exp2());
|
||||
assert_eq!(1.0, 0.0f16.exp2());
|
||||
|
|
@ -534,7 +574,9 @@ fn test_exp2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_ln() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -550,7 +592,9 @@ fn test_ln() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_log() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -569,7 +613,9 @@ fn test_log() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_log2() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -586,7 +632,9 @@ fn test_log2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_log10() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
|
|
@ -634,7 +682,9 @@ fn test_to_radians() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f16.asinh(), 0.0f16);
|
||||
assert_eq!((-0.0f16).asinh(), -0.0f16);
|
||||
|
|
@ -659,7 +709,9 @@ fn test_asinh() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f16.acosh(), 0.0f16);
|
||||
assert!(0.999f16.acosh().is_nan());
|
||||
|
|
@ -678,7 +730,9 @@ fn test_acosh() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f16.atanh(), 0.0f16);
|
||||
assert_eq!((-0.0f16).atanh(), -0.0f16);
|
||||
|
|
@ -698,7 +752,9 @@ fn test_atanh() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_gamma() {
|
||||
// precision can differ among platforms
|
||||
assert_approx_eq!(1.0f16.gamma(), 1.0f16, TOL_0);
|
||||
|
|
@ -719,7 +775,9 @@ fn test_gamma() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_ln_gamma() {
|
||||
assert_approx_eq!(1.0f16.ln_gamma().0, 0.0f16, TOL_0);
|
||||
assert_eq!(1.0f16.ln_gamma().1, 1);
|
||||
|
|
@ -752,7 +810,9 @@ fn test_real_consts() {
|
|||
assert_approx_eq!(frac_1_pi, 1f16 / pi, TOL_0);
|
||||
assert_approx_eq!(frac_2_pi, 2f16 / pi, TOL_0);
|
||||
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
{
|
||||
let frac_2_sqrtpi: f16 = consts::FRAC_2_SQRT_PI;
|
||||
let sqrt2: f16 = consts::SQRT_2;
|
||||
|
|
@ -813,7 +873,9 @@ fn test_clamp_max_is_nan() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(reliable_f16_math)]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_total_cmp() {
|
||||
use core::cmp::Ordering;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#![feature(f16, f128, float_algebraic, float_gamma, float_minimum_maximum)]
|
||||
#![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))]
|
||||
#![cfg_attr(not(bootstrap), expect(internal_features))] // for reliable_f16_f128
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Add, Div, Mul, Rem, Sub};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue