Format libstd with rustfmt

This commit applies rustfmt with rust-lang/rust's default settings to
files in src/libstd *that are not involved in any currently open PR* to
minimize merge conflicts. THe list of files involved in open PRs was
determined by querying GitHub's GraphQL API with this script:
https://gist.github.com/dtolnay/aa9c34993dc051a4f344d1b10e4487e8

With the list of files from the script in outstanding_files, the
relevant commands were:

    $ find src/libstd -name '*.rs' \
        | xargs rustfmt --edition=2018 --unstable-features --skip-children
    $ rg libstd outstanding_files | xargs git checkout --

Repeating this process several months apart should get us coverage of
most of the rest of libstd.

To confirm no funny business:

    $ git checkout $THIS_COMMIT^
    $ git show --pretty= --name-only $THIS_COMMIT \
        | xargs rustfmt --edition=2018 --unstable-features --skip-children
    $ git diff $THIS_COMMIT  # there should be no difference
This commit is contained in:
David Tolnay 2019-11-27 10:29:00 -08:00
parent 9081929d45
commit 4436c9d354
No known key found for this signature in database
GPG key ID: F9BA143B95FF6D82
50 changed files with 2906 additions and 2669 deletions

View file

@ -17,7 +17,7 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::ascii::{EscapeDefault, escape_default}; pub use core::ascii::{escape_default, EscapeDefault};
/// Extension methods for ASCII-subset only operations. /// Extension methods for ASCII-subset only operations.
/// ///

View file

@ -95,10 +95,10 @@ use crate::env;
use crate::fmt; use crate::fmt;
use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use crate::sync::Mutex; use crate::sync::Mutex;
use crate::sys_common::backtrace::{output_filename, lock}; use crate::sys_common::backtrace::{lock, output_filename};
use crate::vec::Vec; use crate::vec::Vec;
use backtrace_rs as backtrace;
use backtrace::BytesOrWideString; use backtrace::BytesOrWideString;
use backtrace_rs as backtrace;
/// A captured OS thread stack backtrace. /// A captured OS thread stack backtrace.
/// ///

View file

@ -1,7 +1,7 @@
#![cfg(test)] #![cfg(test)]
use test::Bencher;
use std::collections::HashMap; use std::collections::HashMap;
use test::Bencher;
#[bench] #[bench]
fn new_drop(b: &mut Bencher) { fn new_drop(b: &mut Bencher) {

View file

@ -413,20 +413,20 @@
#[doc(hidden)] #[doc(hidden)]
pub use crate::ops::Bound; pub use crate::ops::Bound;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{BinaryHeap, BTreeMap, BTreeSet};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{LinkedList, VecDeque};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{binary_heap, btree_map, btree_set}; pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{linked_list, vec_deque}; pub use alloc_crate::collections::{linked_list, vec_deque};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{BTreeMap, BTreeSet, BinaryHeap};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{LinkedList, VecDeque};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::hash_map::HashMap; pub use self::hash_map::HashMap;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::hash_set::HashSet; pub use self::hash_set::HashSet;
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
pub use alloc_crate::collections::TryReserveError; pub use alloc_crate::collections::TryReserveError;
mod hash; mod hash;

View file

@ -78,7 +78,9 @@ pub fn set_current_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
/// ///
/// [`std::env::vars`]: fn.vars.html /// [`std::env::vars`]: fn.vars.html
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub struct Vars { inner: VarsOs } pub struct Vars {
inner: VarsOs,
}
/// An iterator over a snapshot of the environment variables of this process. /// An iterator over a snapshot of the environment variables of this process.
/// ///
@ -87,7 +89,9 @@ pub struct Vars { inner: VarsOs }
/// ///
/// [`std::env::vars_os`]: fn.vars_os.html /// [`std::env::vars_os`]: fn.vars_os.html
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub struct VarsOs { inner: os_imp::Env } pub struct VarsOs {
inner: os_imp::Env,
}
/// Returns an iterator of (variable, value) pairs of strings, for all the /// Returns an iterator of (variable, value) pairs of strings, for all the
/// environment variables of the current process. /// environment variables of the current process.
@ -147,11 +151,11 @@ pub fn vars_os() -> VarsOs {
impl Iterator for Vars { impl Iterator for Vars {
type Item = (String, String); type Item = (String, String);
fn next(&mut self) -> Option<(String, String)> { fn next(&mut self) -> Option<(String, String)> {
self.inner.next().map(|(a, b)| { self.inner.next().map(|(a, b)| (a.into_string().unwrap(), b.into_string().unwrap()))
(a.into_string().unwrap(), b.into_string().unwrap()) }
}) fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
} }
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
} }
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
@ -164,8 +168,12 @@ impl fmt::Debug for Vars {
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
impl Iterator for VarsOs { impl Iterator for VarsOs {
type Item = (OsString, OsString); type Item = (OsString, OsString);
fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() } fn next(&mut self) -> Option<(OsString, OsString)> {
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
} }
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
@ -239,9 +247,8 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
} }
fn _var_os(key: &OsStr) -> Option<OsString> { fn _var_os(key: &OsStr) -> Option<OsString> {
os_imp::getenv(key).unwrap_or_else(|e| { os_imp::getenv(key)
panic!("failed to get environment variable `{:?}`: {}", key, e) .unwrap_or_else(|e| panic!("failed to get environment variable `{:?}`: {}", key, e))
})
} }
/// The error type for operations interacting with environment variables. /// The error type for operations interacting with environment variables.
@ -321,8 +328,7 @@ pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(k: K, v: V) {
fn _set_var(k: &OsStr, v: &OsStr) { fn _set_var(k: &OsStr, v: &OsStr) {
os_imp::setenv(k, v).unwrap_or_else(|e| { os_imp::setenv(k, v).unwrap_or_else(|e| {
panic!("failed to set environment variable `{:?}` to `{:?}`: {}", panic!("failed to set environment variable `{:?}` to `{:?}`: {}", k, v, e)
k, v, e)
}) })
} }
@ -363,9 +369,8 @@ pub fn remove_var<K: AsRef<OsStr>>(k: K) {
} }
fn _remove_var(k: &OsStr) { fn _remove_var(k: &OsStr) {
os_imp::unsetenv(k).unwrap_or_else(|e| { os_imp::unsetenv(k)
panic!("failed to remove environment variable `{:?}`: {}", k, e) .unwrap_or_else(|e| panic!("failed to remove environment variable `{:?}`: {}", k, e))
})
} }
/// An iterator that splits an environment variable into paths according to /// An iterator that splits an environment variable into paths according to
@ -379,7 +384,9 @@ fn _remove_var(k: &OsStr) {
/// [`PathBuf`]: ../../std/path/struct.PathBuf.html /// [`PathBuf`]: ../../std/path/struct.PathBuf.html
/// [`std::env::split_paths`]: fn.split_paths.html /// [`std::env::split_paths`]: fn.split_paths.html
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } pub struct SplitPaths<'a> {
inner: os_imp::SplitPaths<'a>,
}
/// Parses input according to platform conventions for the `PATH` /// Parses input according to platform conventions for the `PATH`
/// environment variable. /// environment variable.
@ -412,8 +419,12 @@ pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
impl<'a> Iterator for SplitPaths<'a> { impl<'a> Iterator for SplitPaths<'a> {
type Item = PathBuf; type Item = PathBuf;
fn next(&mut self) -> Option<PathBuf> { self.inner.next() } fn next(&mut self) -> Option<PathBuf> {
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
} }
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
@ -430,7 +441,7 @@ impl fmt::Debug for SplitPaths<'_> {
#[derive(Debug)] #[derive(Debug)]
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub struct JoinPathsError { pub struct JoinPathsError {
inner: os_imp::JoinPathsError inner: os_imp::JoinPathsError,
} }
/// Joins a collection of [`Path`]s appropriately for the `PATH` /// Joins a collection of [`Path`]s appropriately for the `PATH`
@ -499,11 +510,11 @@ pub struct JoinPathsError {
/// [`env::split_paths`]: fn.split_paths.html /// [`env::split_paths`]: fn.split_paths.html
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError> pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
where I: IntoIterator<Item=T>, T: AsRef<OsStr> where
I: IntoIterator<Item = T>,
T: AsRef<OsStr>,
{ {
os_imp::join_paths(paths.into_iter()).map_err(|e| { os_imp::join_paths(paths.into_iter()).map_err(|e| JoinPathsError { inner: e })
JoinPathsError { inner: e }
})
} }
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
@ -515,7 +526,9 @@ impl fmt::Display for JoinPathsError {
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
impl Error for JoinPathsError { impl Error for JoinPathsError {
fn description(&self) -> &str { self.inner.description() } fn description(&self) -> &str {
self.inner.description()
}
} }
/// Returns the path of the current user's home directory if known. /// Returns the path of the current user's home directory if known.
@ -549,9 +562,11 @@ impl Error for JoinPathsError {
/// None => println!("Impossible to get your home dir!"), /// None => println!("Impossible to get your home dir!"),
/// } /// }
/// ``` /// ```
#[rustc_deprecated(since = "1.29.0", #[rustc_deprecated(
since = "1.29.0",
reason = "This function's behavior is unexpected and probably not what you want. \ reason = "This function's behavior is unexpected and probably not what you want. \
Consider using the home_dir function from https://crates.io/crates/dirs instead.")] Consider using the home_dir function from https://crates.io/crates/dirs instead."
)]
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub fn home_dir() -> Option<PathBuf> { pub fn home_dir() -> Option<PathBuf> {
os_imp::home_dir() os_imp::home_dir()
@ -674,7 +689,9 @@ pub fn current_exe() -> io::Result<PathBuf> {
/// [`String`]: ../string/struct.String.html /// [`String`]: ../string/struct.String.html
/// [`std::env::args`]: ./fn.args.html /// [`std::env::args`]: ./fn.args.html
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub struct Args { inner: ArgsOs } pub struct Args {
inner: ArgsOs,
}
/// An iterator over the arguments of a process, yielding an [`OsString`] value /// An iterator over the arguments of a process, yielding an [`OsString`] value
/// for each argument. /// for each argument.
@ -689,7 +706,9 @@ pub struct Args { inner: ArgsOs }
/// [`OsString`]: ../ffi/struct.OsString.html /// [`OsString`]: ../ffi/struct.OsString.html
/// [`std::env::args_os`]: ./fn.args_os.html /// [`std::env::args_os`]: ./fn.args_os.html
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub struct ArgsOs { inner: sys::args::Args } pub struct ArgsOs {
inner: sys::args::Args,
}
/// Returns the arguments which this program was started with (normally passed /// Returns the arguments which this program was started with (normally passed
/// via the command line). /// via the command line).
@ -769,13 +788,19 @@ impl Iterator for Args {
fn next(&mut self) -> Option<String> { fn next(&mut self) -> Option<String> {
self.inner.next().map(|s| s.into_string().unwrap()) self.inner.next().map(|s| s.into_string().unwrap())
} }
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
} }
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
impl ExactSizeIterator for Args { impl ExactSizeIterator for Args {
fn len(&self) -> usize { self.inner.len() } fn len(&self) -> usize {
fn is_empty(&self) -> bool { self.inner.is_empty() } self.inner.len()
}
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
} }
#[stable(feature = "env_iterators", since = "1.12.0")] #[stable(feature = "env_iterators", since = "1.12.0")]
@ -788,9 +813,7 @@ impl DoubleEndedIterator for Args {
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Args { impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Args") f.debug_struct("Args").field("inner", &self.inner.inner.inner_debug()).finish()
.field("inner", &self.inner.inner.inner_debug())
.finish()
} }
} }
@ -803,27 +826,35 @@ impl !Sync for ArgsOs {}
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
impl Iterator for ArgsOs { impl Iterator for ArgsOs {
type Item = OsString; type Item = OsString;
fn next(&mut self) -> Option<OsString> { self.inner.next() } fn next(&mut self) -> Option<OsString> {
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
} }
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
impl ExactSizeIterator for ArgsOs { impl ExactSizeIterator for ArgsOs {
fn len(&self) -> usize { self.inner.len() } fn len(&self) -> usize {
fn is_empty(&self) -> bool { self.inner.is_empty() } self.inner.len()
}
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
} }
#[stable(feature = "env_iterators", since = "1.12.0")] #[stable(feature = "env_iterators", since = "1.12.0")]
impl DoubleEndedIterator for ArgsOs { impl DoubleEndedIterator for ArgsOs {
fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() } fn next_back(&mut self) -> Option<OsString> {
self.inner.next_back()
}
} }
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ArgsOs { impl fmt::Debug for ArgsOs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ArgsOs") f.debug_struct("ArgsOs").field("inner", &self.inner.inner_debug()).finish()
.field("inner", &self.inner.inner_debug())
.finish()
} }
} }
@ -1033,8 +1064,8 @@ mod tests {
use crate::path::PathBuf; use crate::path::PathBuf;
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() == split_paths(unparsed).collect::<Vec<_>>()
parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>() == parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
} }
assert!(check_parse("", &mut [""])); assert!(check_parse("", &mut [""]));
@ -1042,11 +1073,12 @@ mod tests {
assert!(check_parse(";;", &mut ["", "", ""])); assert!(check_parse(";;", &mut ["", "", ""]));
assert!(check_parse(r"c:\", &mut [r"c:\"])); assert!(check_parse(r"c:\", &mut [r"c:\"]));
assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
assert!(check_parse(r"c:\;c:\Program Files\", assert!(check_parse(r"c:\;c:\Program Files\", &mut [r"c:\", r"c:\Program Files\"]));
&mut [r"c:\", r"c:\Program Files\"]));
assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, assert!(check_parse(
&mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); r#"c:\;c:\"foo;bar"\;c:\baz"#,
&mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]
));
} }
#[test] #[test]
@ -1055,8 +1087,8 @@ mod tests {
use crate::path::PathBuf; use crate::path::PathBuf;
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
split_paths(unparsed).collect::<Vec<_>>() == split_paths(unparsed).collect::<Vec<_>>()
parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>() == parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
} }
assert!(check_parse("", &mut [""])); assert!(check_parse("", &mut [""]));
@ -1072,15 +1104,12 @@ mod tests {
use crate::ffi::OsStr; use crate::ffi::OsStr;
fn test_eq(input: &[&str], output: &str) -> bool { fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() == &*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output)
OsStr::new(output)
} }
assert!(test_eq(&[], "")); assert!(test_eq(&[], ""));
assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], "/bin:/usr/bin:/usr/local/bin"));
"/bin:/usr/bin:/usr/local/bin")); assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], ":/bin:::/usr/bin:"));
assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
":/bin:::/usr/bin:"));
assert!(join_paths(["/te:st"].iter().cloned()).is_err()); assert!(join_paths(["/te:st"].iter().cloned()).is_err());
} }
@ -1090,17 +1119,13 @@ mod tests {
use crate::ffi::OsStr; use crate::ffi::OsStr;
fn test_eq(input: &[&str], output: &str) -> bool { fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() == &*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output)
OsStr::new(output)
} }
assert!(test_eq(&[], "")); assert!(test_eq(&[], ""));
assert!(test_eq(&[r"c:\windows", r"c:\"], assert!(test_eq(&[r"c:\windows", r"c:\"], r"c:\windows;c:\"));
r"c:\windows;c:\")); assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], r";c:\windows;;;c:\;"));
assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], assert!(test_eq(&[r"c:\te;st", r"c:\"], r#""c:\te;st";c:\"#));
r";c:\windows;;;c:\;"));
assert!(test_eq(&[r"c:\te;st", r"c:\"],
r#""c:\te;st";c:\"#));
assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err()); assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());
} }
@ -1108,9 +1133,11 @@ mod tests {
fn args_debug() { fn args_debug() {
assert_eq!( assert_eq!(
format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()), format!("Args {{ inner: {:?} }}", args().collect::<Vec<_>>()),
format!("{:?}", args())); format!("{:?}", args())
);
assert_eq!( assert_eq!(
format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()), format!("ArgsOs {{ inner: {:?} }}", args_os().collect::<Vec<_>>()),
format!("{:?}", args_os())); format!("{:?}", args_os())
);
} }
} }

View file

@ -13,16 +13,16 @@ use crate::intrinsics;
#[cfg(not(test))] #[cfg(not(test))]
use crate::sys::cmath; use crate::sys::cmath;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MIN, MIN_POSITIVE, MAX};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::consts; pub use core::f32::consts;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{DIGITS, EPSILON, MANTISSA_DIGITS, RADIX};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{INFINITY, MAX_10_EXP, NAN, NEG_INFINITY};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MAX, MIN, MIN_POSITIVE};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MAX_EXP, MIN_10_EXP, MIN_EXP};
#[cfg(not(test))] #[cfg(not(test))]
#[lang = "f32_runtime"] #[lang = "f32_runtime"]
@ -142,7 +142,9 @@ impl f32 {
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn fract(self) -> f32 { self - self.trunc() } pub fn fract(self) -> f32 {
self - self.trunc()
}
/// Computes the absolute value of `self`. Returns `NAN` if the /// Computes the absolute value of `self`. Returns `NAN` if the
/// number is `NAN`. /// number is `NAN`.
@ -192,11 +194,7 @@ impl f32 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn signum(self) -> f32 { pub fn signum(self) -> f32 {
if self.is_nan() { if self.is_nan() { NAN } else { 1.0_f32.copysign(self) }
NAN
} else {
1.0_f32.copysign(self)
}
} }
/// Returns a number composed of the magnitude of `self` and the sign of /// Returns a number composed of the magnitude of `self` and the sign of
@ -277,7 +275,7 @@ impl f32 {
pub fn div_euclid(self, rhs: f32) -> f32 { pub fn div_euclid(self, rhs: f32) -> f32 {
let q = (self / rhs).trunc(); let q = (self / rhs).trunc();
if self % rhs < 0.0 { if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
} }
q q
} }
@ -310,13 +308,8 @@ impl f32 {
#[stable(feature = "euclidean_division", since = "1.38.0")] #[stable(feature = "euclidean_division", since = "1.38.0")]
pub fn rem_euclid(self, rhs: f32) -> f32 { pub fn rem_euclid(self, rhs: f32) -> f32 {
let r = self % rhs; let r = self % rhs;
if r < 0.0 { if r < 0.0 { r + rhs.abs() } else { r }
r + rhs.abs()
} else {
r
} }
}
/// Raises a number to an integer power. /// Raises a number to an integer power.
/// ///
@ -383,11 +376,7 @@ impl f32 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sqrt(self) -> f32 { pub fn sqrt(self) -> f32 {
if self < 0.0 { if self < 0.0 { NAN } else { unsafe { intrinsics::sqrtf32(self) } }
NAN
} else {
unsafe { intrinsics::sqrtf32(self) }
}
} }
/// Returns `e^(self)`, (the exponential function). /// Returns `e^(self)`, (the exponential function).
@ -486,7 +475,9 @@ impl f32 {
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log(self, base: f32) -> f32 { self.ln() / base.ln() } pub fn log(self, base: f32) -> f32 {
self.ln() / base.ln()
}
/// Returns the base 2 logarithm of the number. /// Returns the base 2 logarithm of the number.
/// ///
@ -559,14 +550,16 @@ impl f32 {
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
#[rustc_deprecated(since = "1.10.0", #[rustc_deprecated(
since = "1.10.0",
reason = "you probably meant `(self - other).abs()`: \ reason = "you probably meant `(self - other).abs()`: \
this operation is `(self - other).max(0.0)` \ this operation is `(self - other).max(0.0)` \
except that `abs_sub` also propagates NaNs (also \ except that `abs_sub` also propagates NaNs (also \
known as `fdimf` in C). If you truly need the positive \ known as `fdimf` in C). If you truly need the positive \
difference, consider using that expression or the C function \ difference, consider using that expression or the C function \
`fdimf`, depending on how you wish to handle NaN (please consider \ `fdimf`, depending on how you wish to handle NaN (please consider \
filing an issue describing your use-case too).")] filing an issue describing your use-case too)."
)]
pub fn abs_sub(self, other: f32) -> f32 { pub fn abs_sub(self, other: f32) -> f32 {
unsafe { cmath::fdimf(self, other) } unsafe { cmath::fdimf(self, other) }
} }
@ -967,11 +960,7 @@ impl f32 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn acosh(self) -> f32 { pub fn acosh(self) -> f32 {
if self < 1.0 { if self < 1.0 { crate::f32::NAN } else { (self + ((self * self) - 1.0).sqrt()).ln() }
crate::f32::NAN
} else {
(self + ((self * self) - 1.0).sqrt()).ln()
}
} }
/// Inverse hyperbolic tangent function. /// Inverse hyperbolic tangent function.
@ -1022,19 +1011,22 @@ impl f32 {
pub fn clamp(self, min: f32, max: f32) -> f32 { pub fn clamp(self, min: f32, max: f32) -> f32 {
assert!(min <= max); assert!(min <= max);
let mut x = self; let mut x = self;
if x < min { x = min; } if x < min {
if x > max { x = max; } x = min;
}
if x > max {
x = max;
}
x x
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::f32; use crate::f32;
use crate::f32::*; use crate::f32::*;
use crate::num::*;
use crate::num::FpCategory as Fp; use crate::num::FpCategory as Fp;
use crate::num::*;
#[test] #[test]
fn test_num_f32() { fn test_num_f32() {
@ -1279,7 +1271,7 @@ mod tests {
assert_eq!((-0f32).abs(), 0f32); assert_eq!((-0f32).abs(), 0f32);
assert_eq!((-1f32).abs(), 1f32); assert_eq!((-1f32).abs(), 1f32);
assert_eq!(NEG_INFINITY.abs(), INFINITY); assert_eq!(NEG_INFINITY.abs(), INFINITY);
assert_eq!((1f32/NEG_INFINITY).abs(), 0f32); assert_eq!((1f32 / NEG_INFINITY).abs(), 0f32);
assert!(NAN.abs().is_nan()); assert!(NAN.abs().is_nan());
} }
@ -1291,7 +1283,7 @@ mod tests {
assert_eq!((-0f32).signum(), -1f32); assert_eq!((-0f32).signum(), -1f32);
assert_eq!((-1f32).signum(), -1f32); assert_eq!((-1f32).signum(), -1f32);
assert_eq!(NEG_INFINITY.signum(), -1f32); assert_eq!(NEG_INFINITY.signum(), -1f32);
assert_eq!((1f32/NEG_INFINITY).signum(), -1f32); assert_eq!((1f32 / NEG_INFINITY).signum(), -1f32);
assert!(NAN.signum().is_nan()); assert!(NAN.signum().is_nan());
} }
@ -1303,7 +1295,7 @@ mod tests {
assert!(!(-0f32).is_sign_positive()); assert!(!(-0f32).is_sign_positive());
assert!(!(-1f32).is_sign_positive()); assert!(!(-1f32).is_sign_positive());
assert!(!NEG_INFINITY.is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive());
assert!(!(1f32/NEG_INFINITY).is_sign_positive()); assert!(!(1f32 / NEG_INFINITY).is_sign_positive());
assert!(NAN.is_sign_positive()); assert!(NAN.is_sign_positive());
assert!(!(-NAN).is_sign_positive()); assert!(!(-NAN).is_sign_positive());
} }
@ -1316,7 +1308,7 @@ mod tests {
assert!((-0f32).is_sign_negative()); assert!((-0f32).is_sign_negative());
assert!((-1f32).is_sign_negative()); assert!((-1f32).is_sign_negative());
assert!(NEG_INFINITY.is_sign_negative()); assert!(NEG_INFINITY.is_sign_negative());
assert!((1f32/NEG_INFINITY).is_sign_negative()); assert!((1f32 / NEG_INFINITY).is_sign_negative());
assert!(!NAN.is_sign_negative()); assert!(!NAN.is_sign_negative());
assert!((-NAN).is_sign_negative()); assert!((-NAN).is_sign_negative());
} }

View file

@ -13,16 +13,16 @@ use crate::intrinsics;
#[cfg(not(test))] #[cfg(not(test))]
use crate::sys::cmath; use crate::sys::cmath;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MIN, MIN_POSITIVE, MAX};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::consts; pub use core::f64::consts;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{DIGITS, EPSILON, MANTISSA_DIGITS, RADIX};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{INFINITY, MAX_10_EXP, NAN, NEG_INFINITY};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MAX, MIN, MIN_POSITIVE};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MAX_EXP, MIN_10_EXP, MIN_EXP};
#[cfg(not(test))] #[cfg(not(test))]
#[lang = "f64_runtime"] #[lang = "f64_runtime"]
@ -120,7 +120,9 @@ impl f64 {
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn fract(self) -> f64 { self - self.trunc() } pub fn fract(self) -> f64 {
self - self.trunc()
}
/// Computes the absolute value of `self`. Returns `NAN` if the /// Computes the absolute value of `self`. Returns `NAN` if the
/// number is `NAN`. /// number is `NAN`.
@ -170,11 +172,7 @@ impl f64 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn signum(self) -> f64 { pub fn signum(self) -> f64 {
if self.is_nan() { if self.is_nan() { NAN } else { 1.0_f64.copysign(self) }
NAN
} else {
1.0_f64.copysign(self)
}
} }
/// Returns a number composed of the magnitude of `self` and the sign of /// Returns a number composed of the magnitude of `self` and the sign of
@ -286,11 +284,7 @@ impl f64 {
#[stable(feature = "euclidean_division", since = "1.38.0")] #[stable(feature = "euclidean_division", since = "1.38.0")]
pub fn rem_euclid(self, rhs: f64) -> f64 { pub fn rem_euclid(self, rhs: f64) -> f64 {
let r = self % rhs; let r = self % rhs;
if r < 0.0 { if r < 0.0 { r + rhs.abs() } else { r }
r + rhs.abs()
} else {
r
}
} }
/// Raises a number to an integer power. /// Raises a number to an integer power.
@ -348,11 +342,7 @@ impl f64 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sqrt(self) -> f64 { pub fn sqrt(self) -> f64 {
if self < 0.0 { if self < 0.0 { NAN } else { unsafe { intrinsics::sqrtf64(self) } }
NAN
} else {
unsafe { intrinsics::sqrtf64(self) }
}
} }
/// Returns `e^(self)`, (the exponential function). /// Returns `e^(self)`, (the exponential function).
@ -413,7 +403,7 @@ impl f64 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ln(self) -> f64 { pub fn ln(self) -> f64 {
self.log_wrapper(|n| { unsafe { intrinsics::logf64(n) } }) self.log_wrapper(|n| unsafe { intrinsics::logf64(n) })
} }
/// Returns the logarithm of the number with respect to an arbitrary base. /// Returns the logarithm of the number with respect to an arbitrary base.
@ -435,7 +425,9 @@ impl f64 {
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() } pub fn log(self, base: f64) -> f64 {
self.ln() / base.ln()
}
/// Returns the base 2 logarithm of the number. /// Returns the base 2 logarithm of the number.
/// ///
@ -477,7 +469,7 @@ impl f64 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log10(self) -> f64 { pub fn log10(self) -> f64 {
self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } }) self.log_wrapper(|n| unsafe { intrinsics::log10f64(n) })
} }
/// The positive difference of two numbers. /// The positive difference of two numbers.
@ -500,14 +492,16 @@ impl f64 {
#[must_use = "method returns a new number and does not mutate the original value"] #[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
#[rustc_deprecated(since = "1.10.0", #[rustc_deprecated(
since = "1.10.0",
reason = "you probably meant `(self - other).abs()`: \ reason = "you probably meant `(self - other).abs()`: \
this operation is `(self - other).max(0.0)` \ this operation is `(self - other).max(0.0)` \
except that `abs_sub` also propagates NaNs (also \ except that `abs_sub` also propagates NaNs (also \
known as `fdim` in C). If you truly need the positive \ known as `fdim` in C). If you truly need the positive \
difference, consider using that expression or the C function \ difference, consider using that expression or the C function \
`fdim`, depending on how you wish to handle NaN (please consider \ `fdim`, depending on how you wish to handle NaN (please consider \
filing an issue describing your use-case too).")] filing an issue describing your use-case too)."
)]
pub fn abs_sub(self, other: f64) -> f64 { pub fn abs_sub(self, other: f64) -> f64 {
unsafe { cmath::fdim(self, other) } unsafe { cmath::fdim(self, other) }
} }
@ -888,11 +882,7 @@ impl f64 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn acosh(self) -> f64 { pub fn acosh(self) -> f64 {
if self < 1.0 { if self < 1.0 { NAN } else { (self + ((self * self) - 1.0).sqrt()).ln() }
NAN
} else {
(self + ((self * self) - 1.0).sqrt()).ln()
}
} }
/// Inverse hyperbolic tangent function. /// Inverse hyperbolic tangent function.
@ -943,8 +933,12 @@ impl f64 {
pub fn clamp(self, min: f64, max: f64) -> f64 { pub fn clamp(self, min: f64, max: f64) -> f64 {
assert!(min <= max); assert!(min <= max);
let mut x = self; let mut x = self;
if x < min { x = min; } if x < min {
if x > max { x = max; } x = min;
}
if x > max {
x = max;
}
x x
} }
@ -978,8 +972,8 @@ impl f64 {
mod tests { mod tests {
use crate::f64; use crate::f64;
use crate::f64::*; use crate::f64::*;
use crate::num::*;
use crate::num::FpCategory as Fp; use crate::num::FpCategory as Fp;
use crate::num::*;
#[test] #[test]
fn test_num_f64() { fn test_num_f64() {

View file

@ -155,21 +155,23 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")] #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError}; pub use self::c_str::FromBytesWithNulError;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CStr, CString, IntoStringError, NulError};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr}; pub use self::os_str::{OsStr, OsString};
#[stable(feature = "core_c_void", since = "1.30.0")] #[stable(feature = "core_c_void", since = "1.30.0")]
pub use core::ffi::c_void; pub use core::ffi::c_void;
#[unstable(feature = "c_variadic", #[unstable(
feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \ reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms", all supported platforms",
issue = "44930")] issue = "44930"
)]
pub use core::ffi::{VaList, VaListImpl}; pub use core::ffi::{VaList, VaListImpl};
mod c_str; mod c_str;

View file

@ -9,12 +9,12 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use crate::fmt;
use crate::ffi::OsString; use crate::ffi::OsString;
use crate::io::{self, SeekFrom, Seek, Read, Initializer, Write, IoSlice, IoSliceMut}; use crate::fmt;
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
use crate::path::{Path, PathBuf}; use crate::path::{Path, PathBuf};
use crate::sys::fs as fs_imp; use crate::sys::fs as fs_imp;
use crate::sys_common::{AsInnerMut, FromInner, AsInner, IntoInner}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use crate::time::SystemTime; use crate::time::SystemTime;
/// A reference to an open file on the filesystem. /// A reference to an open file on the filesystem.
@ -585,9 +585,7 @@ impl File {
/// ``` /// ```
#[stable(feature = "file_try_clone", since = "1.9.0")] #[stable(feature = "file_try_clone", since = "1.9.0")]
pub fn try_clone(&self) -> io::Result<File> { pub fn try_clone(&self) -> io::Result<File> {
Ok(File { Ok(File { inner: self.inner.duplicate()? })
inner: self.inner.duplicate()?
})
} }
/// Changes the permissions on the underlying file. /// Changes the permissions on the underlying file.
@ -629,7 +627,9 @@ impl File {
} }
impl AsInner<fs_imp::File> for File { impl AsInner<fs_imp::File> for File {
fn as_inner(&self) -> &fs_imp::File { &self.inner } fn as_inner(&self) -> &fs_imp::File {
&self.inner
}
} }
impl FromInner<fs_imp::File> for File { impl FromInner<fs_imp::File> for File {
fn from_inner(f: fs_imp::File) -> File { fn from_inner(f: fs_imp::File) -> File {
@ -674,7 +674,9 @@ impl Write for File {
self.inner.write_vectored(bufs) self.inner.write_vectored(bufs)
} }
fn flush(&mut self) -> io::Result<()> { self.inner.flush() } fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Seek for File { impl Seek for File {
@ -707,7 +709,9 @@ impl Write for &File {
self.inner.write_vectored(bufs) self.inner.write_vectored(bufs)
} }
fn flush(&mut self) -> io::Result<()> { self.inner.flush() } fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Seek for &File { impl Seek for &File {
@ -748,7 +752,8 @@ impl OpenOptions {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn read(&mut self, read: bool) -> &mut OpenOptions { pub fn read(&mut self, read: bool) -> &mut OpenOptions {
self.0.read(read); self self.0.read(read);
self
} }
/// Sets the option for write access. /// Sets the option for write access.
@ -768,7 +773,8 @@ impl OpenOptions {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn write(&mut self, write: bool) -> &mut OpenOptions { pub fn write(&mut self, write: bool) -> &mut OpenOptions {
self.0.write(write); self self.0.write(write);
self
} }
/// Sets the option for the append mode. /// Sets the option for the append mode.
@ -814,7 +820,8 @@ impl OpenOptions {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn append(&mut self, append: bool) -> &mut OpenOptions { pub fn append(&mut self, append: bool) -> &mut OpenOptions {
self.0.append(append); self self.0.append(append);
self
} }
/// Sets the option for truncating a previous file. /// Sets the option for truncating a previous file.
@ -833,7 +840,8 @@ impl OpenOptions {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
self.0.truncate(truncate); self self.0.truncate(truncate);
self
} }
/// Sets the option for creating a new file. /// Sets the option for creating a new file.
@ -856,7 +864,8 @@ impl OpenOptions {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn create(&mut self, create: bool) -> &mut OpenOptions { pub fn create(&mut self, create: bool) -> &mut OpenOptions {
self.0.create(create); self self.0.create(create);
self
} }
/// Sets the option to always create a new file. /// Sets the option to always create a new file.
@ -889,7 +898,8 @@ impl OpenOptions {
/// ``` /// ```
#[stable(feature = "expand_open_options2", since = "1.9.0")] #[stable(feature = "expand_open_options2", since = "1.9.0")]
pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions { pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions {
self.0.create_new(create_new); self self.0.create_new(create_new);
self
} }
/// Opens a file at `path` with the options specified by `self`. /// Opens a file at `path` with the options specified by `self`.
@ -946,11 +956,15 @@ impl OpenOptions {
} }
impl AsInner<fs_imp::OpenOptions> for OpenOptions { impl AsInner<fs_imp::OpenOptions> for OpenOptions {
fn as_inner(&self) -> &fs_imp::OpenOptions { &self.0 } fn as_inner(&self) -> &fs_imp::OpenOptions {
&self.0
}
} }
impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions { impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions {
&mut self.0
}
} }
impl Metadata { impl Metadata {
@ -994,7 +1008,9 @@ impl Metadata {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn is_dir(&self) -> bool { self.file_type().is_dir() } pub fn is_dir(&self) -> bool {
self.file_type().is_dir()
}
/// Returns `true` if this metadata is for a regular file. The /// Returns `true` if this metadata is for a regular file. The
/// result is mutually exclusive to the result of /// result is mutually exclusive to the result of
@ -1017,7 +1033,9 @@ impl Metadata {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn is_file(&self) -> bool { self.file_type().is_file() } pub fn is_file(&self) -> bool {
self.file_type().is_file()
}
/// Returns the size of the file, in bytes, this metadata is for. /// Returns the size of the file, in bytes, this metadata is for.
/// ///
@ -1034,7 +1052,9 @@ impl Metadata {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> u64 { self.0.size() } pub fn len(&self) -> u64 {
self.0.size()
}
/// Returns the permissions of the file this metadata is for. /// Returns the permissions of the file this metadata is for.
/// ///
@ -1170,11 +1190,15 @@ impl fmt::Debug for Metadata {
} }
impl AsInner<fs_imp::FileAttr> for Metadata { impl AsInner<fs_imp::FileAttr> for Metadata {
fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 } fn as_inner(&self) -> &fs_imp::FileAttr {
&self.0
}
} }
impl FromInner<fs_imp::FileAttr> for Metadata { impl FromInner<fs_imp::FileAttr> for Metadata {
fn from_inner(attr: fs_imp::FileAttr) -> Metadata { Metadata(attr) } fn from_inner(attr: fs_imp::FileAttr) -> Metadata {
Metadata(attr)
}
} }
impl Permissions { impl Permissions {
@ -1194,7 +1218,9 @@ impl Permissions {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn readonly(&self) -> bool { self.0.readonly() } pub fn readonly(&self) -> bool {
self.0.readonly()
}
/// Modifies the readonly flag for this set of permissions. If the /// Modifies the readonly flag for this set of permissions. If the
/// `readonly` argument is `true`, using the resulting `Permission` will /// `readonly` argument is `true`, using the resulting `Permission` will
@ -1256,7 +1282,9 @@ impl FileType {
/// } /// }
/// ``` /// ```
#[stable(feature = "file_type", since = "1.1.0")] #[stable(feature = "file_type", since = "1.1.0")]
pub fn is_dir(&self) -> bool { self.0.is_dir() } pub fn is_dir(&self) -> bool {
self.0.is_dir()
}
/// Tests whether this file type represents a regular file. /// Tests whether this file type represents a regular file.
/// The result is mutually exclusive to the results of /// The result is mutually exclusive to the results of
@ -1280,7 +1308,9 @@ impl FileType {
/// } /// }
/// ``` /// ```
#[stable(feature = "file_type", since = "1.1.0")] #[stable(feature = "file_type", since = "1.1.0")]
pub fn is_file(&self) -> bool { self.0.is_file() } pub fn is_file(&self) -> bool {
self.0.is_file()
}
/// Tests whether this file type represents a symbolic link. /// Tests whether this file type represents a symbolic link.
/// The result is mutually exclusive to the results of /// The result is mutually exclusive to the results of
@ -1314,11 +1344,15 @@ impl FileType {
/// } /// }
/// ``` /// ```
#[stable(feature = "file_type", since = "1.1.0")] #[stable(feature = "file_type", since = "1.1.0")]
pub fn is_symlink(&self) -> bool { self.0.is_symlink() } pub fn is_symlink(&self) -> bool {
self.0.is_symlink()
}
} }
impl AsInner<fs_imp::FileType> for FileType { impl AsInner<fs_imp::FileType> for FileType {
fn as_inner(&self) -> &fs_imp::FileType { &self.0 } fn as_inner(&self) -> &fs_imp::FileType {
&self.0
}
} }
impl FromInner<fs_imp::FilePermissions> for Permissions { impl FromInner<fs_imp::FilePermissions> for Permissions {
@ -1328,7 +1362,9 @@ impl FromInner<fs_imp::FilePermissions> for Permissions {
} }
impl AsInner<fs_imp::FilePermissions> for Permissions { impl AsInner<fs_imp::FilePermissions> for Permissions {
fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 } fn as_inner(&self) -> &fs_imp::FilePermissions {
&self.0
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -1370,7 +1406,9 @@ impl DirEntry {
/// ///
/// The exact text, of course, depends on what files you have in `.`. /// The exact text, of course, depends on what files you have in `.`.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn path(&self) -> PathBuf { self.0.path() } pub fn path(&self) -> PathBuf {
self.0.path()
}
/// Returns the metadata for the file that this entry points at. /// Returns the metadata for the file that this entry points at.
/// ///
@ -1468,14 +1506,14 @@ impl DirEntry {
#[stable(feature = "dir_entry_debug", since = "1.13.0")] #[stable(feature = "dir_entry_debug", since = "1.13.0")]
impl fmt::Debug for DirEntry { impl fmt::Debug for DirEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DirEntry") f.debug_tuple("DirEntry").field(&self.path()).finish()
.field(&self.path())
.finish()
} }
} }
impl AsInner<fs_imp::DirEntry> for DirEntry { impl AsInner<fs_imp::DirEntry> for DirEntry {
fn as_inner(&self) -> &fs_imp::DirEntry { &self.0 } fn as_inner(&self) -> &fs_imp::DirEntry {
&self.0
}
} }
/// Removes a file from the filesystem. /// Removes a file from the filesystem.
@ -1744,9 +1782,11 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.1.0", #[rustc_deprecated(
since = "1.1.0",
reason = "replaced with std::os::unix::fs::symlink and \ reason = "replaced with std::os::unix::fs::symlink and \
std::os::windows::fs::{symlink_file, symlink_dir}")] std::os::windows::fs::{symlink_file, symlink_dir}"
)]
pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> { pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
fs_imp::symlink(src.as_ref(), dst.as_ref()) fs_imp::symlink(src.as_ref(), dst.as_ref())
} }
@ -2089,8 +2129,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
/// } /// }
/// ``` /// ```
#[stable(feature = "set_permissions", since = "1.1.0")] #[stable(feature = "set_permissions", since = "1.1.0")]
pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
-> io::Result<()> {
fs_imp::set_perm(path.as_ref(), perm.0) fs_imp::set_perm(path.as_ref(), perm.0)
} }
@ -2107,10 +2146,7 @@ impl DirBuilder {
/// ``` /// ```
#[stable(feature = "dir_builder", since = "1.6.0")] #[stable(feature = "dir_builder", since = "1.6.0")]
pub fn new() -> DirBuilder { pub fn new() -> DirBuilder {
DirBuilder { DirBuilder { inner: fs_imp::DirBuilder::new(), recursive: false }
inner: fs_imp::DirBuilder::new(),
recursive: false,
}
} }
/// Indicates that directories should be created recursively, creating all /// Indicates that directories should be created recursively, creating all
@ -2157,16 +2193,12 @@ impl DirBuilder {
} }
fn _create(&self, path: &Path) -> io::Result<()> { fn _create(&self, path: &Path) -> io::Result<()> {
if self.recursive { if self.recursive { self.create_dir_all(path) } else { self.inner.mkdir(path) }
self.create_dir_all(path)
} else {
self.inner.mkdir(path)
}
} }
fn create_dir_all(&self, path: &Path) -> io::Result<()> { fn create_dir_all(&self, path: &Path) -> io::Result<()> {
if path == Path::new("") { if path == Path::new("") {
return Ok(()) return Ok(());
} }
match self.inner.mkdir(path) { match self.inner.mkdir(path) {
@ -2177,7 +2209,9 @@ impl DirBuilder {
} }
match path.parent() { match path.parent() {
Some(p) => self.create_dir_all(p)?, Some(p) => self.create_dir_all(p)?,
None => return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree")), None => {
return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree"));
}
} }
match self.inner.mkdir(path) { match self.inner.mkdir(path) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
@ -2201,48 +2235,62 @@ mod tests {
use crate::io::{ErrorKind, SeekFrom}; use crate::io::{ErrorKind, SeekFrom};
use crate::path::Path; use crate::path::Path;
use crate::str; use crate::str;
use crate::sys_common::io::test::{TempDir, tmpdir}; use crate::sys_common::io::test::{tmpdir, TempDir};
use crate::thread; use crate::thread;
use rand::{rngs::StdRng, RngCore, SeedableRng}; use rand::{rngs::StdRng, RngCore, SeedableRng};
#[cfg(windows)]
use crate::os::windows::fs::{symlink_dir, symlink_file};
#[cfg(windows)]
use crate::sys::fs::symlink_junction;
#[cfg(unix)] #[cfg(unix)]
use crate::os::unix::fs::symlink as symlink_dir; use crate::os::unix::fs::symlink as symlink_dir;
#[cfg(unix)] #[cfg(unix)]
use crate::os::unix::fs::symlink as symlink_file; use crate::os::unix::fs::symlink as symlink_file;
#[cfg(unix)] #[cfg(unix)]
use crate::os::unix::fs::symlink as symlink_junction; use crate::os::unix::fs::symlink as symlink_junction;
#[cfg(windows)]
use crate::os::windows::fs::{symlink_dir, symlink_file};
#[cfg(windows)]
use crate::sys::fs::symlink_junction;
macro_rules! check { ($e:expr) => ( macro_rules! check {
($e:expr) => {
match $e { match $e {
Ok(t) => t, Ok(t) => t,
Err(e) => panic!("{} failed with: {}", stringify!($e), e), Err(e) => panic!("{} failed with: {}", stringify!($e), e),
} }
) } };
}
#[cfg(windows)] #[cfg(windows)]
macro_rules! error { ($e:expr, $s:expr) => ( macro_rules! error {
($e:expr, $s:expr) => {
match $e { match $e {
Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
Err(ref err) => assert!(err.raw_os_error() == Some($s), Err(ref err) => assert!(
format!("`{}` did not have a code of `{}`", err, $s)) err.raw_os_error() == Some($s),
format!("`{}` did not have a code of `{}`", err, $s)
),
}
};
} }
) }
#[cfg(unix)] #[cfg(unix)]
macro_rules! error { ($e:expr, $s:expr) => ( error_contains!($e, $s) ) } macro_rules! error {
($e:expr, $s:expr) => {
error_contains!($e, $s)
};
}
macro_rules! error_contains { ($e:expr, $s:expr) => ( macro_rules! error_contains {
($e:expr, $s:expr) => {
match $e { match $e {
Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
Err(ref err) => assert!(err.to_string().contains($s), Err(ref err) => assert!(
format!("`{}` did not contain `{}`", err, $s)) err.to_string().contains($s),
format!("`{}` did not contain `{}`", err, $s)
),
}
};
} }
) }
// Several test fail on windows if the user does not have permission to // Several test fail on windows if the user does not have permission to
// create symlinks (the `SeCreateSymbolicLinkPrivilege`). Instead of // create symlinks (the `SeCreateSymbolicLinkPrivilege`). Instead of
@ -2251,7 +2299,9 @@ mod tests {
// tests most of the time, but at least we do if the user has the right // tests most of the time, but at least we do if the user has the right
// permissions. // permissions.
pub fn got_symlink_permission(tmpdir: &TempDir) -> bool { pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
if cfg!(unix) { return true } if cfg!(unix) {
return true;
}
let link = tmpdir.join("some_hopefully_unique_link_name"); let link = tmpdir.join("some_hopefully_unique_link_name");
match symlink_file(r"nonexisting_target", link) { match symlink_file(r"nonexisting_target", link) {
@ -2276,7 +2326,7 @@ mod tests {
let mut read_buf = [0; 1028]; let mut read_buf = [0; 1028];
let read_str = match check!(read_stream.read(&mut read_buf)) { let read_str = match check!(read_stream.read(&mut read_buf)) {
0 => panic!("shouldn't happen"), 0 => panic!("shouldn't happen"),
n => str::from_utf8(&read_buf[..n]).unwrap().to_string() n => str::from_utf8(&read_buf[..n]).unwrap().to_string(),
}; };
assert_eq!(read_str, message); assert_eq!(read_str, message);
} }
@ -2497,13 +2547,11 @@ mod tests {
check!(fs::create_dir(filename)); check!(fs::create_dir(filename));
let mask = 0o7777; let mask = 0o7777;
check!(fs::set_permissions(filename, check!(fs::set_permissions(filename, fs::Permissions::from_mode(0)));
fs::Permissions::from_mode(0)));
let metadata0 = check!(fs::metadata(filename)); let metadata0 = check!(fs::metadata(filename));
assert_eq!(mask & metadata0.permissions().mode(), 0); assert_eq!(mask & metadata0.permissions().mode(), 0);
check!(fs::set_permissions(filename, check!(fs::set_permissions(filename, fs::Permissions::from_mode(0o1777)));
fs::Permissions::from_mode(0o1777)));
let metadata1 = check!(fs::metadata(filename)); let metadata1 = check!(fs::metadata(filename));
assert_eq!(mask & metadata1.permissions().mode(), 0o1777); assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
} }
@ -2568,8 +2616,7 @@ mod tests {
let filename = &tmpdir.join("file_stat_correct_on_is_file.txt"); let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
{ {
let mut opts = OpenOptions::new(); let mut opts = OpenOptions::new();
let mut fs = check!(opts.read(true).write(true) let mut fs = check!(opts.read(true).write(true).create(true).open(filename));
.create(true).open(filename));
let msg = "hw"; let msg = "hw";
fs.write(msg.as_bytes()).unwrap(); fs.write(msg.as_bytes()).unwrap();
@ -2703,7 +2750,7 @@ mod tests {
for _ in 0..40 { for _ in 0..40 {
dir = dir.join("a"); dir = dir.join("a");
} }
let mut join = vec!(); let mut join = vec![];
for _ in 0..8 { for _ in 0..8 {
let dir = dir.clone(); let dir = dir.clone();
join.push(thread::spawn(move || { join.push(thread::spawn(move || {
@ -2771,7 +2818,9 @@ mod tests {
#[cfg(windows)] #[cfg(windows)]
fn recursive_rmdir_of_file_symlink() { fn recursive_rmdir_of_file_symlink() {
let tmpdir = tmpdir(); let tmpdir = tmpdir();
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
let f1 = tmpdir.join("f1"); let f1 = tmpdir.join("f1");
let f2 = tmpdir.join("f2"); let f2 = tmpdir.join("f2");
@ -2854,8 +2903,7 @@ mod tests {
check!(check!(File::open(&out)).read_to_end(&mut v)); check!(check!(File::open(&out)).read_to_end(&mut v));
assert_eq!(v, b"hello"); assert_eq!(v, b"hello");
assert_eq!(check!(input.metadata()).permissions(), assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions());
check!(out.metadata()).permissions());
} }
#[test] #[test]
@ -2865,7 +2913,8 @@ mod tests {
check!(File::create(&out)); check!(File::create(&out));
match fs::copy(&*out, tmpdir.path()) { match fs::copy(&*out, tmpdir.path()) {
Ok(..) => panic!(), Err(..) => {} Ok(..) => panic!(),
Err(..) => {}
} }
} }
@ -2890,7 +2939,8 @@ mod tests {
let out = tmpdir.join("out"); let out = tmpdir.join("out");
match fs::copy(tmpdir.path(), &out) { match fs::copy(tmpdir.path(), &out) {
Ok(..) => panic!(), Err(..) => {} Ok(..) => panic!(),
Err(..) => {}
} }
assert!(!out.exists()); assert!(!out.exists());
} }
@ -2938,7 +2988,9 @@ mod tests {
#[test] #[test]
fn copy_file_follows_dst_symlink() { fn copy_file_follows_dst_symlink() {
let tmp = tmpdir(); let tmp = tmpdir();
if !got_symlink_permission(&tmp) { return }; if !got_symlink_permission(&tmp) {
return;
};
let in_path = tmp.join("in.txt"); let in_path = tmp.join("in.txt");
let out_path = tmp.join("out.txt"); let out_path = tmp.join("out.txt");
@ -2958,7 +3010,9 @@ mod tests {
#[test] #[test]
fn symlinks_work() { fn symlinks_work() {
let tmpdir = tmpdir(); let tmpdir = tmpdir();
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
let input = tmpdir.join("in.txt"); let input = tmpdir.join("in.txt");
let out = tmpdir.join("out.txt"); let out = tmpdir.join("out.txt");
@ -2966,8 +3020,7 @@ mod tests {
check!(check!(File::create(&input)).write("foobar".as_bytes())); check!(check!(File::create(&input)).write("foobar".as_bytes()));
check!(symlink_file(&input, &out)); check!(symlink_file(&input, &out));
assert!(check!(out.symlink_metadata()).file_type().is_symlink()); assert!(check!(out.symlink_metadata()).file_type().is_symlink());
assert_eq!(check!(fs::metadata(&out)).len(), assert_eq!(check!(fs::metadata(&out)).len(), check!(fs::metadata(&input)).len());
check!(fs::metadata(&input)).len());
let mut v = Vec::new(); let mut v = Vec::new();
check!(check!(File::open(&out)).read_to_end(&mut v)); check!(check!(File::open(&out)).read_to_end(&mut v));
assert_eq!(v, b"foobar".to_vec()); assert_eq!(v, b"foobar".to_vec());
@ -2977,31 +3030,40 @@ mod tests {
fn symlink_noexist() { fn symlink_noexist() {
// Symlinks can point to things that don't exist // Symlinks can point to things that don't exist
let tmpdir = tmpdir(); let tmpdir = tmpdir();
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
// Use a relative path for testing. Symlinks get normalized by Windows, // Use a relative path for testing. Symlinks get normalized by Windows,
// so we may not get the same path back for absolute paths // so we may not get the same path back for absolute paths
check!(symlink_file(&"foo", &tmpdir.join("bar"))); check!(symlink_file(&"foo", &tmpdir.join("bar")));
assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))).to_str().unwrap(), assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))).to_str().unwrap(), "foo");
"foo");
} }
#[test] #[test]
fn read_link() { fn read_link() {
if cfg!(windows) { if cfg!(windows) {
// directory symlink // directory symlink
assert_eq!(check!(fs::read_link(r"C:\Users\All Users")).to_str().unwrap(), assert_eq!(
r"C:\ProgramData"); check!(fs::read_link(r"C:\Users\All Users")).to_str().unwrap(),
r"C:\ProgramData"
);
// junction // junction
assert_eq!(check!(fs::read_link(r"C:\Users\Default User")).to_str().unwrap(), assert_eq!(
r"C:\Users\Default"); check!(fs::read_link(r"C:\Users\Default User")).to_str().unwrap(),
r"C:\Users\Default"
);
// junction with special permissions // junction with special permissions
assert_eq!(check!(fs::read_link(r"C:\Documents and Settings\")).to_str().unwrap(), assert_eq!(
r"C:\Users"); check!(fs::read_link(r"C:\Documents and Settings\")).to_str().unwrap(),
r"C:\Users"
);
} }
let tmpdir = tmpdir(); let tmpdir = tmpdir();
let link = tmpdir.join("link"); let link = tmpdir.join("link");
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
check!(symlink_file(&"foo", &link)); check!(symlink_file(&"foo", &link));
assert_eq!(check!(fs::read_link(&link)).to_str().unwrap(), "foo"); assert_eq!(check!(fs::read_link(&link)).to_str().unwrap(), "foo");
} }
@ -3023,10 +3085,8 @@ mod tests {
check!(check!(File::create(&input)).write("foobar".as_bytes())); check!(check!(File::create(&input)).write("foobar".as_bytes()));
check!(fs::hard_link(&input, &out)); check!(fs::hard_link(&input, &out));
assert_eq!(check!(fs::metadata(&out)).len(), assert_eq!(check!(fs::metadata(&out)).len(), check!(fs::metadata(&input)).len());
check!(fs::metadata(&input)).len()); assert_eq!(check!(fs::metadata(&out)).len(), check!(input.metadata()).len());
assert_eq!(check!(fs::metadata(&out)).len(),
check!(input.metadata()).len());
let mut v = Vec::new(); let mut v = Vec::new();
check!(check!(File::open(&out)).read_to_end(&mut v)); check!(check!(File::open(&out)).read_to_end(&mut v));
assert_eq!(v, b"foobar".to_vec()); assert_eq!(v, b"foobar".to_vec());
@ -3134,15 +3194,22 @@ mod tests {
#[test] #[test]
fn open_flavors() { fn open_flavors() {
use crate::fs::OpenOptions as OO; use crate::fs::OpenOptions as OO;
fn c<T: Clone>(t: &T) -> T { t.clone() } fn c<T: Clone>(t: &T) -> T {
t.clone()
}
let tmpdir = tmpdir(); let tmpdir = tmpdir();
let mut r = OO::new(); r.read(true); let mut r = OO::new();
let mut w = OO::new(); w.write(true); r.read(true);
let mut rw = OO::new(); rw.read(true).write(true); let mut w = OO::new();
let mut a = OO::new(); a.append(true); w.write(true);
let mut ra = OO::new(); ra.read(true).append(true); let mut rw = OO::new();
rw.read(true).write(true);
let mut a = OO::new();
a.append(true);
let mut ra = OO::new();
ra.read(true).append(true);
#[cfg(windows)] #[cfg(windows)]
let invalid_options = 87; // ERROR_INVALID_PARAMETER let invalid_options = 87; // ERROR_INVALID_PARAMETER
@ -3279,8 +3346,10 @@ mod tests {
assert!(v == &bytes[..]); assert!(v == &bytes[..]);
check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF])); check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF]));
error_contains!(fs::read_to_string(&tmpdir.join("not-utf8")), error_contains!(
"stream did not contain valid UTF-8"); fs::read_to_string(&tmpdir.join("not-utf8")),
"stream did not contain valid UTF-8"
);
let s = "𐁁𐀓𐀠𐀴𐀍"; let s = "𐁁𐀓𐀠𐀴𐀍";
check!(fs::write(&tmpdir.join("utf8"), s.as_bytes())); check!(fs::write(&tmpdir.join("utf8"), s.as_bytes()));
@ -3292,11 +3361,9 @@ mod tests {
fn file_try_clone() { fn file_try_clone() {
let tmpdir = tmpdir(); let tmpdir = tmpdir();
let mut f1 = check!(OpenOptions::new() let mut f1 = check!(
.read(true) OpenOptions::new().read(true).write(true).create(true).open(&tmpdir.join("test"))
.write(true) );
.create(true)
.open(&tmpdir.join("test")));
let mut f2 = check!(f1.try_clone()); let mut f2 = check!(f1.try_clone());
check!(f1.write_all(b"hello world")); check!(f1.write_all(b"hello world"));
@ -3341,7 +3408,9 @@ mod tests {
#[test] #[test]
fn realpath_works() { fn realpath_works() {
let tmpdir = tmpdir(); let tmpdir = tmpdir();
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
let tmpdir = fs::canonicalize(tmpdir.path()).unwrap(); let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
let file = tmpdir.join("test"); let file = tmpdir.join("test");
@ -3366,7 +3435,9 @@ mod tests {
#[test] #[test]
fn realpath_works_tricky() { fn realpath_works_tricky() {
let tmpdir = tmpdir(); let tmpdir = tmpdir();
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
let tmpdir = fs::canonicalize(tmpdir.path()).unwrap(); let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
let a = tmpdir.join("a"); let a = tmpdir.join("a");
@ -3452,7 +3523,9 @@ mod tests {
assert!(junction.is_dir()); assert!(junction.is_dir());
assert!(b.exists()); assert!(b.exists());
if !got_symlink_permission(&tmpdir) { return }; if !got_symlink_permission(&tmpdir) {
return;
};
check!(symlink_dir(&target, &link)); check!(symlink_dir(&target, &link));
check!(fs::create_dir_all(&d)); check!(fs::create_dir_all(&d));
assert!(link.is_dir()); assert!(link.is_dir());
@ -3482,8 +3555,8 @@ mod tests {
// Not always available // Not always available
match (a.created(), b.created()) { match (a.created(), b.created()) {
(Ok(t1), Ok(t2)) => assert!(t1 <= t2), (Ok(t1), Ok(t2)) => assert!(t1 <= t2),
(Err(e1), Err(e2)) if e1.kind() == ErrorKind::Other && (Err(e1), Err(e2))
e2.kind() == ErrorKind::Other => {} if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other => {}
(a, b) => panic!( (a, b) => panic!(
"creation time must be always supported or not supported: {:?} {:?}", "creation time must be always supported or not supported: {:?} {:?}",
a, b, a, b,

View file

@ -5,8 +5,9 @@ use crate::io::prelude::*;
use crate::cmp; use crate::cmp;
use crate::error; use crate::error;
use crate::fmt; use crate::fmt;
use crate::io::{self, Initializer, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom, IoSlice, use crate::io::{
IoSliceMut}; self, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, SeekFrom, DEFAULT_BUF_SIZE,
};
use crate::memchr; use crate::memchr;
/// The `BufReader<R>` struct adds buffering to any reader. /// The `BufReader<R>` struct adds buffering to any reader.
@ -100,12 +101,7 @@ impl<R: Read> BufReader<R> {
let mut buffer = Vec::with_capacity(capacity); let mut buffer = Vec::with_capacity(capacity);
buffer.set_len(capacity); buffer.set_len(capacity);
inner.initializer().initialize(&mut buffer); inner.initializer().initialize(&mut buffer);
BufReader { BufReader { inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0 }
inner,
buf: buffer.into_boxed_slice(),
pos: 0,
cap: 0,
}
} }
} }
} }
@ -130,7 +126,9 @@ impl<R> BufReader<R> {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &R { &self.inner } pub fn get_ref(&self) -> &R {
&self.inner
}
/// Gets a mutable reference to the underlying reader. /// Gets a mutable reference to the underlying reader.
/// ///
@ -151,7 +149,9 @@ impl<R> BufReader<R> {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner } pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
/// Returns a reference to the internally buffered data. /// Returns a reference to the internally buffered data.
/// ///
@ -199,7 +199,9 @@ impl<R> BufReader<R> {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> R { self.inner } pub fn into_inner(self) -> R {
self.inner
}
/// Invalidates all data in the internal buffer. /// Invalidates all data in the internal buffer.
#[inline] #[inline]
@ -220,17 +222,17 @@ impl<R: Seek> BufReader<R> {
if offset < 0 { if offset < 0 {
if let Some(new_pos) = pos.checked_sub((-offset) as u64) { if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
self.pos = new_pos as usize; self.pos = new_pos as usize;
return Ok(()) return Ok(());
} }
} else { } else {
if let Some(new_pos) = pos.checked_add(offset as u64) { if let Some(new_pos) = pos.checked_add(offset as u64) {
if new_pos <= self.cap as u64 { if new_pos <= self.cap as u64 {
self.pos = new_pos as usize; self.pos = new_pos as usize;
return Ok(()) return Ok(());
} }
} }
} }
self.seek(SeekFrom::Current(offset)).map(|_|()) self.seek(SeekFrom::Current(offset)).map(|_| ())
} }
} }
@ -293,7 +295,10 @@ impl<R: Read> BufRead for BufReader<R> {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug { impl<R> fmt::Debug for BufReader<R>
where
R: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("BufReader") fmt.debug_struct("BufReader")
.field("reader", &self.inner) .field("reader", &self.inner)
@ -483,11 +488,7 @@ impl<W: Write> BufWriter<W> {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> { pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
BufWriter { BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
inner: Some(inner),
buf: Vec::with_capacity(capacity),
panicked: false,
}
} }
fn flush_buf(&mut self) -> io::Result<()> { fn flush_buf(&mut self) -> io::Result<()> {
@ -501,14 +502,16 @@ impl<W: Write> BufWriter<W> {
match r { match r {
Ok(0) => { Ok(0) => {
ret = Err(Error::new(ErrorKind::WriteZero, ret =
"failed to write the buffered data")); Err(Error::new(ErrorKind::WriteZero, "failed to write the buffered data"));
break; break;
} }
Ok(n) => written += n, Ok(n) => written += n,
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => { ret = Err(e); break } Err(e) => {
ret = Err(e);
break;
}
} }
} }
if written > 0 { if written > 0 {
@ -531,7 +534,9 @@ impl<W: Write> BufWriter<W> {
/// let reference = buffer.get_ref(); /// let reference = buffer.get_ref();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } pub fn get_ref(&self) -> &W {
self.inner.as_ref().unwrap()
}
/// Gets a mutable reference to the underlying writer. /// Gets a mutable reference to the underlying writer.
/// ///
@ -549,7 +554,9 @@ impl<W: Write> BufWriter<W> {
/// let reference = buffer.get_mut(); /// let reference = buffer.get_mut();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } pub fn get_mut(&mut self) -> &mut W {
self.inner.as_mut().unwrap()
}
/// Returns a reference to the internally buffered data. /// Returns a reference to the internally buffered data.
/// ///
@ -592,7 +599,7 @@ impl<W: Write> BufWriter<W> {
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> { pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
match self.flush_buf() { match self.flush_buf() {
Err(e) => Err(IntoInnerError(self, e)), Err(e) => Err(IntoInnerError(self, e)),
Ok(()) => Ok(self.inner.take().unwrap()) Ok(()) => Ok(self.inner.take().unwrap()),
} }
} }
} }
@ -634,7 +641,10 @@ impl<W: Write> Write for BufWriter<W> {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug { impl<W: Write> fmt::Debug for BufWriter<W>
where
W: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("BufWriter") fmt.debug_struct("BufWriter")
.field("writer", &self.inner.as_ref().unwrap()) .field("writer", &self.inner.as_ref().unwrap())
@ -693,7 +703,9 @@ impl<W> IntoInnerError<W> {
/// }; /// };
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn error(&self) -> &Error { &self.1 } pub fn error(&self) -> &Error {
&self.1
}
/// Returns the buffered writer instance which generated the error. /// Returns the buffered writer instance which generated the error.
/// ///
@ -726,12 +738,16 @@ impl<W> IntoInnerError<W> {
/// }; /// };
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> W { self.0 } pub fn into_inner(self) -> W {
self.0
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<W> From<IntoInnerError<W>> for Error { impl<W> From<IntoInnerError<W>> for Error {
fn from(iie: IntoInnerError<W>) -> Error { iie.1 } fn from(iie: IntoInnerError<W>) -> Error {
iie.1
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -856,10 +872,7 @@ impl<W: Write> LineWriter<W> {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> { pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
LineWriter { LineWriter { inner: BufWriter::with_capacity(capacity, inner), need_flush: false }
inner: BufWriter::with_capacity(capacity, inner),
need_flush: false,
}
} }
/// Gets a reference to the underlying writer. /// Gets a reference to the underlying writer.
@ -879,7 +892,9 @@ impl<W: Write> LineWriter<W> {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.get_ref() } pub fn get_ref(&self) -> &W {
self.inner.get_ref()
}
/// Gets a mutable reference to the underlying writer. /// Gets a mutable reference to the underlying writer.
/// ///
@ -902,7 +917,9 @@ impl<W: Write> LineWriter<W> {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } pub fn get_mut(&mut self) -> &mut W {
self.inner.get_mut()
}
/// Unwraps this `LineWriter`, returning the underlying writer. /// Unwraps this `LineWriter`, returning the underlying writer.
/// ///
@ -930,10 +947,7 @@ impl<W: Write> LineWriter<W> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> { pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
self.inner.into_inner().map_err(|IntoInnerError(buf, e)| { self.inner.into_inner().map_err(|IntoInnerError(buf, e)| {
IntoInnerError(LineWriter { IntoInnerError(LineWriter { inner: buf, need_flush: false }, e)
inner: buf,
need_flush: false,
}, e)
}) })
} }
} }
@ -953,7 +967,6 @@ impl<W: Write> Write for LineWriter<W> {
None => return self.inner.write(buf), None => return self.inner.write(buf),
}; };
// Ok, we're going to write a partial amount of the data given first // Ok, we're going to write a partial amount of the data given first
// followed by flushing the newline. After we've successfully written // followed by flushing the newline. After we've successfully written
// some data then we *must* report that we wrote that data, so future // some data then we *must* report that we wrote that data, so future
@ -962,7 +975,7 @@ impl<W: Write> Write for LineWriter<W> {
let n = self.inner.write(&buf[..=i])?; let n = self.inner.write(&buf[..=i])?;
self.need_flush = true; self.need_flush = true;
if self.flush().is_err() || n != i + 1 { if self.flush().is_err() || n != i + 1 {
return Ok(n) return Ok(n);
} }
// At this point we successfully wrote `i + 1` bytes and flushed it out, // At this point we successfully wrote `i + 1` bytes and flushed it out,
@ -984,12 +997,17 @@ impl<W: Write> Write for LineWriter<W> {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug { impl<W: Write> fmt::Debug for LineWriter<W>
where
W: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("LineWriter") fmt.debug_struct("LineWriter")
.field("writer", &self.inner.inner) .field("writer", &self.inner.inner)
.field("buffer", .field(
&format_args!("{}/{}", self.inner.buf.len(), self.inner.buf.capacity())) "buffer",
&format_args!("{}/{}", self.inner.buf.len(), self.inner.buf.capacity()),
)
.finish() .finish()
} }
} }
@ -1008,11 +1026,7 @@ mod tests {
impl Read for ShortReader { impl Read for ShortReader {
fn read(&mut self, _: &mut [u8]) -> io::Result<usize> { fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
if self.lengths.is_empty() { if self.lengths.is_empty() { Ok(0) } else { Ok(self.lengths.remove(0)) }
Ok(0)
} else {
Ok(self.lengths.remove(0))
}
} }
} }
@ -1123,7 +1137,7 @@ mod tests {
fn test_buffered_reader_seek_underflow() { fn test_buffered_reader_seek_underflow() {
// gimmick reader that yields its position modulo 256 for each byte // gimmick reader that yields its position modulo 256 for each byte
struct PositionReader { struct PositionReader {
pos: u64 pos: u64,
} }
impl Read for PositionReader { impl Read for PositionReader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
@ -1154,7 +1168,7 @@ mod tests {
let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 }); let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 });
assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..])); assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..]));
assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::max_value()-5)); assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::max_value() - 5));
assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5)); assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
// the following seek will require two underlying seeks // the following seek will require two underlying seeks
let expected = 9223372036854775802; let expected = 9223372036854775802;
@ -1361,7 +1375,7 @@ mod tests {
#[test] #[test]
fn test_short_reads() { fn test_short_reads() {
let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]}; let inner = ShortReader { lengths: vec![0, 1, 2, 0, 1, 0] };
let mut reader = BufReader::new(inner); let mut reader = BufReader::new(inner);
let mut buf = [0, 0]; let mut buf = [0, 0];
assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.read(&mut buf).unwrap(), 0);
@ -1379,7 +1393,9 @@ mod tests {
struct FailFlushWriter; struct FailFlushWriter;
impl Write for FailFlushWriter { impl Write for FailFlushWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
Err(io::Error::last_os_error()) Err(io::Error::last_os_error())
} }
@ -1405,30 +1421,30 @@ mod tests {
WRITES.fetch_add(1, Ordering::SeqCst); WRITES.fetch_add(1, Ordering::SeqCst);
panic!(); panic!();
} }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
thread::spawn(|| { thread::spawn(|| {
let mut writer = BufWriter::new(PanicWriter); let mut writer = BufWriter::new(PanicWriter);
let _ = writer.write(b"hello world"); let _ = writer.write(b"hello world");
let _ = writer.flush(); let _ = writer.flush();
}).join().unwrap_err(); })
.join()
.unwrap_err();
assert_eq!(WRITES.load(Ordering::SeqCst), 1); assert_eq!(WRITES.load(Ordering::SeqCst), 1);
} }
#[bench] #[bench]
fn bench_buffered_reader(b: &mut test::Bencher) { fn bench_buffered_reader(b: &mut test::Bencher) {
b.iter(|| { b.iter(|| BufReader::new(io::empty()));
BufReader::new(io::empty())
});
} }
#[bench] #[bench]
fn bench_buffered_writer(b: &mut test::Bencher) { fn bench_buffered_writer(b: &mut test::Bencher) {
b.iter(|| { b.iter(|| BufWriter::new(io::sink()));
BufWriter::new(io::sink())
});
} }
struct AcceptOneThenFail { struct AcceptOneThenFail {
@ -1457,10 +1473,7 @@ mod tests {
#[test] #[test]
fn erroneous_flush_retried() { fn erroneous_flush_retried() {
let a = AcceptOneThenFail { let a = AcceptOneThenFail { written: false, flushed: false };
written: false,
flushed: false,
};
let mut l = LineWriter::new(a); let mut l = LineWriter::new(a);
assert_eq!(l.write(b"a\nb\na").unwrap(), 4); assert_eq!(l.write(b"a\nb\na").unwrap(), 4);

View file

@ -1,8 +1,8 @@
use crate::convert::From;
use crate::error; use crate::error;
use crate::fmt; use crate::fmt;
use crate::result; use crate::result;
use crate::sys; use crate::sys;
use crate::convert::From;
/// A specialized [`Result`](../result/enum.Result.html) type for I/O /// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations. /// operations.
@ -73,7 +73,7 @@ enum Repr {
#[derive(Debug)] #[derive(Debug)]
struct Custom { struct Custom {
kind: ErrorKind, kind: ErrorKind,
error: Box<dyn error::Error+Send+Sync>, error: Box<dyn error::Error + Send + Sync>,
} }
/// A list specifying general categories of I/O error. /// A list specifying general categories of I/O error.
@ -220,9 +220,7 @@ impl From<ErrorKind> for Error {
/// [`Error`]: ../../std/io/struct.Error.html /// [`Error`]: ../../std/io/struct.Error.html
#[inline] #[inline]
fn from(kind: ErrorKind) -> Error { fn from(kind: ErrorKind) -> Error {
Error { Error { repr: Repr::Simple(kind) }
repr: Repr::Simple(kind)
}
} }
} }
@ -247,18 +245,14 @@ impl Error {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<Box<dyn error::Error+Send+Sync>> where
E: Into<Box<dyn error::Error + Send + Sync>>,
{ {
Self::_new(kind, error.into()) Self::_new(kind, error.into())
} }
fn _new(kind: ErrorKind, error: Box<dyn error::Error+Send+Sync>) -> Error { fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
repr: Repr::Custom(Box::new(Custom {
kind,
error,
}))
}
} }
/// Returns an error representing the last OS error which occurred. /// Returns an error representing the last OS error which occurred.
@ -370,7 +364,7 @@ impl Error {
/// } /// }
/// ``` /// ```
#[stable(feature = "io_error_inner", since = "1.3.0")] #[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_ref(&self) -> Option<&(dyn error::Error+Send+Sync+'static)> { pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None, Repr::Simple(..) => None,
@ -441,7 +435,7 @@ impl Error {
/// } /// }
/// ``` /// ```
#[stable(feature = "io_error_inner", since = "1.3.0")] #[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error+Send+Sync+'static)> { pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None, Repr::Simple(..) => None,
@ -475,11 +469,11 @@ impl Error {
/// } /// }
/// ``` /// ```
#[stable(feature = "io_error_inner", since = "1.3.0")] #[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn into_inner(self) -> Option<Box<dyn error::Error+Send+Sync>> { pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None, Repr::Simple(..) => None,
Repr::Custom(c) => Some(c.error) Repr::Custom(c) => Some(c.error),
} }
} }
@ -514,11 +508,12 @@ impl Error {
impl fmt::Debug for Repr { impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self { match *self {
Repr::Os(code) => Repr::Os(code) => fmt
fmt.debug_struct("Os") .debug_struct("Os")
.field("code", &code) .field("code", &code)
.field("kind", &sys::decode_error_kind(code)) .field("kind", &sys::decode_error_kind(code))
.field("message", &sys::os::error_string(code)).finish(), .field("message", &sys::os::error_string(code))
.finish(),
Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
} }
@ -567,17 +562,17 @@ impl error::Error for Error {
} }
fn _assert_error_is_sync_send() { fn _assert_error_is_sync_send() {
fn _is_sync_send<T: Sync+Send>() {} fn _is_sync_send<T: Sync + Send>() {}
_is_sync_send::<Error>(); _is_sync_send::<Error>();
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{Error, ErrorKind, Repr, Custom}; use super::{Custom, Error, ErrorKind, Repr};
use crate::error; use crate::error;
use crate::fmt; use crate::fmt;
use crate::sys::os::error_string;
use crate::sys::decode_error_kind; use crate::sys::decode_error_kind;
use crate::sys::os::error_string;
#[test] #[test]
fn test_debug_error() { fn test_debug_error() {
@ -587,10 +582,8 @@ mod test {
let err = Error { let err = Error {
repr: Repr::Custom(box Custom { repr: Repr::Custom(box Custom {
kind: ErrorKind::InvalidInput, kind: ErrorKind::InvalidInput,
error: box Error { error: box Error { repr: super::Repr::Os(code) },
repr: super::Repr::Os(code) }),
},
})
}; };
let expected = format!( let expected = format!(
"Custom {{ \ "Custom {{ \

View file

@ -1,7 +1,8 @@
use crate::cmp; use crate::cmp;
use crate::io::{self, SeekFrom, Read, Initializer, Write, Seek, BufRead, Error, ErrorKind,
IoSliceMut, IoSlice};
use crate::fmt; use crate::fmt;
use crate::io::{
self, BufRead, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write,
};
use crate::mem; use crate::mem;
// ============================================================================= // =============================================================================
@ -42,7 +43,9 @@ impl<R: Read + ?Sized> Read for &mut R {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + ?Sized> Write for &mut W { impl<W: Write + ?Sized> Write for &mut W {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(**self).write(buf)
}
#[inline] #[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
@ -50,7 +53,9 @@ impl<W: Write + ?Sized> Write for &mut W {
} }
#[inline] #[inline]
fn flush(&mut self) -> io::Result<()> { (**self).flush() } fn flush(&mut self) -> io::Result<()> {
(**self).flush()
}
#[inline] #[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
@ -65,15 +70,21 @@ impl<W: Write + ?Sized> Write for &mut W {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<S: Seek + ?Sized> Seek for &mut S { impl<S: Seek + ?Sized> Seek for &mut S {
#[inline] #[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) } fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
(**self).seek(pos)
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for &mut B { impl<B: BufRead + ?Sized> BufRead for &mut B {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}
#[inline] #[inline]
fn consume(&mut self, amt: usize) { (**self).consume(amt) } fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
#[inline] #[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
@ -121,7 +132,9 @@ impl<R: Read + ?Sized> Read for Box<R> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + ?Sized> Write for Box<W> { impl<W: Write + ?Sized> Write for Box<W> {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(**self).write(buf)
}
#[inline] #[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
@ -129,7 +142,9 @@ impl<W: Write + ?Sized> Write for Box<W> {
} }
#[inline] #[inline]
fn flush(&mut self) -> io::Result<()> { (**self).flush() } fn flush(&mut self) -> io::Result<()> {
(**self).flush()
}
#[inline] #[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
@ -144,15 +159,21 @@ impl<W: Write + ?Sized> Write for Box<W> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<S: Seek + ?Sized> Seek for Box<S> { impl<S: Seek + ?Sized> Seek for Box<S> {
#[inline] #[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) } fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
(**self).seek(pos)
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for Box<B> { impl<B: BufRead + ?Sized> BufRead for Box<B> {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn fill_buf(&mut self) -> io::Result<&[u8]> {
(**self).fill_buf()
}
#[inline] #[inline]
fn consume(&mut self, amt: usize) { (**self).consume(amt) } fn consume(&mut self, amt: usize) {
(**self).consume(amt)
}
#[inline] #[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
@ -227,8 +248,7 @@ impl Read for &[u8] {
#[inline] #[inline]
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
if buf.len() > self.len() { if buf.len() > self.len() {
return Err(Error::new(ErrorKind::UnexpectedEof, return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"));
"failed to fill whole buffer"));
} }
let (a, b) = self.split_at(buf.len()); let (a, b) = self.split_at(buf.len());
@ -257,10 +277,14 @@ impl Read for &[u8] {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for &[u8] { impl BufRead for &[u8] {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(*self)
}
#[inline] #[inline]
fn consume(&mut self, amt: usize) { *self = &self[amt..]; } fn consume(&mut self, amt: usize) {
*self = &self[amt..];
}
} }
/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting /// Write is implemented for `&mut [u8]` by copying into the slice, overwriting
@ -302,7 +326,9 @@ impl Write for &mut [u8] {
} }
#[inline] #[inline]
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
/// Write is implemented for `Vec<u8>` by appending to the vector. /// Write is implemented for `Vec<u8>` by appending to the vector.
@ -332,7 +358,9 @@ impl Write for Vec<u8> {
} }
#[inline] #[inline]
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -261,49 +261,54 @@
use crate::cmp; use crate::cmp;
use crate::fmt; use crate::fmt;
use crate::slice;
use crate::str;
use crate::memchr; use crate::memchr;
use crate::ops::{Deref, DerefMut}; use crate::ops::{Deref, DerefMut};
use crate::ptr; use crate::ptr;
use crate::slice;
use crate::str;
use crate::sys; use crate::sys;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::{BufReader, BufWriter, LineWriter};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::IntoInnerError; pub use self::buffered::IntoInnerError;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::{BufReader, BufWriter, LineWriter};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::cursor::Cursor; pub use self::cursor::Cursor;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::error::{Result, Error, ErrorKind}; pub use self::error::{Error, ErrorKind, Result};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr}; pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
#[unstable(feature = "print_internals", issue = "0")] #[unstable(feature = "print_internals", issue = "0")]
pub use self::stdio::{_print, _eprint}; pub use self::stdio::{_eprint, _print};
#[unstable(feature = "libstd_io_internals", issue = "42788")] #[unstable(feature = "libstd_io_internals", issue = "42788")]
#[doc(no_inline, hidden)] #[doc(no_inline, hidden)]
pub use self::stdio::{set_panic, set_print}; pub use self::stdio::{set_panic, set_print};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::util::{copy, empty, repeat, sink, Empty, Repeat, Sink};
pub mod prelude;
mod buffered; mod buffered;
mod cursor; mod cursor;
mod error; mod error;
mod impls; mod impls;
mod lazy; mod lazy;
mod util; pub mod prelude;
mod stdio; mod stdio;
mod util;
const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
struct Guard<'a> { buf: &'a mut Vec<u8>, len: usize } struct Guard<'a> {
buf: &'a mut Vec<u8>,
len: usize,
}
impl Drop for Guard<'_> { impl Drop for Guard<'_> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { self.buf.set_len(self.len); } unsafe {
self.buf.set_len(self.len);
}
} }
} }
@ -326,15 +331,15 @@ impl Drop for Guard<'_> {
// the function only *appends* bytes to the buffer. We'll get undefined // the function only *appends* bytes to the buffer. We'll get undefined
// behavior if existing bytes are overwritten to have non-UTF-8 data. // behavior if existing bytes are overwritten to have non-UTF-8 data.
fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize> fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
where F: FnOnce(&mut Vec<u8>) -> Result<usize> where
F: FnOnce(&mut Vec<u8>) -> Result<usize>,
{ {
unsafe { unsafe {
let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
let ret = f(g.buf); let ret = f(g.buf);
if str::from_utf8(&g.buf[g.len..]).is_err() { if str::from_utf8(&g.buf[g.len..]).is_err() {
ret.and_then(|_| { ret.and_then(|_| {
Err(Error::new(ErrorKind::InvalidData, Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8"))
"stream did not contain valid UTF-8"))
}) })
} else { } else {
g.len = g.buf.len(); g.len = g.buf.len();
@ -405,23 +410,17 @@ where
pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
where where
F: FnOnce(&mut [u8]) -> Result<usize> F: FnOnce(&mut [u8]) -> Result<usize>,
{ {
let buf = bufs let buf = bufs.iter_mut().find(|b| !b.is_empty()).map_or(&mut [][..], |b| &mut **b);
.iter_mut()
.find(|b| !b.is_empty())
.map_or(&mut [][..], |b| &mut **b);
read(buf) read(buf)
} }
pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoSlice<'_>]) -> Result<usize> pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoSlice<'_>]) -> Result<usize>
where where
F: FnOnce(&[u8]) -> Result<usize> F: FnOnce(&[u8]) -> Result<usize>,
{ {
let buf = bufs let buf = bufs.iter().find(|b| !b.is_empty()).map_or(&[][..], |b| &**b);
.iter()
.find(|b| !b.is_empty())
.map_or(&[][..], |b| &**b);
write(buf) write(buf)
} }
@ -767,14 +766,16 @@ pub trait Read {
while !buf.is_empty() { while !buf.is_empty() {
match self.read(buf) { match self.read(buf) {
Ok(0) => break, Ok(0) => break,
Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; } Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e), Err(e) => return Err(e),
} }
} }
if !buf.is_empty() { if !buf.is_empty() {
Err(Error::new(ErrorKind::UnexpectedEof, Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
"failed to fill whole buffer"))
} else { } else {
Ok(()) Ok(())
} }
@ -815,7 +816,12 @@ pub trait Read {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self } fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
{
self
}
/// Transforms this `Read` instance to an [`Iterator`] over its bytes. /// Transforms this `Read` instance to an [`Iterator`] over its bytes.
/// ///
@ -852,7 +858,10 @@ pub trait Read {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn bytes(self) -> Bytes<Self> where Self: Sized { fn bytes(self) -> Bytes<Self>
where
Self: Sized,
{
Bytes { inner: self } Bytes { inner: self }
} }
@ -887,7 +896,10 @@ pub trait Read {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized { fn chain<R: Read>(self, next: R) -> Chain<Self, R>
where
Self: Sized,
{
Chain { first: self, second: next, done_first: false } Chain { first: self, second: next, done_first: false }
} }
@ -923,7 +935,10 @@ pub trait Read {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn take(self, limit: u64) -> Take<Self> where Self: Sized { fn take(self, limit: u64) -> Take<Self>
where
Self: Sized,
{
Take { inner: self, limit: limit } Take { inner: self, limit: limit }
} }
} }
@ -1339,8 +1354,9 @@ pub trait Write {
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
while !buf.is_empty() { while !buf.is_empty() {
match self.write(buf) { match self.write(buf) {
Ok(0) => return Err(Error::new(ErrorKind::WriteZero, Ok(0) => {
"failed to write whole buffer")), return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
}
Ok(n) => buf = &buf[n..], Ok(n) => buf = &buf[n..],
Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e), Err(e) => return Err(e),
@ -1444,7 +1460,12 @@ pub trait Write {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self } fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
{
self
}
} }
/// The `Seek` trait provides a cursor which can be moved within a stream of /// The `Seek` trait provides a cursor which can be moved within a stream of
@ -1601,15 +1622,14 @@ pub enum SeekFrom {
Current(#[stable(feature = "rust1", since = "1.0.0")] i64), Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
} }
fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> Result<usize> {
-> Result<usize> {
let mut read = 0; let mut read = 0;
loop { loop {
let (done, used) = { let (done, used) = {
let available = match r.fill_buf() { let available = match r.fill_buf() {
Ok(n) => n, Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e) Err(e) => return Err(e),
}; };
match memchr::memchr(delim, available) { match memchr::memchr(delim, available) {
Some(i) => { Some(i) => {
@ -1900,7 +1920,10 @@ pub trait BufRead: Read {
/// assert_eq!(split_iter.next(), None); /// assert_eq!(split_iter.next(), None);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn split(self, byte: u8) -> Split<Self> where Self: Sized { fn split(self, byte: u8) -> Split<Self>
where
Self: Sized,
{
Split { buf: self, delim: byte } Split { buf: self, delim: byte }
} }
@ -1939,7 +1962,10 @@ pub trait BufRead: Read {
/// ///
/// [`BufRead::read_line`]: trait.BufRead.html#method.read_line /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn lines(self) -> Lines<Self> where Self: Sized { fn lines(self) -> Lines<Self>
where
Self: Sized,
{
Lines { buf: self } Lines { buf: self }
} }
} }
@ -2035,10 +2061,7 @@ impl<T, U> Chain<T, U> {
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> { impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Chain") f.debug_struct("Chain").field("t", &self.first).field("u", &self.second).finish()
.field("t", &self.first)
.field("u", &self.second)
.finish()
} }
} }
@ -2066,11 +2089,7 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
unsafe fn initializer(&self) -> Initializer { unsafe fn initializer(&self) -> Initializer {
let initializer = self.first.initializer(); let initializer = self.first.initializer();
if initializer.should_initialize() { if initializer.should_initialize() { initializer } else { self.second.initializer() }
initializer
} else {
self.second.initializer()
}
} }
} }
@ -2079,7 +2098,9 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
fn fill_buf(&mut self) -> Result<&[u8]> { fn fill_buf(&mut self) -> Result<&[u8]> {
if !self.done_first { if !self.done_first {
match self.first.fill_buf()? { match self.first.fill_buf()? {
buf if buf.is_empty() => { self.done_first = true; } buf if buf.is_empty() => {
self.done_first = true;
}
buf => return Ok(buf), buf => return Ok(buf),
} }
} }
@ -2087,11 +2108,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
} }
fn consume(&mut self, amt: usize) { fn consume(&mut self, amt: usize) {
if !self.done_first { if !self.done_first { self.first.consume(amt) } else { self.second.consume(amt) }
self.first.consume(amt)
} else {
self.second.consume(amt)
}
} }
} }
@ -2137,7 +2154,9 @@ impl<T> Take<T> {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn limit(&self) -> u64 { self.limit } pub fn limit(&self) -> u64 {
self.limit
}
/// Sets the number of bytes that can be read before this instance will /// Sets the number of bytes that can be read before this instance will
/// return EOF. This is the same as constructing a new `Take` instance, so /// return EOF. This is the same as constructing a new `Take` instance, so
@ -2351,7 +2370,7 @@ impl<B: BufRead> Iterator for Split<B> {
} }
Some(Ok(buf)) Some(Ok(buf))
} }
Err(e) => Some(Err(e)) Err(e) => Some(Err(e)),
} }
} }
} }
@ -2385,16 +2404,16 @@ impl<B: BufRead> Iterator for Lines<B> {
} }
Some(Ok(buf)) Some(Ok(buf))
} }
Err(e) => Some(Err(e)) Err(e) => Some(Err(e)),
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{repeat, Cursor, SeekFrom};
use crate::cmp; use crate::cmp;
use crate::io::prelude::*; use crate::io::prelude::*;
use super::{Cursor, SeekFrom, repeat};
use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{self, IoSlice, IoSliceMut};
use crate::mem; use crate::mem;
use crate::ops::Deref; use crate::ops::Deref;
@ -2509,16 +2528,14 @@ mod tests {
let mut buf = [0; 4]; let mut buf = [0; 4];
let mut c = Cursor::new(&b""[..]); let mut c = Cursor::new(&b""[..]);
assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
io::ErrorKind::UnexpectedEof);
let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..])); let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..]));
c.read_exact(&mut buf).unwrap(); c.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"1234"); assert_eq!(&buf, b"1234");
c.read_exact(&mut buf).unwrap(); c.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"5678"); assert_eq!(&buf, b"5678");
assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
io::ErrorKind::UnexpectedEof);
} }
#[test] #[test]
@ -2526,12 +2543,10 @@ mod tests {
let mut buf = [0; 4]; let mut buf = [0; 4];
let mut c = &b""[..]; let mut c = &b""[..];
assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
io::ErrorKind::UnexpectedEof);
let mut c = &b"123"[..]; let mut c = &b"123"[..];
assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
io::ErrorKind::UnexpectedEof);
// make sure the optimized (early returning) method is being used // make sure the optimized (early returning) method is being used
assert_eq!(&buf, &[0; 4]); assert_eq!(&buf, &[0; 4]);
@ -2558,7 +2573,7 @@ mod tests {
fn fill_buf(&mut self) -> io::Result<&[u8]> { fn fill_buf(&mut self) -> io::Result<&[u8]> {
Err(io::Error::new(io::ErrorKind::Other, "")) Err(io::Error::new(io::ErrorKind::Other, ""))
} }
fn consume(&mut self, _amt: usize) { } fn consume(&mut self, _amt: usize) {}
} }
let mut buf = [0; 1]; let mut buf = [0; 1];
@ -2591,11 +2606,9 @@ mod tests {
#[test] #[test]
fn chain_bufread() { fn chain_bufread() {
let testdata = b"ABCDEFGHIJKL"; let testdata = b"ABCDEFGHIJKL";
let chain1 = (&testdata[..3]).chain(&testdata[3..6]) let chain1 =
.chain(&testdata[6..9]) (&testdata[..3]).chain(&testdata[3..6]).chain(&testdata[6..9]).chain(&testdata[9..]);
.chain(&testdata[9..]); let chain2 = (&testdata[..4]).chain(&testdata[4..8]).chain(&testdata[8..]);
let chain2 = (&testdata[..4]).chain(&testdata[4..8])
.chain(&testdata[8..]);
cmp_bufread(chain1, chain2, &testdata[..]); cmp_bufread(chain1, chain2, &testdata[..]);
} }
@ -2651,7 +2664,6 @@ mod tests {
assert_eq!(c.stream_position()?, 15); assert_eq!(c.stream_position()?, 15);
assert_eq!(c.stream_position()?, 15); assert_eq!(c.stream_position()?, 15);
c.seek(SeekFrom::Start(7))?; c.seek(SeekFrom::Start(7))?;
c.seek(SeekFrom::Current(2))?; c.seek(SeekFrom::Current(2))?;
assert_eq!(c.stream_position()?, 9); assert_eq!(c.stream_position()?, 9);
@ -2700,9 +2712,7 @@ mod tests {
// that will not allocate when the limit has already been reached. In // that will not allocate when the limit has already been reached. In
// this case, vec2 never grows. // this case, vec2 never grows.
let mut vec2 = Vec::with_capacity(input.len()); let mut vec2 = Vec::with_capacity(input.len());
ExampleSliceReader { slice: input } ExampleSliceReader { slice: input }.take(input.len() as u64).read_to_end(&mut vec2)?;
.take(input.len() as u64)
.read_to_end(&mut vec2)?;
assert_eq!(vec2.len(), input.len()); assert_eq!(vec2.len(), input.len());
assert_eq!(vec2.capacity(), input.len(), "did not allocate more"); assert_eq!(vec2.capacity(), input.len(), "did not allocate more");

View file

@ -11,4 +11,4 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use super::{Read, Write, BufRead, Seek}; pub use super::{BufRead, Read, Seek, Write};

View file

@ -1,7 +1,7 @@
#![allow(missing_copy_implementations)] #![allow(missing_copy_implementations)]
use crate::fmt; use crate::fmt;
use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoSlice, IoSliceMut}; use crate::io::{self, BufRead, ErrorKind, Initializer, IoSlice, IoSliceMut, Read, Write};
use crate::mem::MaybeUninit; use crate::mem::MaybeUninit;
/// Copies the entire contents of a reader into a writer. /// Copies the entire contents of a reader into a writer.
@ -41,7 +41,9 @@ use crate::mem::MaybeUninit;
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
where R: Read, W: Write where
R: Read,
W: Write,
{ {
let mut buf = MaybeUninit::<[u8; super::DEFAULT_BUF_SIZE]>::uninit(); let mut buf = MaybeUninit::<[u8; super::DEFAULT_BUF_SIZE]>::uninit();
// FIXME(#53491): This is calling `get_mut` and `get_ref` on an uninitialized // FIXME(#53491): This is calling `get_mut` and `get_ref` on an uninitialized
@ -49,7 +51,9 @@ pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<
// This is still technically undefined behavior due to creating a reference // This is still technically undefined behavior due to creating a reference
// to uninitialized data, but within libstd we can rely on more guarantees // to uninitialized data, but within libstd we can rely on more guarantees
// than if this code were in an external lib. // than if this code were in an external lib.
unsafe { reader.initializer().initialize(buf.get_mut()); } unsafe {
reader.initializer().initialize(buf.get_mut());
}
let mut written = 0; let mut written = 0;
loop { loop {
@ -71,7 +75,9 @@ pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<
/// ///
/// [`empty`]: fn.empty.html /// [`empty`]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () } pub struct Empty {
_priv: (),
}
/// Constructs a new handle to an empty reader. /// Constructs a new handle to an empty reader.
/// ///
@ -91,12 +97,16 @@ pub struct Empty { _priv: () }
/// assert!(buffer.is_empty()); /// assert!(buffer.is_empty());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } } pub fn empty() -> Empty {
Empty { _priv: () }
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty { impl Read for Empty {
#[inline] #[inline]
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
Ok(0)
}
#[inline] #[inline]
unsafe fn initializer(&self) -> Initializer { unsafe fn initializer(&self) -> Initializer {
@ -106,7 +116,9 @@ impl Read for Empty {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty { impl BufRead for Empty {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(&[])
}
#[inline] #[inline]
fn consume(&mut self, _n: usize) {} fn consume(&mut self, _n: usize) {}
} }
@ -125,7 +137,9 @@ impl fmt::Debug for Empty {
/// ///
/// [repeat]: fn.repeat.html /// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 } pub struct Repeat {
byte: u8,
}
/// Creates an instance of a reader that infinitely repeats one byte. /// Creates an instance of a reader that infinitely repeats one byte.
/// ///
@ -142,7 +156,9 @@ pub struct Repeat { byte: u8 }
/// assert_eq!(buffer, [0b101, 0b101, 0b101]); /// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte } } pub fn repeat(byte: u8) -> Repeat {
Repeat { byte }
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat { impl Read for Repeat {
@ -183,7 +199,9 @@ impl fmt::Debug for Repeat {
/// ///
/// [sink]: fn.sink.html /// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () } pub struct Sink {
_priv: (),
}
/// Creates an instance of a writer which will successfully consume all data. /// Creates an instance of a writer which will successfully consume all data.
/// ///
@ -200,12 +218,16 @@ pub struct Sink { _priv: () }
/// assert_eq!(num_bytes, 5); /// assert_eq!(num_bytes, 5);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } } pub fn sink() -> Sink {
Sink { _priv: () }
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink { impl Write for Sink {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(buf.len())
}
#[inline] #[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
@ -214,7 +236,9 @@ impl Write for Sink {
} }
#[inline] #[inline]
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
@ -227,7 +251,7 @@ impl fmt::Debug for Sink {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::io::prelude::*; use crate::io::prelude::*;
use crate::io::{copy, sink, empty, repeat}; use crate::io::{copy, empty, repeat, sink};
#[test] #[test]
fn copy_copies() { fn copy_copies() {

View file

@ -313,9 +313,8 @@ macro_rules! dbg {
#[cfg(test)] #[cfg(test)]
macro_rules! assert_approx_eq { macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({ ($a:expr, $b:expr) => {{
let (a, b) = (&$a, &$b); let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6, assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
"{} is not approximately equal to {}", *a, *b); }};
})
} }

View file

@ -1,16 +1,16 @@
use crate::convert::TryInto;
use crate::fmt; use crate::fmt;
use crate::hash; use crate::hash;
use crate::io; use crate::io;
use crate::mem;
use crate::net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
use crate::option;
use crate::sys::net::netc as c;
use crate::sys_common::{FromInner, AsInner, IntoInner};
use crate::sys_common::net::LookupHost;
use crate::vec;
use crate::iter; use crate::iter;
use crate::mem;
use crate::net::{hton, ntoh, IpAddr, Ipv4Addr, Ipv6Addr};
use crate::option;
use crate::slice; use crate::slice;
use crate::convert::TryInto; use crate::sys::net::netc as c;
use crate::sys_common::net::LookupHost;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::vec;
/// An internet socket address, either IPv4 or IPv6. /// An internet socket address, either IPv4 or IPv6.
/// ///
@ -74,7 +74,9 @@ pub enum SocketAddr {
/// ``` /// ```
#[derive(Copy)] #[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV4 { inner: c::sockaddr_in } pub struct SocketAddrV4 {
inner: c::sockaddr_in,
}
/// An IPv6 socket address. /// An IPv6 socket address.
/// ///
@ -104,7 +106,9 @@ pub struct SocketAddrV4 { inner: c::sockaddr_in }
/// ``` /// ```
#[derive(Copy)] #[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV6 { inner: c::sockaddr_in6 } pub struct SocketAddrV6 {
inner: c::sockaddr_in6,
}
impl SocketAddr { impl SocketAddr {
/// Creates a new socket address from an [IP address] and a port number. /// Creates a new socket address from an [IP address] and a port number.
@ -274,7 +278,7 @@ impl SocketAddrV4 {
sin_family: c::AF_INET as c::sa_family_t, sin_family: c::AF_INET as c::sa_family_t,
sin_port: hton(port), sin_port: hton(port),
sin_addr: *ip.as_inner(), sin_addr: *ip.as_inner(),
.. unsafe { mem::zeroed() } ..unsafe { mem::zeroed() }
}, },
} }
} }
@ -291,9 +295,7 @@ impl SocketAddrV4 {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn ip(&self) -> &Ipv4Addr { pub fn ip(&self) -> &Ipv4Addr {
unsafe { unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) }
&*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr)
}
} }
/// Changes the IP address associated with this socket address. /// Changes the IP address associated with this socket address.
@ -362,8 +364,7 @@ impl SocketAddrV6 {
/// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
-> SocketAddrV6 {
SocketAddrV6 { SocketAddrV6 {
inner: c::sockaddr_in6 { inner: c::sockaddr_in6 {
sin6_family: c::AF_INET6 as c::sa_family_t, sin6_family: c::AF_INET6 as c::sa_family_t,
@ -371,7 +372,7 @@ impl SocketAddrV6 {
sin6_addr: *ip.as_inner(), sin6_addr: *ip.as_inner(),
sin6_flowinfo: flowinfo, sin6_flowinfo: flowinfo,
sin6_scope_id: scope_id, sin6_scope_id: scope_id,
.. unsafe { mem::zeroed() } ..unsafe { mem::zeroed() }
}, },
} }
} }
@ -388,9 +389,7 @@ impl SocketAddrV6 {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn ip(&self) -> &Ipv6Addr { pub fn ip(&self) -> &Ipv6Addr {
unsafe { unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) }
&*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr)
}
} }
/// Changes the IP address associated with this socket address. /// Changes the IP address associated with this socket address.
@ -633,27 +632,31 @@ impl fmt::Debug for SocketAddrV6 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SocketAddrV4 { impl Clone for SocketAddrV4 {
fn clone(&self) -> SocketAddrV4 { *self } fn clone(&self) -> SocketAddrV4 {
*self
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SocketAddrV6 { impl Clone for SocketAddrV6 {
fn clone(&self) -> SocketAddrV6 { *self } fn clone(&self) -> SocketAddrV6 {
*self
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for SocketAddrV4 { impl PartialEq for SocketAddrV4 {
fn eq(&self, other: &SocketAddrV4) -> bool { fn eq(&self, other: &SocketAddrV4) -> bool {
self.inner.sin_port == other.inner.sin_port && self.inner.sin_port == other.inner.sin_port
self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr && self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for SocketAddrV6 { impl PartialEq for SocketAddrV6 {
fn eq(&self, other: &SocketAddrV6) -> bool { fn eq(&self, other: &SocketAddrV6) -> bool {
self.inner.sin6_port == other.inner.sin6_port && self.inner.sin6_port == other.inner.sin6_port
self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr && && self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr
self.inner.sin6_flowinfo == other.inner.sin6_flowinfo && && self.inner.sin6_flowinfo == other.inner.sin6_flowinfo
self.inner.sin6_scope_id == other.inner.sin6_scope_id && self.inner.sin6_scope_id == other.inner.sin6_scope_id
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -670,8 +673,13 @@ impl hash::Hash for SocketAddrV4 {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for SocketAddrV6 { impl hash::Hash for SocketAddrV6 {
fn hash<H: hash::Hasher>(&self, s: &mut H) { fn hash<H: hash::Hasher>(&self, s: &mut H) {
(self.inner.sin6_port, &self.inner.sin6_addr.s6_addr, (
self.inner.sin6_flowinfo, self.inner.sin6_scope_id).hash(s) self.inner.sin6_port,
&self.inner.sin6_addr.s6_addr,
self.inner.sin6_flowinfo,
self.inner.sin6_scope_id,
)
.hash(s)
} }
} }
@ -795,7 +803,7 @@ pub trait ToSocketAddrs {
/// Returned iterator over socket addresses which this type may correspond /// Returned iterator over socket addresses which this type may correspond
/// to. /// to.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
type Iter: Iterator<Item=SocketAddr>; type Iter: Iterator<Item = SocketAddr>;
/// Converts this object to an iterator of resolved `SocketAddr`s. /// Converts this object to an iterator of resolved `SocketAddr`s.
/// ///
@ -864,7 +872,12 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
fn resolve_socket_addr(lh: LookupHost) -> io::Result<vec::IntoIter<SocketAddr>> { fn resolve_socket_addr(lh: LookupHost) -> io::Result<vec::IntoIter<SocketAddr>> {
let p = lh.port(); let p = lh.port();
let v: Vec<_> = lh.map(|mut a| { a.set_port(p); a }).collect(); let v: Vec<_> = lh
.map(|mut a| {
a.set_port(p);
a
})
.collect();
Ok(v.into_iter()) Ok(v.into_iter())
} }
@ -877,11 +890,11 @@ impl ToSocketAddrs for (&str, u16) {
// try to parse the host as a regular IP address first // try to parse the host as a regular IP address first
if let Ok(addr) = host.parse::<Ipv4Addr>() { if let Ok(addr) = host.parse::<Ipv4Addr>() {
let addr = SocketAddrV4::new(addr, port); let addr = SocketAddrV4::new(addr, port);
return Ok(vec![SocketAddr::V4(addr)].into_iter()) return Ok(vec![SocketAddr::V4(addr)].into_iter());
} }
if let Ok(addr) = host.parse::<Ipv6Addr>() { if let Ok(addr) = host.parse::<Ipv6Addr>() {
let addr = SocketAddrV6::new(addr, port, 0, 0); let addr = SocketAddrV6::new(addr, port, 0, 0);
return Ok(vec![SocketAddr::V6(addr)].into_iter()) return Ok(vec![SocketAddr::V6(addr)].into_iter());
} }
resolve_socket_addr((host, port).try_into()?) resolve_socket_addr((host, port).try_into()?)
@ -929,8 +942,8 @@ impl ToSocketAddrs for String {
#[cfg(all(test, not(target_os = "emscripten")))] #[cfg(all(test, not(target_os = "emscripten")))]
mod tests { mod tests {
use crate::net::test::{sa4, sa6, tsa};
use crate::net::*; use crate::net::*;
use crate::net::test::{tsa, sa6, sa4};
#[test] #[test]
fn to_socket_addr_ipaddr_u16() { fn to_socket_addr_ipaddr_u16() {
@ -991,8 +1004,12 @@ mod tests {
#[test] #[test]
fn set_ip() { fn set_ip() {
fn ip4(low: u8) -> Ipv4Addr { Ipv4Addr::new(77, 88, 21, low) } fn ip4(low: u8) -> Ipv4Addr {
fn ip6(low: u16) -> Ipv6Addr { Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low) } Ipv4Addr::new(77, 88, 21, low)
}
fn ip6(low: u16) -> Ipv6Addr {
Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low)
}
let mut v4 = SocketAddrV4::new(ip4(11), 80); let mut v4 = SocketAddrV4::new(ip4(11), 80);
assert_eq!(v4.ip(), &ip4(11)); assert_eq!(v4.ip(), &ip4(11));
@ -1068,7 +1085,11 @@ mod tests {
#[test] #[test]
fn is_v6() { fn is_v6() {
let v6 = SocketAddr::V6(SocketAddrV6::new( let v6 = SocketAddr::V6(SocketAddrV6::new(
Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0)); Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1),
80,
10,
0,
));
assert!(!v6.is_ipv4()); assert!(!v6.is_ipv4());
assert!(v6.is_ipv6()); assert!(v6.is_ipv6());
} }

View file

@ -16,10 +16,7 @@ struct Parser<'a> {
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
fn new(s: &'a str) -> Parser<'a> { fn new(s: &'a str) -> Parser<'a> {
Parser { Parser { s: s.as_bytes(), pos: 0 }
s: s.as_bytes(),
pos: 0,
}
} }
fn is_eof(&self) -> bool { fn is_eof(&self) -> bool {
@ -27,7 +24,8 @@ impl<'a> Parser<'a> {
} }
// Commit only if parser returns Some // Commit only if parser returns Some
fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where fn read_atomically<T, F>(&mut self, cb: F) -> Option<T>
where
F: FnOnce(&mut Parser<'_>) -> Option<T>, F: FnOnce(&mut Parser<'_>) -> Option<T>,
{ {
let pos = self.pos; let pos = self.pos;
@ -39,17 +37,18 @@ impl<'a> Parser<'a> {
} }
// Commit only if parser read till EOF // Commit only if parser read till EOF
fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T>
where
F: FnOnce(&mut Parser<'_>) -> Option<T>, F: FnOnce(&mut Parser<'_>) -> Option<T>,
{ {
self.read_atomically(move |p| { self.read_atomically(move |p| cb(p).filter(|_| p.is_eof()))
cb(p).filter(|_| p.is_eof())
})
} }
// Return result of first successful parser // Return result of first successful parser
fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>]) fn read_or<T>(
-> Option<T> { &mut self,
parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>],
) -> Option<T> {
for pf in parsers { for pf in parsers {
if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) { if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) {
return Some(r); return Some(r);
@ -59,11 +58,8 @@ impl<'a> Parser<'a> {
} }
// Apply 3 parsers sequentially // Apply 3 parsers sequentially
fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, fn read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)>
pa: PA, where
pb: PB,
pc: PC)
-> Option<(A, B, C)> where
PA: FnOnce(&mut Parser<'_>) -> Option<A>, PA: FnOnce(&mut Parser<'_>) -> Option<A>,
PB: FnOnce(&mut Parser<'_>) -> Option<B>, PB: FnOnce(&mut Parser<'_>) -> Option<B>,
PC: FnOnce(&mut Parser<'_>) -> Option<C>, PC: FnOnce(&mut Parser<'_>) -> Option<C>,
@ -74,7 +70,7 @@ impl<'a> Parser<'a> {
let c = if b.is_some() { pc(p) } else { None }; let c = if b.is_some() { pc(p) } else { None };
match (a, b, c) { match (a, b, c) {
(Some(a), Some(b), Some(c)) => Some((a, b, c)), (Some(a), Some(b), Some(c)) => Some((a, b, c)),
_ => None _ => None,
} }
}) })
} }
@ -92,11 +88,9 @@ impl<'a> Parser<'a> {
// Return char and advance iff next char is equal to requested // Return char and advance iff next char is equal to requested
fn read_given_char(&mut self, c: char) -> Option<char> { fn read_given_char(&mut self, c: char) -> Option<char> {
self.read_atomically(|p| { self.read_atomically(|p| match p.read_char() {
match p.read_char() {
Some(next) if next == c => Some(next), Some(next) if next == c => Some(next),
_ => None, _ => None,
}
}) })
} }
@ -116,9 +110,7 @@ impl<'a> Parser<'a> {
} }
} }
self.read_atomically(|p| { self.read_atomically(|p| p.read_char().and_then(|c| parse_digit(c, radix)))
p.read_char().and_then(|c| parse_digit(c, radix))
})
} }
fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> { fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
@ -130,14 +122,14 @@ impl<'a> Parser<'a> {
r = r * (radix as u32) + (d as u32); r = r * (radix as u32) + (d as u32);
digit_count += 1; digit_count += 1;
if digit_count > max_digits || r >= upto { if digit_count > max_digits || r >= upto {
return None return None;
} }
} }
None => { None => {
if digit_count == 0 { if digit_count == 0 {
return None return None;
} else { } else {
return Some(r) return Some(r);
} }
} }
}; };
@ -173,12 +165,11 @@ impl<'a> Parser<'a> {
assert!(head.len() + tail.len() <= 8); assert!(head.len() + tail.len() <= 8);
let mut gs = [0; 8]; let mut gs = [0; 8];
gs[..head.len()].copy_from_slice(head); gs[..head.len()].copy_from_slice(head);
gs[(8 - tail.len()) .. 8].copy_from_slice(tail); gs[(8 - tail.len())..8].copy_from_slice(tail);
Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
} }
fn read_groups(p: &mut Parser<'_>, groups: &mut [u16; 8], limit: usize) fn read_groups(p: &mut Parser<'_>, groups: &mut [u16; 8], limit: usize) -> (usize, bool) {
-> (usize, bool) {
let mut i = 0; let mut i = 0;
while i < limit { while i < limit {
if i < limit - 1 { if i < limit - 1 {
@ -206,7 +197,7 @@ impl<'a> Parser<'a> {
}); });
match group { match group {
Some(g) => groups[i] = g, Some(g) => groups[i] = g,
None => return (i, false) None => return (i, false),
} }
i += 1; i += 1;
} }
@ -218,13 +209,13 @@ impl<'a> Parser<'a> {
if head_size == 8 { if head_size == 8 {
return Some(Ipv6Addr::new( return Some(Ipv6Addr::new(
head[0], head[1], head[2], head[3], head[0], head[1], head[2], head[3], head[4], head[5], head[6], head[7],
head[4], head[5], head[6], head[7])) ));
} }
// IPv4 part is not allowed before `::` // IPv4 part is not allowed before `::`
if head_ipv4 { if head_ipv4 {
return None return None;
} }
// read `::` if previous code parsed less than 8 groups // read `::` if previous code parsed less than 8 groups
@ -252,9 +243,7 @@ impl<'a> Parser<'a> {
fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> { fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
let ip_addr = |p: &mut Parser<'_>| p.read_ipv4_addr(); let ip_addr = |p: &mut Parser<'_>| p.read_ipv4_addr();
let colon = |p: &mut Parser<'_>| p.read_given_char(':'); let colon = |p: &mut Parser<'_>| p.read_given_char(':');
let port = |p: &mut Parser<'_>| { let port = |p: &mut Parser<'_>| p.read_number(10, 5, 0x10000).map(|n| n as u16);
p.read_number(10, 5, 0x10000).map(|n| n as u16)
};
self.read_seq_3(ip_addr, colon, port).map(|t| { self.read_seq_3(ip_addr, colon, port).map(|t| {
let (ip, _, port): (Ipv4Addr, char, u16) = t; let (ip, _, port): (Ipv4Addr, char, u16) = t;
@ -270,9 +259,7 @@ impl<'a> Parser<'a> {
p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1) p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1)
}; };
let colon = |p: &mut Parser<'_>| p.read_given_char(':'); let colon = |p: &mut Parser<'_>| p.read_given_char(':');
let port = |p: &mut Parser<'_>| { let port = |p: &mut Parser<'_>| p.read_number(10, 5, 0x10000).map(|n| n as u16);
p.read_number(10, 5, 0x10000).map(|n| n as u16)
};
self.read_seq_3(ip_addr, colon, port).map(|t| { self.read_seq_3(ip_addr, colon, port).map(|t| {
let (ip, _, port): (Ipv6Addr, char, u16) = t; let (ip, _, port): (Ipv6Addr, char, u16) = t;
@ -293,7 +280,7 @@ impl FromStr for IpAddr {
fn from_str(s: &str) -> Result<IpAddr, AddrParseError> { fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) { match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) {
Some(s) => Ok(s), Some(s) => Ok(s),
None => Err(AddrParseError(())) None => Err(AddrParseError(())),
} }
} }
} }
@ -304,7 +291,7 @@ impl FromStr for Ipv4Addr {
fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> { fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) { match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) {
Some(s) => Ok(s), Some(s) => Ok(s),
None => Err(AddrParseError(())) None => Err(AddrParseError(())),
} }
} }
} }
@ -315,7 +302,7 @@ impl FromStr for Ipv6Addr {
fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> { fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) { match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) {
Some(s) => Ok(s), Some(s) => Ok(s),
None => Err(AddrParseError(())) None => Err(AddrParseError(())),
} }
} }
} }

View file

@ -2,7 +2,7 @@ use crate::io::prelude::*;
use crate::fmt; use crate::fmt;
use crate::io::{self, Initializer, IoSlice, IoSliceMut}; use crate::io::{self, Initializer, IoSlice, IoSliceMut};
use crate::net::{ToSocketAddrs, SocketAddr, Shutdown}; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
use crate::sys_common::net as net_imp; use crate::sys_common::net as net_imp;
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration; use crate::time::Duration;
@ -93,7 +93,9 @@ pub struct TcpListener(net_imp::TcpListener);
/// [`TcpListener`]: ../../std/net/struct.TcpListener.html /// [`TcpListener`]: ../../std/net/struct.TcpListener.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)] #[derive(Debug)]
pub struct Incoming<'a> { listener: &'a TcpListener } pub struct Incoming<'a> {
listener: &'a TcpListener,
}
impl TcpStream { impl TcpStream {
/// Opens a TCP connection to a remote host. /// Opens a TCP connection to a remote host.
@ -567,7 +569,9 @@ impl TcpStream {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Read for TcpStream { impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0.read_vectored(bufs) self.0.read_vectored(bufs)
@ -580,17 +584,23 @@ impl Read for TcpStream {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Write for TcpStream { impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs) self.0.write_vectored(bufs)
} }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Read for &TcpStream { impl Read for &TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0.read_vectored(bufs) self.0.read_vectored(bufs)
@ -603,25 +613,35 @@ impl Read for &TcpStream {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Write for &TcpStream { impl Write for &TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs) self.0.write_vectored(bufs)
} }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
impl AsInner<net_imp::TcpStream> for TcpStream { impl AsInner<net_imp::TcpStream> for TcpStream {
fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } fn as_inner(&self) -> &net_imp::TcpStream {
&self.0
}
} }
impl FromInner<net_imp::TcpStream> for TcpStream { impl FromInner<net_imp::TcpStream> for TcpStream {
fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) } fn from_inner(inner: net_imp::TcpStream) -> TcpStream {
TcpStream(inner)
}
} }
impl IntoInner<net_imp::TcpStream> for TcpStream { impl IntoInner<net_imp::TcpStream> for TcpStream {
fn into_inner(self) -> net_imp::TcpStream { self.0 } fn into_inner(self) -> net_imp::TcpStream {
self.0
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -814,16 +834,20 @@ impl TcpListener {
} }
#[stable(feature = "net2_mutators", since = "1.9.0")] #[stable(feature = "net2_mutators", since = "1.9.0")]
#[rustc_deprecated(since = "1.16.0", #[rustc_deprecated(
reason = "this option can only be set before the socket is bound")] since = "1.16.0",
reason = "this option can only be set before the socket is bound"
)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
self.0.set_only_v6(only_v6) self.0.set_only_v6(only_v6)
} }
#[stable(feature = "net2_mutators", since = "1.9.0")] #[stable(feature = "net2_mutators", since = "1.9.0")]
#[rustc_deprecated(since = "1.16.0", #[rustc_deprecated(
reason = "this option can only be set before the socket is bound")] since = "1.16.0",
reason = "this option can only be set before the socket is bound"
)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn only_v6(&self) -> io::Result<bool> { pub fn only_v6(&self) -> io::Result<bool> {
self.0.only_v6() self.0.only_v6()
@ -907,7 +931,9 @@ impl<'a> Iterator for Incoming<'a> {
} }
impl AsInner<net_imp::TcpListener> for TcpListener { impl AsInner<net_imp::TcpListener> for TcpListener {
fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } fn as_inner(&self) -> &net_imp::TcpListener {
&self.0
}
} }
impl FromInner<net_imp::TcpListener> for TcpListener { impl FromInner<net_imp::TcpListener> for TcpListener {
@ -917,7 +943,9 @@ impl FromInner<net_imp::TcpListener> for TcpListener {
} }
impl IntoInner<net_imp::TcpListener> for TcpListener { impl IntoInner<net_imp::TcpListener> for TcpListener {
fn into_inner(self) -> net_imp::TcpListener { self.0 } fn into_inner(self) -> net_imp::TcpListener {
self.0
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -930,13 +958,13 @@ impl fmt::Debug for TcpListener {
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))] #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests { mod tests {
use crate::fmt; use crate::fmt;
use crate::io::{ErrorKind, IoSlice, IoSliceMut};
use crate::io::prelude::*; use crate::io::prelude::*;
use crate::net::*; use crate::io::{ErrorKind, IoSlice, IoSliceMut};
use crate::net::test::{next_test_ip4, next_test_ip6}; use crate::net::test::{next_test_ip4, next_test_ip6};
use crate::net::*;
use crate::sync::mpsc::channel; use crate::sync::mpsc::channel;
use crate::time::{Instant, Duration};
use crate::thread; use crate::thread;
use crate::time::{Duration, Instant};
fn each_ip(f: &mut dyn FnMut(SocketAddr)) { fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
f(next_test_ip4()); f(next_test_ip4());
@ -949,15 +977,14 @@ mod tests {
Ok(t) => t, Ok(t) => t,
Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
} }
} };
} }
#[test] #[test]
fn bind_error() { fn bind_error() {
match TcpListener::bind("1.1.1.1:9999") { match TcpListener::bind("1.1.1.1:9999") {
Ok(..) => panic!(), Ok(..) => panic!(),
Err(e) => Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
} }
} }
@ -965,11 +992,15 @@ mod tests {
fn connect_error() { fn connect_error() {
match TcpStream::connect("0.0.0.0:1") { match TcpStream::connect("0.0.0.0:1") {
Ok(..) => panic!(), Ok(..) => panic!(),
Err(e) => assert!(e.kind() == ErrorKind::ConnectionRefused || Err(e) => assert!(
e.kind() == ErrorKind::InvalidInput || e.kind() == ErrorKind::ConnectionRefused
e.kind() == ErrorKind::AddrInUse || || e.kind() == ErrorKind::InvalidInput
e.kind() == ErrorKind::AddrNotAvailable, || e.kind() == ErrorKind::AddrInUse
"bad error: {} {:?}", e, e.kind()), || e.kind() == ErrorKind::AddrNotAvailable,
"bad error: {} {:?}",
e,
e.kind()
),
} }
} }
@ -979,8 +1010,7 @@ mod tests {
let listener = t!(TcpListener::bind(&socket_addr)); let listener = t!(TcpListener::bind(&socket_addr));
let _t = thread::spawn(move || { let _t = thread::spawn(move || {
let mut stream = t!(TcpStream::connect(&("localhost", let mut stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
socket_addr.port())));
t!(stream.write(&[144])); t!(stream.write(&[144]));
}); });
@ -995,7 +1025,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let host = match addr { let host = match addr {
SocketAddr::V4(..) => "127.0.0.1", SocketAddr::V4(..) => "127.0.0.1",
SocketAddr::V6(..) => "::1", SocketAddr::V6(..) => "::1",
@ -1017,7 +1047,7 @@ mod tests {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let (tx, rx) = channel(); let (tx, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut stream = t!(TcpStream::connect(&addr)); let mut stream = t!(TcpStream::connect(&addr));
t!(stream.write(&[99])); t!(stream.write(&[99]));
tx.send(t!(stream.local_addr())).unwrap(); tx.send(t!(stream.local_addr())).unwrap();
@ -1036,7 +1066,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _stream = t!(TcpStream::connect(&addr)); let _stream = t!(TcpStream::connect(&addr));
// Close // Close
}); });
@ -1056,7 +1086,7 @@ mod tests {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let (tx, rx) = channel(); let (tx, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
drop(t!(TcpStream::connect(&addr))); drop(t!(TcpStream::connect(&addr)));
tx.send(()).unwrap(); tx.send(()).unwrap();
}); });
@ -1067,10 +1097,13 @@ mod tests {
match stream.write(&buf) { match stream.write(&buf) {
Ok(..) => {} Ok(..) => {}
Err(e) => { Err(e) => {
assert!(e.kind() == ErrorKind::ConnectionReset || assert!(
e.kind() == ErrorKind::BrokenPipe || e.kind() == ErrorKind::ConnectionReset
e.kind() == ErrorKind::ConnectionAborted, || e.kind() == ErrorKind::BrokenPipe
"unknown error: {}", e); || e.kind() == ErrorKind::ConnectionAborted,
"unknown error: {}",
e
);
} }
} }
}) })
@ -1082,7 +1115,7 @@ mod tests {
let max = 10; let max = 10;
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
for _ in 0..max { for _ in 0..max {
let mut stream = t!(TcpStream::connect(&addr)); let mut stream = t!(TcpStream::connect(&addr));
t!(stream.write(&[99])); t!(stream.write(&[99]));
@ -1104,11 +1137,11 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let acceptor = acceptor; let acceptor = acceptor;
for (i, stream) in acceptor.incoming().enumerate().take(MAX) { for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
// Start another thread to handle the connection // Start another thread to handle the connection
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut stream = t!(stream); let mut stream = t!(stream);
let mut buf = [0]; let mut buf = [0];
t!(stream.read(&mut buf)); t!(stream.read(&mut buf));
@ -1121,9 +1154,11 @@ mod tests {
}); });
fn connect(i: usize, addr: SocketAddr) { fn connect(i: usize, addr: SocketAddr) {
if i == MAX { return } if i == MAX {
return;
}
let t = thread::spawn(move|| { let t = thread::spawn(move || {
let mut stream = t!(TcpStream::connect(&addr)); let mut stream = t!(TcpStream::connect(&addr));
// Connect again before writing // Connect again before writing
connect(i + 1, addr); connect(i + 1, addr);
@ -1139,10 +1174,10 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
for stream in acceptor.incoming().take(MAX) { for stream in acceptor.incoming().take(MAX) {
// Start another thread to handle the connection // Start another thread to handle the connection
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut stream = t!(stream); let mut stream = t!(stream);
let mut buf = [0]; let mut buf = [0];
t!(stream.read(&mut buf)); t!(stream.read(&mut buf));
@ -1155,9 +1190,11 @@ mod tests {
}); });
fn connect(i: usize, addr: SocketAddr) { fn connect(i: usize, addr: SocketAddr) {
if i == MAX { return } if i == MAX {
return;
}
let t = thread::spawn(move|| { let t = thread::spawn(move || {
let mut stream = t!(TcpStream::connect(&addr)); let mut stream = t!(TcpStream::connect(&addr));
connect(i + 1, addr); connect(i + 1, addr);
t!(stream.write(&[99])); t!(stream.write(&[99]));
@ -1172,7 +1209,7 @@ mod tests {
let listener = t!(TcpListener::bind(&addr)); let listener = t!(TcpListener::bind(&addr));
let so_name = t!(listener.local_addr()); let so_name = t!(listener.local_addr());
assert_eq!(addr, so_name); assert_eq!(addr, so_name);
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
t!(listener.accept()); t!(listener.accept());
}); });
@ -1186,7 +1223,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let (tx, rx) = channel(); let (tx, rx) = channel();
let srv = t!(TcpListener::bind(&addr)); let srv = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut cl = t!(srv.accept()).0; let mut cl = t!(srv.accept()).0;
cl.write(&[10]).unwrap(); cl.write(&[10]).unwrap();
let mut b = [0]; let mut b = [0];
@ -1215,9 +1252,11 @@ mod tests {
let mut a = []; let mut a = [];
let mut b = [0]; let mut b = [0];
let mut c = [0; 3]; let mut c = [0; 3];
let len = t!(s2.read_vectored( let len = t!(s2.read_vectored(&mut [
&mut [IoSliceMut::new(&mut a), IoSliceMut::new(&mut b), IoSliceMut::new(&mut c)], IoSliceMut::new(&mut a),
)); IoSliceMut::new(&mut b),
IoSliceMut::new(&mut c)
],));
assert!(len > 0); assert!(len > 0);
assert_eq!(b, [10]); assert_eq!(b, [10]);
// some implementations don't support readv, so we may only fill the first buffer // some implementations don't support readv, so we may only fill the first buffer
@ -1260,10 +1299,14 @@ mod tests {
listener1, listener2 listener1, listener2
), ),
Err(e) => { Err(e) => {
assert!(e.kind() == ErrorKind::ConnectionRefused || assert!(
e.kind() == ErrorKind::Other || e.kind() == ErrorKind::ConnectionRefused
e.kind() == ErrorKind::AddrInUse, || e.kind() == ErrorKind::Other
"unknown error: {} {:?}", e, e.kind()); || e.kind() == ErrorKind::AddrInUse,
"unknown error: {} {:?}",
e,
e.kind()
);
} }
} }
}) })
@ -1274,7 +1317,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
t!(TcpStream::connect(&addr)); t!(TcpStream::connect(&addr));
}); });
@ -1289,7 +1332,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s = t!(TcpStream::connect(&addr)); let mut s = t!(TcpStream::connect(&addr));
let mut buf = [0, 0]; let mut buf = [0, 0];
assert_eq!(s.read(&mut buf).unwrap(), 1); assert_eq!(s.read(&mut buf).unwrap(), 1);
@ -1302,7 +1345,7 @@ mod tests {
let (tx1, rx1) = channel(); let (tx1, rx1) = channel();
let (tx2, rx2) = channel(); let (tx2, rx2) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s2 = s2; let mut s2 = s2;
rx1.recv().unwrap(); rx1.recv().unwrap();
t!(s2.write(&[1])); t!(s2.write(&[1]));
@ -1322,7 +1365,7 @@ mod tests {
let (tx1, rx) = channel(); let (tx1, rx) = channel();
let tx2 = tx1.clone(); let tx2 = tx1.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s = t!(TcpStream::connect(&addr)); let mut s = t!(TcpStream::connect(&addr));
t!(s.write(&[1])); t!(s.write(&[1]));
rx.recv().unwrap(); rx.recv().unwrap();
@ -1334,7 +1377,7 @@ mod tests {
let s2 = t!(s1.try_clone()); let s2 = t!(s1.try_clone());
let (done, rx) = channel(); let (done, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s2 = s2; let mut s2 = s2;
let mut buf = [0, 0]; let mut buf = [0, 0];
t!(s2.read(&mut buf)); t!(s2.read(&mut buf));
@ -1354,7 +1397,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr)); let acceptor = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s = t!(TcpStream::connect(&addr)); let mut s = t!(TcpStream::connect(&addr));
let mut buf = [0, 1]; let mut buf = [0, 1];
t!(s.read(&mut buf)); t!(s.read(&mut buf));
@ -1365,7 +1408,7 @@ mod tests {
let s2 = t!(s1.try_clone()); let s2 = t!(s1.try_clone());
let (done, rx) = channel(); let (done, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s2 = s2; let mut s2 = s2;
t!(s2.write(&[1])); t!(s2.write(&[1]));
done.send(()).unwrap(); done.send(()).unwrap();
@ -1382,7 +1425,7 @@ mod tests {
fn shutdown_smoke() { fn shutdown_smoke() {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr)); let a = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut c = t!(a.accept()).0; let mut c = t!(a.accept()).0;
let mut b = [0]; let mut b = [0];
assert_eq!(c.read(&mut b).unwrap(), 0); assert_eq!(c.read(&mut b).unwrap(), 0);
@ -1405,7 +1448,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr)); let a = t!(TcpListener::bind(&addr));
let (tx, rx) = channel::<()>(); let (tx, rx) = channel::<()>();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _s = t!(a.accept()); let _s = t!(a.accept());
let _ = rx.recv(); let _ = rx.recv();
}); });
@ -1444,7 +1487,7 @@ mod tests {
each_ip(&mut |addr| { each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr)); let a = t!(TcpListener::bind(&addr));
let (tx1, rx) = channel::<()>(); let (tx1, rx) = channel::<()>();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _s = t!(a.accept()); let _s = t!(a.accept());
let _ = rx.recv(); let _ = rx.recv();
}); });
@ -1452,7 +1495,7 @@ mod tests {
let s = t!(TcpStream::connect(&addr)); let s = t!(TcpStream::connect(&addr));
let s2 = t!(s.try_clone()); let s2 = t!(s.try_clone());
let (tx, rx) = channel(); let (tx, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut s2 = s2; let mut s2 = s2;
assert_eq!(t!(s2.read(&mut [0])), 0); assert_eq!(t!(s2.read(&mut [0])), 0);
tx.send(()).unwrap(); tx.send(()).unwrap();
@ -1475,7 +1518,7 @@ mod tests {
let (tx, rx) = channel(); let (tx, rx) = channel();
let (txdone, rxdone) = channel(); let (txdone, rxdone) = channel();
let txdone2 = txdone.clone(); let txdone2 = txdone.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut tcp = t!(TcpStream::connect(&addr)); let mut tcp = t!(TcpStream::connect(&addr));
rx.recv().unwrap(); rx.recv().unwrap();
t!(tcp.write(&[0])); t!(tcp.write(&[0]));
@ -1486,7 +1529,7 @@ mod tests {
let tcp = t!(accept.accept()).0; let tcp = t!(accept.accept()).0;
let tcp2 = t!(tcp.try_clone()); let tcp2 = t!(tcp.try_clone());
let txdone3 = txdone.clone(); let txdone3 = txdone.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut tcp2 = tcp2; let mut tcp2 = tcp2;
t!(tcp2.read(&mut [0])); t!(tcp2.read(&mut [0]));
txdone3.send(()).unwrap(); txdone3.send(()).unwrap();
@ -1512,10 +1555,10 @@ mod tests {
let a = t!(TcpListener::bind(&addr)); let a = t!(TcpListener::bind(&addr));
let a2 = t!(a.try_clone()); let a2 = t!(a.try_clone());
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _ = TcpStream::connect(&addr); let _ = TcpStream::connect(&addr);
}); });
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _ = TcpStream::connect(&addr); let _ = TcpStream::connect(&addr);
}); });
@ -1533,17 +1576,17 @@ mod tests {
let (tx, rx) = channel(); let (tx, rx) = channel();
let tx2 = tx.clone(); let tx2 = tx.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
tx.send(t!(a.accept())).unwrap(); tx.send(t!(a.accept())).unwrap();
}); });
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
tx2.send(t!(a2.accept())).unwrap(); tx2.send(t!(a2.accept())).unwrap();
}); });
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _ = TcpStream::connect(&addr); let _ = TcpStream::connect(&addr);
}); });
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let _ = TcpStream::connect(&addr); let _ = TcpStream::connect(&addr);
}); });
@ -1563,10 +1606,10 @@ mod tests {
addr.to_string() addr.to_string()
} }
#[cfg(unix)]
use crate::os::unix::io::AsRawFd;
#[cfg(target_env = "sgx")] #[cfg(target_env = "sgx")]
use crate::os::fortanix_sgx::io::AsRawFd; use crate::os::fortanix_sgx::io::AsRawFd;
#[cfg(unix)]
use crate::os::unix::io::AsRawFd;
#[cfg(not(windows))] #[cfg(not(windows))]
fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug { fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
addr.as_raw_fd() addr.as_raw_fd()
@ -1576,22 +1619,26 @@ mod tests {
addr.as_raw_socket() addr.as_raw_socket()
} }
let inner_name = if cfg!(windows) {"socket"} else {"fd"}; let inner_name = if cfg!(windows) { "socket" } else { "fd" };
let socket_addr = next_test_ip4(); let socket_addr = next_test_ip4();
let listener = t!(TcpListener::bind(&socket_addr)); let listener = t!(TcpListener::bind(&socket_addr));
let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}", let compare = format!(
"TcpListener {{ addr: {:?}, {}: {:?} }}",
render_socket_addr(&socket_addr), render_socket_addr(&socket_addr),
inner_name, inner_name,
render_inner(&listener)); render_inner(&listener)
);
assert_eq!(format!("{:?}", listener), compare); assert_eq!(format!("{:?}", listener), compare);
let stream = t!(TcpStream::connect(&("localhost", socket_addr.port()))); let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
let compare = format!("TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}", let compare = format!(
"TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
render_socket_addr(&stream.local_addr().unwrap()), render_socket_addr(&stream.local_addr().unwrap()),
render_socket_addr(&stream.peer_addr().unwrap()), render_socket_addr(&stream.peer_addr().unwrap()),
inner_name, inner_name,
render_inner(&stream)); render_inner(&stream)
);
assert_eq!(format!("{:?}", stream), compare); assert_eq!(format!("{:?}", stream), compare);
} }
@ -1638,8 +1685,11 @@ mod tests {
let mut buf = [0; 10]; let mut buf = [0; 10];
let start = Instant::now(); let start = Instant::now();
let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, assert!(
"unexpected_error: {:?}", kind); kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
"unexpected_error: {:?}",
kind
);
assert!(start.elapsed() > Duration::from_millis(400)); assert!(start.elapsed() > Duration::from_millis(400));
drop(listener); drop(listener);
} }
@ -1662,8 +1712,11 @@ mod tests {
let start = Instant::now(); let start = Instant::now();
let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, assert!(
"unexpected_error: {:?}", kind); kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
"unexpected_error: {:?}",
kind
);
assert!(start.elapsed() > Duration::from_millis(400)); assert!(start.elapsed() > Duration::from_millis(400));
drop(listener); drop(listener);
} }
@ -1749,9 +1802,9 @@ mod tests {
let (txdone, rxdone) = channel(); let (txdone, rxdone) = channel();
let srv = t!(TcpListener::bind(&addr)); let srv = t!(TcpListener::bind(&addr));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut cl = t!(srv.accept()).0; let mut cl = t!(srv.accept()).0;
cl.write(&[1,3,3,7]).unwrap(); cl.write(&[1, 3, 3, 7]).unwrap();
t!(rxdone.recv()); t!(rxdone.recv());
}); });

View file

@ -1,7 +1,7 @@
#![allow(warnings)] // not used on emscripten #![allow(warnings)] // not used on emscripten
use crate::env; use crate::env;
use crate::net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr, ToSocketAddrs}; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::atomic::{AtomicUsize, Ordering};
static PORT: AtomicUsize = AtomicUsize::new(0); static PORT: AtomicUsize = AtomicUsize::new(0);
@ -13,8 +13,7 @@ pub fn next_test_ip4() -> SocketAddr {
pub fn next_test_ip6() -> SocketAddr { pub fn next_test_ip6() -> SocketAddr {
let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port();
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), port, 0, 0))
port, 0, 0))
} }
pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr {
@ -41,11 +40,21 @@ fn base_port() -> u16 {
} else { } else {
env::current_dir().unwrap().into_os_string().into_string().unwrap() env::current_dir().unwrap().into_os_string().into_string().unwrap()
}; };
let dirs = ["32-opt", "32-nopt", let dirs = [
"musl-64-opt", "cross-opt", "32-opt",
"64-opt", "64-nopt", "64-opt-vg", "64-debug-opt", "32-nopt",
"all-opt", "snap3", "dist", "sgx"]; "musl-64-opt",
dirs.iter().enumerate().find(|&(_, dir)| { "cross-opt",
cwd.contains(dir) "64-opt",
}).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600 "64-nopt",
"64-opt-vg",
"64-debug-opt",
"all-opt",
"snap3",
"dist",
"sgx",
];
dirs.iter().enumerate().find(|&(_, dir)| cwd.contains(dir)).map(|p| p.0).unwrap_or(0) as u16
* 1000
+ 19600
} }

View file

@ -1,6 +1,6 @@
use crate::fmt; use crate::fmt;
use crate::io::{self, Error, ErrorKind}; use crate::io::{self, Error, ErrorKind};
use crate::net::{ToSocketAddrs, SocketAddr, Ipv4Addr, Ipv6Addr}; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
use crate::sys_common::net as net_imp; use crate::sys_common::net as net_imp;
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration; use crate::time::Duration;
@ -171,12 +171,10 @@ impl UdpSocket {
/// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data"); /// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
-> io::Result<usize> {
match addr.to_socket_addrs()?.next() { match addr.to_socket_addrs()?.next() {
Some(addr) => self.0.send_to(buf, &addr), Some(addr) => self.0.send_to(buf, &addr),
None => Err(Error::new(ErrorKind::InvalidInput, None => Err(Error::new(ErrorKind::InvalidInput, "no addresses to send data to")),
"no addresses to send data to")),
} }
} }
@ -817,15 +815,21 @@ impl UdpSocket {
} }
impl AsInner<net_imp::UdpSocket> for UdpSocket { impl AsInner<net_imp::UdpSocket> for UdpSocket {
fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } fn as_inner(&self) -> &net_imp::UdpSocket {
&self.0
}
} }
impl FromInner<net_imp::UdpSocket> for UdpSocket { impl FromInner<net_imp::UdpSocket> for UdpSocket {
fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) } fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket {
UdpSocket(inner)
}
} }
impl IntoInner<net_imp::UdpSocket> for UdpSocket { impl IntoInner<net_imp::UdpSocket> for UdpSocket {
fn into_inner(self) -> net_imp::UdpSocket { self.0 } fn into_inner(self) -> net_imp::UdpSocket {
self.0
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -838,12 +842,12 @@ impl fmt::Debug for UdpSocket {
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))] #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
mod tests { mod tests {
use crate::io::ErrorKind; use crate::io::ErrorKind;
use crate::net::*;
use crate::net::test::{next_test_ip4, next_test_ip6}; use crate::net::test::{next_test_ip4, next_test_ip6};
use crate::net::*;
use crate::sync::mpsc::channel; use crate::sync::mpsc::channel;
use crate::sys_common::AsInner; use crate::sys_common::AsInner;
use crate::time::{Instant, Duration};
use crate::thread; use crate::thread;
use crate::time::{Duration, Instant};
fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) { fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
f(next_test_ip4(), next_test_ip4()); f(next_test_ip4(), next_test_ip4());
@ -856,16 +860,14 @@ mod tests {
Ok(t) => t, Ok(t) => t,
Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
} }
} };
} }
#[test] #[test]
fn bind_error() { fn bind_error() {
match UdpSocket::bind("1.1.1.1:9999") { match UdpSocket::bind("1.1.1.1:9999") {
Ok(..) => panic!(), Ok(..) => panic!(),
Err(e) => { Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
assert_eq!(e.kind(), ErrorKind::AddrNotAvailable)
}
} }
} }
@ -875,7 +877,7 @@ mod tests {
let (tx1, rx1) = channel(); let (tx1, rx1) = channel();
let (tx2, rx2) = channel(); let (tx2, rx2) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let client = t!(UdpSocket::bind(&client_ip)); let client = t!(UdpSocket::bind(&client_ip));
rx1.recv().unwrap(); rx1.recv().unwrap();
t!(client.send_to(&[99], &server_ip)); t!(client.send_to(&[99], &server_ip));
@ -917,7 +919,7 @@ mod tests {
let sock1 = t!(UdpSocket::bind(&addr1)); let sock1 = t!(UdpSocket::bind(&addr1));
let sock2 = t!(UdpSocket::bind(&addr2)); let sock2 = t!(UdpSocket::bind(&addr2));
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut buf = [0, 0]; let mut buf = [0, 0];
assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1)); assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
assert_eq!(buf[0], 1); assert_eq!(buf[0], 1);
@ -928,7 +930,7 @@ mod tests {
let (tx1, rx1) = channel(); let (tx1, rx1) = channel();
let (tx2, rx2) = channel(); let (tx2, rx2) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
rx1.recv().unwrap(); rx1.recv().unwrap();
t!(sock3.send_to(&[1], &addr2)); t!(sock3.send_to(&[1], &addr2));
tx2.send(()).unwrap(); tx2.send(()).unwrap();
@ -948,7 +950,7 @@ mod tests {
let (tx1, rx) = channel(); let (tx1, rx) = channel();
let tx2 = tx1.clone(); let tx2 = tx1.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
t!(sock2.send_to(&[1], &addr1)); t!(sock2.send_to(&[1], &addr1));
rx.recv().unwrap(); rx.recv().unwrap();
t!(sock2.send_to(&[2], &addr1)); t!(sock2.send_to(&[2], &addr1));
@ -958,7 +960,7 @@ mod tests {
let sock3 = t!(sock1.try_clone()); let sock3 = t!(sock1.try_clone());
let (done, rx) = channel(); let (done, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut buf = [0, 0]; let mut buf = [0, 0];
t!(sock3.recv_from(&mut buf)); t!(sock3.recv_from(&mut buf));
tx2.send(()).unwrap(); tx2.send(()).unwrap();
@ -981,7 +983,7 @@ mod tests {
let (tx, rx) = channel(); let (tx, rx) = channel();
let (serv_tx, serv_rx) = channel(); let (serv_tx, serv_rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
let mut buf = [0, 1]; let mut buf = [0, 1];
rx.recv().unwrap(); rx.recv().unwrap();
t!(sock2.recv_from(&mut buf)); t!(sock2.recv_from(&mut buf));
@ -992,15 +994,19 @@ mod tests {
let (done, rx) = channel(); let (done, rx) = channel();
let tx2 = tx.clone(); let tx2 = tx.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
match sock3.send_to(&[1], &addr2) { match sock3.send_to(&[1], &addr2) {
Ok(..) => { let _ = tx2.send(()); } Ok(..) => {
let _ = tx2.send(());
}
Err(..) => {} Err(..) => {}
} }
done.send(()).unwrap(); done.send(()).unwrap();
}); });
match sock1.send_to(&[2], &addr2) { match sock1.send_to(&[2], &addr2) {
Ok(..) => { let _ = tx.send(()); } Ok(..) => {
let _ = tx.send(());
}
Err(..) => {} Err(..) => {}
} }
drop(tx); drop(tx);
@ -1012,13 +1018,13 @@ mod tests {
#[test] #[test]
fn debug() { fn debug() {
let name = if cfg!(windows) {"socket"} else {"fd"}; let name = if cfg!(windows) { "socket" } else { "fd" };
let socket_addr = next_test_ip4(); let socket_addr = next_test_ip4();
let udpsock = t!(UdpSocket::bind(&socket_addr)); let udpsock = t!(UdpSocket::bind(&socket_addr));
let udpsock_inner = udpsock.0.socket().as_inner(); let udpsock_inner = udpsock.0.socket().as_inner();
let compare = format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", let compare =
socket_addr, name, udpsock_inner); format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", socket_addr, name, udpsock_inner);
assert_eq!(format!("{:?}", udpsock), compare); assert_eq!(format!("{:?}", udpsock), compare);
} }
@ -1063,8 +1069,11 @@ mod tests {
loop { loop {
let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
if kind != ErrorKind::Interrupted { if kind != ErrorKind::Interrupted {
assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, assert!(
"unexpected_error: {:?}", kind); kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
"unexpected_error: {:?}",
kind
);
break; break;
} }
} }
@ -1088,8 +1097,11 @@ mod tests {
loop { loop {
let kind = stream.recv_from(&mut buf).err().expect("expected error").kind(); let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
if kind != ErrorKind::Interrupted { if kind != ErrorKind::Interrupted {
assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, assert!(
"unexpected_error: {:?}", kind); kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
"unexpected_error: {:?}",
kind
);
break; break;
} }
} }

View file

@ -6,33 +6,41 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)] #![allow(missing_docs)]
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::Wrapping; pub use core::num::Wrapping;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};
#[stable(feature = "nonzero", since = "1.28.0")]
pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
#[stable(feature = "signed_nonzero", since = "1.34.0")] #[stable(feature = "signed_nonzero", since = "1.34.0")]
pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize}; pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
#[stable(feature = "nonzero", since = "1.28.0")]
pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
#[unstable(feature = "int_error_matching", #[unstable(
feature = "int_error_matching",
reason = "it can be useful to match errors when making error messages \ reason = "it can be useful to match errors when making error messages \
for integer parsing", for integer parsing",
issue = "22639")] issue = "22639"
)]
pub use core::num::IntErrorKind; pub use core::num::IntErrorKind;
#[cfg(test)] use crate::fmt; #[cfg(test)]
#[cfg(test)] use crate::ops::{Add, Sub, Mul, Div, Rem}; use crate::fmt;
#[cfg(test)]
use crate::ops::{Add, Div, Mul, Rem, Sub};
/// Helper function for testing numeric operations /// Helper function for testing numeric operations
#[cfg(test)] #[cfg(test)]
pub fn test_num<T>(ten: T, two: T) where pub fn test_num<T>(ten: T, two: T)
where
T: PartialEq T: PartialEq
+ Add<Output=T> + Sub<Output=T> + Add<Output = T>
+ Mul<Output=T> + Div<Output=T> + Sub<Output = T>
+ Rem<Output=T> + fmt::Debug + Mul<Output = T>
+ Copy + Div<Output = T>
+ Rem<Output = T>
+ fmt::Debug
+ Copy,
{ {
assert_eq!(ten.add(two), ten + two); assert_eq!(ten.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two); assert_eq!(ten.sub(two), ten - two);
@ -43,20 +51,20 @@ pub fn test_num<T>(ten: T, two: T) where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::u8; use crate::ops::Mul;
use crate::u16; use crate::u16;
use crate::u32; use crate::u32;
use crate::u64; use crate::u64;
use crate::u8;
use crate::usize; use crate::usize;
use crate::ops::Mul;
#[test] #[test]
fn test_saturating_add_uint() { fn test_saturating_add_uint() {
use crate::usize::MAX; use crate::usize::MAX;
assert_eq!(3_usize.saturating_add(5_usize), 8_usize); assert_eq!(3_usize.saturating_add(5_usize), 8_usize);
assert_eq!(3_usize.saturating_add(MAX-1), MAX); assert_eq!(3_usize.saturating_add(MAX - 1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX); assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX-2).saturating_add(1), MAX-1); assert_eq!((MAX - 2).saturating_add(1), MAX - 1);
} }
#[test] #[test]
@ -65,16 +73,16 @@ mod tests {
assert_eq!(5_usize.saturating_sub(3_usize), 2_usize); assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
assert_eq!(3_usize.saturating_sub(5_usize), 0_usize); assert_eq!(3_usize.saturating_sub(5_usize), 0_usize);
assert_eq!(0_usize.saturating_sub(1_usize), 0_usize); assert_eq!(0_usize.saturating_sub(1_usize), 0_usize);
assert_eq!((MAX-1).saturating_sub(MAX), 0); assert_eq!((MAX - 1).saturating_sub(MAX), 0);
} }
#[test] #[test]
fn test_saturating_add_int() { fn test_saturating_add_int() {
use crate::isize::{MIN,MAX}; use crate::isize::{MAX, MIN};
assert_eq!(3i32.saturating_add(5), 8); assert_eq!(3i32.saturating_add(5), 8);
assert_eq!(3isize.saturating_add(MAX-1), MAX); assert_eq!(3isize.saturating_add(MAX - 1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX); assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX-2).saturating_add(1), MAX-1); assert_eq!((MAX - 2).saturating_add(1), MAX - 1);
assert_eq!(3i32.saturating_add(-5), -2); assert_eq!(3i32.saturating_add(-5), -2);
assert_eq!(MIN.saturating_add(-1), MIN); assert_eq!(MIN.saturating_add(-1), MIN);
assert_eq!((-2isize).saturating_add(-MAX), MIN); assert_eq!((-2isize).saturating_add(-MAX), MIN);
@ -82,14 +90,14 @@ mod tests {
#[test] #[test]
fn test_saturating_sub_int() { fn test_saturating_sub_int() {
use crate::isize::{MIN,MAX}; use crate::isize::{MAX, MIN};
assert_eq!(3i32.saturating_sub(5), -2); assert_eq!(3i32.saturating_sub(5), -2);
assert_eq!(MIN.saturating_sub(1), MIN); assert_eq!(MIN.saturating_sub(1), MIN);
assert_eq!((-2isize).saturating_sub(MAX), MIN); assert_eq!((-2isize).saturating_sub(MAX), MIN);
assert_eq!(3i32.saturating_sub(-5), 8); assert_eq!(3i32.saturating_sub(-5), 8);
assert_eq!(3isize.saturating_sub(-(MAX-1)), MAX); assert_eq!(3isize.saturating_sub(-(MAX - 1)), MAX);
assert_eq!(MAX.saturating_sub(-MAX), MAX); assert_eq!(MAX.saturating_sub(-MAX), MAX);
assert_eq!((MAX-2).saturating_sub(-1), MAX-1); assert_eq!((MAX - 2).saturating_sub(-1), MAX - 1);
} }
#[test] #[test]
@ -128,7 +136,7 @@ mod tests {
} }
macro_rules! test_is_power_of_two { macro_rules! test_is_power_of_two {
($test_name:ident, $T:ident) => ( ($test_name:ident, $T:ident) => {
fn $test_name() { fn $test_name() {
#![test] #![test]
assert_eq!((0 as $T).is_power_of_two(), false); assert_eq!((0 as $T).is_power_of_two(), false);
@ -139,27 +147,29 @@ mod tests {
assert_eq!((5 as $T).is_power_of_two(), false); assert_eq!((5 as $T).is_power_of_two(), false);
assert_eq!(($T::MAX / 2 + 1).is_power_of_two(), true); assert_eq!(($T::MAX / 2 + 1).is_power_of_two(), true);
} }
) };
} }
test_is_power_of_two!{ test_is_power_of_two_u8, u8 } test_is_power_of_two! { test_is_power_of_two_u8, u8 }
test_is_power_of_two!{ test_is_power_of_two_u16, u16 } test_is_power_of_two! { test_is_power_of_two_u16, u16 }
test_is_power_of_two!{ test_is_power_of_two_u32, u32 } test_is_power_of_two! { test_is_power_of_two_u32, u32 }
test_is_power_of_two!{ test_is_power_of_two_u64, u64 } test_is_power_of_two! { test_is_power_of_two_u64, u64 }
test_is_power_of_two!{ test_is_power_of_two_uint, usize } test_is_power_of_two! { test_is_power_of_two_uint, usize }
macro_rules! test_next_power_of_two { macro_rules! test_next_power_of_two {
($test_name:ident, $T:ident) => ( ($test_name:ident, $T:ident) => {
fn $test_name() { fn $test_name() {
#![test] #![test]
assert_eq!((0 as $T).next_power_of_two(), 1); assert_eq!((0 as $T).next_power_of_two(), 1);
let mut next_power = 1; let mut next_power = 1;
for i in 1 as $T..40 { for i in 1 as $T..40 {
assert_eq!(i.next_power_of_two(), next_power); assert_eq!(i.next_power_of_two(), next_power);
if i == next_power { next_power *= 2 } if i == next_power {
next_power *= 2
} }
} }
) }
};
} }
test_next_power_of_two! { test_next_power_of_two_u8, u8 } test_next_power_of_two! { test_next_power_of_two_u8, u8 }
@ -169,12 +179,12 @@ mod tests {
test_next_power_of_two! { test_next_power_of_two_uint, usize } test_next_power_of_two! { test_next_power_of_two_uint, usize }
macro_rules! test_checked_next_power_of_two { macro_rules! test_checked_next_power_of_two {
($test_name:ident, $T:ident) => ( ($test_name:ident, $T:ident) => {
fn $test_name() { fn $test_name() {
#![test] #![test]
assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
let smax = $T::MAX >> 1; let smax = $T::MAX >> 1;
assert_eq!(smax.checked_next_power_of_two(), Some(smax+1)); assert_eq!(smax.checked_next_power_of_two(), Some(smax + 1));
assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1)); assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1));
assert_eq!((smax + 2).checked_next_power_of_two(), None); assert_eq!((smax + 2).checked_next_power_of_two(), None);
assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None); assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
@ -182,10 +192,12 @@ mod tests {
let mut next_power = 1; let mut next_power = 1;
for i in 1 as $T..40 { for i in 1 as $T..40 {
assert_eq!(i.checked_next_power_of_two(), Some(next_power)); assert_eq!(i.checked_next_power_of_two(), Some(next_power));
if i == next_power { next_power *= 2 } if i == next_power {
next_power *= 2
} }
} }
) }
};
} }
test_checked_next_power_of_two! { test_checked_next_power_of_two_u8, u8 } test_checked_next_power_of_two! { test_checked_next_power_of_two_u8, u8 }
@ -196,7 +208,7 @@ mod tests {
#[test] #[test]
fn test_pow() { fn test_pow() {
fn naive_pow<T: Mul<Output=T> + Copy>(one: T, base: T, exp: usize) -> T { fn naive_pow<T: Mul<Output = T> + Copy>(one: T, base: T, exp: usize) -> T {
(0..exp).fold(one, |acc, _| acc * base) (0..exp).fold(one, |acc, _| acc * base)
} }
macro_rules! assert_pow { macro_rules! assert_pow {
@ -204,7 +216,7 @@ mod tests {
let result = $num.pow($exp); let result = $num.pow($exp);
assert_eq!(result, $expected); assert_eq!(result, $expected);
assert_eq!(result, naive_pow(1, $num, $exp)); assert_eq!(result, naive_pow(1, $num, $exp));
}} }};
} }
assert_pow!((3u32, 0 ) => 1); assert_pow!((3u32, 0 ) => 1);
assert_pow!((5u32, 1 ) => 5); assert_pow!((5u32, 1 ) => 5);
@ -280,7 +292,6 @@ mod tests {
} }
} }
#[cfg(test)] #[cfg(test)]
mod bench { mod bench {
use test::Bencher; use test::Bencher;
@ -288,6 +299,8 @@ mod bench {
#[bench] #[bench]
fn bench_pow_function(b: &mut Bencher) { fn bench_pow_function(b: &mut Bencher) {
let v = (0..1024).collect::<Vec<u32>>(); let v = (0..1024).collect::<Vec<u32>>();
b.iter(|| {v.iter().fold(0u32, |old, new| old.pow(*new as u32));}); b.iter(|| {
v.iter().fold(0u32, |old, new| old.pow(*new as u32));
});
} }
} }

View file

@ -7,21 +7,21 @@ use crate::cell::UnsafeCell;
use crate::collections; use crate::collections;
use crate::fmt; use crate::fmt;
use crate::future::Future; use crate::future::Future;
use crate::pin::Pin;
use crate::ops::{Deref, DerefMut}; use crate::ops::{Deref, DerefMut};
use crate::panicking; use crate::panicking;
use crate::ptr::{Unique, NonNull}; use crate::pin::Pin;
use crate::ptr::{NonNull, Unique};
use crate::rc::Rc; use crate::rc::Rc;
use crate::sync::{Arc, Mutex, RwLock};
use crate::sync::atomic; use crate::sync::atomic;
use crate::sync::{Arc, Mutex, RwLock};
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
use crate::thread::Result; use crate::thread::Result;
#[stable(feature = "panic_hooks", since = "1.10.0")] #[stable(feature = "panic_hooks", since = "1.10.0")]
pub use crate::panicking::{take_hook, set_hook}; pub use crate::panicking::{set_hook, take_hook};
#[stable(feature = "panic_hooks", since = "1.10.0")] #[stable(feature = "panic_hooks", since = "1.10.0")]
pub use core::panic::{PanicInfo, Location}; pub use core::panic::{Location, PanicInfo};
/// A marker trait which represents "panic safe" types in Rust. /// A marker trait which represents "panic safe" types in Rust.
/// ///
@ -103,8 +103,8 @@ pub use core::panic::{PanicInfo, Location};
/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html /// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
#[stable(feature = "catch_unwind", since = "1.9.0")] #[stable(feature = "catch_unwind", since = "1.9.0")]
#[rustc_on_unimplemented( #[rustc_on_unimplemented(
message="the type `{Self}` may not be safely transferred across an unwind boundary", message = "the type `{Self}` may not be safely transferred across an unwind boundary",
label="`{Self}` may not be safely transferred across an unwind boundary", label = "`{Self}` may not be safely transferred across an unwind boundary"
)] )]
pub auto trait UnwindSafe {} pub auto trait UnwindSafe {}
@ -121,10 +121,10 @@ pub auto trait UnwindSafe {}
/// [`UnwindSafe`]: ./trait.UnwindSafe.html /// [`UnwindSafe`]: ./trait.UnwindSafe.html
#[stable(feature = "catch_unwind", since = "1.9.0")] #[stable(feature = "catch_unwind", since = "1.9.0")]
#[rustc_on_unimplemented( #[rustc_on_unimplemented(
message="the type `{Self}` may contain interior mutability and a reference may not be safely \ message = "the type `{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary",
label="`{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary", transferrable across a catch_unwind boundary",
label = "`{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary"
)] )]
pub auto trait RefUnwindSafe {} pub auto trait RefUnwindSafe {}
@ -187,10 +187,7 @@ pub auto trait RefUnwindSafe {}
/// // ... /// // ...
/// ``` /// ```
#[stable(feature = "catch_unwind", since = "1.9.0")] #[stable(feature = "catch_unwind", since = "1.9.0")]
pub struct AssertUnwindSafe<T>( pub struct AssertUnwindSafe<T>(#[stable(feature = "catch_unwind", since = "1.9.0")] pub T);
#[stable(feature = "catch_unwind", since = "1.9.0")]
pub T
);
// Implementations of the `UnwindSafe` trait: // Implementations of the `UnwindSafe` trait:
// //
@ -290,7 +287,12 @@ impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
// https://github.com/rust-lang/rust/issues/62301 // https://github.com/rust-lang/rust/issues/62301
#[stable(feature = "hashbrown", since = "1.36.0")] #[stable(feature = "hashbrown", since = "1.36.0")]
impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S> impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S>
where K: UnwindSafe, V: UnwindSafe, S: UnwindSafe {} where
K: UnwindSafe,
V: UnwindSafe,
S: UnwindSafe,
{
}
#[stable(feature = "catch_unwind", since = "1.9.0")] #[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T> Deref for AssertUnwindSafe<T> { impl<T> Deref for AssertUnwindSafe<T> {
@ -320,9 +322,7 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> { impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("AssertUnwindSafe") f.debug_tuple("AssertUnwindSafe").field(&self.0).finish()
.field(&self.0)
.finish()
} }
} }
@ -391,9 +391,7 @@ impl<F: Future> Future for AssertUnwindSafe<F> {
/// ``` /// ```
#[stable(feature = "catch_unwind", since = "1.9.0")] #[stable(feature = "catch_unwind", since = "1.9.0")]
pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> { pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
unsafe { unsafe { panicking::r#try(f) }
panicking::r#try(f)
}
} }
/// Triggers a panic without invoking the panic hook. /// Triggers a panic without invoking the panic hook.

View file

@ -84,7 +84,7 @@ use crate::sync::Arc;
use crate::ffi::{OsStr, OsString}; use crate::ffi::{OsStr, OsString};
use crate::sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// GENERAL NOTES // GENERAL NOTES
@ -196,26 +196,13 @@ impl<'a> Prefix<'a> {
match *self { match *self {
Verbatim(x) => 4 + os_str_len(x), Verbatim(x) => 4 + os_str_len(x),
VerbatimUNC(x, y) => { VerbatimUNC(x, y) => {
8 + os_str_len(x) + 8 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 }
if os_str_len(y) > 0 {
1 + os_str_len(y)
} else {
0
} }
},
VerbatimDisk(_) => 6, VerbatimDisk(_) => 6,
UNC(x, y) => { UNC(x, y) => 2 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 },
2 + os_str_len(x) +
if os_str_len(y) > 0 {
1 + os_str_len(y)
} else {
0
}
},
DeviceNS(x) => 4 + os_str_len(x), DeviceNS(x) => 4 + os_str_len(x),
Disk(_) => 2, Disk(_) => 2,
} }
} }
/// Determines if the prefix is verbatim, i.e., begins with `\\?\`. /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.
@ -291,7 +278,8 @@ pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
// is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
// `iter` after having exhausted `prefix`. // `iter` after having exhausted `prefix`.
fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I> fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
where I: Iterator<Item = Component<'a>> + Clone, where
I: Iterator<Item = Component<'a>> + Clone,
J: Iterator<Item = Component<'b>>, J: Iterator<Item = Component<'b>>,
{ {
loop { loop {
@ -326,11 +314,7 @@ fn has_redox_scheme(s: &[u8]) -> bool {
/// Says whether the first byte after the prefix is a separator. /// Says whether the first byte after the prefix is a separator.
fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool { fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
let path = if let Some(p) = prefix { let path = if let Some(p) = prefix { &s[p.len()..] } else { s };
&s[p.len()..]
} else {
s
};
!path.is_empty() && is_sep_byte(path[0]) !path.is_empty() && is_sep_byte(path[0])
} }
@ -352,8 +336,7 @@ fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
if before == Some(b"") { if before == Some(b"") {
(Some(file), None) (Some(file), None)
} else { } else {
(before.map(|s| u8_slice_as_os_str(s)), (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s)))
after.map(|s| u8_slice_as_os_str(s)))
} }
} }
} }
@ -509,9 +492,7 @@ pub enum Component<'a> {
/// ///
/// [`Prefix`]: enum.Prefix.html /// [`Prefix`]: enum.Prefix.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
Prefix( Prefix(#[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>),
#[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>
),
/// The root directory component, appears after any prefix and before anything else. /// The root directory component, appears after any prefix and before anything else.
/// ///
@ -637,15 +618,11 @@ impl fmt::Debug for Components<'_> {
impl fmt::Debug for DebugHelper<'_> { impl fmt::Debug for DebugHelper<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list() f.debug_list().entries(self.0.components()).finish()
.entries(self.0.components())
.finish()
} }
} }
f.debug_tuple("Components") f.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()
.field(&DebugHelper(self.as_path()))
.finish()
} }
} }
@ -664,26 +641,14 @@ impl<'a> Components<'a> {
/// how much of the prefix is left from the point of view of iteration? /// how much of the prefix is left from the point of view of iteration?
#[inline] #[inline]
fn prefix_remaining(&self) -> usize { fn prefix_remaining(&self) -> usize {
if self.front == State::Prefix { if self.front == State::Prefix { self.prefix_len() } else { 0 }
self.prefix_len()
} else {
0
}
} }
// Given the iteration so far, how much of the pre-State::Body path is left? // Given the iteration so far, how much of the pre-State::Body path is left?
#[inline] #[inline]
fn len_before_body(&self) -> usize { fn len_before_body(&self) -> usize {
let root = if self.front <= State::StartDir && self.has_physical_root { let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 };
1 let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 };
} else {
0
};
let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() {
1
} else {
0
};
self.prefix_remaining() + root + cur_dir self.prefix_remaining() + root + cur_dir
} }
@ -695,11 +660,7 @@ impl<'a> Components<'a> {
#[inline] #[inline]
fn is_sep_byte(&self, b: u8) -> bool { fn is_sep_byte(&self, b: u8) -> bool {
if self.prefix_verbatim() { if self.prefix_verbatim() { is_verbatim_sep(b) } else { is_sep_byte(b) }
is_verbatim_sep(b)
} else {
is_sep_byte(b)
}
} }
/// Extracts a slice corresponding to the portion of the path remaining for iteration. /// Extracts a slice corresponding to the portion of the path remaining for iteration.
@ -835,15 +796,11 @@ impl fmt::Debug for Iter<'_> {
impl fmt::Debug for DebugHelper<'_> { impl fmt::Debug for DebugHelper<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list() f.debug_list().entries(self.0.iter()).finish()
.entries(self.0.iter())
.finish()
} }
} }
f.debug_tuple("Iter") f.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()
.field(&DebugHelper(self.as_path()))
.finish()
} }
} }
@ -1174,9 +1131,7 @@ impl PathBuf {
/// [`OsString`]: ../ffi/struct.OsString.html /// [`OsString`]: ../ffi/struct.OsString.html
#[unstable(feature = "path_buf_capacity", issue = "58234")] #[unstable(feature = "path_buf_capacity", issue = "58234")]
pub fn with_capacity(capacity: usize) -> PathBuf { pub fn with_capacity(capacity: usize) -> PathBuf {
PathBuf { PathBuf { inner: OsString::with_capacity(capacity) }
inner: OsString::with_capacity(capacity)
}
} }
/// Coerces to a [`Path`] slice. /// Coerces to a [`Path`] slice.
@ -1239,8 +1194,10 @@ impl PathBuf {
// in the special case of `C:` on Windows, do *not* add a separator // in the special case of `C:` on Windows, do *not* add a separator
{ {
let comps = self.components(); let comps = self.components();
if comps.prefix_len() > 0 && comps.prefix_len() == comps.path.len() && if comps.prefix_len() > 0
comps.prefix.unwrap().is_drive() { && comps.prefix_len() == comps.path.len()
&& comps.prefix.unwrap().is_drive()
{
need_sep = false need_sep = false
} }
} }
@ -1527,7 +1484,7 @@ impl From<PathBuf> for OsString {
/// Converts a `PathBuf` into a `OsString` /// Converts a `PathBuf` into a `OsString`
/// ///
/// This conversion does not allocate or copy memory. /// This conversion does not allocate or copy memory.
fn from(path_buf : PathBuf) -> OsString { fn from(path_buf: PathBuf) -> OsString {
path_buf.inner path_buf.inner
} }
} }
@ -1992,13 +1949,11 @@ impl Path {
pub fn parent(&self) -> Option<&Path> { pub fn parent(&self) -> Option<&Path> {
let mut comps = self.components(); let mut comps = self.components();
let comp = comps.next_back(); let comp = comps.next_back();
comp.and_then(|p| { comp.and_then(|p| match p {
match p { Component::Normal(_) | Component::CurDir | Component::ParentDir => {
Component::Normal(_) | Some(comps.as_path())
Component::CurDir |
Component::ParentDir => Some(comps.as_path()),
_ => None,
} }
_ => None,
}) })
} }
@ -2026,9 +1981,7 @@ impl Path {
/// [`parent`]: struct.Path.html#method.parent /// [`parent`]: struct.Path.html#method.parent
#[stable(feature = "path_ancestors", since = "1.28.0")] #[stable(feature = "path_ancestors", since = "1.28.0")]
pub fn ancestors(&self) -> Ancestors<'_> { pub fn ancestors(&self) -> Ancestors<'_> {
Ancestors { Ancestors { next: Some(&self) }
next: Some(&self),
}
} }
/// Returns the final component of the `Path`, if there is one. /// Returns the final component of the `Path`, if there is one.
@ -2055,11 +2008,9 @@ impl Path {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn file_name(&self) -> Option<&OsStr> { pub fn file_name(&self) -> Option<&OsStr> {
self.components().next_back().and_then(|p| { self.components().next_back().and_then(|p| match p {
match p {
Component::Normal(p) => Some(p.as_ref()), Component::Normal(p) => Some(p.as_ref()),
_ => None, _ => None,
}
}) })
} }
@ -2092,15 +2043,14 @@ impl Path {
/// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt"))); /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
/// ``` /// ```
#[stable(since = "1.7.0", feature = "path_strip_prefix")] #[stable(since = "1.7.0", feature = "path_strip_prefix")]
pub fn strip_prefix<P>(&self, base: P) pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
-> Result<&Path, StripPrefixError> where
where P: AsRef<Path> P: AsRef<Path>,
{ {
self._strip_prefix(base.as_ref()) self._strip_prefix(base.as_ref())
} }
fn _strip_prefix(&self, base: &Path) fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
-> Result<&Path, StripPrefixError> {
iter_after(self.components(), base.components()) iter_after(self.components(), base.components())
.map(|c| c.as_path()) .map(|c| c.as_path())
.ok_or(StripPrefixError(())) .ok_or(StripPrefixError(()))
@ -2329,8 +2279,8 @@ impl Path {
Components { Components {
path: self.as_u8_slice(), path: self.as_u8_slice(),
prefix, prefix,
has_physical_root: has_physical_root(self.as_u8_slice(), prefix) || has_physical_root: has_physical_root(self.as_u8_slice(), prefix)
has_redox_scheme(self.as_u8_slice()), || has_redox_scheme(self.as_u8_slice()),
front: State::Prefix, front: State::Prefix,
back: State::Body, back: State::Body,
} }
@ -2727,14 +2677,18 @@ impl AsRef<Path> for PathBuf {
impl<'a> IntoIterator for &'a PathBuf { impl<'a> IntoIterator for &'a PathBuf {
type Item = &'a OsStr; type Item = &'a OsStr;
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a> { self.iter() } fn into_iter(self) -> Iter<'a> {
self.iter()
}
} }
#[stable(feature = "path_into_iter", since = "1.6.0")] #[stable(feature = "path_into_iter", since = "1.6.0")]
impl<'a> IntoIterator for &'a Path { impl<'a> IntoIterator for &'a Path {
type Item = &'a OsStr; type Item = &'a OsStr;
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a> { self.iter() } fn into_iter(self) -> Iter<'a> {
self.iter()
}
} }
macro_rules! impl_cmp { macro_rules! impl_cmp {
@ -2742,13 +2696,17 @@ macro_rules! impl_cmp {
#[stable(feature = "partialeq_path", since = "1.6.0")] #[stable(feature = "partialeq_path", since = "1.6.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs { impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline] #[inline]
fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other) } fn eq(&self, other: &$rhs) -> bool {
<Path as PartialEq>::eq(self, other)
}
} }
#[stable(feature = "partialeq_path", since = "1.6.0")] #[stable(feature = "partialeq_path", since = "1.6.0")]
impl<'a, 'b> PartialEq<$lhs> for $rhs { impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline] #[inline]
fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) } fn eq(&self, other: &$lhs) -> bool {
<Path as PartialEq>::eq(self, other)
}
} }
#[stable(feature = "cmp_path", since = "1.8.0")] #[stable(feature = "cmp_path", since = "1.8.0")]
@ -2766,7 +2724,7 @@ macro_rules! impl_cmp {
<Path as PartialOrd>::partial_cmp(self, other) <Path as PartialOrd>::partial_cmp(self, other)
} }
} }
} };
} }
impl_cmp!(PathBuf, Path); impl_cmp!(PathBuf, Path);
@ -2780,13 +2738,17 @@ macro_rules! impl_cmp_os_str {
#[stable(feature = "cmp_path", since = "1.8.0")] #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs { impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline] #[inline]
fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other.as_ref()) } fn eq(&self, other: &$rhs) -> bool {
<Path as PartialEq>::eq(self, other.as_ref())
}
} }
#[stable(feature = "cmp_path", since = "1.8.0")] #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialEq<$lhs> for $rhs { impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline] #[inline]
fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self.as_ref(), other) } fn eq(&self, other: &$lhs) -> bool {
<Path as PartialEq>::eq(self.as_ref(), other)
}
} }
#[stable(feature = "cmp_path", since = "1.8.0")] #[stable(feature = "cmp_path", since = "1.8.0")]
@ -2804,7 +2766,7 @@ macro_rules! impl_cmp_os_str {
<Path as PartialOrd>::partial_cmp(self.as_ref(), other) <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
} }
} }
} };
} }
impl_cmp_os_str!(PathBuf, OsStr); impl_cmp_os_str!(PathBuf, OsStr);
@ -2831,7 +2793,9 @@ impl fmt::Display for StripPrefixError {
#[stable(since = "1.7.0", feature = "strip_prefix")] #[stable(since = "1.7.0", feature = "strip_prefix")]
impl Error for StripPrefixError { impl Error for StripPrefixError {
fn description(&self) -> &str { "prefix not found" } fn description(&self) -> &str {
"prefix not found"
}
} }
#[cfg(test)] #[cfg(test)]
@ -3650,7 +3614,6 @@ mod tests {
extension: Some("txt") extension: Some("txt")
); );
t!("\\\\?\\C:\\", t!("\\\\?\\C:\\",
iter: ["\\\\?\\C:", "\\"], iter: ["\\\\?\\C:", "\\"],
has_root: true, has_root: true,
@ -3661,7 +3624,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\?\\C:", t!("\\\\?\\C:",
iter: ["\\\\?\\C:"], iter: ["\\\\?\\C:"],
has_root: true, has_root: true,
@ -3672,7 +3634,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\?\\foo/bar", t!("\\\\?\\foo/bar",
iter: ["\\\\?\\foo/bar"], iter: ["\\\\?\\foo/bar"],
has_root: true, has_root: true,
@ -3683,7 +3644,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\?\\C:/foo", t!("\\\\?\\C:/foo",
iter: ["\\\\?\\C:/foo"], iter: ["\\\\?\\C:/foo"],
has_root: true, has_root: true,
@ -3694,7 +3654,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\.\\foo\\bar", t!("\\\\.\\foo\\bar",
iter: ["\\\\.\\foo", "\\", "bar"], iter: ["\\\\.\\foo", "\\", "bar"],
has_root: true, has_root: true,
@ -3705,7 +3664,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\.\\foo", t!("\\\\.\\foo",
iter: ["\\\\.\\foo", "\\"], iter: ["\\\\.\\foo", "\\"],
has_root: true, has_root: true,
@ -3716,7 +3674,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\.\\foo/bar", t!("\\\\.\\foo/bar",
iter: ["\\\\.\\foo/bar", "\\"], iter: ["\\\\.\\foo/bar", "\\"],
has_root: true, has_root: true,
@ -3727,7 +3684,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\.\\foo\\bar/baz", t!("\\\\.\\foo\\bar/baz",
iter: ["\\\\.\\foo", "\\", "bar", "baz"], iter: ["\\\\.\\foo", "\\", "bar", "baz"],
has_root: true, has_root: true,
@ -3738,7 +3694,6 @@ mod tests {
extension: None extension: None
); );
t!("\\\\.\\", t!("\\\\.\\",
iter: ["\\\\.\\", "\\"], iter: ["\\\\.\\", "\\"],
has_root: true, has_root: true,
@ -3792,20 +3747,11 @@ mod tests {
extension: Some("") extension: Some("")
); );
t!(".", t!(".", file_stem: None, extension: None);
file_stem: None,
extension: None
);
t!("..", t!("..", file_stem: None, extension: None);
file_stem: None,
extension: None
);
t!("", t!("", file_stem: None, extension: None);
file_stem: None,
extension: None
);
} }
#[test] #[test]
@ -3873,26 +3819,20 @@ mod tests {
tp!("C:a\\b\\c", "C:d", "C:d"); tp!("C:a\\b\\c", "C:d", "C:d");
tp!("C:", r"a\b\c", r"C:a\b\c"); tp!("C:", r"a\b\c", r"C:a\b\c");
tp!("C:", r"..\a", r"C:..\a"); tp!("C:", r"..\a", r"C:..\a");
tp!("\\\\server\\share\\foo", tp!("\\\\server\\share\\foo", "bar", "\\\\server\\share\\foo\\bar");
"bar",
"\\\\server\\share\\foo\\bar");
tp!("\\\\server\\share\\foo", "C:baz", "C:baz"); tp!("\\\\server\\share\\foo", "C:baz", "C:baz");
tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d"); tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d");
tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d"); tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d"); tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz"); tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
tp!("\\\\?\\UNC\\server\\share\\foo", tp!("\\\\?\\UNC\\server\\share\\foo", "bar", "\\\\?\\UNC\\server\\share\\foo\\bar");
"bar",
"\\\\?\\UNC\\server\\share\\foo\\bar");
tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a"); tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a"); tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a");
// Note: modified from old path API // Note: modified from old path API
tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo"); tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo");
tp!("C:\\a", tp!("C:\\a", "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share");
"\\\\?\\UNC\\server\\share",
"\\\\?\\UNC\\server\\share");
tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz"); tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
tp!("\\\\.\\foo\\bar", "C:a", "C:a"); tp!("\\\\.\\foo\\bar", "C:a", "C:a");
// again, not sure about the following, but I'm assuming \\.\ should be verbatim // again, not sure about the following, but I'm assuming \\.\ should be verbatim
@ -3945,15 +3885,9 @@ mod tests {
tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true); tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true); tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true);
tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false); tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false);
tp!("\\\\?\\UNC\\server\\share\\a\\b", tp!("\\\\?\\UNC\\server\\share\\a\\b", "\\\\?\\UNC\\server\\share\\a", true);
"\\\\?\\UNC\\server\\share\\a", tp!("\\\\?\\UNC\\server\\share\\a", "\\\\?\\UNC\\server\\share\\", true);
true); tp!("\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share", false);
tp!("\\\\?\\UNC\\server\\share\\a",
"\\\\?\\UNC\\server\\share\\",
true);
tp!("\\\\?\\UNC\\server\\share",
"\\\\?\\UNC\\server\\share",
false);
tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true); tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
tp!("\\\\.\\a\\b", "\\\\.\\a\\", true); tp!("\\\\.\\a\\b", "\\\\.\\a\\", true);
tp!("\\\\.\\a", "\\\\.\\a", false); tp!("\\\\.\\a", "\\\\.\\a", false);
@ -4051,8 +3985,8 @@ mod tests {
#[test] #[test]
pub fn test_compare() { pub fn test_compare() {
use crate::hash::{Hash, Hasher};
use crate::collections::hash_map::DefaultHasher; use crate::collections::hash_map::DefaultHasher;
use crate::hash::{Hash, Hasher};
fn hash<T: Hash>(t: T) -> u64 { fn hash<T: Hash>(t: T) -> u64 {
let mut s = DefaultHasher::new(); let mut s = DefaultHasher::new();

View file

@ -2,8 +2,6 @@
//! //!
//! See the [module-level documentation](../index.html) for more. //! See the [module-level documentation](../index.html) for more.
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
// Re-exported core operators // Re-exported core operators
@ -22,45 +20,27 @@ pub use crate::mem::drop;
// Re-exported types and traits // Re-exported types and traits
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::convert::{AsRef, AsMut, Into, From}; pub use crate::convert::{AsMut, AsRef, From, Into};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::iter::{Iterator, Extend, IntoIterator};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator}; pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::option::Option::{self, Some, None}; pub use crate::iter::{Extend, IntoIterator, Iterator};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::result::Result::{self, Ok, Err}; pub use crate::option::Option::{self, None, Some};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::result::Result::{self, Err, Ok};
// Re-exported built-in macros // Re-exported built-in macros
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use core::prelude::v1::{ pub use core::prelude::v1::{
asm, asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
assert, format_args_nl, global_asm, include, include_bytes, include_str, line, log_syntax, module_path,
cfg, option_env, stringify, trace_macros,
column,
compile_error,
concat,
concat_idents,
env,
file,
format_args,
format_args_nl,
global_asm,
include,
include_bytes,
include_str,
line,
log_syntax,
module_path,
option_env,
stringify,
trace_macros,
}; };
// FIXME: Attribute and derive macros are not documented because for them rustdoc generates // FIXME: Attribute and derive macros are not documented because for them rustdoc generates
@ -69,21 +49,8 @@ pub use core::prelude::v1::{
#[allow(deprecated)] #[allow(deprecated)]
#[doc(hidden)] #[doc(hidden)]
pub use core::prelude::v1::{ pub use core::prelude::v1::{
Clone, bench, global_allocator, test, test_case, Clone, Copy, Debug, Default, Eq, Hash, Ord,
Copy, PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
Debug,
Default,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
RustcDecodable,
RustcEncodable,
bench,
global_allocator,
test,
test_case,
}; };
// The file so far is equivalent to src/libcore/prelude/v1.rs, // The file so far is equivalent to src/libcore/prelude/v1.rs,
@ -91,15 +58,14 @@ pub use core::prelude::v1::{
// Those files are duplicated rather than using glob imports // Those files are duplicated rather than using glob imports
// because we want docs to show these re-exports as pointing to within `std`. // because we want docs to show these re-exports as pointing to within `std`.
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::borrow::ToOwned; pub use crate::borrow::ToOwned;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::string::{String, ToString}; pub use crate::string::{String, ToString};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] #[doc(no_inline)]

View file

@ -186,7 +186,9 @@ pub struct Child {
} }
impl AsInner<imp::Process> for Child { impl AsInner<imp::Process> for Child {
fn as_inner(&self) -> &imp::Process { &self.handle } fn as_inner(&self) -> &imp::Process {
&self.handle
}
} }
impl FromInner<(imp::Process, imp::StdioPipes)> for Child { impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
@ -201,7 +203,9 @@ impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
} }
impl IntoInner<imp::Process> for Child { impl IntoInner<imp::Process> for Child {
fn into_inner(self) -> imp::Process { self.handle } fn into_inner(self) -> imp::Process {
self.handle
}
} }
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
@ -228,7 +232,7 @@ impl fmt::Debug for Child {
/// [dropped]: ../ops/trait.Drop.html /// [dropped]: ../ops/trait.Drop.html
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdin { pub struct ChildStdin {
inner: AnonPipe inner: AnonPipe,
} }
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
@ -247,11 +251,15 @@ impl Write for ChildStdin {
} }
impl AsInner<AnonPipe> for ChildStdin { impl AsInner<AnonPipe> for ChildStdin {
fn as_inner(&self) -> &AnonPipe { &self.inner } fn as_inner(&self) -> &AnonPipe {
&self.inner
}
} }
impl IntoInner<AnonPipe> for ChildStdin { impl IntoInner<AnonPipe> for ChildStdin {
fn into_inner(self) -> AnonPipe { self.inner } fn into_inner(self) -> AnonPipe {
self.inner
}
} }
impl FromInner<AnonPipe> for ChildStdin { impl FromInner<AnonPipe> for ChildStdin {
@ -279,7 +287,7 @@ impl fmt::Debug for ChildStdin {
/// [dropped]: ../ops/trait.Drop.html /// [dropped]: ../ops/trait.Drop.html
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdout { pub struct ChildStdout {
inner: AnonPipe inner: AnonPipe,
} }
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
@ -299,11 +307,15 @@ impl Read for ChildStdout {
} }
impl AsInner<AnonPipe> for ChildStdout { impl AsInner<AnonPipe> for ChildStdout {
fn as_inner(&self) -> &AnonPipe { &self.inner } fn as_inner(&self) -> &AnonPipe {
&self.inner
}
} }
impl IntoInner<AnonPipe> for ChildStdout { impl IntoInner<AnonPipe> for ChildStdout {
fn into_inner(self) -> AnonPipe { self.inner } fn into_inner(self) -> AnonPipe {
self.inner
}
} }
impl FromInner<AnonPipe> for ChildStdout { impl FromInner<AnonPipe> for ChildStdout {
@ -331,7 +343,7 @@ impl fmt::Debug for ChildStdout {
/// [dropped]: ../ops/trait.Drop.html /// [dropped]: ../ops/trait.Drop.html
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub struct ChildStderr { pub struct ChildStderr {
inner: AnonPipe inner: AnonPipe,
} }
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
@ -351,11 +363,15 @@ impl Read for ChildStderr {
} }
impl AsInner<AnonPipe> for ChildStderr { impl AsInner<AnonPipe> for ChildStderr {
fn as_inner(&self) -> &AnonPipe { &self.inner } fn as_inner(&self) -> &AnonPipe {
&self.inner
}
} }
impl IntoInner<AnonPipe> for ChildStderr { impl IntoInner<AnonPipe> for ChildStderr {
fn into_inner(self) -> AnonPipe { self.inner } fn into_inner(self) -> AnonPipe {
self.inner
}
} }
impl FromInner<AnonPipe> for ChildStderr { impl FromInner<AnonPipe> for ChildStderr {
@ -533,7 +549,9 @@ impl Command {
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn args<I, S>(&mut self, args: I) -> &mut Command pub fn args<I, S>(&mut self, args: I) -> &mut Command
where I: IntoIterator<Item=S>, S: AsRef<OsStr> where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{ {
for arg in args { for arg in args {
self.arg(arg.as_ref()); self.arg(arg.as_ref());
@ -560,7 +578,9 @@ impl Command {
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
where K: AsRef<OsStr>, V: AsRef<OsStr> where
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{ {
self.inner.env_mut().set(key.as_ref(), val.as_ref()); self.inner.env_mut().set(key.as_ref(), val.as_ref());
self self
@ -592,7 +612,10 @@ impl Command {
/// ``` /// ```
#[stable(feature = "command_envs", since = "1.19.0")] #[stable(feature = "command_envs", since = "1.19.0")]
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr> where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{ {
for (ref key, ref val) in vars { for (ref key, ref val) in vars {
self.inner.env_mut().set(key.as_ref(), val.as_ref()); self.inner.env_mut().set(key.as_ref(), val.as_ref());
@ -794,7 +817,9 @@ impl Command {
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn output(&mut self) -> io::Result<Output> { pub fn output(&mut self) -> io::Result<Output> {
self.inner.spawn(imp::Stdio::MakePipe, false).map(Child::from_inner) self.inner
.spawn(imp::Stdio::MakePipe, false)
.map(Child::from_inner)
.and_then(|p| p.wait_with_output()) .and_then(|p| p.wait_with_output())
} }
@ -819,7 +844,9 @@ impl Command {
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn status(&mut self) -> io::Result<ExitStatus> { pub fn status(&mut self) -> io::Result<ExitStatus> {
self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner) self.inner
.spawn(imp::Stdio::Inherit, true)
.map(Child::from_inner)
.and_then(|mut p| p.wait()) .and_then(|mut p| p.wait())
} }
} }
@ -835,11 +862,15 @@ impl fmt::Debug for Command {
} }
impl AsInner<imp::Command> for Command { impl AsInner<imp::Command> for Command {
fn as_inner(&self) -> &imp::Command { &self.inner } fn as_inner(&self) -> &imp::Command {
&self.inner
}
} }
impl AsInnerMut<imp::Command> for Command { impl AsInnerMut<imp::Command> for Command {
fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner } fn as_inner_mut(&mut self) -> &mut imp::Command {
&mut self.inner
}
} }
/// The output of a finished process. /// The output of a finished process.
@ -871,17 +902,16 @@ pub struct Output {
#[stable(feature = "process_output_debug", since = "1.7.0")] #[stable(feature = "process_output_debug", since = "1.7.0")]
impl fmt::Debug for Output { impl fmt::Debug for Output {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let stdout_utf8 = str::from_utf8(&self.stdout); let stdout_utf8 = str::from_utf8(&self.stdout);
let stdout_debug: &dyn fmt::Debug = match stdout_utf8 { let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
Ok(ref str) => str, Ok(ref str) => str,
Err(_) => &self.stdout Err(_) => &self.stdout,
}; };
let stderr_utf8 = str::from_utf8(&self.stderr); let stderr_utf8 = str::from_utf8(&self.stderr);
let stderr_debug: &dyn fmt::Debug = match stderr_utf8 { let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
Ok(ref str) => str, Ok(ref str) => str,
Err(_) => &self.stderr Err(_) => &self.stderr,
}; };
fmt.debug_struct("Output") fmt.debug_struct("Output")
@ -943,7 +973,9 @@ impl Stdio {
/// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH"); /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH");
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) } pub fn piped() -> Stdio {
Stdio(imp::Stdio::MakePipe)
}
/// The child inherits from the corresponding parent descriptor. /// The child inherits from the corresponding parent descriptor.
/// ///
@ -980,7 +1012,9 @@ impl Stdio {
/// io::stdout().write_all(&output.stdout).unwrap(); /// io::stdout().write_all(&output.stdout).unwrap();
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) } pub fn inherit() -> Stdio {
Stdio(imp::Stdio::Inherit)
}
/// This stream will be ignored. This is the equivalent of attaching the /// This stream will be ignored. This is the equivalent of attaching the
/// stream to `/dev/null` /// stream to `/dev/null`
@ -1017,7 +1051,9 @@ impl Stdio {
/// // Ignores any piped-in input /// // Ignores any piped-in input
/// ``` /// ```
#[stable(feature = "process", since = "1.0.0")] #[stable(feature = "process", since = "1.0.0")]
pub fn null() -> Stdio { Stdio(imp::Stdio::Null) } pub fn null() -> Stdio {
Stdio(imp::Stdio::Null)
}
} }
impl FromInner<imp::Stdio> for Stdio { impl FromInner<imp::Stdio> for Stdio {
@ -1217,7 +1253,9 @@ impl ExitStatus {
} }
impl AsInner<imp::ExitStatus> for ExitStatus { impl AsInner<imp::ExitStatus> for ExitStatus {
fn as_inner(&self) -> &imp::ExitStatus { &self.0 } fn as_inner(&self) -> &imp::ExitStatus {
&self.0
}
} }
impl FromInner<imp::ExitStatus> for ExitStatus { impl FromInner<imp::ExitStatus> for ExitStatus {
@ -1449,11 +1487,7 @@ impl Child {
} }
let status = self.wait()?; let status = self.wait()?;
Ok(Output { Ok(Output { status, stdout, stderr })
status,
stdout,
stderr,
})
} }
} }
@ -1604,8 +1638,9 @@ pub fn id() -> u32 {
#[cfg_attr(not(test), lang = "termination")] #[cfg_attr(not(test), lang = "termination")]
#[unstable(feature = "termination_trait_lib", issue = "43301")] #[unstable(feature = "termination_trait_lib", issue = "43301")]
#[rustc_on_unimplemented( #[rustc_on_unimplemented(
message="`main` has invalid return type `{Self}`", message = "`main` has invalid return type `{Self}`",
label="`main` can only return types that implement `{Termination}`")] label = "`main` can only return types that implement `{Termination}`"
)]
pub trait Termination { pub trait Termination {
/// Is called to get the representation of the value as status code. /// Is called to get the representation of the value as status code.
/// This status code is returned to the operating system. /// This status code is returned to the operating system.
@ -1615,7 +1650,9 @@ pub trait Termination {
#[unstable(feature = "termination_trait_lib", issue = "43301")] #[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for () { impl Termination for () {
#[inline] #[inline]
fn report(self) -> i32 { ExitCode::SUCCESS.report() } fn report(self) -> i32 {
ExitCode::SUCCESS.report()
}
} }
#[unstable(feature = "termination_trait_lib", issue = "43301")] #[unstable(feature = "termination_trait_lib", issue = "43301")]
@ -1630,7 +1667,9 @@ impl<E: fmt::Debug> Termination for Result<(), E> {
#[unstable(feature = "termination_trait_lib", issue = "43301")] #[unstable(feature = "termination_trait_lib", issue = "43301")]
impl Termination for ! { impl Termination for ! {
fn report(self) -> i32 { self } fn report(self) -> i32 {
self
}
} }
#[unstable(feature = "termination_trait_lib", issue = "43301")] #[unstable(feature = "termination_trait_lib", issue = "43301")]
@ -1654,9 +1693,9 @@ impl Termination for ExitCode {
mod tests { mod tests {
use crate::io::prelude::*; use crate::io::prelude::*;
use super::{Command, Output, Stdio};
use crate::io::ErrorKind; use crate::io::ErrorKind;
use crate::str; use crate::str;
use super::{Command, Output, Stdio};
// FIXME(#10380) these tests should not all be ignored on android. // FIXME(#10380) these tests should not all be ignored on android.
@ -1702,15 +1741,12 @@ mod tests {
fn signal_reported_right() { fn signal_reported_right() {
use crate::os::unix::process::ExitStatusExt; use crate::os::unix::process::ExitStatusExt;
let mut p = Command::new("/bin/sh") let mut p =
.arg("-c").arg("read a") Command::new("/bin/sh").arg("-c").arg("read a").stdin(Stdio::piped()).spawn().unwrap();
.stdin(Stdio::piped())
.spawn().unwrap();
p.kill().unwrap(); p.kill().unwrap();
match p.wait().unwrap().signal() { match p.wait().unwrap().signal() {
Some(9) => {}, Some(9) => {}
result => panic!("not terminated by signal 9 (instead, {:?})", result => panic!("not terminated by signal 9 (instead, {:?})", result),
result),
} }
} }
@ -1743,9 +1779,7 @@ mod tests {
#[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] #[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)]
fn set_current_dir_works() { fn set_current_dir_works() {
let mut cmd = Command::new("/bin/sh"); let mut cmd = Command::new("/bin/sh");
cmd.arg("-c").arg("pwd") cmd.arg("-c").arg("pwd").current_dir("/").stdout(Stdio::piped());
.current_dir("/")
.stdout(Stdio::piped());
assert_eq!(run_output(cmd), "/\n"); assert_eq!(run_output(cmd), "/\n");
} }
@ -1753,10 +1787,12 @@ mod tests {
#[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)] #[cfg_attr(any(windows, target_os = "android", target_os = "vxworks"), ignore)]
fn stdin_works() { fn stdin_works() {
let mut p = Command::new("/bin/sh") let mut p = Command::new("/bin/sh")
.arg("-c").arg("read line; echo $line") .arg("-c")
.arg("read line; echo $line")
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.spawn().unwrap(); .spawn()
.unwrap();
p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap(); p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
drop(p.stdin.take()); drop(p.stdin.take());
let mut out = String::new(); let mut out = String::new();
@ -1787,15 +1823,14 @@ mod tests {
fn test_process_output_fail_to_start() { fn test_process_output_fail_to_start() {
match Command::new("/no-binary-by-this-name-should-exist").output() { match Command::new("/no-binary-by-this-name-should-exist").output() {
Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound), Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
Ok(..) => panic!() Ok(..) => panic!(),
} }
} }
#[test] #[test]
#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)]
fn test_process_output_output() { fn test_process_output_output() {
let Output {status, stdout, stderr} let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
= if cfg!(target_os = "windows") {
Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap() Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
} else { } else {
Command::new("echo").arg("hello").output().unwrap() Command::new("echo").arg("hello").output().unwrap()
@ -1810,8 +1845,7 @@ mod tests {
#[test] #[test]
#[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)] #[cfg_attr(any(target_os = "vxworks", target_os = "android"), ignore)]
fn test_process_output_error() { fn test_process_output_error() {
let Output {status, stdout, stderr} let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
= if cfg!(target_os = "windows") {
Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap() Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
} else { } else {
Command::new("mkdir").arg("./").output().unwrap() Command::new("mkdir").arg("./").output().unwrap()
@ -1854,7 +1888,7 @@ mod tests {
Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap() Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap()
}; };
let Output {status, stdout, stderr} = prog.wait_with_output().unwrap(); let Output { status, stdout, stderr } = prog.wait_with_output().unwrap();
let output_str = str::from_utf8(&stdout).unwrap(); let output_str = str::from_utf8(&stdout).unwrap();
assert!(status.success()); assert!(status.success());
@ -1862,11 +1896,11 @@ mod tests {
assert_eq!(stderr, Vec::new()); assert_eq!(stderr, Vec::new());
} }
#[cfg(all(unix, not(target_os="android")))] #[cfg(all(unix, not(target_os = "android")))]
pub fn env_cmd() -> Command { pub fn env_cmd() -> Command {
Command::new("env") Command::new("env")
} }
#[cfg(target_os="android")] #[cfg(target_os = "android")]
pub fn env_cmd() -> Command { pub fn env_cmd() -> Command {
let mut cmd = Command::new("/system/bin/sh"); let mut cmd = Command::new("/system/bin/sh");
cmd.arg("-c").arg("set"); cmd.arg("-c").arg("set");
@ -1897,8 +1931,11 @@ mod tests {
let result = cmd.output().unwrap(); let result = cmd.output().unwrap();
let output = String::from_utf8_lossy(&result.stdout).to_string(); let output = String::from_utf8_lossy(&result.stdout).to_string();
assert!(output.contains("RUN_TEST_NEW_ENV=123"), assert!(
"didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); output.contains("RUN_TEST_NEW_ENV=123"),
"didn't find RUN_TEST_NEW_ENV inside of:\n\n{}",
output
);
} }
#[test] #[test]
@ -1907,8 +1944,11 @@ mod tests {
let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap(); let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
let output = String::from_utf8_lossy(&result.stdout).to_string(); let output = String::from_utf8_lossy(&result.stdout).to_string();
assert!(output.contains("RUN_TEST_NEW_ENV=123"), assert!(
"didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); output.contains("RUN_TEST_NEW_ENV=123"),
"didn't find RUN_TEST_NEW_ENV inside of:\n\n{}",
output
);
} }
#[test] #[test]
@ -1927,10 +1967,16 @@ mod tests {
let output = String::from_utf8_lossy(&result.stdout).to_string(); let output = String::from_utf8_lossy(&result.stdout).to_string();
assert!(output.contains("RUN_TEST_NEW_ENV1=123"), assert!(
"didn't find RUN_TEST_NEW_ENV1 inside of:\n\n{}", output); output.contains("RUN_TEST_NEW_ENV1=123"),
assert!(output.contains("RUN_TEST_NEW_ENV2=456"), "didn't find RUN_TEST_NEW_ENV1 inside of:\n\n{}",
"didn't find RUN_TEST_NEW_ENV2 inside of:\n\n{}", output); output
);
assert!(
output.contains("RUN_TEST_NEW_ENV2=456"),
"didn't find RUN_TEST_NEW_ENV2 inside of:\n\n{}",
output
);
} }
// Regression tests for #30858. // Regression tests for #30858.
@ -2005,8 +2051,11 @@ mod tests {
extern "system" { extern "system" {
fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL; fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL;
fn ContinueDebugEvent(dwProcessId: DWORD, dwThreadId: DWORD, fn ContinueDebugEvent(
dwContinueStatus: DWORD) -> BOOL; dwProcessId: DWORD,
dwThreadId: DWORD,
dwContinueStatus: DWORD,
) -> BOOL;
} }
const DEBUG_PROCESS: DWORD = 1; const DEBUG_PROCESS: DWORD = 1;
@ -2015,15 +2064,12 @@ mod tests {
let mut child = Command::new("cmd") let mut child = Command::new("cmd")
.creation_flags(DEBUG_PROCESS) .creation_flags(DEBUG_PROCESS)
.stdin(Stdio::piped()).spawn().unwrap(); .stdin(Stdio::piped())
.spawn()
.unwrap();
child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap(); child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap();
let mut events = 0; let mut events = 0;
let mut event = DEBUG_EVENT { let mut event = DEBUG_EVENT { event_code: 0, process_id: 0, thread_id: 0, _junk: [0; 164] };
event_code: 0,
process_id: 0,
thread_id: 0,
_junk: [0; 164],
};
loop { loop {
if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 { if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 {
panic!("WaitForDebugEvent failed!"); panic!("WaitForDebugEvent failed!");
@ -2034,9 +2080,10 @@ mod tests {
break; break;
} }
if unsafe { ContinueDebugEvent(event.process_id, if unsafe {
event.thread_id, ContinueDebugEvent(event.process_id, event.thread_id, DBG_EXCEPTION_NOT_HANDLED)
DBG_EXCEPTION_NOT_HANDLED) } == 0 { } == 0
{
panic!("ContinueDebugEvent failed!"); panic!("ContinueDebugEvent failed!");
} }
} }

View file

@ -6,21 +6,25 @@
//! and should be considered as private implementation details for the //! and should be considered as private implementation details for the
//! time being. //! time being.
#![unstable(feature = "rt", #![unstable(
feature = "rt",
reason = "this public module should not exist and is highly likely \ reason = "this public module should not exist and is highly likely \
to disappear", to disappear",
issue = "0")] issue = "0"
)]
#![doc(hidden)] #![doc(hidden)]
// Re-export some of our utilities which are expected by other crates. // Re-export some of our utilities which are expected by other crates.
pub use crate::panicking::{begin_panic, begin_panic_fmt, update_panic_count}; pub use crate::panicking::{begin_panic, begin_panic_fmt, update_panic_count};
// To reduce the generated code of the new `lang_start`, this function is doing // To reduce the generated code of the new `lang_start`, this function is doing
// the real work. // the real work.
#[cfg(not(test))] #[cfg(not(test))]
fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe), fn lang_start_internal(
argc: isize, argv: *const *const u8) -> isize { main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
argc: isize,
argv: *const *const u8,
) -> isize {
use crate::panic; use crate::panic;
use crate::sys; use crate::sys;
use crate::sys_common; use crate::sys_common;
@ -55,8 +59,10 @@ fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindS
#[cfg(not(test))] #[cfg(not(test))]
#[lang = "start"] #[lang = "start"]
fn lang_start<T: crate::process::Termination + 'static> fn lang_start<T: crate::process::Termination + 'static>(
(main: fn() -> T, argc: isize, argv: *const *const u8) -> isize main: fn() -> T,
{ argc: isize,
argv: *const *const u8,
) -> isize {
lang_start_internal(&move || main().report(), argc, argv) lang_start_internal(&move || main().report(), argc, argv)
} }

View file

@ -1,5 +1,5 @@
use crate::fmt; use crate::fmt;
use crate::sync::{Mutex, Condvar}; use crate::sync::{Condvar, Mutex};
/// A barrier enables multiple threads to synchronize the beginning /// A barrier enables multiple threads to synchronize the beginning
/// of some computation. /// of some computation.
@ -82,10 +82,7 @@ impl Barrier {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn new(n: usize) -> Barrier { pub fn new(n: usize) -> Barrier {
Barrier { Barrier {
lock: Mutex::new(BarrierState { lock: Mutex::new(BarrierState { count: 0, generation_id: 0 }),
count: 0,
generation_id: 0,
}),
cvar: Condvar::new(), cvar: Condvar::new(),
num_threads: n, num_threads: n,
} }
@ -135,8 +132,7 @@ impl Barrier {
if lock.count < self.num_threads { if lock.count < self.num_threads {
// We need a while loop to guard against spurious wakeups. // We need a while loop to guard against spurious wakeups.
// http://en.wikipedia.org/wiki/Spurious_wakeup // http://en.wikipedia.org/wiki/Spurious_wakeup
while local_gen == lock.generation_id && while local_gen == lock.generation_id && lock.count < self.num_threads {
lock.count < self.num_threads {
lock = self.cvar.wait(lock).unwrap(); lock = self.cvar.wait(lock).unwrap();
} }
BarrierWaitResult(false) BarrierWaitResult(false)
@ -152,9 +148,7 @@ impl Barrier {
#[stable(feature = "std_debug", since = "1.16.0")] #[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for BarrierWaitResult { impl fmt::Debug for BarrierWaitResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BarrierWaitResult") f.debug_struct("BarrierWaitResult").field("is_leader", &self.is_leader()).finish()
.field("is_leader", &self.is_leader())
.finish()
} }
} }
@ -176,13 +170,15 @@ impl BarrierWaitResult {
/// println!("{:?}", barrier_wait_result.is_leader()); /// println!("{:?}", barrier_wait_result.is_leader());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn is_leader(&self) -> bool { self.0 } pub fn is_leader(&self) -> bool {
self.0
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::sync::{Arc, Barrier};
use crate::sync::mpsc::{channel, TryRecvError}; use crate::sync::mpsc::{channel, TryRecvError};
use crate::sync::{Arc, Barrier};
use crate::thread; use crate::thread;
#[test] #[test]
@ -196,7 +192,7 @@ mod tests {
for _ in 0..N - 1 { for _ in 0..N - 1 {
let c = barrier.clone(); let c = barrier.clone();
let tx = tx.clone(); let tx = tx.clone();
thread::spawn(move|| { thread::spawn(move || {
tx.send(c.wait().is_leader()).unwrap(); tx.send(c.wait().is_leader()).unwrap();
}); });
} }

View file

@ -1,9 +1,9 @@
//! Generic support for building blocking abstractions. //! Generic support for building blocking abstractions.
use crate::thread::{self, Thread}; use crate::mem;
use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::Arc; use crate::sync::Arc;
use crate::mem; use crate::thread::{self, Thread};
use crate::time::Instant; use crate::time::Instant;
struct Inner { struct Inner {
@ -28,16 +28,9 @@ impl !Send for WaitToken {}
impl !Sync for WaitToken {} impl !Sync for WaitToken {}
pub fn tokens() -> (WaitToken, SignalToken) { pub fn tokens() -> (WaitToken, SignalToken) {
let inner = Arc::new(Inner { let inner = Arc::new(Inner { thread: thread::current(), woken: AtomicBool::new(false) });
thread: thread::current(), let wait_token = WaitToken { inner: inner.clone() };
woken: AtomicBool::new(false), let signal_token = SignalToken { inner };
});
let wait_token = WaitToken {
inner: inner.clone(),
};
let signal_token = SignalToken {
inner,
};
(wait_token, signal_token) (wait_token, signal_token)
} }

File diff suppressed because it is too large Load diff

View file

@ -13,8 +13,8 @@
pub use self::PopResult::*; pub use self::PopResult::*;
use core::ptr;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use core::ptr;
use crate::boxed::Box; use crate::boxed::Box;
use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sync::atomic::{AtomicPtr, Ordering};
@ -45,15 +45,12 @@ pub struct Queue<T> {
tail: UnsafeCell<*mut Node<T>>, tail: UnsafeCell<*mut Node<T>>,
} }
unsafe impl<T: Send> Send for Queue<T> { } unsafe impl<T: Send> Send for Queue<T> {}
unsafe impl<T: Send> Sync for Queue<T> { } unsafe impl<T: Send> Sync for Queue<T> {}
impl<T> Node<T> { impl<T> Node<T> {
unsafe fn new(v: Option<T>) -> *mut Node<T> { unsafe fn new(v: Option<T>) -> *mut Node<T> {
Box::into_raw(box Node { Box::into_raw(box Node { next: AtomicPtr::new(ptr::null_mut()), value: v })
next: AtomicPtr::new(ptr::null_mut()),
value: v,
})
} }
} }
@ -62,10 +59,7 @@ impl<T> Queue<T> {
/// one consumer. /// one consumer.
pub fn new() -> Queue<T> { pub fn new() -> Queue<T> {
let stub = unsafe { Node::new(None) }; let stub = unsafe { Node::new(None) };
Queue { Queue { head: AtomicPtr::new(stub), tail: UnsafeCell::new(stub) }
head: AtomicPtr::new(stub),
tail: UnsafeCell::new(stub),
}
} }
/// Pushes a new value onto this queue. /// Pushes a new value onto this queue.
@ -101,7 +95,7 @@ impl<T> Queue<T> {
return Data(ret); return Data(ret);
} }
if self.head.load(Ordering::Acquire) == tail {Empty} else {Inconsistent} if self.head.load(Ordering::Acquire) == tail { Empty } else { Inconsistent }
} }
} }
} }
@ -121,7 +115,7 @@ impl<T> Drop for Queue<T> {
#[cfg(all(test, not(target_os = "emscripten")))] #[cfg(all(test, not(target_os = "emscripten")))]
mod tests { mod tests {
use super::{Queue, Data, Empty, Inconsistent}; use super::{Data, Empty, Inconsistent, Queue};
use crate::sync::mpsc::channel; use crate::sync::mpsc::channel;
use crate::sync::Arc; use crate::sync::Arc;
use crate::thread; use crate::thread;
@ -140,7 +134,7 @@ mod tests {
let q = Queue::new(); let q = Queue::new();
match q.pop() { match q.pop() {
Empty => {} Empty => {}
Inconsistent | Data(..) => panic!() Inconsistent | Data(..) => panic!(),
} }
let (tx, rx) = channel(); let (tx, rx) = channel();
let q = Arc::new(q); let q = Arc::new(q);
@ -148,7 +142,7 @@ mod tests {
for _ in 0..nthreads { for _ in 0..nthreads {
let tx = tx.clone(); let tx = tx.clone();
let q = q.clone(); let q = q.clone();
thread::spawn(move|| { thread::spawn(move || {
for i in 0..nmsgs { for i in 0..nmsgs {
q.push(i); q.push(i);
} }
@ -159,8 +153,8 @@ mod tests {
let mut i = 0; let mut i = 0;
while i < nthreads * nmsgs { while i < nthreads * nmsgs {
match q.pop() { match q.pop() {
Empty | Inconsistent => {}, Empty | Inconsistent => {}
Data(_) => { i += 1 } Data(_) => i += 1,
} }
} }
drop(tx); drop(tx);

View file

@ -21,16 +21,15 @@
/// consuming the port). This upgrade is then also stored in the shared packet. /// consuming the port). This upgrade is then also stored in the shared packet.
/// The one caveat to consider is that when a port sees a disconnected channel /// The one caveat to consider is that when a port sees a disconnected channel
/// it must check for data because there is no "data plus upgrade" state. /// it must check for data because there is no "data plus upgrade" state.
pub use self::Failure::*; pub use self::Failure::*;
pub use self::UpgradeResult::*;
use self::MyUpgrade::*; use self::MyUpgrade::*;
pub use self::UpgradeResult::*;
use crate::sync::mpsc::Receiver;
use crate::sync::mpsc::blocking::{self, SignalToken};
use crate::cell::UnsafeCell; use crate::cell::UnsafeCell;
use crate::ptr; use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sync::mpsc::blocking::{self, SignalToken};
use crate::sync::mpsc::Receiver;
use crate::time::Instant; use crate::time::Instant;
// Various states you can find a port in. // Various states you can find a port in.
@ -178,21 +177,17 @@ impl<T> Packet<T> {
// and an upgrade flags the channel as disconnected, so when we see // and an upgrade flags the channel as disconnected, so when we see
// this we first need to check if there's data available and *then* // this we first need to check if there's data available and *then*
// we go through and process the upgrade. // we go through and process the upgrade.
DISCONNECTED => { DISCONNECTED => match (&mut *self.data.get()).take() {
match (&mut *self.data.get()).take() {
Some(data) => Ok(data), Some(data) => Ok(data),
None => { None => match ptr::replace(self.upgrade.get(), SendUsed) {
match ptr::replace(self.upgrade.get(), SendUsed) {
SendUsed | NothingSent => Err(Disconnected), SendUsed | NothingSent => Err(Disconnected),
GoUp(upgrade) => Err(Upgraded(upgrade)) GoUp(upgrade) => Err(Upgraded(upgrade)),
} },
} },
}
}
// We are the sole receiver; there cannot be a blocking // We are the sole receiver; there cannot be a blocking
// receiver already. // receiver already.
_ => unreachable!() _ => unreachable!(),
} }
} }
} }
@ -217,10 +212,13 @@ impl<T> Packet<T> {
// If the other end is already disconnected, then we failed the // If the other end is already disconnected, then we failed the
// upgrade. Be sure to trash the port we were given. // upgrade. Be sure to trash the port we were given.
DISCONNECTED => { ptr::replace(self.upgrade.get(), prev); UpDisconnected } DISCONNECTED => {
ptr::replace(self.upgrade.get(), prev);
UpDisconnected
}
// If someone's waiting, we gotta wake them up // If someone's waiting, we gotta wake them up
ptr => UpWoke(SignalToken::cast_from_usize(ptr)) ptr => UpWoke(SignalToken::cast_from_usize(ptr)),
} }
} }
} }
@ -232,7 +230,7 @@ impl<T> Packet<T> {
// If someone's waiting, we gotta wake them up // If someone's waiting, we gotta wake them up
ptr => unsafe { ptr => unsafe {
SignalToken::cast_from_usize(ptr).signal(); SignalToken::cast_from_usize(ptr).signal();
} },
} }
} }
@ -246,10 +244,12 @@ impl<T> Packet<T> {
// There's data on the channel, so make sure we destroy it promptly. // There's data on the channel, so make sure we destroy it promptly.
// This is why not using an arc is a little difficult (need the box // This is why not using an arc is a little difficult (need the box
// to stay valid while we take the data). // to stay valid while we take the data).
DATA => unsafe { (&mut *self.data.get()).take().unwrap(); }, DATA => unsafe {
(&mut *self.data.get()).take().unwrap();
},
// We're the only ones that can block on this port // We're the only ones that can block on this port
_ => unreachable!() _ => unreachable!(),
} }
} }
@ -265,13 +265,11 @@ impl<T> Packet<T> {
let state = match self.state.load(Ordering::SeqCst) { let state = match self.state.load(Ordering::SeqCst) {
// Each of these states means that no further activity will happen // Each of these states means that no further activity will happen
// with regard to abortion selection // with regard to abortion selection
s @ EMPTY | s @ EMPTY | s @ DATA | s @ DISCONNECTED => s,
s @ DATA |
s @ DISCONNECTED => s,
// If we've got a blocked thread, then use an atomic to gain ownership // If we've got a blocked thread, then use an atomic to gain ownership
// of it (may fail) // of it (may fail)
ptr => self.state.compare_and_swap(ptr, EMPTY, Ordering::SeqCst) ptr => self.state.compare_and_swap(ptr, EMPTY, Ordering::SeqCst),
}; };
// Now that we've got ownership of our state, figure out what to do // Now that we've got ownership of our state, figure out what to do
@ -302,7 +300,7 @@ impl<T> Packet<T> {
ptr => unsafe { ptr => unsafe {
drop(SignalToken::cast_from_usize(ptr)); drop(SignalToken::cast_from_usize(ptr));
Ok(false) Ok(false)
} },
} }
} }
} }

View file

@ -7,7 +7,6 @@
/// High level implementation details can be found in the comment of the parent /// High level implementation details can be found in the comment of the parent
/// module. You'll also note that the implementation of the shared and stream /// module. You'll also note that the implementation of the shared and stream
/// channels are quite similar, and this is no coincidence! /// channels are quite similar, and this is no coincidence!
pub use self::Failure::*; pub use self::Failure::*;
use self::StartResult::*; use self::StartResult::*;
@ -17,7 +16,7 @@ use core::isize;
use crate::cell::UnsafeCell; use crate::cell::UnsafeCell;
use crate::ptr; use crate::ptr;
use crate::sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering}; use crate::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::blocking::{self, SignalToken};
use crate::sync::mpsc::mpsc_queue as mpsc; use crate::sync::mpsc::mpsc_queue as mpsc;
use crate::sync::{Mutex, MutexGuard}; use crate::sync::{Mutex, MutexGuard};
@ -92,9 +91,7 @@ impl<T> Packet<T> {
// threads in select(). // threads in select().
// //
// This can only be called at channel-creation time // This can only be called at channel-creation time
pub fn inherit_blocker(&self, pub fn inherit_blocker(&self, token: Option<SignalToken>, guard: MutexGuard<'_, ()>) {
token: Option<SignalToken>,
guard: MutexGuard<'_, ()>) {
token.map(|token| { token.map(|token| {
assert_eq!(self.cnt.load(Ordering::SeqCst), 0); assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
@ -119,7 +116,9 @@ impl<T> Packet<T> {
// To offset this bad increment, we initially set the steal count to // To offset this bad increment, we initially set the steal count to
// -1. You'll find some special code in abort_selection() as well to // -1. You'll find some special code in abort_selection() as well to
// ensure that this -1 steal count doesn't escape too far. // ensure that this -1 steal count doesn't escape too far.
unsafe { *self.steals.get() = -1; } unsafe {
*self.steals.get() = -1;
}
}); });
// When the shared packet is constructed, we grabbed this lock. The // When the shared packet is constructed, we grabbed this lock. The
@ -132,7 +131,9 @@ impl<T> Packet<T> {
pub fn send(&self, t: T) -> Result<(), T> { pub fn send(&self, t: T) -> Result<(), T> {
// See Port::drop for what's going on // See Port::drop for what's going on
if self.port_dropped.load(Ordering::SeqCst) { return Err(t) } if self.port_dropped.load(Ordering::SeqCst) {
return Err(t);
}
// Note that the multiple sender case is a little trickier // Note that the multiple sender case is a little trickier
// semantically than the single sender case. The logic for // semantically than the single sender case. The logic for
@ -160,7 +161,7 @@ impl<T> Packet<T> {
// received". Once we get beyond this check, we have permanently // received". Once we get beyond this check, we have permanently
// entered the realm of "this may be received" // entered the realm of "this may be received"
if self.cnt.load(Ordering::SeqCst) < DISCONNECTED + FUDGE { if self.cnt.load(Ordering::SeqCst) < DISCONNECTED + FUDGE {
return Err(t) return Err(t);
} }
self.queue.push(t); self.queue.push(t);
@ -197,7 +198,7 @@ impl<T> Packet<T> {
// maybe we're done, if we're not the last ones // maybe we're done, if we're not the last ones
// here, then we need to go try again. // here, then we need to go try again.
if self.sender_drain.fetch_sub(1, Ordering::SeqCst) == 1 { if self.sender_drain.fetch_sub(1, Ordering::SeqCst) == 1 {
break break;
} }
} }
@ -236,7 +237,10 @@ impl<T> Packet<T> {
} }
match self.try_recv() { match self.try_recv() {
data @ Ok(..) => unsafe { *self.steals.get() -= 1; data }, data @ Ok(..) => unsafe {
*self.steals.get() -= 1;
data
},
data => data, data => data,
} }
} }
@ -252,12 +256,16 @@ impl<T> Packet<T> {
let steals = ptr::replace(self.steals.get(), 0); let steals = ptr::replace(self.steals.get(), 0);
match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) { match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) {
DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); } DISCONNECTED => {
self.cnt.store(DISCONNECTED, Ordering::SeqCst);
}
// If we factor in our steals and notice that the channel has no // If we factor in our steals and notice that the channel has no
// data, we successfully sleep // data, we successfully sleep
n => { n => {
assert!(n >= 0); assert!(n >= 0);
if n - steals <= 0 { return Installed } if n - steals <= 0 {
return Installed;
}
} }
} }
@ -290,7 +298,10 @@ impl<T> Packet<T> {
loop { loop {
thread::yield_now(); thread::yield_now();
match self.queue.pop() { match self.queue.pop() {
mpsc::Data(t) => { data = t; break } mpsc::Data(t) => {
data = t;
break;
}
mpsc::Empty => panic!("inconsistent => empty"), mpsc::Empty => panic!("inconsistent => empty"),
mpsc::Inconsistent => {} mpsc::Inconsistent => {}
} }
@ -361,9 +372,13 @@ impl<T> Packet<T> {
} }
match self.cnt.swap(DISCONNECTED, Ordering::SeqCst) { match self.cnt.swap(DISCONNECTED, Ordering::SeqCst) {
-1 => { self.take_to_wake().signal(); } -1 => {
self.take_to_wake().signal();
}
DISCONNECTED => {} DISCONNECTED => {}
n => { assert!(n >= 0); } n => {
assert!(n >= 0);
}
} }
} }
@ -380,7 +395,9 @@ impl<T> Packet<T> {
// control of this thread. // control of this thread.
loop { loop {
match self.queue.pop() { match self.queue.pop() {
mpsc::Data(..) => { steals += 1; } mpsc::Data(..) => {
steals += 1;
}
mpsc::Empty | mpsc::Inconsistent => break, mpsc::Empty | mpsc::Inconsistent => break,
} }
} }
@ -406,7 +423,7 @@ impl<T> Packet<T> {
self.cnt.store(DISCONNECTED, Ordering::SeqCst); self.cnt.store(DISCONNECTED, Ordering::SeqCst);
DISCONNECTED DISCONNECTED
} }
n => n n => n,
} }
} }
@ -432,7 +449,7 @@ impl<T> Packet<T> {
// positive. // positive.
let steals = { let steals = {
let cnt = self.cnt.load(Ordering::SeqCst); let cnt = self.cnt.load(Ordering::SeqCst);
if cnt < 0 && cnt != DISCONNECTED {-cnt} else {0} if cnt < 0 && cnt != DISCONNECTED { -cnt } else { 0 }
}; };
let prev = self.bump(steals + 1); let prev = self.bump(steals + 1);

View file

@ -6,8 +6,8 @@
// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue // http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
use core::ptr;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use core::ptr;
use crate::boxed::Box; use crate::boxed::Box;
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
@ -28,7 +28,7 @@ struct Node<T> {
/// but it can be safely shared in an Arc if it is guaranteed that there /// but it can be safely shared in an Arc if it is guaranteed that there
/// is only one popper and one pusher touching the queue at any one point in /// is only one popper and one pusher touching the queue at any one point in
/// time. /// time.
pub struct Queue<T, ProducerAddition=(), ConsumerAddition=()> { pub struct Queue<T, ProducerAddition = (), ConsumerAddition = ()> {
// consumer fields // consumer fields
consumer: CacheAligned<Consumer<T, ConsumerAddition>>, consumer: CacheAligned<Consumer<T, ConsumerAddition>>,
@ -51,9 +51,9 @@ struct Producer<T, Addition> {
addition: Addition, addition: Addition,
} }
unsafe impl<T: Send, P: Send + Sync, C: Send + Sync> Send for Queue<T, P, C> { } unsafe impl<T: Send, P: Send + Sync, C: Send + Sync> Send for Queue<T, P, C> {}
unsafe impl<T: Send, P: Send + Sync, C: Send + Sync> Sync for Queue<T, P, C> { } unsafe impl<T: Send, P: Send + Sync, C: Send + Sync> Sync for Queue<T, P, C> {}
impl<T> Node<T> { impl<T> Node<T> {
fn new() -> *mut Node<T> { fn new() -> *mut Node<T> {
@ -66,7 +66,6 @@ impl<T> Node<T> {
} }
impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerAddition> { impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerAddition> {
/// Creates a new queue. With given additional elements in the producer and /// Creates a new queue. With given additional elements in the producer and
/// consumer portions of the queue. /// consumer portions of the queue.
/// ///
@ -107,13 +106,13 @@ impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerA
tail_prev: AtomicPtr::new(n1), tail_prev: AtomicPtr::new(n1),
cache_bound: bound, cache_bound: bound,
cached_nodes: AtomicUsize::new(0), cached_nodes: AtomicUsize::new(0),
addition: consumer_addition addition: consumer_addition,
}), }),
producer: CacheAligned::new(Producer { producer: CacheAligned::new(Producer {
head: UnsafeCell::new(n2), head: UnsafeCell::new(n2),
first: UnsafeCell::new(n1), first: UnsafeCell::new(n1),
tail_copy: UnsafeCell::new(n1), tail_copy: UnsafeCell::new(n1),
addition: producer_addition addition: producer_addition,
}), }),
} }
} }
@ -142,8 +141,7 @@ impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerA
} }
// If the above fails, then update our copy of the tail and try // If the above fails, then update our copy of the tail and try
// again. // again.
*self.producer.0.tail_copy.get() = *self.producer.0.tail_copy.get() = self.consumer.tail_prev.load(Ordering::Acquire);
self.consumer.tail_prev.load(Ordering::Acquire);
if *self.producer.first.get() != *self.producer.tail_copy.get() { if *self.producer.first.get() != *self.producer.tail_copy.get() {
let ret = *self.producer.first.get(); let ret = *self.producer.first.get();
*self.producer.0.first.get() = (*ret).next.load(Ordering::Relaxed); *self.producer.0.first.get() = (*ret).next.load(Ordering::Relaxed);
@ -164,7 +162,9 @@ impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerA
// the current tail node is a candidate for going into the cache. // the current tail node is a candidate for going into the cache.
let tail = *self.consumer.tail.get(); let tail = *self.consumer.tail.get();
let next = (*tail).next.load(Ordering::Acquire); let next = (*tail).next.load(Ordering::Acquire);
if next.is_null() { return None } if next.is_null() {
return None;
}
assert!((*next).value.is_some()); assert!((*next).value.is_some());
let ret = (*next).value.take(); let ret = (*next).value.take();
@ -182,7 +182,8 @@ impl<T, ProducerAddition, ConsumerAddition> Queue<T, ProducerAddition, ConsumerA
self.consumer.tail_prev.store(tail, Ordering::Release); self.consumer.tail_prev.store(tail, Ordering::Release);
} else { } else {
(*self.consumer.tail_prev.load(Ordering::Relaxed)) (*self.consumer.tail_prev.load(Ordering::Relaxed))
.next.store(next, Ordering::Relaxed); .next
.store(next, Ordering::Relaxed);
// We have successfully erased all references to 'tail', so // We have successfully erased all references to 'tail', so
// now we can safely drop it. // now we can safely drop it.
let _: Box<Node<T>> = Box::from_raw(tail); let _: Box<Node<T>> = Box::from_raw(tail);
@ -234,9 +235,9 @@ impl<T, ProducerAddition, ConsumerAddition> Drop for Queue<T, ProducerAddition,
#[cfg(all(test, not(target_os = "emscripten")))] #[cfg(all(test, not(target_os = "emscripten")))]
mod tests { mod tests {
use super::Queue; use super::Queue;
use crate::sync::mpsc::channel;
use crate::sync::Arc; use crate::sync::Arc;
use crate::thread; use crate::thread;
use crate::sync::mpsc::channel;
#[test] #[test]
fn smoke() { fn smoke() {
@ -265,15 +266,15 @@ mod tests {
match queue.peek() { match queue.peek() {
Some(vec) => { Some(vec) => {
assert_eq!(&*vec, &[1]); assert_eq!(&*vec, &[1]);
}, }
None => unreachable!() None => unreachable!(),
} }
match queue.pop() { match queue.pop() {
Some(vec) => { Some(vec) => {
assert_eq!(&*vec, &[1]); assert_eq!(&*vec, &[1]);
}, }
None => unreachable!() None => unreachable!(),
} }
} }
} }
@ -316,7 +317,7 @@ mod tests {
let (tx, rx) = channel(); let (tx, rx) = channel();
let q2 = q.clone(); let q2 = q.clone();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
for _ in 0..100000 { for _ in 0..100000 {
loop { loop {
match q2.pop() { match q2.pop() {

View file

@ -6,10 +6,9 @@
/// ///
/// High level implementation details can be found in the comment of the parent /// High level implementation details can be found in the comment of the parent
/// module. /// module.
pub use self::Failure::*; pub use self::Failure::*;
pub use self::UpgradeResult::*;
use self::Message::*; use self::Message::*;
pub use self::UpgradeResult::*;
use core::cmp; use core::cmp;
use core::isize; use core::isize;
@ -19,10 +18,10 @@ use crate::ptr;
use crate::thread; use crate::thread;
use crate::time::Instant; use crate::time::Instant;
use crate::sync::atomic::{AtomicIsize, AtomicUsize, Ordering, AtomicBool}; use crate::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
use crate::sync::mpsc::Receiver;
use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::blocking::{self, SignalToken};
use crate::sync::mpsc::spsc_queue as spsc; use crate::sync::mpsc::spsc_queue as spsc;
use crate::sync::mpsc::Receiver;
const DISCONNECTED: isize = isize::MIN; const DISCONNECTED: isize = isize::MIN;
#[cfg(test)] #[cfg(test)]
@ -46,7 +45,6 @@ struct ConsumerAddition {
steals: UnsafeCell<isize>, // How many times has a port received without blocking? steals: UnsafeCell<isize>, // How many times has a port received without blocking?
} }
pub enum Failure<T> { pub enum Failure<T> {
Empty, Empty,
Disconnected, Disconnected,
@ -69,7 +67,8 @@ enum Message<T> {
impl<T> Packet<T> { impl<T> Packet<T> {
pub fn new() -> Packet<T> { pub fn new() -> Packet<T> {
Packet { Packet {
queue: unsafe { spsc::Queue::with_additions( queue: unsafe {
spsc::Queue::with_additions(
128, 128,
ProducerAddition { ProducerAddition {
cnt: AtomicIsize::new(0), cnt: AtomicIsize::new(0),
@ -77,10 +76,9 @@ impl<T> Packet<T> {
port_dropped: AtomicBool::new(false), port_dropped: AtomicBool::new(false),
}, },
ConsumerAddition { ConsumerAddition { steals: UnsafeCell::new(0) },
steals: UnsafeCell::new(0), )
} },
)},
} }
} }
@ -88,11 +86,15 @@ impl<T> Packet<T> {
// If the other port has deterministically gone away, then definitely // If the other port has deterministically gone away, then definitely
// must return the data back up the stack. Otherwise, the data is // must return the data back up the stack. Otherwise, the data is
// considered as being sent. // considered as being sent.
if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) { return Err(t) } if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) {
return Err(t);
}
match self.do_send(Data(t)) { match self.do_send(Data(t)) {
UpSuccess | UpDisconnected => {}, UpSuccess | UpDisconnected => {}
UpWoke(token) => { token.signal(); } UpWoke(token) => {
token.signal();
}
} }
Ok(()) Ok(())
} }
@ -101,7 +103,7 @@ impl<T> Packet<T> {
// If the port has gone away, then there's no need to proceed any // If the port has gone away, then there's no need to proceed any
// further. // further.
if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) { if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) {
return UpDisconnected return UpDisconnected;
} }
self.do_send(GoUp(up)) self.do_send(GoUp(up))
@ -136,7 +138,10 @@ impl<T> Packet<T> {
// Otherwise we just sent some data on a non-waiting queue, so just // Otherwise we just sent some data on a non-waiting queue, so just
// make sure the world is sane and carry on! // make sure the world is sane and carry on!
n => { assert!(n >= 0); UpSuccess } n => {
assert!(n >= 0);
UpSuccess
}
} }
} }
@ -166,7 +171,9 @@ impl<T> Packet<T> {
// data, we successfully sleep // data, we successfully sleep
n => { n => {
assert!(n >= 0); assert!(n >= 0);
if n - steals <= 0 { return Ok(()) } if n - steals <= 0 {
return Ok(());
}
} }
} }
@ -199,8 +206,7 @@ impl<T> Packet<T> {
// Messages which actually popped from the queue shouldn't count as // Messages which actually popped from the queue shouldn't count as
// a steal, so offset the decrement here (we already have our // a steal, so offset the decrement here (we already have our
// "steal" factored into the channel count above). // "steal" factored into the channel count above).
data @ Ok(..) | data @ Ok(..) | data @ Err(Upgraded(..)) => unsafe {
data @ Err(Upgraded(..)) => unsafe {
*self.queue.consumer_addition().steals.get() -= 1; *self.queue.consumer_addition().steals.get() -= 1;
data data
}, },
@ -226,8 +232,10 @@ impl<T> Packet<T> {
if *self.queue.consumer_addition().steals.get() > MAX_STEALS { if *self.queue.consumer_addition().steals.get() > MAX_STEALS {
match self.queue.producer_addition().cnt.swap(0, Ordering::SeqCst) { match self.queue.producer_addition().cnt.swap(0, Ordering::SeqCst) {
DISCONNECTED => { DISCONNECTED => {
self.queue.producer_addition().cnt.store( self.queue
DISCONNECTED, Ordering::SeqCst); .producer_addition()
.cnt
.store(DISCONNECTED, Ordering::SeqCst);
} }
n => { n => {
let m = cmp::min(n, *self.queue.consumer_addition().steals.get()); let m = cmp::min(n, *self.queue.consumer_addition().steals.get());
@ -259,13 +267,11 @@ impl<T> Packet<T> {
// We can ignore steals because the other end is // We can ignore steals because the other end is
// disconnected and we'll never need to really factor in our // disconnected and we'll never need to really factor in our
// steals again. // steals again.
_ => { _ => match self.queue.pop() {
match self.queue.pop() {
Some(Data(t)) => Ok(t), Some(Data(t)) => Ok(t),
Some(GoUp(up)) => Err(Upgraded(up)), Some(GoUp(up)) => Err(Upgraded(up)),
None => Err(Disconnected), None => Err(Disconnected),
} },
}
} }
} }
} }
@ -275,9 +281,13 @@ impl<T> Packet<T> {
// Dropping a channel is pretty simple, we just flag it as disconnected // Dropping a channel is pretty simple, we just flag it as disconnected
// and then wakeup a blocker if there is one. // and then wakeup a blocker if there is one.
match self.queue.producer_addition().cnt.swap(DISCONNECTED, Ordering::SeqCst) { match self.queue.producer_addition().cnt.swap(DISCONNECTED, Ordering::SeqCst) {
-1 => { self.take_to_wake().signal(); } -1 => {
self.take_to_wake().signal();
}
DISCONNECTED => {} DISCONNECTED => {}
n => { assert!(n >= 0); } n => {
assert!(n >= 0);
}
} }
} }
@ -314,10 +324,15 @@ impl<T> Packet<T> {
let mut steals = unsafe { *self.queue.consumer_addition().steals.get() }; let mut steals = unsafe { *self.queue.consumer_addition().steals.get() };
while { while {
let cnt = self.queue.producer_addition().cnt.compare_and_swap( let cnt = self.queue.producer_addition().cnt.compare_and_swap(
steals, DISCONNECTED, Ordering::SeqCst); steals,
DISCONNECTED,
Ordering::SeqCst,
);
cnt != DISCONNECTED && cnt != steals cnt != DISCONNECTED && cnt != steals
} { } {
while let Some(_) = self.queue.pop() { steals += 1; } while let Some(_) = self.queue.pop() {
steals += 1;
}
} }
// At this point in time, we have gated all future senders from sending, // At this point in time, we have gated all future senders from sending,
@ -338,13 +353,12 @@ impl<T> Packet<T> {
self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst); self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst);
DISCONNECTED DISCONNECTED
} }
n => n n => n,
} }
} }
// Removes a previous thread from being blocked in this port // Removes a previous thread from being blocked in this port
pub fn abort_selection(&self, pub fn abort_selection(&self, was_upgrade: bool) -> Result<bool, Receiver<T>> {
was_upgrade: bool) -> Result<bool, Receiver<T>> {
// If we're aborting selection after upgrading from a oneshot, then // If we're aborting selection after upgrading from a oneshot, then
// we're guarantee that no one is waiting. The only way that we could // we're guarantee that no one is waiting. The only way that we could
// have seen the upgrade is if data was actually sent on the channel // have seen the upgrade is if data was actually sent on the channel
@ -361,7 +375,7 @@ impl<T> Packet<T> {
if was_upgrade { if was_upgrade {
assert_eq!(unsafe { *self.queue.consumer_addition().steals.get() }, 0); assert_eq!(unsafe { *self.queue.consumer_addition().steals.get() }, 0);
assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0);
return Ok(true) return Ok(true);
} }
// We want to make sure that the count on the channel goes non-negative, // We want to make sure that the count on the channel goes non-negative,
@ -416,12 +430,10 @@ impl<T> Packet<T> {
// upgraded port. // upgraded port.
if has_data { if has_data {
match self.queue.peek() { match self.queue.peek() {
Some(&mut GoUp(..)) => { Some(&mut GoUp(..)) => match self.queue.pop() {
match self.queue.pop() {
Some(GoUp(port)) => Err(port), Some(GoUp(port)) => Err(port),
_ => unreachable!(), _ => unreachable!(),
} },
}
_ => Ok(true), _ => Ok(true),
} }
} else { } else {

View file

@ -1,3 +1,4 @@
use self::Blocker::*;
/// Synchronous channels/ports /// Synchronous channels/ports
/// ///
/// This channel implementation differs significantly from the asynchronous /// This channel implementation differs significantly from the asynchronous
@ -22,17 +23,15 @@
/// implementation shares almost all code for the buffered and unbuffered cases /// implementation shares almost all code for the buffered and unbuffered cases
/// of a synchronous channel. There are a few branches for the unbuffered case, /// of a synchronous channel. There are a few branches for the unbuffered case,
/// but they're mostly just relevant to blocking senders. /// but they're mostly just relevant to blocking senders.
pub use self::Failure::*; pub use self::Failure::*;
use self::Blocker::*;
use core::intrinsics::abort; use core::intrinsics::abort;
use core::isize; use core::isize;
use core::mem; use core::mem;
use core::ptr; use core::ptr;
use crate::sync::atomic::{Ordering, AtomicUsize}; use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sync::mpsc::blocking::{self, WaitToken, SignalToken}; use crate::sync::mpsc::blocking::{self, SignalToken, WaitToken};
use crate::sync::{Mutex, MutexGuard}; use crate::sync::{Mutex, MutexGuard};
use crate::time::Instant; use crate::time::Instant;
@ -46,9 +45,9 @@ pub struct Packet<T> {
lock: Mutex<State<T>>, lock: Mutex<State<T>>,
} }
unsafe impl<T: Send> Send for Packet<T> { } unsafe impl<T: Send> Send for Packet<T> {}
unsafe impl<T: Send> Sync for Packet<T> { } unsafe impl<T: Send> Sync for Packet<T> {}
struct State<T> { struct State<T> {
disconnected: bool, // Is the channel disconnected yet? disconnected: bool, // Is the channel disconnected yet?
@ -72,7 +71,7 @@ unsafe impl<T: Send> Send for State<T> {}
enum Blocker { enum Blocker {
BlockedSender(SignalToken), BlockedSender(SignalToken),
BlockedReceiver(SignalToken), BlockedReceiver(SignalToken),
NoneBlocked NoneBlocked,
} }
/// Simple queue for threading threads together. Nodes are stack-allocated, so /// Simple queue for threading threads together. Nodes are stack-allocated, so
@ -104,11 +103,11 @@ pub enum Failure {
/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock` /// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
/// in the meantime. This re-locks the mutex upon returning. /// in the meantime. This re-locks the mutex upon returning.
fn wait<'a, 'b, T>(lock: &'a Mutex<State<T>>, fn wait<'a, 'b, T>(
lock: &'a Mutex<State<T>>,
mut guard: MutexGuard<'b, State<T>>, mut guard: MutexGuard<'b, State<T>>,
f: fn(SignalToken) -> Blocker) f: fn(SignalToken) -> Blocker,
-> MutexGuard<'a, State<T>> ) -> MutexGuard<'a, State<T>> {
{
let (wait_token, signal_token) = blocking::tokens(); let (wait_token, signal_token) = blocking::tokens();
match mem::replace(&mut guard.blocker, f(signal_token)) { match mem::replace(&mut guard.blocker, f(signal_token)) {
NoneBlocked => {} NoneBlocked => {}
@ -120,12 +119,12 @@ fn wait<'a, 'b, T>(lock: &'a Mutex<State<T>>,
} }
/// Same as wait, but waiting at most until `deadline`. /// Same as wait, but waiting at most until `deadline`.
fn wait_timeout_receiver<'a, 'b, T>(lock: &'a Mutex<State<T>>, fn wait_timeout_receiver<'a, 'b, T>(
lock: &'a Mutex<State<T>>,
deadline: Instant, deadline: Instant,
mut guard: MutexGuard<'b, State<T>>, mut guard: MutexGuard<'b, State<T>>,
success: &mut bool) success: &mut bool,
-> MutexGuard<'a, State<T>> ) -> MutexGuard<'a, State<T>> {
{
let (wait_token, signal_token) = blocking::tokens(); let (wait_token, signal_token) = blocking::tokens();
match mem::replace(&mut guard.blocker, BlockedReceiver(signal_token)) { match mem::replace(&mut guard.blocker, BlockedReceiver(signal_token)) {
NoneBlocked => {} NoneBlocked => {}
@ -147,7 +146,10 @@ fn abort_selection<T>(guard: &mut MutexGuard<'_, State<T>>) -> bool {
guard.blocker = BlockedSender(token); guard.blocker = BlockedSender(token);
true true
} }
BlockedReceiver(token) => { drop(token); false } BlockedReceiver(token) => {
drop(token);
false
}
} }
} }
@ -168,12 +170,9 @@ impl<T> Packet<T> {
blocker: NoneBlocked, blocker: NoneBlocked,
cap: capacity, cap: capacity,
canceled: None, canceled: None,
queue: Queue { queue: Queue { head: ptr::null_mut(), tail: ptr::null_mut() },
head: ptr::null_mut(),
tail: ptr::null_mut(),
},
buf: Buffer { buf: Buffer {
buf: (0..capacity + if capacity == 0 {1} else {0}).map(|_| None).collect(), buf: (0..capacity + if capacity == 0 { 1 } else { 0 }).map(|_| None).collect(),
start: 0, start: 0,
size: 0, size: 0,
}, },
@ -200,7 +199,9 @@ impl<T> Packet<T> {
pub fn send(&self, t: T) -> Result<(), T> { pub fn send(&self, t: T) -> Result<(), T> {
let mut guard = self.acquire_send_slot(); let mut guard = self.acquire_send_slot();
if guard.disconnected { return Err(t) } if guard.disconnected {
return Err(t);
}
guard.buf.enqueue(t); guard.buf.enqueue(t);
match mem::replace(&mut guard.blocker, NoneBlocked) { match mem::replace(&mut guard.blocker, NoneBlocked) {
@ -213,14 +214,17 @@ impl<T> Packet<T> {
assert!(guard.canceled.is_none()); assert!(guard.canceled.is_none());
guard.canceled = Some(unsafe { mem::transmute(&mut canceled) }); guard.canceled = Some(unsafe { mem::transmute(&mut canceled) });
let mut guard = wait(&self.lock, guard, BlockedSender); let mut guard = wait(&self.lock, guard, BlockedSender);
if canceled {Err(guard.buf.dequeue())} else {Ok(())} if canceled { Err(guard.buf.dequeue()) } else { Ok(()) }
} }
// success, we buffered some data // success, we buffered some data
NoneBlocked => Ok(()), NoneBlocked => Ok(()),
// success, someone's about to receive our buffered data. // success, someone's about to receive our buffered data.
BlockedReceiver(token) => { wakeup(token, guard); Ok(()) } BlockedReceiver(token) => {
wakeup(token, guard);
Ok(())
}
BlockedSender(..) => panic!("lolwut"), BlockedSender(..) => panic!("lolwut"),
} }
@ -271,10 +275,8 @@ impl<T> Packet<T> {
// while loop because we're the only receiver. // while loop because we're the only receiver.
if !guard.disconnected && guard.buf.size() == 0 { if !guard.disconnected && guard.buf.size() == 0 {
if let Some(deadline) = deadline { if let Some(deadline) = deadline {
guard = wait_timeout_receiver(&self.lock, guard =
deadline, wait_timeout_receiver(&self.lock, deadline, guard, &mut woke_up_after_waiting);
guard,
&mut woke_up_after_waiting);
} else { } else {
guard = wait(&self.lock, guard, BlockedReceiver); guard = wait(&self.lock, guard, BlockedReceiver);
woke_up_after_waiting = true; woke_up_after_waiting = true;
@ -290,7 +292,9 @@ impl<T> Packet<T> {
// Pick up the data, wake up our neighbors, and carry on // Pick up the data, wake up our neighbors, and carry on
assert!(guard.buf.size() > 0 || (deadline.is_some() && !woke_up_after_waiting)); assert!(guard.buf.size() > 0 || (deadline.is_some() && !woke_up_after_waiting));
if guard.buf.size() == 0 { return Err(Empty); } if guard.buf.size() == 0 {
return Err(Empty);
}
let ret = guard.buf.dequeue(); let ret = guard.buf.dequeue();
self.wakeup_senders(woke_up_after_waiting, guard); self.wakeup_senders(woke_up_after_waiting, guard);
@ -301,8 +305,12 @@ impl<T> Packet<T> {
let mut guard = self.lock.lock().unwrap(); let mut guard = self.lock.lock().unwrap();
// Easy cases first // Easy cases first
if guard.disconnected && guard.buf.size() == 0 { return Err(Disconnected) } if guard.disconnected && guard.buf.size() == 0 {
if guard.buf.size() == 0 { return Err(Empty) } return Err(Disconnected);
}
if guard.buf.size() == 0 {
return Err(Empty);
}
// Be sure to wake up neighbors // Be sure to wake up neighbors
let ret = Ok(guard.buf.dequeue()); let ret = Ok(guard.buf.dequeue());
@ -357,12 +365,14 @@ impl<T> Packet<T> {
// Only flag the channel as disconnected if we're the last channel // Only flag the channel as disconnected if we're the last channel
match self.channels.fetch_sub(1, Ordering::SeqCst) { match self.channels.fetch_sub(1, Ordering::SeqCst) {
1 => {} 1 => {}
_ => return _ => return,
} }
// Not much to do other than wake up a receiver if one's there // Not much to do other than wake up a receiver if one's there
let mut guard = self.lock.lock().unwrap(); let mut guard = self.lock.lock().unwrap();
if guard.disconnected { return } if guard.disconnected {
return;
}
guard.disconnected = true; guard.disconnected = true;
match mem::replace(&mut guard.blocker, NoneBlocked) { match mem::replace(&mut guard.blocker, NoneBlocked) {
NoneBlocked => {} NoneBlocked => {}
@ -374,7 +384,9 @@ impl<T> Packet<T> {
pub fn drop_port(&self) { pub fn drop_port(&self) {
let mut guard = self.lock.lock().unwrap(); let mut guard = self.lock.lock().unwrap();
if guard.disconnected { return } if guard.disconnected {
return;
}
guard.disconnected = true; guard.disconnected = true;
// If the capacity is 0, then the sender may want its data back after // If the capacity is 0, then the sender may want its data back after
@ -382,15 +394,9 @@ impl<T> Packet<T> {
// the buffered data. As with many other portions of this code, this // the buffered data. As with many other portions of this code, this
// needs to be careful to destroy the data *outside* of the lock to // needs to be careful to destroy the data *outside* of the lock to
// prevent deadlock. // prevent deadlock.
let _data = if guard.cap != 0 { let _data = if guard.cap != 0 { mem::take(&mut guard.buf.buf) } else { Vec::new() };
mem::take(&mut guard.buf.buf) let mut queue =
} else { mem::replace(&mut guard.queue, Queue { head: ptr::null_mut(), tail: ptr::null_mut() });
Vec::new()
};
let mut queue = mem::replace(&mut guard.queue, Queue {
head: ptr::null_mut(),
tail: ptr::null_mut(),
});
let waiter = match mem::replace(&mut guard.blocker, NoneBlocked) { let waiter = match mem::replace(&mut guard.blocker, NoneBlocked) {
NoneBlocked => None, NoneBlocked => None,
@ -402,7 +408,9 @@ impl<T> Packet<T> {
}; };
mem::drop(guard); mem::drop(guard);
while let Some(token) = queue.dequeue() { token.signal(); } while let Some(token) = queue.dequeue() {
token.signal();
}
waiter.map(|t| t.signal()); waiter.map(|t| t.signal());
} }
} }
@ -416,7 +424,6 @@ impl<T> Drop for Packet<T> {
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Buffer, a simple ring buffer backed by Vec<T> // Buffer, a simple ring buffer backed by Vec<T>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -437,8 +444,12 @@ impl<T> Buffer<T> {
result.take().unwrap() result.take().unwrap()
} }
fn size(&self) -> usize { self.size } fn size(&self) -> usize {
fn capacity(&self) -> usize { self.buf.len() } self.size
}
fn capacity(&self) -> usize {
self.buf.len()
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -466,7 +477,7 @@ impl Queue {
fn dequeue(&mut self) -> Option<SignalToken> { fn dequeue(&mut self) -> Option<SignalToken> {
if self.head.is_null() { if self.head.is_null() {
return None return None;
} }
let node = self.head; let node = self.head;
self.head = unsafe { (*node).next }; self.head = unsafe { (*node).next };

View file

@ -6,20 +6,24 @@ use crate::ptr;
// The minimum alignment guaranteed by the architecture. This value is used to // The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. // add fast paths for low alignment values.
#[cfg(all(any(target_arch = "x86", #[cfg(all(any(
target_arch = "x86",
target_arch = "arm", target_arch = "arm",
target_arch = "mips", target_arch = "mips",
target_arch = "powerpc", target_arch = "powerpc",
target_arch = "powerpc64", target_arch = "powerpc64",
target_arch = "asmjs", target_arch = "asmjs",
target_arch = "wasm32", target_arch = "wasm32",
target_arch = "hexagon")))] target_arch = "hexagon"
)))]
pub const MIN_ALIGN: usize = 8; pub const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86_64", #[cfg(all(any(
target_arch = "x86_64",
target_arch = "aarch64", target_arch = "aarch64",
target_arch = "mips64", target_arch = "mips64",
target_arch = "s390x", target_arch = "s390x",
target_arch = "sparc64")))] target_arch = "sparc64"
)))]
pub const MIN_ALIGN: usize = 16; pub const MIN_ALIGN: usize = 16;
pub unsafe fn realloc_fallback( pub unsafe fn realloc_fallback(

View file

@ -25,7 +25,7 @@ pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter<'_>) -> Result {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::fmt::{Formatter, Result, Debug}; use crate::fmt::{Debug, Formatter, Result};
#[test] #[test]
fn smoke() { fn smoke() {

View file

@ -1,13 +1,15 @@
#![allow(dead_code)] // not used on all platforms #![allow(dead_code)] // not used on all platforms
use crate::path::Path;
use crate::fs; use crate::fs;
use crate::io::{self, Error, ErrorKind}; use crate::io::{self, Error, ErrorKind};
use crate::path::Path;
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
if !from.is_file() { if !from.is_file() {
return Err(Error::new(ErrorKind::InvalidInput, return Err(Error::new(
"the source path is not an existing regular file")) ErrorKind::InvalidInput,
"the source path is not an existing regular file",
));
} }
let mut reader = fs::File::open(from)?; let mut reader = fs::File::open(from)?;
@ -21,11 +23,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
pub fn remove_dir_all(path: &Path) -> io::Result<()> { pub fn remove_dir_all(path: &Path) -> io::Result<()> {
let filetype = fs::symlink_metadata(path)?.file_type(); let filetype = fs::symlink_metadata(path)?.file_type();
if filetype.is_symlink() { if filetype.is_symlink() { fs::remove_file(path) } else { remove_dir_all_recursive(path) }
fs::remove_file(path)
} else {
remove_dir_all_recursive(path)
}
} }
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {

View file

@ -3,9 +3,9 @@ pub const DEFAULT_BUF_SIZE: usize = 8 * 1024;
#[cfg(test)] #[cfg(test)]
#[allow(dead_code)] // not used on emscripten #[allow(dead_code)] // not used on emscripten
pub mod test { pub mod test {
use crate::path::{Path, PathBuf};
use crate::env; use crate::env;
use crate::fs; use crate::fs;
use crate::path::{Path, PathBuf};
use rand::RngCore; use rand::RngCore;
pub struct TempDir(PathBuf); pub struct TempDir(PathBuf);

View file

@ -1,79 +1,119 @@
use crate::cmp; use crate::cmp;
use crate::convert::{TryFrom, TryInto};
use crate::ffi::CString; use crate::ffi::CString;
use crate::fmt; use crate::fmt;
use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut}; use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut};
use crate::mem; use crate::mem;
use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::ptr; use crate::ptr;
use crate::sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
use crate::sys::net::netc as c; use crate::sys::net::netc as c;
use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration; use crate::time::Duration;
use crate::convert::{TryFrom, TryInto};
use libc::{c_int, c_void}; use libc::{c_int, c_void};
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", #[cfg(not(any(
target_os = "ios", target_os = "macos", target_os = "dragonfly",
target_os = "openbsd", target_os = "netbsd", target_os = "freebsd",
target_os = "solaris", target_os = "haiku", target_os = "l4re"))] target_os = "ios",
use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; target_os = "macos",
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd",
target_os = "ios", target_os = "macos", target_os = "netbsd",
target_os = "openbsd", target_os = "netbsd", target_os = "solaris",
target_os = "solaris", target_os = "haiku", target_os = "l4re")))] target_os = "haiku",
target_os = "l4re"
)))]
use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", #[cfg(not(any(
target_os = "ios", target_os = "macos", target_os = "dragonfly",
target_os = "openbsd", target_os = "netbsd", target_os = "freebsd",
target_os = "solaris", target_os = "haiku", target_os = "l4re"))] target_os = "ios",
use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; target_os = "macos",
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd",
target_os = "ios", target_os = "macos", target_os = "netbsd",
target_os = "openbsd", target_os = "netbsd", target_os = "solaris",
target_os = "solaris", target_os = "haiku", target_os = "l4re")))] target_os = "haiku",
target_os = "l4re"
)))]
use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP; use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "haiku",
target_os = "l4re"
))]
use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "haiku",
target_os = "l4re"
))]
use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
#[cfg(any(target_os = "linux", target_os = "android", #[cfg(any(
target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
target_os = "openbsd", target_os = "netbsd", target_os = "android",
target_os = "haiku"))] target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "haiku"
))]
use libc::MSG_NOSIGNAL; use libc::MSG_NOSIGNAL;
#[cfg(not(any(target_os = "linux", target_os = "android", #[cfg(not(any(
target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
target_os = "openbsd", target_os = "netbsd", target_os = "android",
target_os = "haiku")))] target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "haiku"
)))]
const MSG_NOSIGNAL: c_int = 0x0; const MSG_NOSIGNAL: c_int = 0x0;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// sockaddr and misc bindings // sockaddr and misc bindings
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> {
payload: T) -> io::Result<()> {
unsafe { unsafe {
let payload = &payload as *const T as *const c_void; let payload = &payload as *const T as *const c_void;
cvt(c::setsockopt(*sock.as_inner(), opt, val, payload, cvt(c::setsockopt(
mem::size_of::<T>() as c::socklen_t))?; *sock.as_inner(),
opt,
val,
payload,
mem::size_of::<T>() as c::socklen_t,
))?;
Ok(()) Ok(())
} }
} }
pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<T> {
val: c_int) -> io::Result<T> {
unsafe { unsafe {
let mut slot: T = mem::zeroed(); let mut slot: T = mem::zeroed();
let mut len = mem::size_of::<T>() as c::socklen_t; let mut len = mem::size_of::<T>() as c::socklen_t;
cvt(c::getsockopt(*sock.as_inner(), opt, val, cvt(c::getsockopt(*sock.as_inner(), opt, val, &mut slot as *mut _ as *mut _, &mut len))?;
&mut slot as *mut _ as *mut _,
&mut len))?;
assert_eq!(len as usize, mem::size_of::<T>()); assert_eq!(len as usize, mem::size_of::<T>());
Ok(slot) Ok(slot)
} }
} }
fn sockname<F>(f: F) -> io::Result<SocketAddr> fn sockname<F>(f: F) -> io::Result<SocketAddr>
where F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int where
F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
{ {
unsafe { unsafe {
let mut storage: c::sockaddr_storage = mem::zeroed(); let mut storage: c::sockaddr_storage = mem::zeroed();
@ -83,8 +123,7 @@ fn sockname<F>(f: F) -> io::Result<SocketAddr>
} }
} }
pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
len: usize) -> io::Result<SocketAddr> {
match storage.ss_family as c_int { match storage.ss_family as c_int {
c::AF_INET => { c::AF_INET => {
assert!(len as usize >= mem::size_of::<c::sockaddr_in>()); assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
@ -98,9 +137,7 @@ pub fn sockaddr_to_addr(storage: &c::sockaddr_storage,
*(storage as *const _ as *const c::sockaddr_in6) *(storage as *const _ as *const c::sockaddr_in6)
}))) })))
} }
_ => { _ => Err(Error::new(ErrorKind::InvalidInput, "invalid argument")),
Err(Error::new(ErrorKind::InvalidInput, "invalid argument"))
}
} }
} }
@ -121,7 +158,7 @@ fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
pub struct LookupHost { pub struct LookupHost {
original: *mut c::addrinfo, original: *mut c::addrinfo,
cur: *mut c::addrinfo, cur: *mut c::addrinfo,
port: u16 port: u16,
} }
impl LookupHost { impl LookupHost {
@ -137,9 +174,7 @@ impl Iterator for LookupHost {
unsafe { unsafe {
let cur = self.cur.as_ref()?; let cur = self.cur.as_ref()?;
self.cur = cur.ai_next; self.cur = cur.ai_next;
match sockaddr_to_addr(mem::transmute(cur.ai_addr), match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) {
cur.ai_addrlen as usize)
{
Ok(addr) => return Some(addr), Ok(addr) => return Some(addr),
Err(_) => continue, Err(_) => continue,
} }
@ -162,13 +197,12 @@ impl TryFrom<&str> for LookupHost {
fn try_from(s: &str) -> io::Result<LookupHost> { fn try_from(s: &str) -> io::Result<LookupHost> {
macro_rules! try_opt { macro_rules! try_opt {
($e:expr, $msg:expr) => ( ($e:expr, $msg:expr) => {
match $e { match $e {
Some(r) => r, Some(r) => r,
None => return Err(io::Error::new(io::ErrorKind::InvalidInput, None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)),
$msg)),
} }
) };
} }
// split the string by ':' and convert the second part to u16 // split the string by ':' and convert the second part to u16
@ -192,9 +226,8 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
hints.ai_socktype = c::SOCK_STREAM; hints.ai_socktype = c::SOCK_STREAM;
let mut res = ptr::null_mut(); let mut res = ptr::null_mut();
unsafe { unsafe {
cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| { cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
LookupHost { original: res, cur: res, port } .map(|_| LookupHost { original: res, cur: res, port })
})
} }
} }
} }
@ -228,9 +261,13 @@ impl TcpStream {
Ok(TcpStream { inner: sock }) Ok(TcpStream { inner: sock })
} }
pub fn socket(&self) -> &Socket { &self.inner } pub fn socket(&self) -> &Socket {
&self.inner
}
pub fn into_socket(self) -> Socket { self.inner } pub fn into_socket(self) -> Socket {
self.inner
}
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.inner.set_timeout(dur, c::SO_RCVTIMEO) self.inner.set_timeout(dur, c::SO_RCVTIMEO)
@ -263,10 +300,7 @@ impl TcpStream {
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let ret = cvt(unsafe { let ret = cvt(unsafe {
c::send(*self.inner.as_inner(), c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
buf.as_ptr() as *const c_void,
len,
MSG_NOSIGNAL)
})?; })?;
Ok(ret as usize) Ok(ret as usize)
} }
@ -276,15 +310,11 @@ impl TcpStream {
} }
pub fn peer_addr(&self) -> io::Result<SocketAddr> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
c::getpeername(*self.inner.as_inner(), buf, len)
})
} }
pub fn socket_addr(&self) -> io::Result<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
c::getsockname(*self.inner.as_inner(), buf, len)
})
} }
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
@ -339,9 +369,8 @@ impl fmt::Debug for TcpStream {
res.field("peer", &peer); res.field("peer", &peer);
} }
let name = if cfg!(windows) {"socket"} else {"fd"}; let name = if cfg!(windows) { "socket" } else { "fd" };
res.field(name, &self.inner.as_inner()) res.field(name, &self.inner.as_inner()).finish()
.finish()
} }
} }
@ -365,8 +394,7 @@ impl TcpListener {
// to quickly rebind a socket, without needing to wait for // to quickly rebind a socket, without needing to wait for
// the OS to clean up the previous one. // the OS to clean up the previous one.
if !cfg!(windows) { if !cfg!(windows) {
setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
1 as c_int)?;
} }
// Bind our new socket // Bind our new socket
@ -378,23 +406,24 @@ impl TcpListener {
Ok(TcpListener { inner: sock }) Ok(TcpListener { inner: sock })
} }
pub fn socket(&self) -> &Socket { &self.inner } pub fn socket(&self) -> &Socket {
&self.inner
}
pub fn into_socket(self) -> Socket { self.inner } pub fn into_socket(self) -> Socket {
self.inner
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
c::getsockname(*self.inner.as_inner(), buf, len)
})
} }
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
let mut len = mem::size_of_val(&storage) as c::socklen_t; let mut len = mem::size_of_val(&storage) as c::socklen_t;
let sock = self.inner.accept(&mut storage as *mut _ as *mut _, let sock = self.inner.accept(&mut storage as *mut _ as *mut _, &mut len)?;
&mut len)?;
let addr = sockaddr_to_addr(&storage, len as usize)?; let addr = sockaddr_to_addr(&storage, len as usize)?;
Ok((TcpStream { inner: sock, }, addr)) Ok((TcpStream { inner: sock }, addr))
} }
pub fn duplicate(&self) -> io::Result<TcpListener> { pub fn duplicate(&self) -> io::Result<TcpListener> {
@ -442,9 +471,8 @@ impl fmt::Debug for TcpListener {
res.field("addr", &addr); res.field("addr", &addr);
} }
let name = if cfg!(windows) {"socket"} else {"fd"}; let name = if cfg!(windows) { "socket" } else { "fd" };
res.field(name, &self.inner.as_inner()) res.field(name, &self.inner.as_inner()).finish()
.finish()
} }
} }
@ -468,20 +496,20 @@ impl UdpSocket {
Ok(UdpSocket { inner: sock }) Ok(UdpSocket { inner: sock })
} }
pub fn socket(&self) -> &Socket { &self.inner } pub fn socket(&self) -> &Socket {
&self.inner
}
pub fn into_socket(self) -> Socket { self.inner } pub fn into_socket(self) -> Socket {
self.inner
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
c::getpeername(*self.inner.as_inner(), buf, len)
})
} }
pub fn socket_addr(&self) -> io::Result<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
sockname(|buf, len| unsafe { sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
c::getsockname(*self.inner.as_inner(), buf, len)
})
} }
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
@ -496,9 +524,14 @@ impl UdpSocket {
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let (dstp, dstlen) = dst.into_inner(); let (dstp, dstlen) = dst.into_inner();
let ret = cvt(unsafe { let ret = cvt(unsafe {
c::sendto(*self.inner.as_inner(), c::sendto(
buf.as_ptr() as *const c_void, len, *self.inner.as_inner(),
MSG_NOSIGNAL, dstp, dstlen) buf.as_ptr() as *const c_void,
len,
MSG_NOSIGNAL,
dstp,
dstlen,
)
})?; })?;
Ok(ret as usize) Ok(ret as usize)
} }
@ -559,8 +592,7 @@ impl UdpSocket {
Ok(raw != 0) Ok(raw != 0)
} }
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
-> io::Result<()> {
let mreq = c::ip_mreq { let mreq = c::ip_mreq {
imr_multiaddr: *multiaddr.as_inner(), imr_multiaddr: *multiaddr.as_inner(),
imr_interface: *interface.as_inner(), imr_interface: *interface.as_inner(),
@ -568,8 +600,7 @@ impl UdpSocket {
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
} }
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
-> io::Result<()> {
let mreq = c::ipv6_mreq { let mreq = c::ipv6_mreq {
ipv6mr_multiaddr: *multiaddr.as_inner(), ipv6mr_multiaddr: *multiaddr.as_inner(),
ipv6mr_interface: to_ipv6mr_interface(interface), ipv6mr_interface: to_ipv6mr_interface(interface),
@ -577,8 +608,7 @@ impl UdpSocket {
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
} }
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
-> io::Result<()> {
let mreq = c::ip_mreq { let mreq = c::ip_mreq {
imr_multiaddr: *multiaddr.as_inner(), imr_multiaddr: *multiaddr.as_inner(),
imr_interface: *interface.as_inner(), imr_interface: *interface.as_inner(),
@ -586,8 +616,7 @@ impl UdpSocket {
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
} }
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
-> io::Result<()> {
let mreq = c::ipv6_mreq { let mreq = c::ipv6_mreq {
ipv6mr_multiaddr: *multiaddr.as_inner(), ipv6mr_multiaddr: *multiaddr.as_inner(),
ipv6mr_interface: to_ipv6mr_interface(interface), ipv6mr_interface: to_ipv6mr_interface(interface),
@ -623,10 +652,7 @@ impl UdpSocket {
pub fn send(&self, buf: &[u8]) -> io::Result<usize> { pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let ret = cvt(unsafe { let ret = cvt(unsafe {
c::send(*self.inner.as_inner(), c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
buf.as_ptr() as *const c_void,
len,
MSG_NOSIGNAL)
})?; })?;
Ok(ret as usize) Ok(ret as usize)
} }
@ -651,9 +677,8 @@ impl fmt::Debug for UdpSocket {
res.field("addr", &addr); res.field("addr", &addr);
} }
let name = if cfg!(windows) {"socket"} else {"fd"}; let name = if cfg!(windows) { "socket" } else { "fd" };
res.field(name, &self.inner.as_inner()) res.field(name, &self.inner.as_inner()).finish()
.finish()
} }
} }
@ -667,10 +692,15 @@ mod tests {
let mut addrs = HashMap::new(); let mut addrs = HashMap::new();
let lh = match LookupHost::try_from(("localhost", 0)) { let lh = match LookupHost::try_from(("localhost", 0)) {
Ok(lh) => lh, Ok(lh) => lh,
Err(e) => panic!("couldn't resolve `localhost': {}", e) Err(e) => panic!("couldn't resolve `localhost': {}", e),
}; };
for sa in lh { *addrs.entry(sa).or_insert(0) += 1; }; for sa in lh {
assert_eq!(addrs.iter().filter(|&(_, &v)| v > 1).collect::<Vec<_>>(), vec![], *addrs.entry(sa).or_insert(0) += 1;
"There should be no duplicate localhost entries"); }
assert_eq!(
addrs.iter().filter(|&(_, &v)| v > 1).collect::<Vec<_>>(),
vec![],
"There should be no duplicate localhost entries"
);
} }
} }

View file

@ -4,18 +4,18 @@
use crate::borrow::Cow; use crate::borrow::Cow;
use crate::ffi::{OsStr, OsString}; use crate::ffi::{OsStr, OsString};
use crate::fmt; use crate::fmt;
use crate::str;
use crate::mem; use crate::mem;
use crate::rc::Rc; use crate::rc::Rc;
use crate::str;
use crate::sync::Arc; use crate::sync::Arc;
use crate::sys_common::{FromInner, IntoInner, AsInner};
use crate::sys_common::bytestring::debug_fmt_bytestring; use crate::sys_common::bytestring::debug_fmt_bytestring;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use core::str::lossy::Utf8Lossy; use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)] #[derive(Clone, Hash)]
pub(crate) struct Buf { pub(crate) struct Buf {
pub inner: Vec<u8> pub inner: Vec<u8>,
} }
// FIXME: // FIXME:
@ -25,7 +25,7 @@ pub(crate) struct Buf {
// Anyway, `Slice` representation and layout are considered implementation detail, are // Anyway, `Slice` representation and layout are considered implementation detail, are
// not documented and must not be relied upon. // not documented and must not be relied upon.
pub(crate) struct Slice { pub(crate) struct Slice {
pub inner: [u8] pub inner: [u8],
} }
impl fmt::Debug for Slice { impl fmt::Debug for Slice {
@ -64,7 +64,6 @@ impl AsInner<[u8]> for Buf {
} }
} }
impl Buf { impl Buf {
pub fn from_string(s: String) -> Buf { pub fn from_string(s: String) -> Buf {
Buf { inner: s.into_bytes() } Buf { inner: s.into_bytes() }
@ -72,9 +71,7 @@ impl Buf {
#[inline] #[inline]
pub fn with_capacity(capacity: usize) -> Buf { pub fn with_capacity(capacity: usize) -> Buf {
Buf { Buf { inner: Vec::with_capacity(capacity) }
inner: Vec::with_capacity(capacity)
}
} }
#[inline] #[inline]
@ -112,7 +109,7 @@ impl Buf {
} }
pub fn into_string(self) -> Result<String, Buf> { pub fn into_string(self) -> Result<String, Buf> {
String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } ) String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
} }
pub fn push_slice(&mut self, s: &Slice) { pub fn push_slice(&mut self, s: &Slice) {

View file

@ -1,9 +1,11 @@
use crate::error::{Error}; use crate::error::Error;
use crate::fmt; use crate::fmt;
use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::atomic::{AtomicBool, Ordering};
use crate::thread; use crate::thread;
pub struct Flag { failed: AtomicBool } pub struct Flag {
failed: AtomicBool,
}
// Note that the Ordering uses to access the `failed` field of `Flag` below is // Note that the Ordering uses to access the `failed` field of `Flag` below is
// always `Relaxed`, and that's because this isn't actually protecting any data, // always `Relaxed`, and that's because this isn't actually protecting any data,
@ -24,11 +26,7 @@ impl Flag {
#[inline] #[inline]
pub fn borrow(&self) -> LockResult<Guard> { pub fn borrow(&self) -> LockResult<Guard> {
let ret = Guard { panicking: thread::panicking() }; let ret = Guard { panicking: thread::panicking() };
if self.get() { if self.get() { Err(PoisonError::new(ret)) } else { Ok(ret) }
Err(PoisonError::new(ret))
} else {
Ok(ret)
}
} }
#[inline] #[inline]
@ -192,17 +190,23 @@ impl<T> PoisonError<T> {
/// println!("recovered {} items", data.len()); /// println!("recovered {} items", data.len());
/// ``` /// ```
#[stable(feature = "sync_poison", since = "1.2.0")] #[stable(feature = "sync_poison", since = "1.2.0")]
pub fn into_inner(self) -> T { self.guard } pub fn into_inner(self) -> T {
self.guard
}
/// Reaches into this error indicating that a lock is poisoned, returning a /// Reaches into this error indicating that a lock is poisoned, returning a
/// reference to the underlying guard to allow access regardless. /// reference to the underlying guard to allow access regardless.
#[stable(feature = "sync_poison", since = "1.2.0")] #[stable(feature = "sync_poison", since = "1.2.0")]
pub fn get_ref(&self) -> &T { &self.guard } pub fn get_ref(&self) -> &T {
&self.guard
}
/// Reaches into this error indicating that a lock is poisoned, returning a /// Reaches into this error indicating that a lock is poisoned, returning a
/// mutable reference to the underlying guard to allow access regardless. /// mutable reference to the underlying guard to allow access regardless.
#[stable(feature = "sync_poison", since = "1.2.0")] #[stable(feature = "sync_poison", since = "1.2.0")]
pub fn get_mut(&mut self) -> &mut T { &mut self.guard } pub fn get_mut(&mut self) -> &mut T {
&mut self.guard
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -217,7 +221,7 @@ impl<T> fmt::Debug for TryLockError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self { match *self {
TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f), TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
TryLockError::WouldBlock => "WouldBlock".fmt(f) TryLockError::WouldBlock => "WouldBlock".fmt(f),
} }
} }
} }
@ -227,8 +231,9 @@ impl<T> fmt::Display for TryLockError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self { match *self {
TryLockError::Poisoned(..) => "poisoned lock: another task failed inside", TryLockError::Poisoned(..) => "poisoned lock: another task failed inside",
TryLockError::WouldBlock => "try_lock failed because the operation would block" TryLockError::WouldBlock => "try_lock failed because the operation would block",
}.fmt(f) }
.fmt(f)
} }
} }
@ -237,23 +242,24 @@ impl<T> Error for TryLockError<T> {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
TryLockError::Poisoned(ref p) => p.description(), TryLockError::Poisoned(ref p) => p.description(),
TryLockError::WouldBlock => "try_lock failed because the operation would block" TryLockError::WouldBlock => "try_lock failed because the operation would block",
} }
} }
fn cause(&self) -> Option<&dyn Error> { fn cause(&self) -> Option<&dyn Error> {
match *self { match *self {
TryLockError::Poisoned(ref p) => Some(p), TryLockError::Poisoned(ref p) => Some(p),
_ => None _ => None,
} }
} }
} }
pub fn map_result<T, U, F>(result: LockResult<T>, f: F) pub fn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>
-> LockResult<U> where
where F: FnOnce(T) -> U { F: FnOnce(T) -> U,
{
match result { match result {
Ok(t) => Ok(f(t)), Ok(t) => Ok(f(t)),
Err(PoisonError { guard }) => Err(PoisonError::new(f(guard))) Err(PoisonError { guard }) => Err(PoisonError::new(f(guard))),
} }
} }

View file

@ -11,16 +11,12 @@ use crate::sys::process::EnvKey;
pub struct CommandEnv { pub struct CommandEnv {
clear: bool, clear: bool,
saw_path: bool, saw_path: bool,
vars: BTreeMap<EnvKey, Option<OsString>> vars: BTreeMap<EnvKey, Option<OsString>>,
} }
impl Default for CommandEnv { impl Default for CommandEnv {
fn default() -> Self { fn default() -> Self {
CommandEnv { CommandEnv { clear: false, saw_path: false, vars: Default::default() }
clear: false,
saw_path: false,
vars: Default::default()
}
} }
} }
@ -64,11 +60,7 @@ impl CommandEnv {
} }
pub fn capture_if_changed(&self) -> Option<BTreeMap<EnvKey, OsString>> { pub fn capture_if_changed(&self) -> Option<BTreeMap<EnvKey, OsString>> {
if self.is_unchanged() { if self.is_unchanged() { None } else { Some(self.capture()) }
None
} else {
Some(self.capture())
}
} }
// The following functions build up changes // The following functions build up changes

View file

@ -12,16 +12,19 @@ struct ThreadInfo {
thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) } thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) }
impl ThreadInfo { impl ThreadInfo {
fn with<R, F>(f: F) -> Option<R> where F: FnOnce(&mut ThreadInfo) -> R { fn with<R, F>(f: F) -> Option<R>
THREAD_INFO.try_with(move |c| { where
F: FnOnce(&mut ThreadInfo) -> R,
{
THREAD_INFO
.try_with(move |c| {
if c.borrow().is_none() { if c.borrow().is_none() {
*c.borrow_mut() = Some(ThreadInfo { *c.borrow_mut() =
stack_guard: None, Some(ThreadInfo { stack_guard: None, thread: Thread::new(None) })
thread: Thread::new(None),
})
} }
f(c.borrow_mut().as_mut().unwrap()) f(c.borrow_mut().as_mut().unwrap())
}).ok() })
.ok()
} }
} }
@ -35,10 +38,7 @@ pub fn stack_guard() -> Option<Guard> {
pub fn set(stack_guard: Option<Guard>, thread: Thread) { pub fn set(stack_guard: Option<Guard>, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo { stack_guard, thread }));
stack_guard,
thread,
}));
} }
pub fn reset_guard(stack_guard: Option<Guard>) { pub fn reset_guard(stack_guard: Option<Guard>) {

View file

@ -16,11 +16,15 @@ pub fn dumb_print(args: fmt::Arguments<'_>) {
pub fn abort(args: fmt::Arguments<'_>) -> ! { pub fn abort(args: fmt::Arguments<'_>) -> ! {
dumb_print(format_args!("fatal runtime error: {}\n", args)); dumb_print(format_args!("fatal runtime error: {}\n", args));
unsafe { crate::sys::abort_internal(); } unsafe {
crate::sys::abort_internal();
}
} }
#[allow(dead_code)] // stack overflow detection not enabled on all platforms #[allow(dead_code)] // stack overflow detection not enabled on all platforms
pub unsafe fn report_overflow() { pub unsafe fn report_overflow() {
dumb_print(format_args!("\nthread '{}' has overflowed its stack\n", dumb_print(format_args!(
thread::current().name().unwrap_or("<unknown>"))); "\nthread '{}' has overflowed its stack\n",
thread::current().name().unwrap_or("<unknown>")
));
} }

View file

@ -39,7 +39,7 @@ const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}";
/// a code point that is not a surrogate (U+D800 to U+DFFF). /// a code point that is not a surrogate (U+D800 to U+DFFF).
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)] #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
pub struct CodePoint { pub struct CodePoint {
value: u32 value: u32,
} }
/// Format the code point as `U+` followed by four to six hexadecimal digits. /// Format the code point as `U+` followed by four to six hexadecimal digits.
@ -66,8 +66,8 @@ impl CodePoint {
#[inline] #[inline]
pub fn from_u32(value: u32) -> Option<CodePoint> { pub fn from_u32(value: u32) -> Option<CodePoint> {
match value { match value {
0 ..= 0x10FFFF => Some(CodePoint { value }), 0..=0x10FFFF => Some(CodePoint { value }),
_ => None _ => None,
} }
} }
@ -91,8 +91,8 @@ impl CodePoint {
#[inline] #[inline]
pub fn to_char(&self) -> Option<char> { pub fn to_char(&self) -> Option<char> {
match self.value { match self.value {
0xD800 ..= 0xDFFF => None, 0xD800..=0xDFFF => None,
_ => Some(unsafe { char::from_u32_unchecked(self.value) }) _ => Some(unsafe { char::from_u32_unchecked(self.value) }),
} }
} }
@ -112,7 +112,7 @@ impl CodePoint {
/// if theyre not in a surrogate pair. /// if theyre not in a surrogate pair.
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] #[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
pub struct Wtf8Buf { pub struct Wtf8Buf {
bytes: Vec<u8> bytes: Vec<u8>,
} }
impl ops::Deref for Wtf8Buf { impl ops::Deref for Wtf8Buf {
@ -188,9 +188,7 @@ impl Wtf8Buf {
Err(surrogate) => { Err(surrogate) => {
let surrogate = surrogate.unpaired_surrogate(); let surrogate = surrogate.unpaired_surrogate();
// Surrogates are known to be in the code point range. // Surrogates are known to be in the code point range.
let code_point = unsafe { let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) };
CodePoint::from_u32_unchecked(surrogate as u32)
};
// Skip the WTF-8 concatenation check, // Skip the WTF-8 concatenation check,
// surrogate pairs are already decoded by decode_utf16 // surrogate pairs are already decoded by decode_utf16
string.push_code_point_unchecked(code_point) string.push_code_point_unchecked(code_point)
@ -203,9 +201,7 @@ impl Wtf8Buf {
/// Copied from String::push /// Copied from String::push
/// This does **not** include the WTF-8 concatenation check. /// This does **not** include the WTF-8 concatenation check.
fn push_code_point_unchecked(&mut self, code_point: CodePoint) { fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
let c = unsafe { let c = unsafe { char::from_u32_unchecked(code_point.value) };
char::from_u32_unchecked(code_point.value)
};
let mut bytes = [0; 4]; let mut bytes = [0; 4];
let bytes = c.encode_utf8(&mut bytes).as_bytes(); let bytes = c.encode_utf8(&mut bytes).as_bytes();
self.bytes.extend_from_slice(bytes) self.bytes.extend_from_slice(bytes)
@ -278,7 +274,7 @@ impl Wtf8Buf {
self.push_char(decode_surrogate_pair(lead, trail)); self.push_char(decode_surrogate_pair(lead, trail));
self.bytes.extend_from_slice(other_without_trail_surrogate); self.bytes.extend_from_slice(other_without_trail_surrogate);
} }
_ => self.bytes.extend_from_slice(&other.bytes) _ => self.bytes.extend_from_slice(&other.bytes),
} }
} }
@ -300,7 +296,7 @@ impl Wtf8Buf {
let len_without_lead_surrogate = self.len() - 3; let len_without_lead_surrogate = self.len() - 3;
self.bytes.truncate(len_without_lead_surrogate); self.bytes.truncate(len_without_lead_surrogate);
self.push_char(decode_surrogate_pair(lead, trail as u16)); self.push_char(decode_surrogate_pair(lead, trail as u16));
return return;
} }
} }
@ -347,8 +343,8 @@ impl Wtf8Buf {
pos = surrogate_pos + 3; pos = surrogate_pos + 3;
self.bytes[surrogate_pos..pos] self.bytes[surrogate_pos..pos]
.copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
}, }
None => return unsafe { String::from_utf8_unchecked(self.bytes) } None => return unsafe { String::from_utf8_unchecked(self.bytes) },
} }
} }
} }
@ -371,7 +367,7 @@ impl Wtf8Buf {
/// This replaces surrogate code point pairs with supplementary code points, /// This replaces surrogate code point pairs with supplementary code points,
/// like concatenating ill-formed UTF-16 strings effectively would. /// like concatenating ill-formed UTF-16 strings effectively would.
impl FromIterator<CodePoint> for Wtf8Buf { impl FromIterator<CodePoint> for Wtf8Buf {
fn from_iter<T: IntoIterator<Item=CodePoint>>(iter: T) -> Wtf8Buf { fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf {
let mut string = Wtf8Buf::new(); let mut string = Wtf8Buf::new();
string.extend(iter); string.extend(iter);
string string
@ -383,7 +379,7 @@ impl FromIterator<CodePoint> for Wtf8Buf {
/// This replaces surrogate code point pairs with supplementary code points, /// This replaces surrogate code point pairs with supplementary code points,
/// like concatenating ill-formed UTF-16 strings effectively would. /// like concatenating ill-formed UTF-16 strings effectively would.
impl Extend<CodePoint> for Wtf8Buf { impl Extend<CodePoint> for Wtf8Buf {
fn extend<T: IntoIterator<Item=CodePoint>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) {
let iterator = iter.into_iter(); let iterator = iter.into_iter();
let (low, _high) = iterator.size_hint(); let (low, _high) = iterator.size_hint();
// Lower bound of one byte per code point (ASCII only) // Lower bound of one byte per code point (ASCII only)
@ -398,11 +394,13 @@ impl Extend<CodePoint> for Wtf8Buf {
/// if theyre not in a surrogate pair. /// if theyre not in a surrogate pair.
#[derive(Eq, Ord, PartialEq, PartialOrd)] #[derive(Eq, Ord, PartialEq, PartialOrd)]
pub struct Wtf8 { pub struct Wtf8 {
bytes: [u8] bytes: [u8],
} }
impl AsInner<[u8]> for Wtf8 { impl AsInner<[u8]> for Wtf8 {
fn as_inner(&self) -> &[u8] { &self.bytes } fn as_inner(&self) -> &[u8] {
&self.bytes
}
} }
/// Format the slice with double quotes, /// Format the slice with double quotes,
@ -421,19 +419,13 @@ impl fmt::Debug for Wtf8 {
formatter.write_str("\"")?; formatter.write_str("\"")?;
let mut pos = 0; let mut pos = 0;
while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) { while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
write_str_escaped( write_str_escaped(formatter, unsafe {
formatter, str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos])
unsafe { str::from_utf8_unchecked( })?;
&self.bytes[pos .. surrogate_pos]
)},
)?;
write!(formatter, "\\u{{{:x}}}", surrogate)?; write!(formatter, "\\u{{{:x}}}", surrogate)?;
pos = surrogate_pos + 3; pos = surrogate_pos + 3;
} }
write_str_escaped( write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?;
formatter,
unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) },
)?;
formatter.write_str("\"") formatter.write_str("\"")
} }
} }
@ -446,20 +438,14 @@ impl fmt::Display for Wtf8 {
match self.next_surrogate(pos) { match self.next_surrogate(pos) {
Some((surrogate_pos, _)) => { Some((surrogate_pos, _)) => {
formatter.write_str(unsafe { formatter.write_str(unsafe {
str::from_utf8_unchecked(&wtf8_bytes[pos .. surrogate_pos]) str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos])
})?; })?;
formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?; formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?;
pos = surrogate_pos + 3; pos = surrogate_pos + 3;
},
None => {
let s = unsafe {
str::from_utf8_unchecked(&wtf8_bytes[pos..])
};
if pos == 0 {
return s.fmt(formatter)
} else {
return formatter.write_str(s)
} }
None => {
let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) };
if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) }
} }
} }
} }
@ -513,8 +499,8 @@ impl Wtf8 {
#[inline] #[inline]
pub fn ascii_byte_at(&self, position: usize) -> u8 { pub fn ascii_byte_at(&self, position: usize) -> u8 {
match self.bytes[position] { match self.bytes[position] {
ascii_byte @ 0x00 ..= 0x7F => ascii_byte, ascii_byte @ 0x00..=0x7F => ascii_byte,
_ => 0xFF _ => 0xFF,
} }
} }
@ -558,13 +544,13 @@ impl Wtf8 {
loop { loop {
match self.next_surrogate(pos) { match self.next_surrogate(pos) {
Some((surrogate_pos, _)) => { Some((surrogate_pos, _)) => {
utf8_bytes.extend_from_slice(&wtf8_bytes[pos .. surrogate_pos]); utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]);
utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
pos = surrogate_pos + 3; pos = surrogate_pos + 3;
}, }
None => { None => {
utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]); utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) }) return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) });
} }
} }
} }
@ -594,9 +580,9 @@ impl Wtf8 {
} else if b == 0xED { } else if b == 0xED {
match (iter.next(), iter.next()) { match (iter.next(), iter.next()) {
(Some(&b2), Some(&b3)) if b2 >= 0xA0 => { (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
return Some((pos, decode_surrogate(b2, b3))) return Some((pos, decode_surrogate(b2, b3)));
} }
_ => pos += 3 _ => pos += 3,
} }
} else if b < 0xF0 { } else if b < 0xF0 {
iter.next(); iter.next();
@ -615,11 +601,11 @@ impl Wtf8 {
fn final_lead_surrogate(&self) -> Option<u16> { fn final_lead_surrogate(&self) -> Option<u16> {
let len = self.len(); let len = self.len();
if len < 3 { if len < 3 {
return None return None;
} }
match &self.bytes[(len - 3)..] { match &self.bytes[(len - 3)..] {
&[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
_ => None _ => None,
} }
} }
@ -627,11 +613,11 @@ impl Wtf8 {
fn initial_trail_surrogate(&self) -> Option<u16> { fn initial_trail_surrogate(&self) -> Option<u16> {
let len = self.len(); let len = self.len();
if len < 3 { if len < 3 {
return None return None;
} }
match &self.bytes[..3] { match &self.bytes[..3] {
&[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)), &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
_ => None _ => None,
} }
} }
@ -661,7 +647,6 @@ impl Wtf8 {
} }
} }
/// Returns a slice of the given string for the byte range [`begin`..`end`). /// Returns a slice of the given string for the byte range [`begin`..`end`).
/// ///
/// # Panics /// # Panics
@ -674,9 +659,10 @@ impl ops::Index<ops::Range<usize>> for Wtf8 {
#[inline] #[inline]
fn index(&self, range: ops::Range<usize>) -> &Wtf8 { fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
// is_code_point_boundary checks that the index is in [0, .len()] // is_code_point_boundary checks that the index is in [0, .len()]
if range.start <= range.end && if range.start <= range.end
is_code_point_boundary(self, range.start) && && is_code_point_boundary(self, range.start)
is_code_point_boundary(self, range.end) { && is_code_point_boundary(self, range.end)
{
unsafe { slice_unchecked(self, range.start, range.end) } unsafe { slice_unchecked(self, range.start, range.end) }
} else { } else {
slice_error_fail(self, range.start, range.end) slice_error_fail(self, range.start, range.end)
@ -748,7 +734,9 @@ fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
/// Copied from core::str::StrPrelude::is_char_boundary /// Copied from core::str::StrPrelude::is_char_boundary
#[inline] #[inline]
pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool { pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
if index == slice.len() { return true; } if index == slice.len() {
return true;
}
match slice.bytes.get(index) { match slice.bytes.get(index) {
None => false, None => false,
Some(&b) => b < 128 || b >= 192, Some(&b) => b < 128 || b >= 192,
@ -759,18 +747,14 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
#[inline] #[inline]
pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
// memory layout of an &[u8] and &Wtf8 are the same // memory layout of an &[u8] and &Wtf8 are the same
Wtf8::from_bytes_unchecked(slice::from_raw_parts( Wtf8::from_bytes_unchecked(slice::from_raw_parts(s.bytes.as_ptr().add(begin), end - begin))
s.bytes.as_ptr().add(begin),
end - begin
))
} }
/// Copied from core::str::raw::slice_error_fail /// Copied from core::str::raw::slice_error_fail
#[inline(never)] #[inline(never)]
pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! { pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
assert!(begin <= end); assert!(begin <= end);
panic!("index {} and/or {} in `{:?}` do not lie on character boundary", panic!("index {} and/or {} in `{:?}` do not lie on character boundary", begin, end, s);
begin, end, s);
} }
/// Iterator for the code points of a WTF-8 string. /// Iterator for the code points of a WTF-8 string.
@ -778,7 +762,7 @@ pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
/// Created with the method `.code_points()`. /// Created with the method `.code_points()`.
#[derive(Clone)] #[derive(Clone)]
pub struct Wtf8CodePoints<'a> { pub struct Wtf8CodePoints<'a> {
bytes: slice::Iter<'a, u8> bytes: slice::Iter<'a, u8>,
} }
impl<'a> Iterator for Wtf8CodePoints<'a> { impl<'a> Iterator for Wtf8CodePoints<'a> {
@ -801,7 +785,7 @@ impl<'a> Iterator for Wtf8CodePoints<'a> {
#[derive(Clone)] #[derive(Clone)]
pub struct EncodeWide<'a> { pub struct EncodeWide<'a> {
code_points: Wtf8CodePoints<'a>, code_points: Wtf8CodePoints<'a>,
extra: u16 extra: u16,
} }
// Copied from libunicode/u_str.rs // Copied from libunicode/u_str.rs
@ -819,9 +803,7 @@ impl<'a> Iterator for EncodeWide<'a> {
let mut buf = [0; 2]; let mut buf = [0; 2];
self.code_points.next().map(|code_point| { self.code_points.next().map(|code_point| {
let c = unsafe { let c = unsafe { char::from_u32_unchecked(code_point.value) };
char::from_u32_unchecked(code_point.value)
};
let n = c.encode_utf16(&mut buf).len(); let n = c.encode_utf16(&mut buf).len();
if n == 2 { if n == 2 {
self.extra = buf[1]; self.extra = buf[1];
@ -864,13 +846,15 @@ impl Hash for Wtf8 {
} }
impl Wtf8 { impl Wtf8 {
pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } pub fn make_ascii_uppercase(&mut self) {
self.bytes.make_ascii_uppercase()
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::borrow::Cow;
use super::*; use super::*;
use crate::borrow::Cow;
#[test] #[test]
fn code_point_from_u32() { fn code_point_from_u32() {
@ -882,7 +866,9 @@ mod tests {
#[test] #[test]
fn code_point_to_u32() { fn code_point_to_u32() {
fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() } fn c(value: u32) -> CodePoint {
CodePoint::from_u32(value).unwrap()
}
assert_eq!(c(0).to_u32(), 0); assert_eq!(c(0).to_u32(), 0);
assert_eq!(c(0xD800).to_u32(), 0xD800); assert_eq!(c(0xD800).to_u32(), 0xD800);
assert_eq!(c(0x10FFFF).to_u32(), 0x10FFFF); assert_eq!(c(0x10FFFF).to_u32(), 0x10FFFF);
@ -902,7 +888,9 @@ mod tests {
#[test] #[test]
fn code_point_to_char() { fn code_point_to_char() {
fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() } fn c(value: u32) -> CodePoint {
CodePoint::from_u32(value).unwrap()
}
assert_eq!(c(0x61).to_char(), Some('a')); assert_eq!(c(0x61).to_char(), Some('a'));
assert_eq!(c(0x1F4A9).to_char(), Some('💩')); assert_eq!(c(0x1F4A9).to_char(), Some('💩'));
assert_eq!(c(0xD800).to_char(), None); assert_eq!(c(0xD800).to_char(), None);
@ -910,7 +898,9 @@ mod tests {
#[test] #[test]
fn code_point_to_char_lossy() { fn code_point_to_char_lossy() {
fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() } fn c(value: u32) -> CodePoint {
CodePoint::from_u32(value).unwrap()
}
assert_eq!(c(0x61).to_char_lossy(), 'a'); assert_eq!(c(0x61).to_char_lossy(), 'a');
assert_eq!(c(0x1F4A9).to_char_lossy(), '💩'); assert_eq!(c(0x1F4A9).to_char_lossy(), '💩');
assert_eq!(c(0xD800).to_char_lossy(), '\u{FFFD}'); assert_eq!(c(0xD800).to_char_lossy(), '\u{FFFD}');
@ -924,23 +914,25 @@ mod tests {
#[test] #[test]
fn wtf8buf_from_str() { fn wtf8buf_from_str() {
assert_eq!(Wtf8Buf::from_str("").bytes, b""); assert_eq!(Wtf8Buf::from_str("").bytes, b"");
assert_eq!(Wtf8Buf::from_str("aé 💩").bytes, assert_eq!(Wtf8Buf::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
b"a\xC3\xA9 \xF0\x9F\x92\xA9");
} }
#[test] #[test]
fn wtf8buf_from_string() { fn wtf8buf_from_string() {
assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b""); assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b"");
assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes, assert_eq!(
b"a\xC3\xA9 \xF0\x9F\x92\xA9"); Wtf8Buf::from_string(String::from("aé 💩")).bytes,
b"a\xC3\xA9 \xF0\x9F\x92\xA9"
);
} }
#[test] #[test]
fn wtf8buf_from_wide() { fn wtf8buf_from_wide() {
assert_eq!(Wtf8Buf::from_wide(&[]).bytes, b""); assert_eq!(Wtf8Buf::from_wide(&[]).bytes, b"");
assert_eq!(Wtf8Buf::from_wide( assert_eq!(
&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]).bytes, Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]).bytes,
b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9"); b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9"
);
} }
#[test] #[test]
@ -966,7 +958,9 @@ mod tests {
string.push(CodePoint::from_char('💩')); string.push(CodePoint::from_char('💩'));
assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() } fn c(value: u32) -> CodePoint {
CodePoint::from_u32(value).unwrap()
}
let mut string = Wtf8Buf::new(); let mut string = Wtf8Buf::new();
string.push(c(0xD83D)); // lead string.push(c(0xD83D)); // lead
@ -1011,7 +1005,9 @@ mod tests {
string.push_wtf8(Wtf8::from_str(" 💩")); string.push_wtf8(Wtf8::from_str(" 💩"));
assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
fn w(v: &[u8]) -> &Wtf8 { unsafe { Wtf8::from_bytes_unchecked(v) } } fn w(v: &[u8]) -> &Wtf8 {
unsafe { Wtf8::from_bytes_unchecked(v) }
}
let mut string = Wtf8Buf::new(); let mut string = Wtf8Buf::new();
string.push_wtf8(w(b"\xED\xA0\xBD")); // lead string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
@ -1105,14 +1101,15 @@ mod tests {
#[test] #[test]
fn wtf8buf_extend() { fn wtf8buf_extend() {
fn e(initial: &[u32], extended: &[u32]) -> Wtf8Buf { fn e(initial: &[u32], extended: &[u32]) -> Wtf8Buf {
fn c(value: &u32) -> CodePoint { CodePoint::from_u32(*value).unwrap() } fn c(value: &u32) -> CodePoint {
CodePoint::from_u32(*value).unwrap()
}
let mut string = initial.iter().map(c).collect::<Wtf8Buf>(); let mut string = initial.iter().map(c).collect::<Wtf8Buf>();
string.extend(extended.iter().map(c)); string.extend(extended.iter().map(c));
string string
} }
assert_eq!(e(&[0x61, 0xE9], &[0x20, 0x1F4A9]).bytes, assert_eq!(e(&[0x61, 0xE9], &[0x20, 0x1F4A9]).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
b"a\xC3\xA9 \xF0\x9F\x92\xA9");
assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic! assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
assert_eq!(e(&[0xD83D, 0x20], &[0xDCA9]).bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); assert_eq!(e(&[0xD83D, 0x20], &[0xDCA9]).bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
@ -1156,13 +1153,13 @@ mod tests {
#[test] #[test]
fn wtf8_slice() { fn wtf8_slice() {
assert_eq!(&Wtf8::from_str("aé 💩")[1.. 4].bytes, b"\xC3\xA9 "); assert_eq!(&Wtf8::from_str("aé 💩")[1..4].bytes, b"\xC3\xA9 ");
} }
#[test] #[test]
#[should_panic] #[should_panic]
fn wtf8_slice_not_code_point_boundary() { fn wtf8_slice_not_code_point_boundary() {
&Wtf8::from_str("aé 💩")[2.. 4]; &Wtf8::from_str("aé 💩")[2..4];
} }
#[test] #[test]
@ -1199,7 +1196,9 @@ mod tests {
#[test] #[test]
fn wtf8_code_points() { fn wtf8_code_points() {
fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() } fn c(value: u32) -> CodePoint {
CodePoint::from_u32(value).unwrap()
}
fn cp(string: &Wtf8Buf) -> Vec<Option<char>> { fn cp(string: &Wtf8Buf) -> Vec<Option<char>> {
string.code_points().map(|c| c.to_char()).collect::<Vec<_>>() string.code_points().map(|c| c.to_char()).collect::<Vec<_>>()
} }
@ -1249,7 +1248,9 @@ mod tests {
let mut string = Wtf8Buf::from_str(""); let mut string = Wtf8Buf::from_str("");
string.push(CodePoint::from_u32(0xD83D).unwrap()); string.push(CodePoint::from_u32(0xD83D).unwrap());
string.push_char('💩'); string.push_char('💩');
assert_eq!(string.encode_wide().collect::<Vec<_>>(), assert_eq!(
vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]); string.encode_wide().collect::<Vec<_>>(),
vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]
);
} }
} }

View file

@ -1,13 +1,12 @@
use std::env::*; use std::env::*;
use std::ffi::{OsString, OsStr}; use std::ffi::{OsStr, OsString};
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric; use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
fn make_rand_name() -> OsString { fn make_rand_name() -> OsString {
let rng = thread_rng(); let rng = thread_rng();
let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10) let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10).collect::<String>());
.collect::<String>());
let n = OsString::from(n); let n = OsString::from(n);
assert!(var_os(&n).is_none()); assert!(var_os(&n).is_none());
n n
@ -73,11 +72,7 @@ fn test_env_set_var() {
let mut e = vars_os(); let mut e = vars_os();
set_var(&n, "VALUE"); set_var(&n, "VALUE");
assert!(!e.any(|(k, v)| { assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
&*k == &*n && &*v == "VALUE"
}));
assert!(vars_os().any(|(k, v)| { assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
&*k == &*n && &*v == "VALUE"
}));
} }

View file

@ -142,9 +142,7 @@ macro_rules! thread_local {
} }
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "thread_local_internals", #[unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "0")]
reason = "should not be necessary",
issue = "0")]
#[macro_export] #[macro_export]
#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] #[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
#[allow_internal_unsafe] #[allow_internal_unsafe]
@ -214,13 +212,13 @@ impl Error for AccessError {}
impl<T: 'static> LocalKey<T> { impl<T: 'static> LocalKey<T> {
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "thread_local_internals", #[unstable(
feature = "thread_local_internals",
reason = "recently added to create a key", reason = "recently added to create a key",
issue = "0")] issue = "0"
)]
pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> { pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> {
LocalKey { LocalKey { inner }
inner,
}
} }
/// Acquires a reference to the value in this TLS key. /// Acquires a reference to the value in this TLS key.
@ -235,9 +233,13 @@ impl<T: 'static> LocalKey<T> {
/// previously been run for this thread. /// previously been run for this thread.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn with<F, R>(&'static self, f: F) -> R pub fn with<F, R>(&'static self, f: F) -> R
where F: FnOnce(&T) -> R { where
self.try_with(f).expect("cannot access a Thread Local Storage value \ F: FnOnce(&T) -> R,
during or after destruction") {
self.try_with(f).expect(
"cannot access a Thread Local Storage value \
during or after destruction",
)
} }
/// Acquires a reference to the value in this TLS key. /// Acquires a reference to the value in this TLS key.
@ -256,9 +258,7 @@ impl<T: 'static> LocalKey<T> {
F: FnOnce(&T) -> R, F: FnOnce(&T) -> R,
{ {
unsafe { unsafe {
let thread_local = (self.inner)().ok_or(AccessError { let thread_local = (self.inner)().ok_or(AccessError { _private: () })?;
_private: (),
})?;
Ok(f(thread_local)) Ok(f(thread_local))
} }
} }
@ -266,8 +266,8 @@ impl<T: 'static> LocalKey<T> {
mod lazy { mod lazy {
use crate::cell::UnsafeCell; use crate::cell::UnsafeCell;
use crate::mem;
use crate::hint; use crate::hint;
use crate::mem;
pub struct LazyKeyInner<T> { pub struct LazyKeyInner<T> {
inner: UnsafeCell<Option<T>>, inner: UnsafeCell<Option<T>>,
@ -275,9 +275,7 @@ mod lazy {
impl<T> LazyKeyInner<T> { impl<T> LazyKeyInner<T> {
pub const fn new() -> LazyKeyInner<T> { pub const fn new() -> LazyKeyInner<T> {
LazyKeyInner { LazyKeyInner { inner: UnsafeCell::new(None) }
inner: UnsafeCell::new(None),
}
} }
pub unsafe fn get(&self) -> Option<&'static T> { pub unsafe fn get(&self) -> Option<&'static T> {
@ -334,7 +332,7 @@ pub mod statik {
inner: LazyKeyInner<T>, inner: LazyKeyInner<T>,
} }
unsafe impl<T> Sync for Key<T> { } unsafe impl<T> Sync for Key<T> {}
impl<T> fmt::Debug for Key<T> { impl<T> fmt::Debug for Key<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -344,9 +342,7 @@ pub mod statik {
impl<T> Key<T> { impl<T> Key<T> {
pub const fn new() -> Key<T> { pub const fn new() -> Key<T> {
Key { Key { inner: LazyKeyInner::new() }
inner: LazyKeyInner::new(),
}
} }
pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> { pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> {
@ -404,10 +400,7 @@ pub mod fast {
impl<T> Key<T> { impl<T> Key<T> {
pub const fn new() -> Key<T> { pub const fn new() -> Key<T> {
Key { Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
inner: LazyKeyInner::new(),
dtor_state: Cell::new(DtorState::Unregistered),
}
} }
pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
@ -441,8 +434,7 @@ pub mod fast {
match self.dtor_state.get() { match self.dtor_state.get() {
DtorState::Unregistered => { DtorState::Unregistered => {
// dtor registration happens before initialization. // dtor registration happens before initialization.
register_dtor(self as *const _ as *mut u8, register_dtor(self as *const _ as *mut u8, destroy_value::<T>);
destroy_value::<T>);
self.dtor_state.set(DtorState::Registered); self.dtor_state.set(DtorState::Registered);
true true
} }
@ -450,14 +442,12 @@ pub mod fast {
// recursively initialized // recursively initialized
true true
} }
DtorState::RunningOrHasRun => { DtorState::RunningOrHasRun => false,
false
}
} }
} }
} }
unsafe extern fn destroy_value<T>(ptr: *mut u8) { unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
let ptr = ptr as *mut Key<T>; let ptr = ptr as *mut Key<T>;
// Right before we run the user destructor be sure to set the // Right before we run the user destructor be sure to set the
@ -491,7 +481,7 @@ pub mod os {
} }
} }
unsafe impl<T> Sync for Key<T> { } unsafe impl<T> Sync for Key<T> {}
struct Value<T: 'static> { struct Value<T: 'static> {
inner: LazyKeyInner<T>, inner: LazyKeyInner<T>,
@ -500,10 +490,7 @@ pub mod os {
impl<T: 'static> Key<T> { impl<T: 'static> Key<T> {
pub const fn new() -> Key<T> { pub const fn new() -> Key<T> {
Key { Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData }
os: OsStaticKey::new(Some(destroy_value::<T>)),
marker: marker::PhantomData
}
} }
pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> { pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> {
@ -523,16 +510,13 @@ pub mod os {
let ptr = self.os.get() as *mut Value<T>; let ptr = self.os.get() as *mut Value<T>;
if ptr as usize == 1 { if ptr as usize == 1 {
// destructor is running // destructor is running
return None return None;
} }
let ptr = if ptr.is_null() { let ptr = if ptr.is_null() {
// If the lookup returned null, we haven't initialized our own // If the lookup returned null, we haven't initialized our own
// local copy, so do that now. // local copy, so do that now.
let ptr: Box<Value<T>> = box Value { let ptr: Box<Value<T>> = box Value { inner: LazyKeyInner::new(), key: self };
inner: LazyKeyInner::new(),
key: self,
};
let ptr = Box::into_raw(ptr); let ptr = Box::into_raw(ptr);
self.os.set(ptr as *mut u8); self.os.set(ptr as *mut u8);
ptr ptr
@ -545,7 +529,7 @@ pub mod os {
} }
} }
unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) { unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
// The OS TLS ensures that this key contains a NULL value when this // The OS TLS ensures that this key contains a NULL value when this
// destructor starts to run. We set it back to a sentinel value of 1 to // destructor starts to run. We set it back to a sentinel value of 1 to
// ensure that any future calls to `get` for this thread will return // ensure that any future calls to `get` for this thread will return
@ -563,8 +547,8 @@ pub mod os {
#[cfg(all(test, not(target_os = "emscripten")))] #[cfg(all(test, not(target_os = "emscripten")))]
mod tests { mod tests {
use crate::sync::mpsc::{channel, Sender};
use crate::cell::{Cell, UnsafeCell}; use crate::cell::{Cell, UnsafeCell};
use crate::sync::mpsc::{channel, Sender};
use crate::thread; use crate::thread;
struct Foo(Sender<()>); struct Foo(Sender<()>);
@ -585,7 +569,7 @@ mod tests {
f.set(2); f.set(2);
}); });
let (tx, rx) = channel(); let (tx, rx) = channel();
let _t = thread::spawn(move|| { let _t = thread::spawn(move || {
FOO.with(|f| { FOO.with(|f| {
assert_eq!(f.get(), 1); assert_eq!(f.get(), 1);
}); });
@ -610,7 +594,10 @@ mod tests {
thread::spawn(|| { thread::spawn(|| {
assert!(FOO.try_with(|_| ()).is_ok()); assert!(FOO.try_with(|_| ()).is_ok());
}).join().ok().expect("thread panicked"); })
.join()
.ok()
.expect("thread panicked");
} }
#[test] #[test]
@ -618,7 +605,7 @@ mod tests {
thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None)); thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
let (tx, rx) = channel(); let (tx, rx) = channel();
let _t = thread::spawn(move|| unsafe { let _t = thread::spawn(move || unsafe {
let mut tx = Some(tx); let mut tx = Some(tx);
FOO.with(|f| { FOO.with(|f| {
*f.get() = Some(Foo(tx.take().unwrap())); *f.get() = Some(Foo(tx.take().unwrap()));
@ -662,9 +649,12 @@ mod tests {
} }
} }
thread::spawn(move|| { thread::spawn(move || {
drop(S1); drop(S1);
}).join().ok().expect("thread panicked"); })
.join()
.ok()
.expect("thread panicked");
} }
#[test] #[test]
@ -678,9 +668,12 @@ mod tests {
} }
} }
thread::spawn(move|| unsafe { thread::spawn(move || unsafe {
K1.with(|s| *s.get() = Some(S1)); K1.with(|s| *s.get() = Some(S1));
}).join().ok().expect("thread panicked"); })
.join()
.ok()
.expect("thread panicked");
} }
// Note that this test will deadlock if TLS destructors aren't run (this // Note that this test will deadlock if TLS destructors aren't run (this
@ -701,7 +694,7 @@ mod tests {
} }
let (tx, rx) = channel(); let (tx, rx) = channel();
let _t = thread::spawn(move|| unsafe { let _t = thread::spawn(move || unsafe {
let mut tx = Some(tx); let mut tx = Some(tx);
K1.with(|s| *s.get() = Some(S1(tx.take().unwrap()))); K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
}); });
@ -716,7 +709,9 @@ mod dynamic_tests {
#[test] #[test]
fn smoke() { fn smoke() {
fn square(i: i32) -> i32 { i * i } fn square(i: i32) -> i32 {
i * i
}
thread_local!(static FOO: i32 = square(3)); thread_local!(static FOO: i32 = square(3));
FOO.with(|f| { FOO.with(|f| {