aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src
diff options
context:
space:
mode:
authorFenrir <[email protected]>2018-04-14 20:02:05 -0600
committerFenrir <[email protected]>2018-04-21 16:35:01 -0600
commitb330206f5590d88a2f995321d2ea847ded951d1d (patch)
tree4fecd0ca00b754c494e96b13e9837db48de93109 /ctr-std/src
parentMove more implementation details to `imp` module (diff)
downloadctru-rs-b330206f5590d88a2f995321d2ea847ded951d1d.tar.xz
ctru-rs-b330206f5590d88a2f995321d2ea847ded951d1d.zip
Update for Rust nightly 2018-04-19
Diffstat (limited to 'ctr-std/src')
-rw-r--r--ctr-std/src/alloc.rs121
-rw-r--r--ctr-std/src/ascii.rs498
-rw-r--r--ctr-std/src/collections/hash/map.rs367
-rw-r--r--ctr-std/src/collections/hash/set.rs46
-rw-r--r--ctr-std/src/collections/hash/table.rs93
-rw-r--r--ctr-std/src/collections/mod.rs28
-rw-r--r--ctr-std/src/env.rs22
-rw-r--r--ctr-std/src/error.rs36
-rw-r--r--ctr-std/src/f32.rs60
-rw-r--r--ctr-std/src/f64.rs59
-rw-r--r--ctr-std/src/ffi/c_str.rs34
-rw-r--r--ctr-std/src/ffi/os_str.rs30
-rw-r--r--ctr-std/src/fs.rs620
-rw-r--r--ctr-std/src/heap.rs175
-rw-r--r--ctr-std/src/io/buffered.rs245
-rw-r--r--ctr-std/src/io/cursor.rs20
-rw-r--r--ctr-std/src/io/error.rs8
-rw-r--r--ctr-std/src/io/mod.rs622
-rw-r--r--ctr-std/src/io/stdio.rs148
-rw-r--r--ctr-std/src/io/util.rs15
-rw-r--r--ctr-std/src/lib.rs52
-rw-r--r--ctr-std/src/macros.rs98
-rw-r--r--ctr-std/src/net/addr.rs14
-rw-r--r--ctr-std/src/net/ip.rs95
-rw-r--r--ctr-std/src/net/mod.rs17
-rw-r--r--ctr-std/src/net/parser.rs19
-rw-r--r--ctr-std/src/net/tcp.rs83
-rw-r--r--ctr-std/src/net/udp.rs87
-rw-r--r--ctr-std/src/num.rs8
-rw-r--r--ctr-std/src/panic.rs9
-rw-r--r--ctr-std/src/primitive_docs.rs63
-rw-r--r--ctr-std/src/process.rs106
-rw-r--r--ctr-std/src/rt.rs2
-rw-r--r--ctr-std/src/sync/condvar.rs222
-rw-r--r--ctr-std/src/sync/mod.rs2
-rw-r--r--ctr-std/src/sync/mpsc/mpsc_queue.rs3
-rw-r--r--ctr-std/src/sync/mpsc/spsc_queue.rs2
-rw-r--r--ctr-std/src/sync/rwlock.rs4
-rw-r--r--ctr-std/src/sys/unix/os_str.rs7
-rw-r--r--ctr-std/src/sys/unix/process.rs18
-rw-r--r--ctr-std/src/sys/unix/thread.rs2
-rw-r--r--ctr-std/src/sys_common/at_exit_imp.rs2
-rw-r--r--ctr-std/src/sys_common/bytestring.rs2
-rw-r--r--ctr-std/src/sys_common/process.rs2
-rw-r--r--ctr-std/src/sys_common/thread.rs2
-rw-r--r--ctr-std/src/sys_common/wtf8.rs45
-rw-r--r--ctr-std/src/termination.rs80
-rw-r--r--ctr-std/src/thread/local.rs128
-rw-r--r--ctr-std/src/thread/mod.rs8
-rw-r--r--ctr-std/src/time.rs29
50 files changed, 2346 insertions, 2112 deletions
diff --git a/ctr-std/src/alloc.rs b/ctr-std/src/alloc.rs
new file mode 100644
index 0000000..ff578ec
--- /dev/null
+++ b/ctr-std/src/alloc.rs
@@ -0,0 +1,121 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! dox
+
+#![unstable(issue = "32838", feature = "allocator_api")]
+
+#[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap;
+#[doc(inline)] pub use alloc_crate::alloc::Global;
+#[doc(inline)] pub use alloc_system::System;
+#[doc(inline)] pub use core::alloc::*;
+
+#[cfg(not(test))]
+#[doc(hidden)]
+#[allow(unused_attributes)]
+pub mod __default_lib_allocator {
+ use super::{System, Layout, GlobalAlloc, Opaque};
+ // for symbol names src/librustc/middle/allocator.rs
+ // for signatures src/librustc_allocator/lib.rs
+
+ // linkage directives are provided as part of the current compiler allocator
+ // ABI
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
+ let layout = Layout::from_size_align_unchecked(size, align);
+ System.alloc(layout) as *mut u8
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_oom() -> ! {
+ System.oom()
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
+ size: usize,
+ align: usize) {
+ System.dealloc(ptr as *mut Opaque, Layout::from_size_align_unchecked(size, align))
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
+ old_size: usize,
+ align: usize,
+ new_size: usize) -> *mut u8 {
+ let old_layout = Layout::from_size_align_unchecked(old_size, align);
+ System.realloc(ptr as *mut Opaque, old_layout, new_size) as *mut u8
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
+ let layout = Layout::from_size_align_unchecked(size, align);
+ System.alloc_zeroed(layout) as *mut u8
+ }
+
+ #[cfg(stage0)]
+ pub mod stage0 {
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_usable_size(_layout: *const u8,
+ _min: *mut usize,
+ _max: *mut usize) {
+ unimplemented!()
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_alloc_excess(_size: usize,
+ _align: usize,
+ _excess: *mut usize,
+ _err: *mut u8) -> *mut u8 {
+ unimplemented!()
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_realloc_excess(_ptr: *mut u8,
+ _old_size: usize,
+ _old_align: usize,
+ _new_size: usize,
+ _new_align: usize,
+ _excess: *mut usize,
+ _err: *mut u8) -> *mut u8 {
+ unimplemented!()
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_grow_in_place(_ptr: *mut u8,
+ _old_size: usize,
+ _old_align: usize,
+ _new_size: usize,
+ _new_align: usize) -> u8 {
+ unimplemented!()
+ }
+
+ #[no_mangle]
+ #[rustc_std_internal_symbol]
+ pub unsafe extern fn __rdl_shrink_in_place(_ptr: *mut u8,
+ _old_size: usize,
+ _old_align: usize,
+ _new_size: usize,
+ _new_align: usize) -> u8 {
+ unimplemented!()
+ }
+
+ }
+}
diff --git a/ctr-std/src/ascii.rs b/ctr-std/src/ascii.rs
index 82e1a34..6472edb 100644
--- a/ctr-std/src/ascii.rs
+++ b/ctr-std/src/ascii.rs
@@ -26,9 +26,8 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use fmt;
-use ops::Range;
-use iter::FusedIterator;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::ascii::{EscapeDefault, escape_default};
/// Extension methods for ASCII-subset only operations.
///
@@ -53,6 +52,7 @@ use iter::FusedIterator;
///
/// [combining character]: https://en.wikipedia.org/wiki/Combining_character
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
pub trait AsciiExt {
/// Container type for copied ASCII characters.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -85,6 +85,7 @@ pub trait AsciiExt {
/// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
/// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
#[stable(feature = "rust1", since = "1.0.0")]
+ #[allow(deprecated)]
fn to_ascii_uppercase(&self) -> Self::Owned;
/// Makes a copy of the value in its ASCII lower case equivalent.
@@ -105,6 +106,7 @@ pub trait AsciiExt {
/// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
/// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
#[stable(feature = "rust1", since = "1.0.0")]
+ #[allow(deprecated)]
fn to_ascii_lowercase(&self) -> Self::Owned;
/// Checks that two values are an ASCII case-insensitive match.
@@ -163,6 +165,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII uppercase character:
@@ -175,6 +178,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII lowercase character:
@@ -187,6 +191,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII alphanumeric character:
@@ -200,6 +205,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII decimal digit:
@@ -212,6 +218,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_digit(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII hexadecimal digit:
@@ -225,6 +232,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII punctuation character:
@@ -242,10 +250,11 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII graphic character:
- /// U+0021 '@' ... U+007E '~'.
+ /// U+0021 '!' ... U+007E '~'.
/// For strings, true if all characters in the string are
/// ASCII graphic characters.
///
@@ -254,6 +263,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII whitespace character:
@@ -283,6 +293,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII control character:
@@ -295,6 +306,7 @@ pub trait AsciiExt {
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_control(&self) -> bool { unimplemented!(); }
}
@@ -355,6 +367,7 @@ macro_rules! delegating_ascii_ctype_methods {
}
#[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
impl AsciiExt for u8 {
type Owned = u8;
@@ -363,6 +376,7 @@ impl AsciiExt for u8 {
}
#[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
impl AsciiExt for char {
type Owned = char;
@@ -371,6 +385,7 @@ impl AsciiExt for char {
}
#[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
impl AsciiExt for [u8] {
type Owned = Vec<u8>;
@@ -428,6 +443,7 @@ impl AsciiExt for [u8] {
}
#[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
impl AsciiExt for str {
type Owned = String;
@@ -483,477 +499,3 @@ impl AsciiExt for str {
self.bytes().all(|b| b.is_ascii_control())
}
}
-
-/// An iterator over the escaped version of a byte.
-///
-/// This `struct` is created by the [`escape_default`] function. See its
-/// documentation for more.
-///
-/// [`escape_default`]: fn.escape_default.html
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct EscapeDefault {
- range: Range<usize>,
- data: [u8; 4],
-}
-
-/// Returns an iterator that produces an escaped version of a `u8`.
-///
-/// The default is chosen with a bias toward producing literals that are
-/// legal in a variety of languages, including C++11 and similar C-family
-/// languages. The exact rules are:
-///
-/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
-/// - Single-quote, double-quote and backslash chars are backslash-escaped.
-/// - Any other chars in the range [0x20,0x7e] are not escaped.
-/// - Any other chars are given hex escapes of the form '\xNN'.
-/// - Unicode escapes are never generated by this function.
-///
-/// # Examples
-///
-/// ```
-/// use std::ascii;
-///
-/// let escaped = ascii::escape_default(b'0').next().unwrap();
-/// assert_eq!(b'0', escaped);
-///
-/// let mut escaped = ascii::escape_default(b'\t');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b't', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\r');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'r', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\n');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'n', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\'');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'\'', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'"');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'"', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\\');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'\\', escaped.next().unwrap());
-///
-/// let mut escaped = ascii::escape_default(b'\x9d');
-///
-/// assert_eq!(b'\\', escaped.next().unwrap());
-/// assert_eq!(b'x', escaped.next().unwrap());
-/// assert_eq!(b'9', escaped.next().unwrap());
-/// assert_eq!(b'd', escaped.next().unwrap());
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn escape_default(c: u8) -> EscapeDefault {
- let (data, len) = match c {
- b'\t' => ([b'\\', b't', 0, 0], 2),
- b'\r' => ([b'\\', b'r', 0, 0], 2),
- b'\n' => ([b'\\', b'n', 0, 0], 2),
- b'\\' => ([b'\\', b'\\', 0, 0], 2),
- b'\'' => ([b'\\', b'\'', 0, 0], 2),
- b'"' => ([b'\\', b'"', 0, 0], 2),
- b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
- _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
- };
-
- return EscapeDefault { range: (0.. len), data: data };
-
- fn hexify(b: u8) -> u8 {
- match b {
- 0 ... 9 => b'0' + b,
- _ => b'a' + b - 10,
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for EscapeDefault {
- type Item = u8;
- fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
- fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl DoubleEndedIterator for EscapeDefault {
- fn next_back(&mut self) -> Option<u8> {
- self.range.next_back().map(|i| self.data[i])
- }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl ExactSizeIterator for EscapeDefault {}
-#[unstable(feature = "fused", issue = "35602")]
-impl FusedIterator for EscapeDefault {}
-
-#[stable(feature = "std_debug", since = "1.16.0")]
-impl fmt::Debug for EscapeDefault {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.pad("EscapeDefault { .. }")
- }
-}
-
-
-#[cfg(test)]
-mod tests {
- //! Note that most of these tests are not testing `AsciiExt` methods, but
- //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is
- //! just using those methods, though.
- use super::AsciiExt;
- use char::from_u32;
-
- #[test]
- fn test_is_ascii() {
- assert!(b"".is_ascii());
- assert!(b"banana\0\x7F".is_ascii());
- assert!(b"banana\0\x7F".iter().all(|b| b.is_ascii()));
- assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii());
- assert!(!b"Vi\xe1\xbb\x87t Nam".iter().all(|b| b.is_ascii()));
- assert!(!b"\xe1\xbb\x87".iter().any(|b| b.is_ascii()));
-
- assert!("".is_ascii());
- assert!("banana\0\u{7F}".is_ascii());
- assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
- assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
- assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
- }
-
- #[test]
- fn test_to_ascii_uppercase() {
- assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
- assert_eq!("hıKß".to_ascii_uppercase(), "HıKß");
-
- for i in 0..501 {
- let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 }
- else { i };
- assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(),
- (from_u32(upper).unwrap()).to_string());
- }
- }
-
- #[test]
- fn test_to_ascii_lowercase() {
- assert_eq!("url()URL()uRl()Ürl".to_ascii_lowercase(), "url()url()url()Ürl");
- // Dotted capital I, Kelvin sign, Sharp S.
- assert_eq!("HİKß".to_ascii_lowercase(), "hİKß");
-
- for i in 0..501 {
- let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
- else { i };
- assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(),
- (from_u32(lower).unwrap()).to_string());
- }
- }
-
- #[test]
- fn test_make_ascii_lower_case() {
- macro_rules! test {
- ($from: expr, $to: expr) => {
- {
- let mut x = $from;
- x.make_ascii_lowercase();
- assert_eq!(x, $to);
- }
- }
- }
- test!(b'A', b'a');
- test!(b'a', b'a');
- test!(b'!', b'!');
- test!('A', 'a');
- test!('À', 'À');
- test!('a', 'a');
- test!('!', '!');
- test!(b"H\xc3\x89".to_vec(), b"h\xc3\x89");
- test!("HİKß".to_string(), "hİKß");
- }
-
-
- #[test]
- fn test_make_ascii_upper_case() {
- macro_rules! test {
- ($from: expr, $to: expr) => {
- {
- let mut x = $from;
- x.make_ascii_uppercase();
- assert_eq!(x, $to);
- }
- }
- }
- test!(b'a', b'A');
- test!(b'A', b'A');
- test!(b'!', b'!');
- test!('a', 'A');
- test!('à', 'à');
- test!('A', 'A');
- test!('!', '!');
- test!(b"h\xc3\xa9".to_vec(), b"H\xc3\xa9");
- test!("hıKß".to_string(), "HıKß");
-
- let mut x = "Hello".to_string();
- x[..3].make_ascii_uppercase(); // Test IndexMut on String.
- assert_eq!(x, "HELlo")
- }
-
- #[test]
- fn test_eq_ignore_ascii_case() {
- assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
- assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
- // Dotted capital I, Kelvin sign, Sharp S.
- assert!("HİKß".eq_ignore_ascii_case("hİKß"));
- assert!(!"İ".eq_ignore_ascii_case("i"));
- assert!(!"K".eq_ignore_ascii_case("k"));
- assert!(!"ß".eq_ignore_ascii_case("s"));
-
- for i in 0..501 {
- let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 }
- else { i };
- assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case(
- &from_u32(lower).unwrap().to_string()));
- }
- }
-
- #[test]
- fn inference_works() {
- let x = "a".to_string();
- x.eq_ignore_ascii_case("A");
- }
-
- // Shorthands used by the is_ascii_* tests.
- macro_rules! assert_all {
- ($what:ident, $($str:tt),+) => {{
- $(
- for b in $str.chars() {
- if !b.$what() {
- panic!("expected {}({}) but it isn't",
- stringify!($what), b);
- }
- }
- for b in $str.as_bytes().iter() {
- if !b.$what() {
- panic!("expected {}(0x{:02x})) but it isn't",
- stringify!($what), b);
- }
- }
- assert!($str.$what());
- assert!($str.as_bytes().$what());
- )+
- }};
- ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
- }
- macro_rules! assert_none {
- ($what:ident, $($str:tt),+) => {{
- $(
- for b in $str.chars() {
- if b.$what() {
- panic!("expected not-{}({}) but it is",
- stringify!($what), b);
- }
- }
- for b in $str.as_bytes().iter() {
- if b.$what() {
- panic!("expected not-{}(0x{:02x})) but it is",
- stringify!($what), b);
- }
- }
- )*
- }};
- ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
- }
-
- #[test]
- fn test_is_ascii_alphabetic() {
- assert_all!(is_ascii_alphabetic,
- "",
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- );
- assert_none!(is_ascii_alphabetic,
- "0123456789",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_uppercase() {
- assert_all!(is_ascii_uppercase,
- "",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- );
- assert_none!(is_ascii_uppercase,
- "abcdefghijklmnopqrstuvwxyz",
- "0123456789",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_lowercase() {
- assert_all!(is_ascii_lowercase,
- "abcdefghijklmnopqrstuvwxyz",
- );
- assert_none!(is_ascii_lowercase,
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "0123456789",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_alphanumeric() {
- assert_all!(is_ascii_alphanumeric,
- "",
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "0123456789",
- );
- assert_none!(is_ascii_alphanumeric,
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_digit() {
- assert_all!(is_ascii_digit,
- "",
- "0123456789",
- );
- assert_none!(is_ascii_digit,
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_hexdigit() {
- assert_all!(is_ascii_hexdigit,
- "",
- "0123456789",
- "abcdefABCDEF",
- );
- assert_none!(is_ascii_hexdigit,
- "ghijklmnopqrstuvwxyz",
- "GHIJKLMNOQPRSTUVWXYZ",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_punctuation() {
- assert_all!(is_ascii_punctuation,
- "",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- );
- assert_none!(is_ascii_punctuation,
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "0123456789",
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_graphic() {
- assert_all!(is_ascii_graphic,
- "",
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "0123456789",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- );
- assert_none!(is_ascii_graphic,
- " \t\n\x0c\r",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_whitespace() {
- assert_all!(is_ascii_whitespace,
- "",
- " \t\n\x0c\r",
- );
- assert_none!(is_ascii_whitespace,
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "0123456789",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x0b\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- }
-
- #[test]
- fn test_is_ascii_control() {
- assert_all!(is_ascii_control,
- "",
- "\x00\x01\x02\x03\x04\x05\x06\x07",
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
- "\x10\x11\x12\x13\x14\x15\x16\x17",
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
- "\x7f",
- );
- assert_none!(is_ascii_control,
- "abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
- "0123456789",
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
- " ",
- );
- }
-}
diff --git a/ctr-std/src/collections/hash/map.rs b/ctr-std/src/collections/hash/map.rs
index a82ff91..20a4f9b 100644
--- a/ctr-std/src/collections/hash/map.rs
+++ b/ctr-std/src/collections/hash/map.rs
@@ -11,6 +11,7 @@
use self::Entry::*;
use self::VacantEntryState::*;
+use alloc::{Global, Alloc, CollectionAllocErr};
use cell::Cell;
use borrow::Borrow;
use cmp::max;
@@ -19,8 +20,7 @@ use fmt::{self, Debug};
use hash::{Hash, Hasher, BuildHasher, SipHasher13};
use iter::{FromIterator, FusedIterator};
use mem::{self, replace};
-use ops::{Deref, Index, InPlace, Place, Placer};
-use ptr;
+use ops::{Deref, Index};
use sys;
use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
@@ -42,21 +42,28 @@ impl DefaultResizePolicy {
/// provide that capacity, accounting for maximum loading. The raw capacity
/// is always zero or a power of two.
#[inline]
- fn raw_capacity(&self, len: usize) -> usize {
+ fn try_raw_capacity(&self, len: usize) -> Result<usize, CollectionAllocErr> {
if len == 0 {
- 0
+ Ok(0)
} else {
// 1. Account for loading: `raw_capacity >= len * 1.1`.
// 2. Ensure it is a power of two.
// 3. Ensure it is at least the minimum size.
- let mut raw_cap = len * 11 / 10;
- assert!(raw_cap >= len, "raw_cap overflow");
- raw_cap = raw_cap.checked_next_power_of_two().expect("raw_capacity overflow");
+ let mut raw_cap = len.checked_mul(11)
+ .map(|l| l / 10)
+ .and_then(|l| l.checked_next_power_of_two())
+ .ok_or(CollectionAllocErr::CapacityOverflow)?;
+
raw_cap = max(MIN_NONZERO_RAW_CAPACITY, raw_cap);
- raw_cap
+ Ok(raw_cap)
}
}
+ #[inline]
+ fn raw_capacity(&self, len: usize) -> usize {
+ self.try_raw_capacity(len).expect("raw_capacity overflow")
+ }
+
/// The capacity of the given raw capacity.
#[inline]
fn capacity(&self, raw_cap: usize) -> usize {
@@ -620,7 +627,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
///
/// ```
/// use std::collections::HashMap;
- /// let mut map: HashMap<&str, isize> = HashMap::new();
+ /// let mut map: HashMap<&str, i32> = HashMap::new();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -637,7 +644,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
///
/// ```
/// use std::collections::HashMap;
- /// let mut map: HashMap<&str, isize> = HashMap::with_capacity(10);
+ /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -724,7 +731,7 @@ impl<K, V, S> HashMap<K, V, S>
/// use std::collections::hash_map::RandomState;
///
/// let hasher = RandomState::new();
- /// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher);
+ /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
/// let hasher: &RandomState = map.hasher();
/// ```
#[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
@@ -741,7 +748,7 @@ impl<K, V, S> HashMap<K, V, S>
///
/// ```
/// use std::collections::HashMap;
- /// let map: HashMap<isize, isize> = HashMap::with_capacity(100);
+ /// let map: HashMap<i32, i32> = HashMap::with_capacity(100);
/// assert!(map.capacity() >= 100);
/// ```
#[inline]
@@ -770,22 +777,50 @@ impl<K, V, S> HashMap<K, V, S>
///
/// ```
/// use std::collections::HashMap;
- /// let mut map: HashMap<&str, isize> = HashMap::new();
+ /// let mut map: HashMap<&str, i32> = HashMap::new();
/// map.reserve(10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve(&mut self, additional: usize) {
+ match self.try_reserve(additional) {
+ Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+ Err(CollectionAllocErr::AllocErr) => Global.oom(),
+ Ok(()) => { /* yay */ }
+ }
+ }
+
+ /// Tries to reserve capacity for at least `additional` more elements to be inserted
+ /// in the given `HashMap<K,V>`. The collection may reserve more space to avoid
+ /// frequent reallocations.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(try_reserve)]
+ /// use std::collections::HashMap;
+ /// let mut map: HashMap<&str, isize> = HashMap::new();
+ /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
+ /// ```
+ #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
let remaining = self.capacity() - self.len(); // this can't overflow
if remaining < additional {
- let min_cap = self.len().checked_add(additional).expect("reserve overflow");
- let raw_cap = self.resize_policy.raw_capacity(min_cap);
- self.resize(raw_cap);
+ let min_cap = self.len().checked_add(additional)
+ .ok_or(CollectionAllocErr::CapacityOverflow)?;
+ let raw_cap = self.resize_policy.try_raw_capacity(min_cap)?;
+ self.try_resize(raw_cap)?;
} else if self.table.tag() && remaining <= self.len() {
// Probe sequence is too long and table is half full,
// resize early to reduce probing length.
let new_capacity = self.table.capacity() * 2;
- self.resize(new_capacity);
+ self.try_resize(new_capacity)?;
}
+ Ok(())
}
/// Resizes the internal vectors to a new capacity. It's your
@@ -795,15 +830,15 @@ impl<K, V, S> HashMap<K, V, S>
/// 2) Ensure `new_raw_cap` is a power of two or zero.
#[inline(never)]
#[cold]
- fn resize(&mut self, new_raw_cap: usize) {
+ fn try_resize(&mut self, new_raw_cap: usize) -> Result<(), CollectionAllocErr> {
assert!(self.table.size() <= new_raw_cap);
assert!(new_raw_cap.is_power_of_two() || new_raw_cap == 0);
- let mut old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
+ let mut old_table = replace(&mut self.table, RawTable::try_new(new_raw_cap)?);
let old_size = old_table.size();
if old_table.size() == 0 {
- return;
+ return Ok(());
}
let mut bucket = Bucket::head_bucket(&mut old_table);
@@ -838,6 +873,7 @@ impl<K, V, S> HashMap<K, V, S>
}
assert_eq!(self.table.size(), old_size);
+ Ok(())
}
/// Shrinks the capacity of the map as much as possible. It will drop
@@ -849,7 +885,7 @@ impl<K, V, S> HashMap<K, V, S>
/// ```
/// use std::collections::HashMap;
///
- /// let mut map: HashMap<isize, isize> = HashMap::with_capacity(100);
+ /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
/// map.insert(1, 2);
/// map.insert(3, 4);
/// assert!(map.capacity() >= 100);
@@ -872,6 +908,46 @@ impl<K, V, S> HashMap<K, V, S>
}
}
+ /// Shrinks the capacity of the map with a lower limit. It will drop
+ /// down no lower than the supplied limit while maintaining the internal rules
+ /// and possibly leaving some space in accordance with the resize policy.
+ ///
+ /// Panics if the current capacity is smaller than the supplied
+ /// minimum capacity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(shrink_to)]
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
+ /// map.insert(1, 2);
+ /// map.insert(3, 4);
+ /// assert!(map.capacity() >= 100);
+ /// map.shrink_to(10);
+ /// assert!(map.capacity() >= 10);
+ /// map.shrink_to(0);
+ /// assert!(map.capacity() >= 2);
+ /// ```
+ #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity");
+
+ let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity));
+ if self.raw_capacity() != new_raw_cap {
+ let old_table = replace(&mut self.table, RawTable::new(new_raw_cap));
+ let old_size = old_table.size();
+
+ // Shrink the table. Naive algorithm for resizing:
+ for (h, k, v) in old_table.into_iter() {
+ self.insert_hashed_nocheck(h, k, v);
+ }
+
+ debug_assert_eq!(self.table.size(), old_size);
+ }
+ }
+
/// Insert a pre-hashed key-value pair, without first checking
/// that there's enough room in the buckets. Returns a reference to the
/// newly insert value.
@@ -1146,6 +1222,34 @@ impl<K, V, S> HashMap<K, V, S>
self.search(k).map(|bucket| bucket.into_refs().1)
}
+ /// Returns the key-value pair corresponding to the supplied key.
+ ///
+ /// The supplied key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(map_get_key_value)]
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
+ /// assert_eq!(map.get_key_value(&2), None);
+ /// ```
+ #[unstable(feature = "map_get_key_value", issue = "49347")]
+ pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
+ where K: Borrow<Q>,
+ Q: Hash + Eq
+ {
+ self.search(k).map(|bucket| bucket.into_refs())
+ }
+
/// Returns true if the map contains a value for the specified key.
///
/// The key may be any borrowed form of the map's key type, but
@@ -1306,7 +1410,7 @@ impl<K, V, S> HashMap<K, V, S>
/// ```
/// use std::collections::HashMap;
///
- /// let mut map: HashMap<isize, isize> = (0..8).map(|x|(x, x*10)).collect();
+ /// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
/// map.retain(|&k, _| k % 2 == 0);
/// assert_eq!(map.len(), 4);
/// ```
@@ -1722,7 +1826,7 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
/// map.insert("c", 3);
///
/// // Not possible with .iter()
- /// let vec: Vec<(&str, isize)> = map.into_iter().collect();
+ /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
/// ```
fn into_iter(self) -> IntoIter<K, V> {
IntoIter { inner: self.table.into_iter() }
@@ -1750,7 +1854,7 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1773,7 +1877,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
self.inner.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1808,7 +1912,7 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> {
self.inner.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<K, V> FusedIterator for IntoIter<K, V> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1840,7 +1944,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
self.inner.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1863,7 +1967,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
self.inner.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
#[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1886,7 +1990,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
self.inner.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1921,7 +2025,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
self.inner.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1936,80 +2040,6 @@ impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
}
}
-/// A place for insertion to a `Entry`.
-///
-/// See [`HashMap::entry`](struct.HashMap.html#method.entry) for details.
-#[must_use = "places do nothing unless written to with `<-` syntax"]
-#[unstable(feature = "collection_placement",
- reason = "struct name and placement protocol is subject to change",
- issue = "30172")]
-pub struct EntryPlace<'a, K: 'a, V: 'a> {
- bucket: FullBucketMut<'a, K, V>,
-}
-
-#[unstable(feature = "collection_placement",
- reason = "struct name and placement protocol is subject to change",
- issue = "30172")]
-impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for EntryPlace<'a, K, V> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("EntryPlace")
- .field("key", self.bucket.read().0)
- .field("value", self.bucket.read().1)
- .finish()
- }
-}
-
-#[unstable(feature = "collection_placement",
- reason = "struct name and placement protocol is subject to change",
- issue = "30172")]
-impl<'a, K, V> Drop for EntryPlace<'a, K, V> {
- fn drop(&mut self) {
- // Inplacement insertion failed. Only key need to drop.
- // The value is failed to insert into map.
- unsafe { self.bucket.remove_key() };
- }
-}
-
-#[unstable(feature = "collection_placement",
- reason = "placement protocol is subject to change",
- issue = "30172")]
-impl<'a, K, V> Placer<V> for Entry<'a, K, V> {
- type Place = EntryPlace<'a, K, V>;
-
- fn make_place(self) -> EntryPlace<'a, K, V> {
- let b = match self {
- Occupied(mut o) => {
- unsafe { ptr::drop_in_place(o.elem.read_mut().1); }
- o.elem
- }
- Vacant(v) => {
- unsafe { v.insert_key() }
- }
- };
- EntryPlace { bucket: b }
- }
-}
-
-#[unstable(feature = "collection_placement",
- reason = "placement protocol is subject to change",
- issue = "30172")]
-unsafe impl<'a, K, V> Place<V> for EntryPlace<'a, K, V> {
- fn pointer(&mut self) -> *mut V {
- self.bucket.read_mut().1
- }
-}
-
-#[unstable(feature = "collection_placement",
- reason = "placement protocol is subject to change",
- issue = "30172")]
-impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V> {
- type Owner = ();
-
- unsafe fn finalize(self) {
- mem::forget(self);
- }
-}
-
impl<'a, K, V> Entry<'a, K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
/// Ensures a value is in the entry by inserting the default if empty, and returns
@@ -2082,7 +2112,6 @@ impl<'a, K, V> Entry<'a, K, V> {
/// # Examples
///
/// ```
- /// #![feature(entry_and_modify)]
/// use std::collections::HashMap;
///
/// let mut map: HashMap<&str, u32> = HashMap::new();
@@ -2097,7 +2126,7 @@ impl<'a, K, V> Entry<'a, K, V> {
/// .or_insert(42);
/// assert_eq!(map["poneyland"], 43);
/// ```
- #[unstable(feature = "entry_and_modify", issue = "44733")]
+ #[stable(feature = "entry_and_modify", since = "1.26.0")]
pub fn and_modify<F>(self, mut f: F) -> Self
where F: FnMut(&mut V)
{
@@ -2433,26 +2462,6 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
};
b.into_mut_refs().1
}
-
- // Only used for InPlacement insert. Avoid unnecessary value copy.
- // The value remains uninitialized.
- unsafe fn insert_key(self) -> FullBucketMut<'a, K, V> {
- match self.elem {
- NeqElem(mut bucket, disp) => {
- if disp >= DISPLACEMENT_THRESHOLD {
- bucket.table_mut().set_tag(true);
- }
- let uninit = mem::uninitialized();
- robin_hood(bucket, disp, self.hash, self.key, uninit)
- },
- NoElem(mut bucket, disp) => {
- if disp >= DISPLACEMENT_THRESHOLD {
- bucket.table_mut().set_tag(true);
- }
- bucket.put_key(self.hash, self.key)
- },
- }
- }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2717,7 +2726,9 @@ mod test_map {
use super::RandomState;
use cell::RefCell;
use rand::{thread_rng, Rng};
- use panic;
+ use realstd::collections::CollectionAllocErr::*;
+ use realstd::mem::size_of;
+ use realstd::usize;
#[test]
fn test_zero_capacities() {
@@ -2787,24 +2798,24 @@ mod test_map {
assert_eq!(m2.len(), 2);
}
- thread_local! { static DROP_VECTOR: RefCell<Vec<isize>> = RefCell::new(Vec::new()) }
+ thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = RefCell::new(Vec::new()) }
#[derive(Hash, PartialEq, Eq)]
- struct Dropable {
+ struct Droppable {
k: usize,
}
- impl Dropable {
- fn new(k: usize) -> Dropable {
+ impl Droppable {
+ fn new(k: usize) -> Droppable {
DROP_VECTOR.with(|slot| {
slot.borrow_mut()[k] += 1;
});
- Dropable { k: k }
+ Droppable { k: k }
}
}
- impl Drop for Dropable {
+ impl Drop for Droppable {
fn drop(&mut self) {
DROP_VECTOR.with(|slot| {
slot.borrow_mut()[self.k] -= 1;
@@ -2812,9 +2823,9 @@ mod test_map {
}
}
- impl Clone for Dropable {
- fn clone(&self) -> Dropable {
- Dropable::new(self.k)
+ impl Clone for Droppable {
+ fn clone(&self) -> Droppable {
+ Droppable::new(self.k)
}
}
@@ -2834,8 +2845,8 @@ mod test_map {
});
for i in 0..100 {
- let d1 = Dropable::new(i);
- let d2 = Dropable::new(i + 100);
+ let d1 = Droppable::new(i);
+ let d2 = Droppable::new(i + 100);
m.insert(d1, d2);
}
@@ -2846,7 +2857,7 @@ mod test_map {
});
for i in 0..50 {
- let k = Dropable::new(i);
+ let k = Droppable::new(i);
let v = m.remove(&k);
assert!(v.is_some());
@@ -2893,8 +2904,8 @@ mod test_map {
});
for i in 0..100 {
- let d1 = Dropable::new(i);
- let d2 = Dropable::new(i + 100);
+ let d1 = Droppable::new(i);
+ let d2 = Droppable::new(i + 100);
hm.insert(d1, d2);
}
@@ -2944,13 +2955,13 @@ mod test_map {
#[test]
fn test_empty_remove() {
- let mut m: HashMap<isize, bool> = HashMap::new();
+ let mut m: HashMap<i32, bool> = HashMap::new();
assert_eq!(m.remove(&0), None);
}
#[test]
fn test_empty_entry() {
- let mut m: HashMap<isize, bool> = HashMap::new();
+ let mut m: HashMap<i32, bool> = HashMap::new();
match m.entry(0) {
Occupied(_) => panic!(),
Vacant(_) => {}
@@ -2961,7 +2972,7 @@ mod test_map {
#[test]
fn test_empty_iter() {
- let mut m: HashMap<isize, bool> = HashMap::new();
+ let mut m: HashMap<i32, bool> = HashMap::new();
assert_eq!(m.drain().next(), None);
assert_eq!(m.keys().next(), None);
assert_eq!(m.values().next(), None);
@@ -3462,7 +3473,7 @@ mod test_map {
fn test_entry_take_doesnt_corrupt() {
#![allow(deprecated)] //rand
// Test for #19292
- fn check(m: &HashMap<isize, ()>) {
+ fn check(m: &HashMap<i32, ()>) {
for k in m.keys() {
assert!(m.contains_key(k),
"{} is in keys() but not in the map?", k);
@@ -3571,7 +3582,7 @@ mod test_map {
#[test]
fn test_retain() {
- let mut map: HashMap<isize, isize> = (0..100).map(|x|(x, x*10)).collect();
+ let mut map: HashMap<i32, i32> = (0..100).map(|x|(x, x*10)).collect();
map.retain(|&k, _| k % 2 == 0);
assert_eq!(map.len(), 50);
@@ -3601,55 +3612,31 @@ mod test_map {
}
#[test]
- fn test_placement_in() {
- let mut map = HashMap::new();
- map.extend((0..10).map(|i| (i, i)));
-
- map.entry(100) <- 100;
- assert_eq!(map[&100], 100);
+ fn test_try_reserve() {
- map.entry(0) <- 10;
- assert_eq!(map[&0], 10);
-
- assert_eq!(map.len(), 11);
- }
-
- #[test]
- fn test_placement_panic() {
- let mut map = HashMap::new();
- map.extend((0..10).map(|i| (i, i)));
+ let mut empty_bytes: HashMap<u8,u8> = HashMap::new();
- fn mkpanic() -> usize { panic!() }
+ const MAX_USIZE: usize = usize::MAX;
- // modify existing key
- // when panic happens, previous key is removed.
- let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
- assert_eq!(map.len(), 9);
- assert!(!map.contains_key(&0));
+ // HashMap and RawTables use complicated size calculations
+ // hashes_size is sizeof(HashUint) * capacity;
+ // pairs_size is sizeof((K. V)) * capacity;
+ // alignment_hashes_size is 8
+ // alignment_pairs size is 4
+ let size_of_multiplier = (size_of::<usize>() + size_of::<(u8, u8)>()).next_power_of_two();
+ // The following formula is used to calculate the new capacity
+ let max_no_ovf = ((MAX_USIZE / 11) * 10) / size_of_multiplier - 1;
- // add new key
- let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); }));
- assert_eq!(map.len(), 9);
- assert!(!map.contains_key(&100));
- }
+ if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
+ } else { panic!("usize::MAX should trigger an overflow!"); }
- #[test]
- fn test_placement_drop() {
- // correctly drop
- struct TestV<'a>(&'a mut bool);
- impl<'a> Drop for TestV<'a> {
- fn drop(&mut self) {
- if !*self.0 { panic!("value double drop!"); } // no double drop
- *self.0 = false;
- }
+ if size_of::<usize>() < 8 {
+ if let Err(CapacityOverflow) = empty_bytes.try_reserve(max_no_ovf) {
+ } else { panic!("isize::MAX + 1 should trigger a CapacityOverflow!") }
+ } else {
+ if let Err(AllocErr) = empty_bytes.try_reserve(max_no_ovf) {
+ } else { panic!("isize::MAX + 1 should trigger an OOM!") }
}
-
- fn makepanic<'a>() -> TestV<'a> { panic!() }
-
- let mut can_drop = true;
- let mut hm = HashMap::new();
- hm.insert(0, TestV(&mut can_drop));
- let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); }));
- assert_eq!(hm.len(), 0);
}
+
}
diff --git a/ctr-std/src/collections/hash/set.rs b/ctr-std/src/collections/hash/set.rs
index e9427fb..855563a 100644
--- a/ctr-std/src/collections/hash/set.rs
+++ b/ctr-std/src/collections/hash/set.rs
@@ -292,6 +292,34 @@ impl<T, S> HashSet<T, S>
self.map.shrink_to_fit()
}
+ /// Shrinks the capacity of the set with a lower limit. It will drop
+ /// down no lower than the supplied limit while maintaining the internal rules
+ /// and possibly leaving some space in accordance with the resize policy.
+ ///
+ /// Panics if the current capacity is smaller than the supplied
+ /// minimum capacity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(shrink_to)]
+ /// use std::collections::HashSet;
+ ///
+ /// let mut set = HashSet::with_capacity(100);
+ /// set.insert(1);
+ /// set.insert(2);
+ /// assert!(set.capacity() >= 100);
+ /// set.shrink_to(10);
+ /// assert!(set.capacity() >= 10);
+ /// set.shrink_to(0);
+ /// assert!(set.capacity() >= 2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.map.shrink_to(min_capacity)
+ }
+
/// An iterator visiting all elements in arbitrary order.
/// The iterator element type is `&'a T`.
///
@@ -724,7 +752,7 @@ impl<T, S> HashSet<T, S>
/// use std::collections::HashSet;
///
/// let xs = [1,2,3,4,5,6];
- /// let mut set: HashSet<isize> = xs.iter().cloned().collect();
+ /// let mut set: HashSet<i32> = xs.iter().cloned().collect();
/// set.retain(|&k| k % 2 == 0);
/// assert_eq!(set.len(), 3);
/// ```
@@ -1097,7 +1125,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> {
self.iter.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K> FusedIterator for Iter<'a, K> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1124,7 +1152,7 @@ impl<K> ExactSizeIterator for IntoIter<K> {
self.iter.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<K> FusedIterator for IntoIter<K> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1155,7 +1183,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> {
self.iter.len()
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K> FusedIterator for Drain<'a, K> {}
#[stable(feature = "std_debug", since = "1.16.0")]
@@ -1208,7 +1236,7 @@ impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T, S> FusedIterator for Intersection<'a, T, S>
where T: Eq + Hash,
S: BuildHasher
@@ -1244,7 +1272,7 @@ impl<'a, T, S> Iterator for Difference<'a, T, S>
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T, S> FusedIterator for Difference<'a, T, S>
where T: Eq + Hash,
S: BuildHasher
@@ -1283,7 +1311,7 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
where T: Eq + Hash,
S: BuildHasher
@@ -1307,7 +1335,7 @@ impl<'a, T, S> Clone for Union<'a, T, S> {
}
}
-#[unstable(feature = "fused", issue = "35602")]
+#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T, S> FusedIterator for Union<'a, T, S>
where T: Eq + Hash,
S: BuildHasher
@@ -1745,7 +1773,7 @@ mod test_set {
#[test]
fn test_retain() {
let xs = [1, 2, 3, 4, 5, 6];
- let mut set: HashSet<isize> = xs.iter().cloned().collect();
+ let mut set: HashSet<i32> = xs.iter().cloned().collect();
set.retain(|&k| k % 2 == 0);
assert_eq!(set.len(), 3);
assert!(set.contains(&2));
diff --git a/ctr-std/src/collections/hash/table.rs b/ctr-std/src/collections/hash/table.rs
index 73bd574..93f0590 100644
--- a/ctr-std/src/collections/hash/table.rs
+++ b/ctr-std/src/collections/hash/table.rs
@@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use alloc::heap::{Heap, Alloc, Layout};
-
+use alloc::{Global, Alloc, Layout, CollectionAllocErr};
use cmp;
use hash::{BuildHasher, Hash, Hasher};
use marker;
@@ -484,21 +483,6 @@ impl<K, V, M> EmptyBucket<K, V, M>
table: self.table,
}
}
-
- /// Puts given key, remain value uninitialized.
- /// It is only used for inplacement insertion.
- pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
- *self.raw.hash() = hash.inspect();
- let pair_ptr = self.raw.pair();
- ptr::write(&mut (*pair_ptr).0, key);
-
- self.table.borrow_table_mut().size += 1;
-
- FullBucket {
- raw: self.raw,
- table: self.table,
- }
- }
}
impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
@@ -574,17 +558,6 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
v)
}
}
-
- /// Remove this bucket's `key` from the hashtable.
- /// Only used for inplacement insertion.
- /// NOTE: `Value` is uninitialized when this function is called, don't try to drop the `Value`.
- pub unsafe fn remove_key(&mut self) {
- self.table.size -= 1;
-
- *self.raw.hash() = EMPTY_BUCKET;
- let pair_ptr = self.raw.pair();
- ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key
- }
}
// This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases
@@ -741,14 +714,15 @@ fn test_offset_calculation() {
impl<K, V> RawTable<K, V> {
/// Does not initialize the buckets. The caller should ensure they,
/// at the very least, set every hash to EMPTY_BUCKET.
- unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
+ /// Returns an error if it cannot allocate or capacity overflows.
+ unsafe fn try_new_uninitialized(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
if capacity == 0 {
- return RawTable {
+ return Ok(RawTable {
size: 0,
capacity_mask: capacity.wrapping_sub(1),
hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint),
marker: marker::PhantomData,
- };
+ });
}
// No need for `checked_mul` before a more restrictive check performed
@@ -768,25 +742,36 @@ impl<K, V> RawTable<K, V> {
align_of::<HashUint>(),
pairs_size,
align_of::<(K, V)>());
- assert!(!oflo, "capacity overflow");
+ if oflo {
+ return Err(CollectionAllocErr::CapacityOverflow);
+ }
// One check for overflow that covers calculation and rounding of size.
- let size_of_bucket = size_of::<HashUint>().checked_add(size_of::<(K, V)>()).unwrap();
- assert!(size >=
- capacity.checked_mul(size_of_bucket)
- .expect("capacity overflow"),
- "capacity overflow");
-
- let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
- .unwrap_or_else(|e| Heap.oom(e));
+ let size_of_bucket = size_of::<HashUint>().checked_add(size_of::<(K, V)>())
+ .ok_or(CollectionAllocErr::CapacityOverflow)?;
+ let capacity_mul_size_of_bucket = capacity.checked_mul(size_of_bucket);
+ if capacity_mul_size_of_bucket.is_none() || size < capacity_mul_size_of_bucket.unwrap() {
+ return Err(CollectionAllocErr::CapacityOverflow);
+ }
- let hashes = buffer as *mut HashUint;
+ let buffer = Global.alloc(Layout::from_size_align(size, alignment)
+ .map_err(|_| CollectionAllocErr::CapacityOverflow)?)?;
- RawTable {
+ Ok(RawTable {
capacity_mask: capacity.wrapping_sub(1),
size: 0,
- hashes: TaggedHashUintPtr::new(hashes),
+ hashes: TaggedHashUintPtr::new(buffer.cast().as_ptr()),
marker: marker::PhantomData,
+ })
+ }
+
+ /// Does not initialize the buckets. The caller should ensure they,
+ /// at the very least, set every hash to EMPTY_BUCKET.
+ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
+ match Self::try_new_uninitialized(capacity) {
+ Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+ Err(CollectionAllocErr::AllocErr) => Global.oom(),
+ Ok(table) => { table }
}
}
@@ -809,13 +794,23 @@ impl<K, V> RawTable<K, V> {
}
}
+ /// Tries to create a new raw table from a given capacity. If it cannot allocate,
+ /// it returns with AllocErr.
+ pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
+ unsafe {
+ let ret = RawTable::try_new_uninitialized(capacity)?;
+ ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
+ Ok(ret)
+ }
+ }
+
/// Creates a new raw table from a given capacity. All buckets are
/// initially empty.
pub fn new(capacity: usize) -> RawTable<K, V> {
- unsafe {
- let ret = RawTable::new_uninitialized(capacity);
- ptr::write_bytes(ret.hashes.ptr(), 0, capacity);
- ret
+ match Self::try_new(capacity) {
+ Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
+ Err(CollectionAllocErr::AllocErr) => Global.oom(),
+ Ok(table) => { table }
}
}
@@ -1188,8 +1183,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
debug_assert!(!oflo, "should be impossible");
unsafe {
- Heap.dealloc(self.hashes.ptr() as *mut u8,
- Layout::from_size_align(size, align).unwrap());
+ Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).as_opaque(),
+ Layout::from_size_align(size, align).unwrap());
// Remember how everything was allocated out of one buffer
// during initialization? We only need one call to free here.
}
diff --git a/ctr-std/src/collections/mod.rs b/ctr-std/src/collections/mod.rs
index b8a6a66..9cf7382 100644
--- a/ctr-std/src/collections/mod.rs
+++ b/ctr-std/src/collections/mod.rs
@@ -64,11 +64,11 @@
//! * You want a map, with no extra functionality.
//!
//! ### Use a `BTreeMap` when:
+//! * You want a map sorted by its keys.
+//! * You want to be able to get a range of entries on-demand.
//! * You're interested in what the smallest or largest key-value pair is.
//! * You want to find the largest or smallest key that is smaller or larger
//! than something.
-//! * You want to be able to get all of the entries in order on-demand.
-//! * You want a map sorted by its keys.
//!
//! ### Use the `Set` variant of any of these `Map`s when:
//! * You just want to remember which keys you've seen.
@@ -420,23 +420,33 @@
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::Bound;
+#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")]
+#[doc(hidden)]
+pub use ops::Bound;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{BinaryHeap, BTreeMap, BTreeSet};
+pub use alloc_crate::{BinaryHeap, BTreeMap, BTreeSet};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{LinkedList, VecDeque};
+pub use alloc_crate::{LinkedList, VecDeque};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{binary_heap, btree_map, btree_set};
+pub use alloc_crate::{binary_heap, btree_map, btree_set};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{linked_list, vec_deque};
+pub use alloc_crate::{linked_list, vec_deque};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::hash_map::HashMap;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::hash_set::HashSet;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::range;
+#[unstable(feature = "collections_range", issue = "30877")]
+#[rustc_deprecated(reason = "renamed and moved to `std::ops::RangeBounds`", since = "1.26.0")]
+#[doc(hidden)]
+/// Range syntax
+pub mod range {
+ pub use ops::RangeBounds as RangeArgument;
+}
+
+#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
+pub use heap::CollectionAllocErr;
mod hash;
diff --git a/ctr-std/src/env.rs b/ctr-std/src/env.rs
index c4946b6..a103c0b 100644
--- a/ctr-std/src/env.rs
+++ b/ctr-std/src/env.rs
@@ -552,17 +552,17 @@ pub fn home_dir() -> Option<PathBuf> {
///
/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx
///
-/// ```
+/// ```no_run
/// use std::env;
/// use std::fs::File;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut dir = env::temp_dir();
-/// dir.push("foo.txt");
+/// fn main() -> std::io::Result<()> {
+/// let mut dir = env::temp_dir();
+/// dir.push("foo.txt");
///
-/// let f = File::create(dir)?;
-/// # Ok(())
-/// # }
+/// let f = File::create(dir)?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "env", since = "1.0.0")]
pub fn temp_dir() -> PathBuf {
@@ -723,10 +723,10 @@ pub fn args_os() -> ArgsOs {
ArgsOs { inner: sys::args::args() }
}
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
impl !Send for Args {}
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
impl !Sync for Args {}
#[stable(feature = "env", since = "1.0.0")]
@@ -760,10 +760,10 @@ impl fmt::Debug for Args {
}
}
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
impl !Send for ArgsOs {}
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
impl !Sync for ArgsOs {}
#[stable(feature = "env", since = "1.0.0")]
diff --git a/ctr-std/src/error.rs b/ctr-std/src/error.rs
index eb5022a..3c20992 100644
--- a/ctr-std/src/error.rs
+++ b/ctr-std/src/error.rs
@@ -51,14 +51,13 @@
// coherence challenge (e.g., specialization, neg impls, etc) we can
// reconsider what crate these items belong in.
-use alloc::allocator;
use any::TypeId;
use borrow::Cow;
use cell;
use char;
-use convert;
use core::array;
use fmt::{self, Debug, Display};
+use heap::{AllocErr, LayoutErr, CannotReallocInPlace};
use mem::transmute;
use num;
use str;
@@ -234,7 +233,7 @@ impl<'a> From<Cow<'a, str>> for Box<Error> {
}
}
-#[unstable(feature = "never_type", issue = "35121")]
+#[stable(feature = "never_type", since = "1.26.0")]
impl Error for ! {
fn description(&self) -> &str { *self }
}
@@ -242,18 +241,27 @@ impl Error for ! {
#[unstable(feature = "allocator_api",
reason = "the precise API and guarantees it provides may be tweaked.",
issue = "32838")]
-impl Error for allocator::AllocErr {
+impl Error for AllocErr {
fn description(&self) -> &str {
- allocator::AllocErr::description(self)
+ "memory allocation failed"
}
}
#[unstable(feature = "allocator_api",
reason = "the precise API and guarantees it provides may be tweaked.",
issue = "32838")]
-impl Error for allocator::CannotReallocInPlace {
+impl Error for LayoutErr {
fn description(&self) -> &str {
- allocator::CannotReallocInPlace::description(self)
+ "invalid parameters to Layout::from_size_align"
+ }
+}
+
+#[unstable(feature = "allocator_api",
+ reason = "the precise API and guarantees it provides may be tweaked.",
+ issue = "32838")]
+impl Error for CannotReallocInPlace {
+ fn description(&self) -> &str {
+ CannotReallocInPlace::description(self)
}
}
@@ -276,14 +284,14 @@ impl Error for num::ParseIntError {
}
}
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
impl Error for num::TryFromIntError {
fn description(&self) -> &str {
self.__description()
}
}
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
impl Error for array::TryFromSliceError {
fn description(&self) -> &str {
self.__description()
@@ -357,7 +365,7 @@ impl Error for cell::BorrowMutError {
}
}
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
impl Error for char::CharTryFromError {
fn description(&self) -> &str {
"converted integer out of range for `char`"
@@ -371,14 +379,6 @@ impl Error for char::ParseCharError {
}
}
-#[unstable(feature = "try_from", issue = "33417")]
-impl Error for convert::Infallible {
- fn description(&self) -> &str {
- match *self {
- }
- }
-}
-
// copied from any.rs
impl Error + 'static {
/// Returns true if the boxed type is the same as `T`
diff --git a/ctr-std/src/f32.rs b/ctr-std/src/f32.rs
index a760922..ca39089 100644
--- a/ctr-std/src/f32.rs
+++ b/ctr-std/src/f32.rs
@@ -329,6 +329,57 @@ impl f32 {
unsafe { intrinsics::fmaf32(self, a, b) }
}
+ /// Calculates Euclidean division, the matching method for `mod_euc`.
+ ///
+ /// This computes the integer `n` such that
+ /// `self = n * rhs + self.mod_euc(rhs)`.
+ /// In other words, the result is `self / rhs` rounded to the integer `n`
+ /// such that `self >= n * rhs`.
+ ///
+ /// ```
+ /// #![feature(euclidean_division)]
+ /// let a: f32 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
+ /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
+ /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
+ /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
+ /// ```
+ #[inline]
+ #[unstable(feature = "euclidean_division", issue = "49048")]
+ pub fn div_euc(self, rhs: f32) -> f32 {
+ let q = (self / rhs).trunc();
+ if self % rhs < 0.0 {
+ return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
+ }
+ q
+ }
+
+ /// Calculates the Euclidean modulo (self mod rhs), which is never negative.
+ ///
+ /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
+ ///
+ /// ```
+ /// #![feature(euclidean_division)]
+ /// let a: f32 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.mod_euc(b), 3.0);
+ /// assert_eq!((-a).mod_euc(b), 1.0);
+ /// assert_eq!(a.mod_euc(-b), 3.0);
+ /// assert_eq!((-a).mod_euc(-b), 1.0);
+ /// ```
+ #[inline]
+ #[unstable(feature = "euclidean_division", issue = "49048")]
+ pub fn mod_euc(self, rhs: f32) -> f32 {
+ let r = self % rhs;
+ if r < 0.0 {
+ r + rhs.abs()
+ } else {
+ r
+ }
+ }
+
+
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
@@ -780,7 +831,7 @@ impl f32 {
unsafe { cmath::atanf(self) }
}
- /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
+ /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
///
/// * `x = 0`, `y = 0`: `0`
/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
@@ -791,12 +842,13 @@ impl f32 {
/// use std::f32;
///
/// let pi = f32::consts::PI;
- /// // All angles from horizontal right (+x)
- /// // 45 deg counter-clockwise
+ /// // Positive angles measured counter-clockwise
+ /// // from positive x axis
+ /// // -pi/4 radians (45 deg clockwise)
/// let x1 = 3.0f32;
/// let y1 = -3.0f32;
///
- /// // 135 deg clockwise
+ /// // 3pi/4 radians (135 deg counter-clockwise)
/// let x2 = -3.0f32;
/// let y2 = 3.0f32;
///
diff --git a/ctr-std/src/f64.rs b/ctr-std/src/f64.rs
index 6f34f17..a958567 100644
--- a/ctr-std/src/f64.rs
+++ b/ctr-std/src/f64.rs
@@ -315,6 +315,56 @@ impl f64 {
unsafe { intrinsics::fmaf64(self, a, b) }
}
+ /// Calculates Euclidean division, the matching method for `mod_euc`.
+ ///
+ /// This computes the integer `n` such that
+ /// `self = n * rhs + self.mod_euc(rhs)`.
+ /// In other words, the result is `self / rhs` rounded to the integer `n`
+ /// such that `self >= n * rhs`.
+ ///
+ /// ```
+ /// #![feature(euclidean_division)]
+ /// let a: f64 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
+ /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
+ /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
+ /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
+ /// ```
+ #[inline]
+ #[unstable(feature = "euclidean_division", issue = "49048")]
+ pub fn div_euc(self, rhs: f64) -> f64 {
+ let q = (self / rhs).trunc();
+ if self % rhs < 0.0 {
+ return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
+ }
+ q
+ }
+
+ /// Calculates the Euclidean modulo (self mod rhs), which is never negative.
+ ///
+ /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
+ ///
+ /// ```
+ /// #![feature(euclidean_division)]
+ /// let a: f64 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.mod_euc(b), 3.0);
+ /// assert_eq!((-a).mod_euc(b), 1.0);
+ /// assert_eq!(a.mod_euc(-b), 3.0);
+ /// assert_eq!((-a).mod_euc(-b), 1.0);
+ /// ```
+ #[inline]
+ #[unstable(feature = "euclidean_division", issue = "49048")]
+ pub fn mod_euc(self, rhs: f64) -> f64 {
+ let r = self % rhs;
+ if r < 0.0 {
+ r + rhs.abs()
+ } else {
+ r
+ }
+ }
+
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
@@ -716,7 +766,7 @@ impl f64 {
unsafe { cmath::atan(self) }
}
- /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
+ /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
///
/// * `x = 0`, `y = 0`: `0`
/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
@@ -727,12 +777,13 @@ impl f64 {
/// use std::f64;
///
/// let pi = f64::consts::PI;
- /// // All angles from horizontal right (+x)
- /// // 45 deg counter-clockwise
+ /// // Positive angles measured counter-clockwise
+ /// // from positive x axis
+ /// // -pi/4 radians (45 deg clockwise)
/// let x1 = 3.0_f64;
/// let y1 = -3.0_f64;
///
- /// // 135 deg clockwise
+ /// // 3pi/4 radians (135 deg counter-clockwise)
/// let x2 = -3.0_f64;
/// let y2 = 3.0_f64;
///
diff --git a/ctr-std/src/ffi/c_str.rs b/ctr-std/src/ffi/c_str.rs
index a19fe82..c88c2bc 100644
--- a/ctr-std/src/ffi/c_str.rs
+++ b/ctr-std/src/ffi/c_str.rs
@@ -91,7 +91,7 @@ use sys;
///
/// # Examples
///
-/// ```no_run
+/// ```ignore (extern-declaration)
/// # fn main() {
/// use std::ffi::CString;
/// use std::os::raw::c_char;
@@ -150,7 +150,7 @@ pub struct CString {
///
/// Inspecting a foreign C string:
///
-/// ```no_run
+/// ```ignore (extern-declaration)
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
@@ -164,7 +164,7 @@ pub struct CString {
///
/// Passing a Rust-originating C string:
///
-/// ```no_run
+/// ```ignore (extern-declaration)
/// use std::ffi::{CString, CStr};
/// use std::os::raw::c_char;
///
@@ -180,7 +180,7 @@ pub struct CString {
///
/// Converting a foreign C string into a Rust [`String`]:
///
-/// ```no_run
+/// ```ignore (extern-declaration)
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
@@ -307,7 +307,7 @@ impl CString {
///
/// # Examples
///
- /// ```no_run
+ /// ```ignore (extern-declaration)
/// use std::ffi::CString;
/// use std::os::raw::c_char;
///
@@ -389,7 +389,7 @@ impl CString {
/// Create a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
/// ownership with `from_raw`:
///
- /// ```no_run
+ /// ```ignore (extern-declaration)
/// use std::ffi::CString;
/// use std::os::raw::c_char;
///
@@ -875,6 +875,8 @@ impl CStr {
/// `ptr`.
/// * There is no guarantee that the memory pointed to by `ptr` contains a
/// valid nul terminator byte at the end of the string.
+ /// * It is not guaranteed that the memory pointed by `ptr` won't change
+ /// before the `CStr` has been destroyed.
///
/// > **Note**: This operation is intended to be a 0-cost cast but it is
/// > currently implemented with an up-front calculation of the length of
@@ -882,7 +884,7 @@ impl CStr {
///
/// # Examples
///
- /// ```no_run
+ /// ```ignore (extern-declaration)
/// # fn main() {
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
@@ -1026,9 +1028,9 @@ impl CStr {
/// The returned slice will **not** contain the trailing nul terminator that this C
/// string has.
///
- /// > **Note**: This method is currently implemented as a 0-cost cast, but
- /// > it is planned to alter its definition in the future to perform the
- /// > length calculation whenever this method is called.
+ /// > **Note**: This method is currently implemented as a constant-time
+ /// > cast, but it is planned to alter its definition in the future to
+ /// > perform the length calculation whenever this method is called.
///
/// # Examples
///
@@ -1077,9 +1079,9 @@ impl CStr {
/// it will return an error with details of where UTF-8 validation failed.
///
/// > **Note**: This method is currently implemented to check for validity
- /// > after a 0-cost cast, but it is planned to alter its definition in the
- /// > future to perform the length calculation in addition to the UTF-8
- /// > check whenever this method is called.
+ /// > after a constant-time cast, but it is planned to alter its definition
+ /// > in the future to perform the length calculation in addition to the
+ /// > UTF-8 check whenever this method is called.
///
/// [`&str`]: ../primitive.str.html
///
@@ -1110,9 +1112,9 @@ impl CStr {
/// with the result.
///
/// > **Note**: This method is currently implemented to check for validity
- /// > after a 0-cost cast, but it is planned to alter its definition in the
- /// > future to perform the length calculation in addition to the UTF-8
- /// > check whenever this method is called.
+ /// > after a constant-time cast, but it is planned to alter its definition
+ /// > in the future to perform the length calculation in addition to the
+ /// > UTF-8 check whenever this method is called.
///
/// [`Cow`]: ../borrow/enum.Cow.html
/// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
diff --git a/ctr-std/src/ffi/os_str.rs b/ctr-std/src/ffi/os_str.rs
index 3959e85..7520121 100644
--- a/ctr-std/src/ffi/os_str.rs
+++ b/ctr-std/src/ffi/os_str.rs
@@ -295,6 +295,36 @@ impl OsString {
self.inner.shrink_to_fit()
}
+ /// Shrinks the capacity of the `OsString` with a lower bound.
+ ///
+ /// The capacity will remain at least as large as both the length
+ /// and the supplied value.
+ ///
+ /// Panics if the current capacity is smaller than the supplied
+ /// minimum capacity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(shrink_to)]
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::from("foo");
+ ///
+ /// s.reserve(100);
+ /// assert!(s.capacity() >= 100);
+ ///
+ /// s.shrink_to(10);
+ /// assert!(s.capacity() >= 10);
+ /// s.shrink_to(0);
+ /// assert!(s.capacity() >= 3);
+ /// ```
+ #[inline]
+ #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.inner.shrink_to(min_capacity)
+ }
+
/// Converts this `OsString` into a boxed [`OsStr`].
///
/// [`OsStr`]: struct.OsStr.html
diff --git a/ctr-std/src/fs.rs b/ctr-std/src/fs.rs
index d1f3ccb..7bd1adc 100644
--- a/ctr-std/src/fs.rs
+++ b/ctr-std/src/fs.rs
@@ -41,11 +41,11 @@ use time::SystemTime;
/// use std::fs::File;
/// use std::io::prelude::*;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut file = File::create("foo.txt")?;
-/// file.write_all(b"Hello, world!")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let mut file = File::create("foo.txt")?;
+/// file.write_all(b"Hello, world!")?;
+/// Ok(())
+/// }
/// ```
///
/// Read the contents of a file into a [`String`]:
@@ -54,13 +54,13 @@ use time::SystemTime;
/// use std::fs::File;
/// use std::io::prelude::*;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut file = File::open("foo.txt")?;
-/// let mut contents = String::new();
-/// file.read_to_string(&mut contents)?;
-/// assert_eq!(contents, "Hello, world!");
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let mut file = File::open("foo.txt")?;
+/// let mut contents = String::new();
+/// file.read_to_string(&mut contents)?;
+/// assert_eq!(contents, "Hello, world!");
+/// Ok(())
+/// }
/// ```
///
/// It can be more efficient to read the contents of a file with a buffered
@@ -71,19 +71,28 @@ use time::SystemTime;
/// use std::io::BufReader;
/// use std::io::prelude::*;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let file = File::open("foo.txt")?;
-/// let mut buf_reader = BufReader::new(file);
-/// let mut contents = String::new();
-/// buf_reader.read_to_string(&mut contents)?;
-/// assert_eq!(contents, "Hello, world!");
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let file = File::open("foo.txt")?;
+/// let mut buf_reader = BufReader::new(file);
+/// let mut contents = String::new();
+/// buf_reader.read_to_string(&mut contents)?;
+/// assert_eq!(contents, "Hello, world!");
+/// Ok(())
+/// }
/// ```
///
+/// Note that, although read and write methods require a `&mut File`, because
+/// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can
+/// still modify the file, either through methods that take `&File` or by
+/// retrieving the underlying OS object and modifying the file that way.
+/// Additionally, many operating systems allow concurrent modification of files
+/// by different processes. Avoid assuming that holding a `&File` means that the
+/// file will not change.
+///
/// [`Seek`]: ../io/trait.Seek.html
/// [`String`]: ../string/struct.String.html
/// [`Read`]: ../io/trait.Read.html
+/// [`Write`]: ../io/trait.Write.html
/// [`BufReader<R>`]: ../io/struct.BufReader.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct File {
@@ -222,7 +231,9 @@ fn initial_buffer_size(file: &File) -> usize {
/// Read the entire contents of a file into a bytes vector.
///
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
-/// with fewer imports and without an intermediate variable.
+/// with fewer imports and without an intermediate variable. It pre-allocates a
+/// buffer based on the file size when available, so it is generally faster than
+/// reading into a vector created with `Vec::new()`.
///
/// [`File::open`]: struct.File.html#method.open
/// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end
@@ -242,17 +253,15 @@ fn initial_buffer_size(file: &File) -> usize {
/// # Examples
///
/// ```no_run
-/// #![feature(fs_read_write)]
-///
/// use std::fs;
/// use std::net::SocketAddr;
///
-/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
-/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
-/// # Ok(())
-/// # }
+/// fn main() -> Result<(), Box<std::error::Error + 'static>> {
+/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
+/// Ok(())
+/// }
/// ```
-#[unstable(feature = "fs_read_write", issue = "46588")]
+#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
let mut file = File::open(path)?;
let mut bytes = Vec::with_capacity(initial_buffer_size(&file));
@@ -263,7 +272,9 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
/// Read the entire contents of a file into a string.
///
/// This is a convenience function for using [`File::open`] and [`read_to_string`]
-/// with fewer imports and without an intermediate variable.
+/// with fewer imports and without an intermediate variable. It pre-allocates a
+/// buffer based on the file size when available, so it is generally faster than
+/// reading into a string created with `String::new()`.
///
/// [`File::open`]: struct.File.html#method.open
/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
@@ -289,13 +300,13 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
/// use std::fs;
/// use std::net::SocketAddr;
///
-/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
-/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?;
-/// # Ok(())
-/// # }
+/// fn main() -> Result<(), Box<std::error::Error + 'static>> {
+/// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?;
+/// Ok(())
+/// }
/// ```
-#[unstable(feature = "fs_read_write", issue = "46588")]
-pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
+#[stable(feature = "fs_read_write", since = "1.26.0")]
+pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
let mut file = File::open(path)?;
let mut string = String::with_capacity(initial_buffer_size(&file));
file.read_to_string(&mut string)?;
@@ -316,16 +327,14 @@ pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
/// # Examples
///
/// ```no_run
-/// #![feature(fs_read_write)]
-///
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::write("foo.txt", b"Lorem ipsum")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::write("foo.txt", b"Lorem ipsum")?;
+/// Ok(())
+/// }
/// ```
-#[unstable(feature = "fs_read_write", issue = "46588")]
+#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
File::create(path)?.write_all(contents.as_ref())
}
@@ -347,7 +356,7 @@ impl File {
/// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
+ /// fn main() -> std::io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// # Ok(())
/// # }
@@ -371,10 +380,10 @@ impl File {
/// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::create("foo.txt")?;
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let mut f = File::create("foo.txt")?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
@@ -392,13 +401,13 @@ impl File {
/// use std::fs::File;
/// use std::io::prelude::*;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::create("foo.txt")?;
- /// f.write_all(b"Hello, world!")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut f = File::create("foo.txt")?;
+ /// f.write_all(b"Hello, world!")?;
///
- /// f.sync_all()?;
- /// # Ok(())
- /// # }
+ /// f.sync_all()?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_all(&self) -> io::Result<()> {
@@ -423,13 +432,13 @@ impl File {
/// use std::fs::File;
/// use std::io::prelude::*;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::create("foo.txt")?;
- /// f.write_all(b"Hello, world!")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut f = File::create("foo.txt")?;
+ /// f.write_all(b"Hello, world!")?;
///
- /// f.sync_data()?;
- /// # Ok(())
- /// # }
+ /// f.sync_data()?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_data(&self) -> io::Result<()> {
@@ -444,6 +453,10 @@ impl File {
/// will be extended to `size` and have all of the intermediate data filled
/// in with 0s.
///
+ /// The file's cursor isn't changed. In particular, if the cursor was at the
+ /// end and the file is shrunk using this operation, the cursor will now be
+ /// past the end.
+ ///
/// # Errors
///
/// This function will return an error if the file is not opened for writing.
@@ -453,12 +466,15 @@ impl File {
/// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::create("foo.txt")?;
- /// f.set_len(10)?;
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let mut f = File::create("foo.txt")?;
+ /// f.set_len(10)?;
+ /// Ok(())
+ /// }
/// ```
+ ///
+ /// Note that this method alters the content of the underlying file, even
+ /// though it takes `&self` rather than `&mut self`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn set_len(&self, size: u64) -> io::Result<()> {
self.inner.truncate(size)
@@ -471,33 +487,55 @@ impl File {
/// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let metadata = f.metadata()?;
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let metadata = f.metadata()?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn metadata(&self) -> io::Result<Metadata> {
self.inner.file_attr().map(Metadata)
}
- /// Creates a new independently owned handle to the underlying file.
- ///
- /// The returned `File` is a reference to the same state that this object
- /// references. Both handles will read and write with the same cursor
- /// position.
+ /// Create a new `File` instance that shares the same underlying file handle
+ /// as the existing `File` instance. Reads, writes, and seeks will affect
+ /// both `File` instances simultaneously.
///
/// # Examples
///
+ /// Create two handles for a file named `foo.txt`:
+ ///
/// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let file_copy = f.try_clone()?;
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
+ /// let file_copy = file.try_clone()?;
+ /// Ok(())
+ /// }
+ /// ```
+ ///
+ /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create
+ /// two handles, seek one of them, and read the remaining bytes from the
+ /// other handle:
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// use std::io::SeekFrom;
+ /// use std::io::prelude::*;
+ ///
+ /// fn main() -> std::io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
+ /// let mut file_copy = file.try_clone()?;
+ ///
+ /// file.seek(SeekFrom::Start(3))?;
+ ///
+ /// let mut contents = vec![];
+ /// file_copy.read_to_end(&mut contents)?;
+ /// assert_eq!(contents, b"def\n");
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "file_try_clone", since = "1.9.0")]
pub fn try_clone(&self) -> io::Result<File> {
@@ -524,17 +562,20 @@ impl File {
///
/// # Examples
///
+ /// ```no_run
+ /// fn main() -> std::io::Result<()> {
+ /// use std::fs::File;
+ ///
+ /// let file = File::open("foo.txt")?;
+ /// let mut perms = file.metadata()?.permissions();
+ /// perms.set_readonly(true);
+ /// file.set_permissions(perms)?;
+ /// Ok(())
+ /// }
/// ```
- /// # fn foo() -> std::io::Result<()> {
- /// use std::fs::File;
///
- /// let file = File::open("foo.txt")?;
- /// let mut perms = file.metadata()?.permissions();
- /// perms.set_readonly(true);
- /// file.set_permissions(perms)?;
- /// # Ok(())
- /// # }
- /// ```
+ /// Note that this method alters the permissions of the underlying file,
+ /// even though it takes `&self` rather than `&mut self`.
#[stable(feature = "set_permissions_atomic", since = "1.16.0")]
pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
self.inner.set_permissions(perm.0)
@@ -850,51 +891,63 @@ impl Metadata {
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
- /// use std::fs;
+ /// ```no_run
+ /// fn main() -> std::io::Result<()> {
+ /// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// println!("{:?}", metadata.file_type());
- /// # Ok(())
- /// # }
+ /// println!("{:?}", metadata.file_type());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "file_type", since = "1.1.0")]
pub fn file_type(&self) -> FileType {
FileType(self.0.file_type())
}
- /// Returns whether this metadata is for a directory.
+ /// Returns whether this metadata is for a directory. The
+ /// result is mutually exclusive to the result of
+ /// [`is_file`], and will be false for symlink metadata
+ /// obtained from [`symlink_metadata`].
+ ///
+ /// [`is_file`]: struct.Metadata.html#method.is_file
+ /// [`symlink_metadata`]: fn.symlink_metadata.html
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
- /// use std::fs;
+ /// ```no_run
+ /// fn main() -> std::io::Result<()> {
+ /// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// assert!(!metadata.is_dir());
- /// # Ok(())
- /// # }
+ /// assert!(!metadata.is_dir());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_dir(&self) -> bool { self.file_type().is_dir() }
- /// Returns whether this metadata is for a regular file.
+ /// Returns whether this metadata is for a regular file. The
+ /// result is mutually exclusive to the result of
+ /// [`is_dir`], and will be false for symlink metadata
+ /// obtained from [`symlink_metadata`].
+ ///
+ /// [`is_dir`]: struct.Metadata.html#method.is_dir
+ /// [`symlink_metadata`]: fn.symlink_metadata.html
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// assert!(metadata.is_file());
- /// # Ok(())
- /// # }
+ /// assert!(metadata.is_file());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_file(&self) -> bool { self.file_type().is_file() }
@@ -903,15 +956,15 @@ impl Metadata {
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// assert_eq!(0, metadata.len());
- /// # Ok(())
- /// # }
+ /// assert_eq!(0, metadata.len());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> u64 { self.0.size() }
@@ -920,15 +973,15 @@ impl Metadata {
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// assert!(!metadata.permissions().readonly());
- /// # Ok(())
- /// # }
+ /// assert!(!metadata.permissions().readonly());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn permissions(&self) -> Permissions {
@@ -947,19 +1000,19 @@ impl Metadata {
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// if let Ok(time) = metadata.modified() {
- /// println!("{:?}", time);
- /// } else {
- /// println!("Not supported on this platform");
+ /// if let Ok(time) = metadata.modified() {
+ /// println!("{:?}", time);
+ /// } else {
+ /// println!("Not supported on this platform");
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
#[stable(feature = "fs_time", since = "1.10.0")]
pub fn modified(&self) -> io::Result<SystemTime> {
@@ -982,26 +1035,26 @@ impl Metadata {
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// if let Ok(time) = metadata.accessed() {
- /// println!("{:?}", time);
- /// } else {
- /// println!("Not supported on this platform");
+ /// if let Ok(time) = metadata.accessed() {
+ /// println!("{:?}", time);
+ /// } else {
+ /// println!("Not supported on this platform");
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
#[stable(feature = "fs_time", since = "1.10.0")]
pub fn accessed(&self) -> io::Result<SystemTime> {
self.0.accessed().map(FromInner::from_inner)
}
- /// Returns the creation time listed in the this metadata.
+ /// Returns the creation time listed in this metadata.
///
/// The returned value corresponds to the `birthtime` field of `stat` on
/// Unix platforms and the `ftCreationTime` field on Windows platforms.
@@ -1013,19 +1066,19 @@ impl Metadata {
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::metadata("foo.txt")?;
///
- /// if let Ok(time) = metadata.created() {
- /// println!("{:?}", time);
- /// } else {
- /// println!("Not supported on this platform");
+ /// if let Ok(time) = metadata.created() {
+ /// println!("{:?}", time);
+ /// } else {
+ /// println!("Not supported on this platform");
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
#[stable(feature = "fs_time", since = "1.10.0")]
pub fn created(&self) -> io::Result<SystemTime> {
@@ -1057,16 +1110,16 @@ impl Permissions {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut f = File::create("foo.txt")?;
- /// let metadata = f.metadata()?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut f = File::create("foo.txt")?;
+ /// let metadata = f.metadata()?;
///
- /// assert_eq!(false, metadata.permissions().readonly());
- /// # Ok(())
- /// # }
+ /// assert_eq!(false, metadata.permissions().readonly());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn readonly(&self) -> bool { self.0.readonly() }
@@ -1082,23 +1135,23 @@ impl Permissions {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f = File::create("foo.txt")?;
- /// let metadata = f.metadata()?;
- /// let mut permissions = metadata.permissions();
+ /// fn main() -> std::io::Result<()> {
+ /// let f = File::create("foo.txt")?;
+ /// let metadata = f.metadata()?;
+ /// let mut permissions = metadata.permissions();
///
- /// permissions.set_readonly(true);
+ /// permissions.set_readonly(true);
///
- /// // filesystem doesn't change
- /// assert_eq!(false, metadata.permissions().readonly());
+ /// // filesystem doesn't change
+ /// assert_eq!(false, metadata.permissions().readonly());
///
- /// // just this particular `permissions`.
- /// assert_eq!(true, permissions.readonly());
- /// # Ok(())
- /// # }
+ /// // just this particular `permissions`.
+ /// assert_eq!(true, permissions.readonly());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn set_readonly(&mut self, readonly: bool) {
@@ -1107,43 +1160,58 @@ impl Permissions {
}
impl FileType {
- /// Test whether this file type represents a directory.
+ /// Test whether this file type represents a directory. The
+ /// result is mutually exclusive to the results of
+ /// [`is_file`] and [`is_symlink`]; only zero or one of these
+ /// tests may pass.
+ ///
+ /// [`is_file`]: struct.FileType.html#method.is_file
+ /// [`is_symlink`]: struct.FileType.html#method.is_symlink
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
- /// use std::fs;
+ /// ```no_run
+ /// fn main() -> std::io::Result<()> {
+ /// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
- /// let file_type = metadata.file_type();
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let file_type = metadata.file_type();
///
- /// assert_eq!(file_type.is_dir(), false);
- /// # Ok(())
- /// # }
+ /// assert_eq!(file_type.is_dir(), false);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "file_type", since = "1.1.0")]
pub fn is_dir(&self) -> bool { self.0.is_dir() }
/// Test whether this file type represents a regular file.
+ /// The result is mutually exclusive to the results of
+ /// [`is_dir`] and [`is_symlink`]; only zero or one of these
+ /// tests may pass.
+ ///
+ /// [`is_dir`]: struct.FileType.html#method.is_dir
+ /// [`is_symlink`]: struct.FileType.html#method.is_symlink
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
- /// use std::fs;
+ /// ```no_run
+ /// fn main() -> std::io::Result<()> {
+ /// use std::fs;
///
- /// let metadata = fs::metadata("foo.txt")?;
- /// let file_type = metadata.file_type();
+ /// let metadata = fs::metadata("foo.txt")?;
+ /// let file_type = metadata.file_type();
///
- /// assert_eq!(file_type.is_file(), true);
- /// # Ok(())
- /// # }
+ /// assert_eq!(file_type.is_file(), true);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "file_type", since = "1.1.0")]
pub fn is_file(&self) -> bool { self.0.is_file() }
/// Test whether this file type represents a symbolic link.
+ /// The result is mutually exclusive to the results of
+ /// [`is_dir`] and [`is_file`]; only zero or one of these
+ /// tests may pass.
///
/// The underlying [`Metadata`] struct needs to be retrieved
/// with the [`fs::symlink_metadata`] function and not the
@@ -1154,20 +1222,22 @@ impl FileType {
/// [`Metadata`]: struct.Metadata.html
/// [`fs::metadata`]: fn.metadata.html
/// [`fs::symlink_metadata`]: fn.symlink_metadata.html
+ /// [`is_dir`]: struct.FileType.html#method.is_dir
+ /// [`is_file`]: struct.FileType.html#method.is_file
/// [`is_symlink`]: struct.FileType.html#method.is_symlink
///
/// # Examples
///
- /// ```
- /// # fn foo() -> std::io::Result<()> {
+ /// ```no_run
/// use std::fs;
///
- /// let metadata = fs::symlink_metadata("foo.txt")?;
- /// let file_type = metadata.file_type();
+ /// fn main() -> std::io::Result<()> {
+ /// let metadata = fs::symlink_metadata("foo.txt")?;
+ /// let file_type = metadata.file_type();
///
- /// assert_eq!(file_type.is_symlink(), false);
- /// # Ok(())
- /// # }
+ /// assert_eq!(file_type.is_symlink(), false);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "file_type", since = "1.1.0")]
pub fn is_symlink(&self) -> bool { self.0.is_symlink() }
@@ -1204,15 +1274,16 @@ impl DirEntry {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs;
- /// # fn foo() -> std::io::Result<()> {
- /// for entry in fs::read_dir(".")? {
- /// let dir = entry?;
- /// println!("{:?}", dir.path());
+ ///
+ /// fn main() -> std::io::Result<()> {
+ /// for entry in fs::read_dir(".")? {
+ /// let dir = entry?;
+ /// println!("{:?}", dir.path());
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
///
/// This prints output like:
@@ -1357,13 +1428,13 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::remove_file("a.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::remove_file("a.txt")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1394,14 +1465,14 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// # Examples
///
-/// ```rust
-/// # fn foo() -> std::io::Result<()> {
+/// ```rust,no_run
/// use std::fs;
///
-/// let attr = fs::metadata("/some/file/path.txt")?;
-/// // inspect attr ...
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let attr = fs::metadata("/some/file/path.txt")?;
+/// // inspect attr ...
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
@@ -1428,14 +1499,14 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
///
/// # Examples
///
-/// ```rust
-/// # fn foo() -> std::io::Result<()> {
+/// ```rust,no_run
/// use std::fs;
///
-/// let attr = fs::symlink_metadata("/some/file/path.txt")?;
-/// // inspect attr ...
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let attr = fs::symlink_metadata("/some/file/path.txt")?;
+/// // inspect attr ...
+/// Ok(())
+/// }
/// ```
#[stable(feature = "symlink_metadata", since = "1.1.0")]
pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
@@ -1472,13 +1543,13 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
@@ -1523,9 +1594,10 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt
-/// # Ok(()) }
+/// fn main() -> std::io::Result<()> {
+/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
@@ -1554,13 +1626,13 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
@@ -1577,13 +1649,13 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::soft_link("a.txt", "b.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::soft_link("a.txt", "b.txt")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.1.0",
@@ -1614,13 +1686,13 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let path = fs::read_link("a.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let path = fs::read_link("a.txt")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
@@ -1648,13 +1720,13 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let path = fs::canonicalize("../a/../foo.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let path = fs::canonicalize("../a/../foo.txt")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "fs_canonicalize", since = "1.5.0")]
pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
@@ -1681,13 +1753,13 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::create_dir("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::create_dir("/some/dir")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1723,13 +1795,13 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::create_dir_all("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::create_dir_all("/some/dir")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1756,13 +1828,13 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::remove_dir("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::remove_dir("/some/dir")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1790,13 +1862,13 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::fs;
///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::remove_dir_all("/some/dir")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// fs::remove_dir_all("/some/dir")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
@@ -1876,15 +1948,15 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
///
/// # Examples
///
-/// ```
-/// # fn foo() -> std::io::Result<()> {
+/// ```no_run
/// use std::fs;
///
-/// let mut perms = fs::metadata("foo.txt")?.permissions();
-/// perms.set_readonly(true);
-/// fs::set_permissions("foo.txt", perms)?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+/// let mut perms = fs::metadata("foo.txt")?.permissions();
+/// perms.set_readonly(true);
+/// fs::set_permissions("foo.txt", perms)?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "set_permissions", since = "1.1.0")]
pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions)
@@ -3054,12 +3126,12 @@ mod tests {
assert!(v == &bytes[..]);
check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF]));
- error_contains!(fs::read_string(&tmpdir.join("not-utf8")),
+ error_contains!(fs::read_to_string(&tmpdir.join("not-utf8")),
"stream did not contain valid UTF-8");
let s = "𐁁𐀓𐀠𐀴𐀍";
check!(fs::write(&tmpdir.join("utf8"), s.as_bytes()));
- let string = check!(fs::read_string(&tmpdir.join("utf8")));
+ let string = check!(fs::read_to_string(&tmpdir.join("utf8")));
assert_eq!(string, s);
}
diff --git a/ctr-std/src/heap.rs b/ctr-std/src/heap.rs
deleted file mode 100644
index 4d5e4df..0000000
--- a/ctr-std/src/heap.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! dox
-
-#![unstable(issue = "32838", feature = "allocator_api")]
-
-pub use alloc::heap::{Heap, Alloc, Layout, Excess, CannotReallocInPlace, AllocErr};
-pub use alloc_system::System;
-
-#[cfg(not(test))]
-#[doc(hidden)]
-#[allow(unused_attributes)]
-pub mod __default_lib_allocator {
- use super::{System, Layout, Alloc, AllocErr};
- use ptr;
-
- // for symbol names src/librustc/middle/allocator.rs
- // for signatures src/librustc_allocator/lib.rs
-
- // linkage directives are provided as part of the current compiler allocator
- // ABI
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_alloc(size: usize,
- align: usize,
- err: *mut u8) -> *mut u8 {
- let layout = Layout::from_size_align_unchecked(size, align);
- match System.alloc(layout) {
- Ok(p) => p,
- Err(e) => {
- ptr::write(err as *mut AllocErr, e);
- 0 as *mut u8
- }
- }
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
- System.oom((*(err as *const AllocErr)).clone())
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
- size: usize,
- align: usize) {
- System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_usable_size(layout: *const u8,
- min: *mut usize,
- max: *mut usize) {
- let pair = System.usable_size(&*(layout as *const Layout));
- *min = pair.0;
- *max = pair.1;
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
- old_size: usize,
- old_align: usize,
- new_size: usize,
- new_align: usize,
- err: *mut u8) -> *mut u8 {
- let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
- let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
- match System.realloc(ptr, old_layout, new_layout) {
- Ok(p) => p,
- Err(e) => {
- ptr::write(err as *mut AllocErr, e);
- 0 as *mut u8
- }
- }
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
- align: usize,
- err: *mut u8) -> *mut u8 {
- let layout = Layout::from_size_align_unchecked(size, align);
- match System.alloc_zeroed(layout) {
- Ok(p) => p,
- Err(e) => {
- ptr::write(err as *mut AllocErr, e);
- 0 as *mut u8
- }
- }
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_alloc_excess(size: usize,
- align: usize,
- excess: *mut usize,
- err: *mut u8) -> *mut u8 {
- let layout = Layout::from_size_align_unchecked(size, align);
- match System.alloc_excess(layout) {
- Ok(p) => {
- *excess = p.1;
- p.0
- }
- Err(e) => {
- ptr::write(err as *mut AllocErr, e);
- 0 as *mut u8
- }
- }
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
- old_size: usize,
- old_align: usize,
- new_size: usize,
- new_align: usize,
- excess: *mut usize,
- err: *mut u8) -> *mut u8 {
- let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
- let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
- match System.realloc_excess(ptr, old_layout, new_layout) {
- Ok(p) => {
- *excess = p.1;
- p.0
- }
- Err(e) => {
- ptr::write(err as *mut AllocErr, e);
- 0 as *mut u8
- }
- }
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
- old_size: usize,
- old_align: usize,
- new_size: usize,
- new_align: usize) -> u8 {
- let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
- let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
- match System.grow_in_place(ptr, old_layout, new_layout) {
- Ok(()) => 1,
- Err(_) => 0,
- }
- }
-
- #[no_mangle]
- #[rustc_std_internal_symbol]
- pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
- old_size: usize,
- old_align: usize,
- new_size: usize,
- new_align: usize) -> u8 {
- let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
- let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
- match System.shrink_in_place(ptr, old_layout, new_layout) {
- Ok(()) => 1,
- Err(_) => 0,
- }
- }
-}
diff --git a/ctr-std/src/io/buffered.rs b/ctr-std/src/io/buffered.rs
index 4e7db5f..d6eac74 100644
--- a/ctr-std/src/io/buffered.rs
+++ b/ctr-std/src/io/buffered.rs
@@ -25,26 +25,32 @@ use memchr;
/// results in a system call. A `BufReader` performs large, infrequent reads on
/// the underlying [`Read`] and maintains an in-memory buffer of the results.
///
+/// `BufReader` can improve the speed of programs that make *small* and
+/// *repeated* read calls to the same file or network socket. It does not
+/// help when reading very large amounts at once, or reading just one or a few
+/// times. It also provides no advantage when reading from a source that is
+/// already in memory, like a `Vec<u8>`.
+///
/// [`Read`]: ../../std/io/trait.Read.html
/// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::io::prelude::*;
/// use std::io::BufReader;
/// use std::fs::File;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let f = File::open("log.txt")?;
-/// let mut reader = BufReader::new(f);
+/// fn main() -> std::io::Result<()> {
+/// let f = File::open("log.txt")?;
+/// let mut reader = BufReader::new(f);
///
-/// let mut line = String::new();
-/// let len = reader.read_line(&mut line)?;
-/// println!("First line is {} bytes long", len);
-/// # Ok(())
-/// # }
+/// let mut line = String::new();
+/// let len = reader.read_line(&mut line)?;
+/// println!("First line is {} bytes long", len);
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufReader<R> {
@@ -59,15 +65,15 @@ impl<R: Read> BufReader<R> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f = File::open("log.txt")?;
- /// let reader = BufReader::new(f);
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let f = File::open("log.txt")?;
+ /// let reader = BufReader::new(f);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> {
@@ -80,15 +86,15 @@ impl<R: Read> BufReader<R> {
///
/// Creating a buffer with ten bytes of capacity:
///
- /// ```
+ /// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f = File::open("log.txt")?;
- /// let reader = BufReader::with_capacity(10, f);
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let f = File::open("log.txt")?;
+ /// let reader = BufReader::with_capacity(10, f);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
@@ -111,17 +117,17 @@ impl<R: Read> BufReader<R> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f1 = File::open("log.txt")?;
- /// let reader = BufReader::new(f1);
+ /// fn main() -> std::io::Result<()> {
+ /// let f1 = File::open("log.txt")?;
+ /// let reader = BufReader::new(f1);
///
- /// let f2 = reader.get_ref();
- /// # Ok(())
- /// # }
+ /// let f2 = reader.get_ref();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &R { &self.inner }
@@ -132,17 +138,17 @@ impl<R: Read> BufReader<R> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f1 = File::open("log.txt")?;
- /// let mut reader = BufReader::new(f1);
+ /// fn main() -> std::io::Result<()> {
+ /// let f1 = File::open("log.txt")?;
+ /// let mut reader = BufReader::new(f1);
///
- /// let f2 = reader.get_mut();
- /// # Ok(())
- /// # }
+ /// let f2 = reader.get_mut();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
@@ -150,26 +156,55 @@ impl<R: Read> BufReader<R> {
/// Returns `true` if there are no bytes in the internal buffer.
///
/// # Examples
- /// ```
+ //
+ /// ```no_run
/// # #![feature(bufreader_is_empty)]
/// use std::io::BufReader;
/// use std::io::BufRead;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f1 = File::open("log.txt")?;
- /// let mut reader = BufReader::new(f1);
- /// assert!(reader.is_empty());
+ /// fn main() -> std::io::Result<()> {
+ /// let f1 = File::open("log.txt")?;
+ /// let mut reader = BufReader::new(f1);
+ /// assert!(reader.is_empty());
///
- /// if reader.fill_buf()?.len() > 0 {
- /// assert!(!reader.is_empty());
+ /// if reader.fill_buf()?.len() > 0 {
+ /// assert!(!reader.is_empty());
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
#[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+ #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
pub fn is_empty(&self) -> bool {
- self.pos == self.cap
+ self.buffer().is_empty()
+ }
+
+ /// Returns a reference to the internally buffered data.
+ ///
+ /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// # #![feature(bufreader_buffer)]
+ /// use std::io::{BufReader, BufRead};
+ /// use std::fs::File;
+ ///
+ /// fn main() -> std::io::Result<()> {
+ /// let f = File::open("log.txt")?;
+ /// let mut reader = BufReader::new(f);
+ /// assert!(reader.buffer().is_empty());
+ ///
+ /// if reader.fill_buf()?.len() > 0 {
+ /// assert!(!reader.buffer().is_empty());
+ /// }
+ /// Ok(())
+ /// }
+ /// ```
+ #[unstable(feature = "bufreader_buffer", issue = "45323")]
+ pub fn buffer(&self) -> &[u8] {
+ &self.buf[self.pos..self.cap]
}
/// Unwraps this `BufReader`, returning the underlying reader.
@@ -178,17 +213,17 @@ impl<R: Read> BufReader<R> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let f1 = File::open("log.txt")?;
- /// let reader = BufReader::new(f1);
+ /// fn main() -> std::io::Result<()> {
+ /// let f1 = File::open("log.txt")?;
+ /// let reader = BufReader::new(f1);
///
- /// let f2 = reader.into_inner();
- /// # Ok(())
- /// # }
+ /// let f2 = reader.into_inner();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> R { self.inner }
@@ -293,7 +328,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// where `n` minus the internal buffer length overflows an `i64`, two
/// seeks will be performed instead of one. If the second seek returns
/// `Err`, the underlying reader will be left at the same position it would
- /// have if you seeked to `SeekFrom::Current(0)`.
+ /// have if you called `seek` with `SeekFrom::Current(0)`.
///
/// [`seek_relative`]: #method.seek_relative
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
@@ -330,6 +365,12 @@ impl<R: Seek> Seek for BufReader<R> {
/// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying
/// writer in large, infrequent batches.
///
+/// `BufWriter` can improve the speed of programs that make *small* and
+/// *repeated* write calls to the same file or network socket. It does not
+/// help when writing very large amounts at once, or writing just one or a few
+/// times. It also provides no advantage when writing to a destination that is
+/// in memory, like a `Vec<u8>`.
+///
/// When the `BufWriter` is dropped, the contents of its buffer will be written
/// out. However, any errors that happen in the process of flushing the buffer
/// when the writer is dropped will be ignored. Code that wishes to handle such
@@ -696,34 +737,34 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// We can use `LineWriter` to write one line at a time, significantly
/// reducing the number of actual writes to the file.
///
-/// ```
+/// ```no_run
/// use std::fs::File;
/// use std::io::prelude::*;
/// use std::io::LineWriter;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let road_not_taken = b"I shall be telling this with a sigh
+/// fn main() -> std::io::Result<()> {
+/// let road_not_taken = b"I shall be telling this with a sigh
/// Somewhere ages and ages hence:
/// Two roads diverged in a wood, and I -
/// I took the one less traveled by,
/// And that has made all the difference.";
///
-/// let file = File::create("poem.txt")?;
-/// let mut file = LineWriter::new(file);
+/// let file = File::create("poem.txt")?;
+/// let mut file = LineWriter::new(file);
///
-/// for &byte in road_not_taken.iter() {
-/// file.write(&[byte]).unwrap();
-/// }
+/// for &byte in road_not_taken.iter() {
+/// file.write(&[byte]).unwrap();
+/// }
///
-/// // let's check we did the right thing.
-/// let mut file = File::open("poem.txt")?;
-/// let mut contents = String::new();
+/// // let's check we did the right thing.
+/// let mut file = File::open("poem.txt")?;
+/// let mut contents = String::new();
///
-/// file.read_to_string(&mut contents)?;
+/// file.read_to_string(&mut contents)?;
///
-/// assert_eq!(contents.as_bytes(), &road_not_taken[..]);
-/// # Ok(())
-/// # }
+/// assert_eq!(contents.as_bytes(), &road_not_taken[..]);
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LineWriter<W: Write> {
@@ -736,15 +777,15 @@ impl<W: Write> LineWriter<W> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let file = File::create("poem.txt")?;
- /// let file = LineWriter::new(file);
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let file = File::create("poem.txt")?;
+ /// let file = LineWriter::new(file);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> LineWriter<W> {
@@ -757,15 +798,15 @@ impl<W: Write> LineWriter<W> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let file = File::create("poem.txt")?;
- /// let file = LineWriter::with_capacity(100, file);
- /// # Ok(())
- /// # }
+ /// fn main() -> std::io::Result<()> {
+ /// let file = File::create("poem.txt")?;
+ /// let file = LineWriter::with_capacity(100, file);
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
@@ -779,17 +820,17 @@ impl<W: Write> LineWriter<W> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let file = File::create("poem.txt")?;
- /// let file = LineWriter::new(file);
+ /// fn main() -> std::io::Result<()> {
+ /// let file = File::create("poem.txt")?;
+ /// let file = LineWriter::new(file);
///
- /// let reference = file.get_ref();
- /// # Ok(())
- /// # }
+ /// let reference = file.get_ref();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.get_ref() }
@@ -801,18 +842,18 @@ impl<W: Write> LineWriter<W> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let file = File::create("poem.txt")?;
- /// let mut file = LineWriter::new(file);
+ /// fn main() -> std::io::Result<()> {
+ /// let file = File::create("poem.txt")?;
+ /// let mut file = LineWriter::new(file);
///
- /// // we can use reference just like file
- /// let reference = file.get_mut();
- /// # Ok(())
- /// # }
+ /// // we can use reference just like file
+ /// let reference = file.get_mut();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() }
@@ -827,18 +868,18 @@ impl<W: Write> LineWriter<W> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let file = File::create("poem.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let file = File::create("poem.txt")?;
///
- /// let writer: LineWriter<File> = LineWriter::new(file);
+ /// let writer: LineWriter<File> = LineWriter::new(file);
///
- /// let file: File = writer.into_inner()?;
- /// # Ok(())
- /// # }
+ /// let file: File = writer.into_inner()?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
diff --git a/ctr-std/src/io/cursor.rs b/ctr-std/src/io/cursor.rs
index 76bcb5f..2673f3c 100644
--- a/ctr-std/src/io/cursor.rs
+++ b/ctr-std/src/io/cursor.rs
@@ -10,7 +10,6 @@
use io::prelude::*;
-use core::convert::TryInto;
use cmp;
use io::{self, Initializer, SeekFrom, Error, ErrorKind};
@@ -260,9 +259,26 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<us
Ok(amt)
}
+/// Compensate removal of some impls per
+/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243
+#[cfg(any(target_pointer_width = "16",
+ target_pointer_width = "32"))]
+fn try_into(n: u64) -> Result<usize, ()> {
+ if n <= (<usize>::max_value() as u64) {
+ Ok(n as usize)
+ } else {
+ Err(())
+ }
+}
+
+#[cfg(any(target_pointer_width = "64"))]
+fn try_into(n: u64) -> Result<usize, ()> {
+ Ok(n as usize)
+}
+
// Resizing write implementation
fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
- let pos: usize = (*pos_mut).try_into().map_err(|_| {
+ let pos: usize = try_into(*pos_mut).map_err(|_| {
Error::new(ErrorKind::InvalidInput,
"cursor position exceeds maximum possible vector length")
})?;
diff --git a/ctr-std/src/io/error.rs b/ctr-std/src/io/error.rs
index f0b41f3..bdd675e 100644
--- a/ctr-std/src/io/error.rs
+++ b/ctr-std/src/io/error.rs
@@ -292,8 +292,8 @@ impl Error {
/// # if cfg!(target_os = "linux") {
/// use std::io;
///
- /// let error = io::Error::from_raw_os_error(98);
- /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
+ /// let error = io::Error::from_raw_os_error(22);
+ /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
/// # }
/// ```
///
@@ -303,8 +303,8 @@ impl Error {
/// # if cfg!(windows) {
/// use std::io;
///
- /// let error = io::Error::from_raw_os_error(10048);
- /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
+ /// let error = io::Error::from_raw_os_error(10022);
+ /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/ctr-std/src/io/mod.rs b/ctr-std/src/io/mod.rs
index 33d11eb..b02e133 100644
--- a/ctr-std/src/io/mod.rs
+++ b/ctr-std/src/io/mod.rs
@@ -24,21 +24,21 @@
//! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on
//! [`File`]s:
//!
-//! ```
+//! ```no_run
//! use std::io;
//! use std::io::prelude::*;
//! use std::fs::File;
//!
-//! # fn foo() -> io::Result<()> {
-//! let mut f = File::open("foo.txt")?;
-//! let mut buffer = [0; 10];
+//! fn main() -> io::Result<()> {
+//! let mut f = File::open("foo.txt")?;
+//! let mut buffer = [0; 10];
//!
-//! // read up to 10 bytes
-//! f.read(&mut buffer)?;
+//! // read up to 10 bytes
+//! f.read(&mut buffer)?;
//!
-//! println!("The bytes: {:?}", buffer);
-//! # Ok(())
-//! # }
+//! println!("The bytes: {:?}", buffer);
+//! Ok(())
+//! }
//! ```
//!
//! [`Read`] and [`Write`] are so important, implementors of the two traits have a
@@ -52,25 +52,25 @@
//! how the reading happens. [`Seek`] lets you control where the next byte is
//! coming from:
//!
-//! ```
+//! ```no_run
//! use std::io;
//! use std::io::prelude::*;
//! use std::io::SeekFrom;
//! use std::fs::File;
//!
-//! # fn foo() -> io::Result<()> {
-//! let mut f = File::open("foo.txt")?;
-//! let mut buffer = [0; 10];
+//! fn main() -> io::Result<()> {
+//! let mut f = File::open("foo.txt")?;
+//! let mut buffer = [0; 10];
//!
-//! // skip to the last 10 bytes of the file
-//! f.seek(SeekFrom::End(-10))?;
+//! // skip to the last 10 bytes of the file
+//! f.seek(SeekFrom::End(-10))?;
//!
-//! // read up to 10 bytes
-//! f.read(&mut buffer)?;
+//! // read up to 10 bytes
+//! f.read(&mut buffer)?;
//!
-//! println!("The bytes: {:?}", buffer);
-//! # Ok(())
-//! # }
+//! println!("The bytes: {:?}", buffer);
+//! Ok(())
+//! }
//! ```
//!
//! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but
@@ -87,70 +87,70 @@
//! For example, [`BufReader`] works with the [`BufRead`] trait to add extra
//! methods to any reader:
//!
-//! ```
+//! ```no_run
//! use std::io;
//! use std::io::prelude::*;
//! use std::io::BufReader;
//! use std::fs::File;
//!
-//! # fn foo() -> io::Result<()> {
-//! let f = File::open("foo.txt")?;
-//! let mut reader = BufReader::new(f);
-//! let mut buffer = String::new();
+//! fn main() -> io::Result<()> {
+//! let f = File::open("foo.txt")?;
+//! let mut reader = BufReader::new(f);
+//! let mut buffer = String::new();
//!
-//! // read a line into buffer
-//! reader.read_line(&mut buffer)?;
+//! // read a line into buffer
+//! reader.read_line(&mut buffer)?;
//!
-//! println!("{}", buffer);
-//! # Ok(())
-//! # }
+//! println!("{}", buffer);
+//! Ok(())
+//! }
//! ```
//!
//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
//! to [`write`][`Write::write`]:
//!
-//! ```
+//! ```no_run
//! use std::io;
//! use std::io::prelude::*;
//! use std::io::BufWriter;
//! use std::fs::File;
//!
-//! # fn foo() -> io::Result<()> {
-//! let f = File::create("foo.txt")?;
-//! {
-//! let mut writer = BufWriter::new(f);
+//! fn main() -> io::Result<()> {
+//! let f = File::create("foo.txt")?;
+//! {
+//! let mut writer = BufWriter::new(f);
//!
-//! // write a byte to the buffer
-//! writer.write(&[42])?;
+//! // write a byte to the buffer
+//! writer.write(&[42])?;
//!
-//! } // the buffer is flushed once writer goes out of scope
+//! } // the buffer is flushed once writer goes out of scope
//!
-//! # Ok(())
-//! # }
+//! Ok(())
+//! }
//! ```
//!
//! ## Standard input and output
//!
//! A very common source of input is standard input:
//!
-//! ```
+//! ```no_run
//! use std::io;
//!
-//! # fn foo() -> io::Result<()> {
-//! let mut input = String::new();
+//! fn main() -> io::Result<()> {
+//! let mut input = String::new();
//!
-//! io::stdin().read_line(&mut input)?;
+//! io::stdin().read_line(&mut input)?;
//!
-//! println!("You typed: {}", input.trim());
-//! # Ok(())
-//! # }
+//! println!("You typed: {}", input.trim());
+//! Ok(())
+//! }
//! ```
//!
//! Note that you cannot use the [`?` operator] in functions that do not return
//! a [`Result<T, E>`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`]
//! or `match` on the return value to catch any possible errors:
//!
-//! ```
+//! ```no_run
//! use std::io;
//!
//! let mut input = String::new();
@@ -160,14 +160,14 @@
//!
//! And a very common source of output is standard output:
//!
-//! ```
+//! ```no_run
//! use std::io;
//! use std::io::prelude::*;
//!
-//! # fn foo() -> io::Result<()> {
-//! io::stdout().write(&[42])?;
-//! # Ok(())
-//! # }
+//! fn main() -> io::Result<()> {
+//! io::stdout().write(&[42])?;
+//! Ok(())
+//! }
//! ```
//!
//! Of course, using [`io::stdout`] directly is less common than something like
@@ -179,22 +179,21 @@
//! ways of iterating over I/O. For example, [`Lines`] is used to split over
//! lines:
//!
-//! ```
+//! ```no_run
//! use std::io;
//! use std::io::prelude::*;
//! use std::io::BufReader;
//! use std::fs::File;
//!
-//! # fn foo() -> io::Result<()> {
-//! let f = File::open("foo.txt")?;
-//! let reader = BufReader::new(f);
+//! fn main() -> io::Result<()> {
+//! let f = File::open("foo.txt")?;
+//! let reader = BufReader::new(f);
//!
-//! for line in reader.lines() {
-//! println!("{}", line?);
+//! for line in reader.lines() {
+//! println!("{}", line?);
+//! }
+//! Ok(())
//! }
-//!
-//! # Ok(())
-//! # }
//! ```
//!
//! ## Functions
@@ -203,13 +202,13 @@
//! features. For example, we can use three of these functions to copy everything
//! from standard input to standard output:
//!
-//! ```
+//! ```no_run
//! use std::io;
//!
-//! # fn foo() -> io::Result<()> {
-//! io::copy(&mut io::stdin(), &mut io::stdout())?;
-//! # Ok(())
-//! # }
+//! fn main() -> io::Result<()> {
+//! io::copy(&mut io::stdin(), &mut io::stdout())?;
+//! Ok(())
+//! }
//! ```
//!
//! [functions-list]: #functions-1
@@ -416,47 +415,47 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
///
/// [`File`]s implement `Read`:
///
-/// ```
-/// # use std::io;
+/// ```no_run
+/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
-/// # fn foo() -> io::Result<()> {
-/// let mut f = File::open("foo.txt")?;
-/// let mut buffer = [0; 10];
+/// fn main() -> io::Result<()> {
+/// let mut f = File::open("foo.txt")?;
+/// let mut buffer = [0; 10];
///
-/// // read up to 10 bytes
-/// f.read(&mut buffer)?;
+/// // read up to 10 bytes
+/// f.read(&mut buffer)?;
///
-/// let mut buffer = vec![0; 10];
-/// // read the whole file
-/// f.read_to_end(&mut buffer)?;
+/// let mut buffer = vec![0; 10];
+/// // read the whole file
+/// f.read_to_end(&mut buffer)?;
///
-/// // read into a String, so that you don't need to do the conversion.
-/// let mut buffer = String::new();
-/// f.read_to_string(&mut buffer)?;
+/// // read into a String, so that you don't need to do the conversion.
+/// let mut buffer = String::new();
+/// f.read_to_string(&mut buffer)?;
///
-/// // and more! See the other methods for more details.
-/// # Ok(())
-/// # }
+/// // and more! See the other methods for more details.
+/// Ok(())
+/// }
/// ```
///
/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`:
///
-/// ```
+/// ```no_run
/// # use std::io;
/// use std::io::prelude::*;
///
-/// # fn foo() -> io::Result<()> {
-/// let mut b = "This string will be read".as_bytes();
-/// let mut buffer = [0; 10];
+/// fn main() -> io::Result<()> {
+/// let mut b = "This string will be read".as_bytes();
+/// let mut buffer = [0; 10];
///
-/// // read up to 10 bytes
-/// b.read(&mut buffer)?;
+/// // read up to 10 bytes
+/// b.read(&mut buffer)?;
///
-/// // etc... it works exactly as a File does!
-/// # Ok(())
-/// # }
+/// // etc... it works exactly as a File does!
+/// Ok(())
+/// }
/// ```
///
/// [`read()`]: trait.Read.html#tymethod.read
@@ -509,19 +508,19 @@ pub trait Read {
/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
/// [`File`]: ../fs/struct.File.html
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let mut buffer = [0; 10];
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let mut buffer = [0; 10];
///
- /// // read up to 10 bytes
- /// f.read(&mut buffer[..])?;
- /// # Ok(())
- /// # }
+ /// // read up to 10 bytes
+ /// f.read(&mut buffer[..])?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
@@ -582,20 +581,25 @@ pub trait Read {
/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
/// [`File`]: ../fs/struct.File.html
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let mut buffer = Vec::new();
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let mut buffer = Vec::new();
///
- /// // read the whole file
- /// f.read_to_end(&mut buffer)?;
- /// # Ok(())
- /// # }
+ /// // read the whole file
+ /// f.read_to_end(&mut buffer)?;
+ /// Ok(())
+ /// }
/// ```
+ ///
+ /// (See also the [`std::fs::read`] convenience function for reading from a
+ /// file.)
+ ///
+ /// [`std::fs::read`]: ../fs/fn.read.html
#[stable(feature = "rust1", since = "1.0.0")]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
read_to_end(self, buf)
@@ -621,19 +625,24 @@ pub trait Read {
///
/// [file]: ../fs/struct.File.html
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let mut buffer = String::new();
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let mut buffer = String::new();
///
- /// f.read_to_string(&mut buffer)?;
- /// # Ok(())
- /// # }
+ /// f.read_to_string(&mut buffer)?;
+ /// Ok(())
+ /// }
/// ```
+ ///
+ /// (See also the [`std::fs::read_to_string`] convenience function for
+ /// reading from a file.)
+ ///
+ /// [`std::fs::read_to_string`]: ../fs/fn.read_to_string.html
#[stable(feature = "rust1", since = "1.0.0")]
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
// Note that we do *not* call `.read_to_end()` here. We are passing
@@ -683,19 +692,19 @@ pub trait Read {
/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
/// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let mut buffer = [0; 10];
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let mut buffer = [0; 10];
///
- /// // read exactly 10 bytes
- /// f.read_exact(&mut buffer)?;
- /// # Ok(())
- /// # }
+ /// // read exactly 10 bytes
+ /// f.read_exact(&mut buffer)?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "read_exact", since = "1.6.0")]
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
@@ -726,28 +735,28 @@ pub trait Read {
///
/// [file]: ../fs/struct.File.html
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::Read;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let mut buffer = Vec::new();
- /// let mut other_buffer = Vec::new();
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let mut buffer = Vec::new();
+ /// let mut other_buffer = Vec::new();
///
- /// {
- /// let reference = f.by_ref();
+ /// {
+ /// let reference = f.by_ref();
///
- /// // read at most 5 bytes
- /// reference.take(5).read_to_end(&mut buffer)?;
+ /// // read at most 5 bytes
+ /// reference.take(5).read_to_end(&mut buffer)?;
///
- /// } // drop our &mut reference so we can use f again
+ /// } // drop our &mut reference so we can use f again
///
- /// // original file still usable, read the rest
- /// f.read_to_end(&mut other_buffer)?;
- /// # Ok(())
- /// # }
+ /// // original file still usable, read the rest
+ /// f.read_to_end(&mut other_buffer)?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
@@ -772,19 +781,19 @@ pub trait Read {
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
///
- /// for byte in f.bytes() {
- /// println!("{}", byte.unwrap());
+ /// for byte in f.bytes() {
+ /// println!("{}", byte.unwrap());
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn bytes(self) -> Bytes<Self> where Self: Sized {
@@ -812,20 +821,20 @@ pub trait Read {
/// [`char`]: ../../std/primitive.char.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///
- /// ```
+ /// ```no_run
/// #![feature(io)]
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
///
- /// for c in f.chars() {
- /// println!("{}", c.unwrap());
+ /// for c in f.chars() {
+ /// println!("{}", c.unwrap());
+ /// }
+ /// Ok(())
/// }
- /// # Ok(())
- /// # }
/// ```
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
of where errors happen is currently \
@@ -847,23 +856,23 @@ pub trait Read {
///
/// [file]: ../fs/struct.File.html
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f1 = File::open("foo.txt")?;
- /// let mut f2 = File::open("bar.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut f1 = File::open("foo.txt")?;
+ /// let mut f2 = File::open("bar.txt")?;
///
- /// let mut handle = f1.chain(f2);
- /// let mut buffer = String::new();
+ /// let mut handle = f1.chain(f2);
+ /// let mut buffer = String::new();
///
- /// // read the value into a String. We could use any Read method here,
- /// // this is just one example.
- /// handle.read_to_string(&mut buffer)?;
- /// # Ok(())
- /// # }
+ /// // read the value into a String. We could use any Read method here,
+ /// // this is just one example.
+ /// handle.read_to_string(&mut buffer)?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
@@ -885,21 +894,21 @@ pub trait Read {
/// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
/// [`read()`]: trait.Read.html#tymethod.read
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut f = File::open("foo.txt")?;
- /// let mut buffer = [0; 5];
+ /// fn main() -> io::Result<()> {
+ /// let mut f = File::open("foo.txt")?;
+ /// let mut buffer = [0; 5];
///
- /// // read at most five bytes
- /// let mut handle = f.take(5);
+ /// // read at most five bytes
+ /// let mut handle = f.take(5);
///
- /// handle.read(&mut buffer)?;
- /// # Ok(())
- /// # }
+ /// handle.read(&mut buffer)?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn take(self, limit: u64) -> Take<Self> where Self: Sized {
@@ -974,16 +983,16 @@ impl Initializer {
///
/// # Examples
///
-/// ```
+/// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut buffer = File::create("foo.txt")?;
+/// fn main() -> std::io::Result<()> {
+/// let mut buffer = File::create("foo.txt")?;
///
-/// buffer.write(b"some bytes")?;
-/// # Ok(())
-/// # }
+/// buffer.write(b"some bytes")?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(spotlight)]
@@ -1022,17 +1031,17 @@ pub trait Write {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut buffer = File::create("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut buffer = File::create("foo.txt")?;
///
- /// // Writes some prefix of the byte string, not necessarily all of it.
- /// buffer.write(b"some bytes")?;
- /// # Ok(())
- /// # }
+ /// // Writes some prefix of the byte string, not necessarily all of it.
+ /// buffer.write(b"some bytes")?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, buf: &[u8]) -> Result<usize>;
@@ -1047,18 +1056,18 @@ pub trait Write {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::prelude::*;
/// use std::io::BufWriter;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut buffer = BufWriter::new(File::create("foo.txt")?);
+ /// fn main() -> std::io::Result<()> {
+ /// let mut buffer = BufWriter::new(File::create("foo.txt")?);
///
- /// buffer.write(b"some bytes")?;
- /// buffer.flush()?;
- /// # Ok(())
- /// # }
+ /// buffer.write(b"some bytes")?;
+ /// buffer.flush()?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn flush(&mut self) -> Result<()>;
@@ -1082,16 +1091,16 @@ pub trait Write {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut buffer = File::create("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut buffer = File::create("foo.txt")?;
///
- /// buffer.write_all(b"some bytes")?;
- /// # Ok(())
- /// # }
+ /// buffer.write_all(b"some bytes")?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
@@ -1131,19 +1140,19 @@ pub trait Write {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut buffer = File::create("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut buffer = File::create("foo.txt")?;
///
- /// // this call
- /// write!(buffer, "{:.*}", 2, 1.234567)?;
- /// // turns into this:
- /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?;
- /// # Ok(())
- /// # }
+ /// // this call
+ /// write!(buffer, "{:.*}", 2, 1.234567)?;
+ /// // turns into this:
+ /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
@@ -1187,19 +1196,19 @@ pub trait Write {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::Write;
/// use std::fs::File;
///
- /// # fn foo() -> std::io::Result<()> {
- /// let mut buffer = File::create("foo.txt")?;
+ /// fn main() -> std::io::Result<()> {
+ /// let mut buffer = File::create("foo.txt")?;
///
- /// let reference = buffer.by_ref();
+ /// let reference = buffer.by_ref();
///
- /// // we can use reference just like our original buffer
- /// reference.write_all(b"some bytes")?;
- /// # Ok(())
- /// # }
+ /// // we can use reference just like our original buffer
+ /// reference.write_all(b"some bytes")?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
@@ -1217,19 +1226,19 @@ pub trait Write {
///
/// [file]: ../fs/struct.File.html
///
-/// ```
+/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
/// use std::io::SeekFrom;
///
-/// # fn foo() -> io::Result<()> {
-/// let mut f = File::open("foo.txt")?;
+/// fn main() -> io::Result<()> {
+/// let mut f = File::open("foo.txt")?;
///
-/// // move the cursor 42 bytes from the start of the file
-/// f.seek(SeekFrom::Start(42))?;
-/// # Ok(())
-/// # }
+/// // move the cursor 42 bytes from the start of the file
+/// f.seek(SeekFrom::Start(42))?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Seek {
@@ -1320,7 +1329,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
///
/// A locked standard input implements `BufRead`:
///
-/// ```
+/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
///
@@ -1342,21 +1351,21 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
/// [`lines`]: #method.lines
/// [`Read`]: trait.Read.html
///
-/// ```
+/// ```no_run
/// use std::io::{self, BufReader};
/// use std::io::prelude::*;
/// use std::fs::File;
///
-/// # fn foo() -> io::Result<()> {
-/// let f = File::open("foo.txt")?;
-/// let f = BufReader::new(f);
+/// fn main() -> io::Result<()> {
+/// let f = File::open("foo.txt")?;
+/// let f = BufReader::new(f);
///
-/// for line in f.lines() {
-/// println!("{}", line.unwrap());
-/// }
+/// for line in f.lines() {
+/// println!("{}", line.unwrap());
+/// }
///
-/// # Ok(())
-/// # }
+/// Ok(())
+/// }
/// ```
///
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1383,7 +1392,7 @@ pub trait BufRead: Read {
///
/// A locked standard input implements `BufRead`:
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
///
@@ -1437,8 +1446,6 @@ pub trait BufRead: Read {
///
/// If successful, this function will return the total number of bytes read.
///
- /// An empty buffer returned indicates that the stream has reached EOF.
- ///
/// # Errors
///
/// This function will ignore all instances of [`ErrorKind::Interrupted`] and
@@ -1508,6 +1515,8 @@ pub trait BufRead: Read {
/// error is encountered then `buf` may contain some bytes already read in
/// the event that all data read so far was valid UTF-8.
///
+ /// [`read_until`]: #method.read_until
+ ///
/// # Examples
///
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
@@ -1645,19 +1654,19 @@ impl<T, U> Chain<T, U> {
///
/// # Examples
///
- /// ```
- /// # use std::io;
+ /// ```no_run
+ /// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut foo_file = File::open("foo.txt")?;
- /// let mut bar_file = File::open("bar.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut foo_file = File::open("foo.txt")?;
+ /// let mut bar_file = File::open("bar.txt")?;
///
- /// let chain = foo_file.chain(bar_file);
- /// let (foo_file, bar_file) = chain.into_inner();
- /// # Ok(())
- /// # }
+ /// let chain = foo_file.chain(bar_file);
+ /// let (foo_file, bar_file) = chain.into_inner();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn into_inner(self) -> (T, U) {
@@ -1668,19 +1677,19 @@ impl<T, U> Chain<T, U> {
///
/// # Examples
///
- /// ```
- /// # use std::io;
+ /// ```no_run
+ /// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut foo_file = File::open("foo.txt")?;
- /// let mut bar_file = File::open("bar.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut foo_file = File::open("foo.txt")?;
+ /// let mut bar_file = File::open("bar.txt")?;
///
- /// let chain = foo_file.chain(bar_file);
- /// let (foo_file, bar_file) = chain.get_ref();
- /// # Ok(())
- /// # }
+ /// let chain = foo_file.chain(bar_file);
+ /// let (foo_file, bar_file) = chain.get_ref();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn get_ref(&self) -> (&T, &U) {
@@ -1695,19 +1704,19 @@ impl<T, U> Chain<T, U> {
///
/// # Examples
///
- /// ```
- /// # use std::io;
+ /// ```no_run
+ /// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut foo_file = File::open("foo.txt")?;
- /// let mut bar_file = File::open("bar.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut foo_file = File::open("foo.txt")?;
+ /// let mut bar_file = File::open("bar.txt")?;
///
- /// let mut chain = foo_file.chain(bar_file);
- /// let (foo_file, bar_file) = chain.get_mut();
- /// # Ok(())
- /// # }
+ /// let mut chain = foo_file.chain(bar_file);
+ /// let (foo_file, bar_file) = chain.get_mut();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn get_mut(&mut self) -> (&mut T, &mut U) {
@@ -1794,20 +1803,20 @@ impl<T> Take<T> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let f = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let f = File::open("foo.txt")?;
///
- /// // read at most five bytes
- /// let handle = f.take(5);
+ /// // read at most five bytes
+ /// let handle = f.take(5);
///
- /// println!("limit: {}", handle.limit());
- /// # Ok(())
- /// # }
+ /// println!("limit: {}", handle.limit());
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn limit(&self) -> u64 { self.limit }
@@ -1819,24 +1828,23 @@ impl<T> Take<T> {
///
/// # Examples
///
- /// ```
- /// #![feature(take_set_limit)]
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let f = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let f = File::open("foo.txt")?;
///
- /// // read at most five bytes
- /// let mut handle = f.take(5);
- /// handle.set_limit(10);
+ /// // read at most five bytes
+ /// let mut handle = f.take(5);
+ /// handle.set_limit(10);
///
- /// assert_eq!(handle.limit(), 10);
- /// # Ok(())
- /// # }
+ /// assert_eq!(handle.limit(), 10);
+ /// Ok(())
+ /// }
/// ```
- #[unstable(feature = "take_set_limit", issue = "42781")]
+ #[stable(feature = "take_set_limit", since = "1.27.0")]
pub fn set_limit(&mut self, limit: u64) {
self.limit = limit;
}
@@ -1845,21 +1853,21 @@ impl<T> Take<T> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut file = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
///
- /// let mut buffer = [0; 5];
- /// let mut handle = file.take(5);
- /// handle.read(&mut buffer)?;
+ /// let mut buffer = [0; 5];
+ /// let mut handle = file.take(5);
+ /// handle.read(&mut buffer)?;
///
- /// let file = handle.into_inner();
- /// # Ok(())
- /// # }
+ /// let file = handle.into_inner();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "io_take_into_inner", since = "1.15.0")]
pub fn into_inner(self) -> T {
@@ -1870,21 +1878,21 @@ impl<T> Take<T> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut file = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
///
- /// let mut buffer = [0; 5];
- /// let mut handle = file.take(5);
- /// handle.read(&mut buffer)?;
+ /// let mut buffer = [0; 5];
+ /// let mut handle = file.take(5);
+ /// handle.read(&mut buffer)?;
///
- /// let file = handle.get_ref();
- /// # Ok(())
- /// # }
+ /// let file = handle.get_ref();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn get_ref(&self) -> &T {
@@ -1899,21 +1907,21 @@ impl<T> Take<T> {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
- /// # fn foo() -> io::Result<()> {
- /// let mut file = File::open("foo.txt")?;
+ /// fn main() -> io::Result<()> {
+ /// let mut file = File::open("foo.txt")?;
///
- /// let mut buffer = [0; 5];
- /// let mut handle = file.take(5);
- /// handle.read(&mut buffer)?;
+ /// let mut buffer = [0; 5];
+ /// let mut handle = file.take(5);
+ /// handle.read(&mut buffer)?;
///
- /// let file = handle.get_mut();
- /// # Ok(())
- /// # }
+ /// let file = handle.get_mut();
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn get_mut(&mut self) -> &mut T {
diff --git a/ctr-std/src/io/stdio.rs b/ctr-std/src/io/stdio.rs
index 831688b..2472bed 100644
--- a/ctr-std/src/io/stdio.rs
+++ b/ctr-std/src/io/stdio.rs
@@ -17,7 +17,7 @@ use io::{self, Initializer, BufReader, LineWriter};
use sync::{Arc, Mutex, MutexGuard};
use sys::stdio;
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
-use thread::{LocalKey, LocalKeyState};
+use thread::LocalKey;
/// Stdout used by print! and println! macros
thread_local! {
@@ -171,29 +171,29 @@ pub struct StdinLock<'a> {
///
/// Using implicit synchronization:
///
-/// ```
+/// ```no_run
/// use std::io::{self, Read};
///
-/// # fn foo() -> io::Result<String> {
-/// let mut buffer = String::new();
-/// io::stdin().read_to_string(&mut buffer)?;
-/// # Ok(buffer)
-/// # }
+/// fn main() -> io::Result<()> {
+/// let mut buffer = String::new();
+/// io::stdin().read_to_string(&mut buffer)?;
+/// Ok(())
+/// }
/// ```
///
/// Using explicit synchronization:
///
-/// ```
+/// ```no_run
/// use std::io::{self, Read};
///
-/// # fn foo() -> io::Result<String> {
-/// let mut buffer = String::new();
-/// let stdin = io::stdin();
-/// let mut handle = stdin.lock();
+/// fn main() -> io::Result<()> {
+/// let mut buffer = String::new();
+/// let stdin = io::stdin();
+/// let mut handle = stdin.lock();
///
-/// handle.read_to_string(&mut buffer)?;
-/// # Ok(buffer)
-/// # }
+/// handle.read_to_string(&mut buffer)?;
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
@@ -225,17 +225,17 @@ impl Stdin {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::{self, Read};
///
- /// # fn foo() -> io::Result<String> {
- /// let mut buffer = String::new();
- /// let stdin = io::stdin();
- /// let mut handle = stdin.lock();
+ /// fn main() -> io::Result<()> {
+ /// let mut buffer = String::new();
+ /// let stdin = io::stdin();
+ /// let mut handle = stdin.lock();
///
- /// handle.read_to_string(&mut buffer)?;
- /// # Ok(buffer)
- /// # }
+ /// handle.read_to_string(&mut buffer)?;
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdinLock {
@@ -369,29 +369,29 @@ pub struct StdoutLock<'a> {
///
/// Using implicit synchronization:
///
-/// ```
+/// ```no_run
/// use std::io::{self, Write};
///
-/// # fn foo() -> io::Result<()> {
-/// io::stdout().write(b"hello world")?;
+/// fn main() -> io::Result<()> {
+/// io::stdout().write(b"hello world")?;
///
-/// # Ok(())
-/// # }
+/// Ok(())
+/// }
/// ```
///
/// Using explicit synchronization:
///
-/// ```
+/// ```no_run
/// use std::io::{self, Write};
///
-/// # fn foo() -> io::Result<()> {
-/// let stdout = io::stdout();
-/// let mut handle = stdout.lock();
+/// fn main() -> io::Result<()> {
+/// let stdout = io::stdout();
+/// let mut handle = stdout.lock();
///
-/// handle.write(b"hello world")?;
+/// handle.write(b"hello world")?;
///
-/// # Ok(())
-/// # }
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
@@ -419,17 +419,17 @@ impl Stdout {
///
/// # Examples
///
- /// ```
+ /// ```no_run
/// use std::io::{self, Write};
///
- /// # fn foo() -> io::Result<()> {
- /// let stdout = io::stdout();
- /// let mut handle = stdout.lock();
+ /// fn main() -> io::Result<()> {
+ /// let stdout = io::stdout();
+ /// let mut handle = stdout.lock();
///
- /// handle.write(b"hello world")?;
+ /// handle.write(b"hello world")?;
///
- /// # Ok(())
- /// # }
+ /// Ok(())
+ /// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdoutLock {
@@ -505,29 +505,29 @@ pub struct StderrLock<'a> {
///
/// Using implicit synchronization:
///
-/// ```
+/// ```no_run
/// use std::io::{self, Write};
///
-/// # fn foo() -> io::Result<()> {
-/// io::stderr().write(b"hello world")?;
+/// fn main() -> io::Result<()> {
+/// io::stderr().write(b"hello world")?;
///
-/// # Ok(())
-/// # }
+/// Ok(())
+/// }
/// ```
///
/// Using explicit synchronization:
///
-/// ```
+/// ```no_run
/// use std::io::{self, Write};
///
-/// # fn foo() -> io::Result<()> {
-/// let stderr = io::stderr();
-/// let mut handle = stderr.lock();
+/// fn main() -> io::Result<()> {
+/// let stderr = io::stderr();
+/// let mut handle = stderr.lock();
///
-/// handle.write(b"hello world")?;
+/// handle.write(b"hello world")?;
///
-/// # Ok(())
-/// # }
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
@@ -663,29 +663,31 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
///
/// This function is used to print error messages, so it takes extra
/// care to avoid causing a panic when `local_stream` is unusable.
-/// For instance, if the TLS key for the local stream is uninitialized
-/// or already destroyed, or if the local stream is locked by another
+/// For instance, if the TLS key for the local stream is
+/// already destroyed, or if the local stream is locked by another
/// thread, it will just fall back to the global stream.
///
/// However, if the actual I/O causes an error, this function does panic.
-fn print_to<T>(args: fmt::Arguments,
- local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
- global_s: fn() -> T,
- label: &str) where T: Write {
- let result = match local_s.state() {
- LocalKeyState::Uninitialized |
- LocalKeyState::Destroyed => global_s().write_fmt(args),
- LocalKeyState::Valid => {
- local_s.with(|s| {
- if let Ok(mut borrowed) = s.try_borrow_mut() {
- if let Some(w) = borrowed.as_mut() {
- return w.write_fmt(args);
- }
- }
- global_s().write_fmt(args)
- })
+fn print_to<T>(
+ args: fmt::Arguments,
+ local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
+ global_s: fn() -> T,
+ label: &str,
+)
+where
+ T: Write,
+{
+ let result = local_s.try_with(|s| {
+ if let Ok(mut borrowed) = s.try_borrow_mut() {
+ if let Some(w) = borrowed.as_mut() {
+ return w.write_fmt(args);
+ }
}
- };
+ global_s().write_fmt(args)
+ }).unwrap_or_else(|_| {
+ global_s().write_fmt(args)
+ });
+
if let Err(e) = result {
panic!("failed printing to {}: {}", label, e);
}
diff --git a/ctr-std/src/io/util.rs b/ctr-std/src/io/util.rs
index 45d281e..195310a 100644
--- a/ctr-std/src/io/util.rs
+++ b/ctr-std/src/io/util.rs
@@ -34,16 +34,15 @@ use mem;
/// ```
/// use std::io;
///
-/// # fn foo() -> io::Result<()> {
-/// let mut reader: &[u8] = b"hello";
-/// let mut writer: Vec<u8> = vec![];
+/// fn main() -> io::Result<()> {
+/// let mut reader: &[u8] = b"hello";
+/// let mut writer: Vec<u8> = vec![];
///
-/// io::copy(&mut reader, &mut writer)?;
+/// io::copy(&mut reader, &mut writer)?;
///
-/// assert_eq!(&b"hello"[..], &writer[..]);
-/// # Ok(())
-/// # }
-/// # foo().unwrap();
+/// assert_eq!(&b"hello"[..], &writer[..]);
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
diff --git a/ctr-std/src/lib.rs b/ctr-std/src/lib.rs
index a0d76cf..146e23c 100644
--- a/ctr-std/src/lib.rs
+++ b/ctr-std/src/lib.rs
@@ -259,6 +259,7 @@
#![feature(core_float)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
+#![feature(exhaustive_patterns)]
#![feature(exact_size_is_empty)]
#![feature(fs_read_write)]
#![feature(fixed_size_array)]
@@ -266,11 +267,9 @@
#![feature(fn_traits)]
#![feature(fnbox)]
#![feature(fused)]
-#![feature(generic_param_attrs)]
#![feature(hashmap_hasher)]
+#![feature(hashmap_internals)]
#![feature(heap_api)]
-#![feature(i128)]
-#![feature(i128_type)]
#![feature(inclusive_range)]
#![feature(int_error_internals)]
#![feature(integer_atomics)]
@@ -283,6 +282,8 @@
#![feature(macro_vis_matcher)]
#![feature(needs_panic_runtime)]
#![feature(never_type)]
+#![feature(nonnull_cast)]
+#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
#![feature(on_unimplemented)]
@@ -297,21 +298,23 @@
#![feature(rand)]
#![feature(raw)]
#![feature(rustc_attrs)]
+#![feature(shrink_to)]
#![feature(sip_hash_13)]
#![feature(slice_bytes)]
#![feature(slice_concat_ext)]
#![feature(slice_internals)]
#![feature(slice_patterns)]
#![feature(staged_api)]
+#![feature(stdsimd)]
#![feature(stmt_expr_attributes)]
#![feature(str_char)]
#![feature(str_internals)]
#![feature(str_utf16)]
-#![feature(termination_trait)]
#![feature(test, rustc_private)]
#![feature(thread_local)]
#![feature(toowned_clone_into)]
#![feature(try_from)]
+#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(untagged_unions)]
@@ -352,15 +355,14 @@ use prelude::v1::*;
// We want to re-export a few macros from core but libcore has already been
// imported by the compiler (via our #[no_std] attribute) In this case we just
// add a new crate name so we can attach the re-exports to it.
-#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
+#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
extern crate core as __core;
#[macro_use]
#[macro_reexport(vec, format)]
-extern crate alloc;
+extern crate alloc as alloc_crate;
extern crate alloc_system;
-extern crate std_unicode;
#[doc(masked)]
extern crate libc;
@@ -372,10 +374,6 @@ extern crate ctru_sys as libctru;
#[allow(unused_extern_crates)]
extern crate unwind;
-// compiler-rt intrinsics
-#[doc(masked)]
-extern crate compiler_builtins;
-
// During testing, this crate is not actually the "real" std library, but rather
// it links to the real std library, which was compiled from this same source
// code. So any lang items std defines are conditionally excluded (or else they
@@ -447,23 +445,23 @@ pub use core::u32;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::u64;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::boxed;
+pub use alloc_crate::boxed;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::rc;
+pub use alloc_crate::rc;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::borrow;
+pub use alloc_crate::borrow;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::fmt;
+pub use alloc_crate::fmt;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::slice;
+pub use alloc_crate::slice;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::str;
+pub use alloc_crate::str;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::string;
+pub use alloc_crate::string;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::vec;
+pub use alloc_crate::vec;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use std_unicode::char;
+pub use core::char;
#[unstable(feature = "i128", issue = "35118")]
pub use core::u128;
@@ -487,7 +485,14 @@ pub mod path;
pub mod process;
pub mod sync;
pub mod time;
-pub mod heap;
+pub mod alloc;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
+/// Use the `alloc` module instead.
+pub mod heap {
+ pub use alloc::*;
+}
// Platform-abstraction modules
#[macro_use]
@@ -501,11 +506,6 @@ mod memchr;
// The runtime entry point and a few unstable public functions used by the
// compiler
pub mod rt;
-// The trait to support returning arbitrary types in the main function
-mod termination;
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-pub use self::termination::Termination;
// Include a number of private modules that exist solely to provide
// the rustdoc documentation for primitive types. Using `include!`
diff --git a/ctr-std/src/macros.rs b/ctr-std/src/macros.rs
index f058b1c..5ef7c15 100644
--- a/ctr-std/src/macros.rs
+++ b/ctr-std/src/macros.rs
@@ -68,6 +68,9 @@ macro_rules! panic {
($msg:expr) => ({
$crate::rt::begin_panic($msg, &(file!(), line!(), __rust_unstable_column!()))
});
+ ($msg:expr,) => ({
+ panic!($msg)
+ });
($fmt:expr, $($arg:tt)+) => ({
$crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+),
&(file!(), line!(), __rust_unstable_column!()))
@@ -312,7 +315,10 @@ pub mod builtin {
/// ```
#[stable(feature = "compile_error_macro", since = "1.20.0")]
#[macro_export]
- macro_rules! compile_error { ($msg:expr) => ({ /* compiler built-in */ }) }
+ macro_rules! compile_error {
+ ($msg:expr) => ({ /* compiler built-in */ });
+ ($msg:expr,) => ({ /* compiler built-in */ });
+ }
/// The core macro for formatted string creation & output.
///
@@ -329,6 +335,18 @@ pub mod builtin {
/// proxied through this one. `format_args!`, unlike its derived macros, avoids
/// heap allocations.
///
+ /// You can use the [`fmt::Arguments`] value that `format_args!` returns
+ /// in `Debug` and `Display` contexts as seen below. The example also shows
+ /// that `Debug` and `Display` format to the same thing: the interpolated
+ /// format string in `format_args!`.
+ ///
+ /// ```rust
+ /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
+ /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
+ /// assert_eq!("1 foo 2", display);
+ /// assert_eq!(display, debug);
+ /// ```
+ ///
/// For more information, see the documentation in [`std::fmt`].
///
/// [`Display`]: ../std/fmt/trait.Display.html
@@ -400,7 +418,10 @@ pub mod builtin {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
- macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
+ macro_rules! option_env {
+ ($name:expr) => ({ /* compiler built-in */ });
+ ($name:expr,) => ({ /* compiler built-in */ });
+ }
/// Concatenate identifiers into one identifier.
///
@@ -463,7 +484,7 @@ pub mod builtin {
/// The expanded expression has type `u32` and is 1-based, so the first line
/// in each file evaluates to 1, the second to 2, etc. This is consistent
/// with error messages by common compilers or popular editors.
- /// The returned line is not the invocation of the `line!` macro itself,
+ /// The returned line is *not necessarily* the line of the `line!` invocation itself,
/// but rather the first macro invocation leading up to the invocation
/// of the `line!` macro.
///
@@ -488,7 +509,7 @@ pub mod builtin {
/// The expanded expression has type `u32` and is 1-based, so the first column
/// in each line evaluates to 1, the second to 2, etc. This is consistent
/// with error messages by common compilers or popular editors.
- /// The returned column is not the invocation of the `column!` macro itself,
+ /// The returned column is *not necessarily* the line of the `column!` invocation itself,
/// but rather the first macro invocation leading up to the invocation
/// of the `column!` macro.
///
@@ -580,7 +601,10 @@ pub mod builtin {
/// Compiling 'main.rs' and running the resulting binary will print "adiós".
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
- macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
+ macro_rules! include_str {
+ ($file:expr) => ({ /* compiler built-in */ });
+ ($file:expr,) => ({ /* compiler built-in */ });
+ }
/// Includes a file as a reference to a byte array.
///
@@ -614,7 +638,10 @@ pub mod builtin {
/// Compiling 'main.rs' and running the resulting binary will print "adiós".
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
- macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) }
+ macro_rules! include_bytes {
+ ($file:expr) => ({ /* compiler built-in */ });
+ ($file:expr,) => ({ /* compiler built-in */ });
+ }
/// Expands to a string that represents the current module path.
///
@@ -700,7 +727,64 @@ pub mod builtin {
/// "🙈🙊🙉🙈🙊🙉".
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
- macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
+ macro_rules! include {
+ ($file:expr) => ({ /* compiler built-in */ });
+ ($file:expr,) => ({ /* compiler built-in */ });
+ }
+
+ /// Ensure that a boolean expression is `true` at runtime.
+ ///
+ /// This will invoke the [`panic!`] macro if the provided expression cannot be
+ /// evaluated to `true` at runtime.
+ ///
+ /// # Uses
+ ///
+ /// Assertions are always checked in both debug and release builds, and cannot
+ /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
+ /// release builds by default.
+ ///
+ /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+ /// violated could lead to unsafety.
+ ///
+ /// Other use-cases of `assert!` include [testing] and enforcing run-time
+ /// invariants in safe code (whose violation cannot result in unsafety).
+ ///
+ /// # Custom Messages
+ ///
+ /// This macro has a second form, where a custom panic message can
+ /// be provided with or without arguments for formatting. See [`std::fmt`]
+ /// for syntax for this form.
+ ///
+ /// [`panic!`]: macro.panic.html
+ /// [`debug_assert!`]: macro.debug_assert.html
+ /// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro
+ /// [`std::fmt`]: ../std/fmt/index.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// // the panic message for these assertions is the stringified value of the
+ /// // expression given.
+ /// assert!(true);
+ ///
+ /// fn some_computation() -> bool { true } // a very simple function
+ ///
+ /// assert!(some_computation());
+ ///
+ /// // assert with a custom message
+ /// let x = true;
+ /// assert!(x, "x wasn't true!");
+ ///
+ /// let a = 3; let b = 27;
+ /// assert!(a + b == 30, "a = {}, b = {}", a, b);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[macro_export]
+ macro_rules! assert {
+ ($cond:expr) => ({ /* compiler built-in */ });
+ ($cond:expr,) => ({ /* compiler built-in */ });
+ ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+ }
}
/// A macro for defining #[cfg] if-else statements.
diff --git a/ctr-std/src/net/addr.rs b/ctr-std/src/net/addr.rs
index 1ca7e66..bc2c9f5 100644
--- a/ctr-std/src/net/addr.rs
+++ b/ctr-std/src/net/addr.rs
@@ -12,7 +12,9 @@ use fmt;
use hash;
use io;
use mem;
-use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+#[allow(deprecated)]
+use net::lookup_host;
use option;
use sys::net::netc as c;
use sys_common::{FromInner, AsInner, IntoInner};
@@ -26,6 +28,9 @@ use slice;
/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
/// [`SocketAddrV6`]'s respective documentation for more details.
///
+/// The size of a `SocketAddr` instance may vary depending on the target operating
+/// system.
+///
/// [IP address]: ../../std/net/enum.IpAddr.html
/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
@@ -59,6 +64,9 @@ pub enum SocketAddr {
///
/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
///
+/// The size of a `SocketAddrV4` struct may vary depending on the target operating
+/// system.
+///
/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
@@ -86,6 +94,9 @@ pub struct SocketAddrV4 { inner: c::sockaddr_in }
///
/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
///
+/// The size of a `SocketAddrV6` struct may vary depending on the target operating
+/// system.
+///
/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
/// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
@@ -845,6 +856,7 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
}
}
+#[allow(deprecated)]
fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
let ips = lookup_host(s)?;
let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect();
diff --git a/ctr-std/src/net/ip.rs b/ctr-std/src/net/ip.rs
index 0d73a6f..fcec8d0 100644
--- a/ctr-std/src/net/ip.rs
+++ b/ctr-std/src/net/ip.rs
@@ -26,6 +26,9 @@ use sys_common::{AsInner, FromInner};
/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
/// respective documentation for more details.
///
+/// The size of an `IpAddr` instance may vary depending on the target operating
+/// system.
+///
/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
///
@@ -61,6 +64,9 @@ pub enum IpAddr {
///
/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
///
+/// The size of an `Ipv4Addr` struct may vary depending on the target operating
+/// system.
+///
/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
///
@@ -93,6 +99,9 @@ pub struct Ipv4Addr {
///
/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
///
+/// The size of an `Ipv6Addr` struct may vary depending on the target operating
+/// system.
+///
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
///
@@ -769,7 +778,16 @@ impl FromInner<c::in_addr> for Ipv4Addr {
#[stable(feature = "ip_u32", since = "1.1.0")]
impl From<Ipv4Addr> for u32 {
- /// It performs the conversion in network order (big-endian).
+ /// Convert an `Ipv4Addr` into a host byte order `u32`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(13, 12, 11, 10);
+ /// assert_eq!(0x0d0c0b0au32, u32::from(addr));
+ /// ```
fn from(ip: Ipv4Addr) -> u32 {
let ip = ip.octets();
((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
@@ -778,7 +796,16 @@ impl From<Ipv4Addr> for u32 {
#[stable(feature = "ip_u32", since = "1.1.0")]
impl From<u32> for Ipv4Addr {
- /// It performs the conversion in network order (big-endian).
+ /// Convert a host byte order `u32` into an `Ipv4Addr`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::from(0x0d0c0b0au32);
+ /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+ /// ```
fn from(ip: u32) -> Ipv4Addr {
Ipv4Addr::new((ip >> 24) as u8, (ip >> 16) as u8, (ip >> 8) as u8, ip as u8)
}
@@ -786,6 +813,14 @@ impl From<u32> for Ipv4Addr {
#[stable(feature = "from_slice_v4", since = "1.9.0")]
impl From<[u8; 4]> for Ipv4Addr {
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
+ /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+ /// ```
fn from(octets: [u8; 4]) -> Ipv4Addr {
Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
}
@@ -793,6 +828,16 @@ impl From<[u8; 4]> for Ipv4Addr {
#[stable(feature = "ip_from_slice", since = "1.17.0")]
impl From<[u8; 4]> for IpAddr {
+ /// Create an `IpAddr::V4` from a four element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr};
+ ///
+ /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
+ /// ```
fn from(octets: [u8; 4]) -> IpAddr {
IpAddr::V4(Ipv4Addr::from(octets))
}
@@ -1346,7 +1391,7 @@ impl FromInner<c::in6_addr> for Ipv6Addr {
}
}
-#[unstable(feature = "i128", issue = "35118")]
+#[stable(feature = "i128", since = "1.26.0")]
impl From<Ipv6Addr> for u128 {
fn from(ip: Ipv6Addr) -> u128 {
let ip = ip.segments();
@@ -1355,7 +1400,7 @@ impl From<Ipv6Addr> for u128 {
((ip[6] as u128) << 16) + (ip[7] as u128)
}
}
-#[unstable(feature = "i128", issue = "35118")]
+#[stable(feature = "i128", since = "1.26.0")]
impl From<u128> for Ipv6Addr {
fn from(ip: u128) -> Ipv6Addr {
Ipv6Addr::new(
@@ -1386,6 +1431,27 @@ impl From<[u16; 8]> for Ipv6Addr {
#[stable(feature = "ip_from_slice", since = "1.17.0")]
impl From<[u8; 16]> for IpAddr {
+ /// Create an `IpAddr::V6` from a sixteen element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = IpAddr::from([
+ /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+ /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+ /// ]);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(
+ /// 0x1918, 0x1716,
+ /// 0x1514, 0x1312,
+ /// 0x1110, 0x0f0e,
+ /// 0x0d0c, 0x0b0a
+ /// )),
+ /// addr
+ /// );
+ /// ```
fn from(octets: [u8; 16]) -> IpAddr {
IpAddr::V6(Ipv6Addr::from(octets))
}
@@ -1393,6 +1459,27 @@ impl From<[u8; 16]> for IpAddr {
#[stable(feature = "ip_from_slice", since = "1.17.0")]
impl From<[u16; 8]> for IpAddr {
+ /// Create an `IpAddr::V6` from an eight element 16-bit array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = IpAddr::from([
+ /// 525u16, 524u16, 523u16, 522u16,
+ /// 521u16, 520u16, 519u16, 518u16,
+ /// ]);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(
+ /// 0x20d, 0x20c,
+ /// 0x20b, 0x20a,
+ /// 0x209, 0x208,
+ /// 0x207, 0x206
+ /// )),
+ /// addr
+ /// );
+ /// ```
fn from(segments: [u16; 8]) -> IpAddr {
IpAddr::V6(Ipv6Addr::from(segments))
}
diff --git a/ctr-std/src/net/mod.rs b/ctr-std/src/net/mod.rs
index 9fcb93e..b0d5e56 100644
--- a/ctr-std/src/net/mod.rs
+++ b/ctr-std/src/net/mod.rs
@@ -134,12 +134,15 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
iterator and returning socket \
addresses",
issue = "27705")]
+#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
pub struct LookupHost(net_imp::LookupHost);
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
iterator and returning socket \
addresses",
issue = "27705")]
+#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
impl Iterator for LookupHost {
type Item = SocketAddr;
fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
@@ -149,6 +152,8 @@ impl Iterator for LookupHost {
iterator and returning socket \
addresses",
issue = "27705")]
+#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
impl fmt::Debug for LookupHost {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("LookupHost { .. }")
@@ -170,17 +175,19 @@ impl fmt::Debug for LookupHost {
///
/// use std::net;
///
-/// # fn foo() -> std::io::Result<()> {
-/// for host in net::lookup_host("rust-lang.org")? {
-/// println!("found address: {}", host);
+/// fn main() -> std::io::Result<()> {
+/// for host in net::lookup_host("rust-lang.org")? {
+/// println!("found address: {}", host);
+/// }
+/// Ok(())
/// }
-/// # Ok(())
-/// # }
/// ```
#[unstable(feature = "lookup_host", reason = "unsure about the returned \
iterator and returning socket \
addresses",
issue = "27705")]
+#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
net_imp::lookup_host(host).map(LookupHost)
}
diff --git a/ctr-std/src/net/parser.rs b/ctr-std/src/net/parser.rs
index 261d44e..ae5037c 100644
--- a/ctr-std/src/net/parser.rs
+++ b/ctr-std/src/net/parser.rs
@@ -372,6 +372,25 @@ impl FromStr for SocketAddr {
/// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and
/// [`SocketAddrV6`].
///
+/// # Potential causes
+///
+/// `AddrParseError` may be thrown because the provided string does not parse as the given type,
+/// often because it includes information only handled by a different address type.
+///
+/// ```should_panic
+/// use std::net::IpAddr;
+/// let _foo: IpAddr = "127.0.0.1:8080".parse().expect("Cannot handle the socket port");
+/// ```
+///
+/// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead.
+///
+/// ```
+/// use std::net::SocketAddr;
+///
+/// // No problem, the `panic!` message has disappeared.
+/// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic");
+/// ```
+///
/// [`FromStr`]: ../../std/str/trait.FromStr.html
/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
diff --git a/ctr-std/src/net/tcp.rs b/ctr-std/src/net/tcp.rs
index 78235ea..0f60b5b 100644
--- a/ctr-std/src/net/tcp.rs
+++ b/ctr-std/src/net/tcp.rs
@@ -72,7 +72,7 @@ pub struct TcpStream(net_imp::TcpStream);
///
/// # Examples
///
-/// ```
+/// ```no_run
/// # use std::io;
/// use std::net::{TcpListener, TcpStream};
///
@@ -80,15 +80,15 @@ pub struct TcpStream(net_imp::TcpStream);
/// // ...
/// }
///
-/// # fn process() -> io::Result<()> {
-/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+/// fn main() -> io::Result<()> {
+/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
///
-/// // accept connections and process them serially
-/// for stream in listener.incoming() {
-/// handle_client(stream?);
+/// // accept connections and process them serially
+/// for stream in listener.incoming() {
+/// handle_client(stream?);
+/// }
+/// Ok(())
/// }
-/// # Ok(())
-/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpListener(net_imp::TcpListener);
@@ -259,19 +259,21 @@ impl TcpStream {
/// Sets the read timeout to the timeout specified.
///
/// If the value specified is [`None`], then [`read`] calls will block
- /// indefinitely. It is an error to pass the zero `Duration` to this
- /// method.
+ /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+ /// passed to this method.
///
- /// # Note
+ /// # Platform-specific behavior
///
/// Platforms may return a different error code whenever a read times out as
/// a result of setting this option. For example Unix typically returns an
/// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
+ /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`read`]: ../../std/io/trait.Read.html#tymethod.read
/// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
/// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+ /// [`Duration`]: ../../std/time/struct.Duration.html
///
/// # Examples
///
@@ -282,6 +284,20 @@ impl TcpStream {
/// .expect("Couldn't connect to the server...");
/// stream.set_read_timeout(None).expect("set_read_timeout call failed");
/// ```
+ ///
+ /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+ /// method:
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::net::TcpStream;
+ /// use std::time::Duration;
+ ///
+ /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
+ /// let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_read_timeout(dur)
@@ -290,16 +306,17 @@ impl TcpStream {
/// Sets the write timeout to the timeout specified.
///
/// If the value specified is [`None`], then [`write`] calls will block
- /// indefinitely. It is an error to pass the zero [`Duration`] to this
- /// method.
+ /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+ /// passed to this method.
///
- /// # Note
+ /// # Platform-specific behavior
///
/// Platforms may return a different error code whenever a write times out
/// as a result of setting this option. For example Unix typically returns
/// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
+ /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`write`]: ../../std/io/trait.Write.html#tymethod.write
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -314,6 +331,20 @@ impl TcpStream {
/// .expect("Couldn't connect to the server...");
/// stream.set_write_timeout(None).expect("set_write_timeout call failed");
/// ```
+ ///
+ /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+ /// method:
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::net::TcpStream;
+ /// use std::time::Duration;
+ ///
+ /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
+ /// let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_write_timeout(dur)
@@ -323,7 +354,7 @@ impl TcpStream {
///
/// If the timeout is [`None`], then [`read`] calls will block indefinitely.
///
- /// # Note
+ /// # Platform-specific behavior
///
/// Some platforms do not provide access to the current timeout.
///
@@ -349,7 +380,7 @@ impl TcpStream {
///
/// If the timeout is [`None`], then [`write`] calls will block indefinitely.
///
- /// # Note
+ /// # Platform-specific behavior
///
/// Some platforms do not provide access to the current timeout.
///
@@ -1545,6 +1576,26 @@ mod tests {
drop(listener);
}
+ // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+ // when passed zero Durations
+ #[test]
+ fn test_timeout_zero_duration() {
+ let addr = next_test_ip4();
+
+ let listener = t!(TcpListener::bind(&addr));
+ let stream = t!(TcpStream::connect(&addr));
+
+ let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+ let err = result.unwrap_err();
+ assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+ let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+ let err = result.unwrap_err();
+ assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+ drop(listener);
+ }
+
#[test]
fn nodelay() {
let addr = next_test_ip4();
diff --git a/ctr-std/src/net/udp.rs b/ctr-std/src/net/udp.rs
index fc7f920..d25e299 100644
--- a/ctr-std/src/net/udp.rs
+++ b/ctr-std/src/net/udp.rs
@@ -44,22 +44,22 @@ use time::Duration;
/// ```no_run
/// use std::net::UdpSocket;
///
-/// # fn foo() -> std::io::Result<()> {
-/// {
-/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
+/// fn main() -> std::io::Result<()> {
+/// {
+/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
///
-/// // Receives a single datagram message on the socket. If `buf` is too small to hold
-/// // the message, it will be cut off.
-/// let mut buf = [0; 10];
-/// let (amt, src) = socket.recv_from(&mut buf)?;
+/// // Receives a single datagram message on the socket. If `buf` is too small to hold
+/// // the message, it will be cut off.
+/// let mut buf = [0; 10];
+/// let (amt, src) = socket.recv_from(&mut buf)?;
///
-/// // Redeclare `buf` as slice of the received data and send reverse data back to origin.
-/// let buf = &mut buf[..amt];
-/// buf.reverse();
-/// socket.send_to(buf, &src)?;
-/// # Ok(())
-/// } // the socket is closed here
-/// # }
+/// // Redeclare `buf` as slice of the received data and send reverse data back to origin.
+/// let buf = &mut buf[..amt];
+/// buf.reverse();
+/// socket.send_to(buf, &src)?;
+/// } // the socket is closed here
+/// Ok(())
+/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct UdpSocket(net_imp::UdpSocket);
@@ -228,16 +228,17 @@ impl UdpSocket {
/// Sets the read timeout to the timeout specified.
///
/// If the value specified is [`None`], then [`read`] calls will block
- /// indefinitely. It is an error to pass the zero [`Duration`] to this
- /// method.
+ /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+ /// passed to this method.
///
- /// # Note
+ /// # Platform-specific behavior
///
/// Platforms may return a different error code whenever a read times out as
/// a result of setting this option. For example Unix typically returns an
/// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
+ /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`read`]: ../../std/io/trait.Read.html#tymethod.read
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -251,6 +252,20 @@ impl UdpSocket {
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_read_timeout(None).expect("set_read_timeout call failed");
/// ```
+ ///
+ /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+ /// method:
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::net::UdpSocket;
+ /// use std::time::Duration;
+ ///
+ /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+ /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_read_timeout(dur)
@@ -259,16 +274,17 @@ impl UdpSocket {
/// Sets the write timeout to the timeout specified.
///
/// If the value specified is [`None`], then [`write`] calls will block
- /// indefinitely. It is an error to pass the zero [`Duration`] to this
- /// method.
+ /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+ /// passed to this method.
///
- /// # Note
+ /// # Platform-specific behavior
///
/// Platforms may return a different error code whenever a write times out
/// as a result of setting this option. For example Unix typically returns
/// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
+ /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`write`]: ../../std/io/trait.Write.html#tymethod.write
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -282,6 +298,20 @@ impl UdpSocket {
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_write_timeout(None).expect("set_write_timeout call failed");
/// ```
+ ///
+ /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+ /// method:
+ ///
+ /// ```no_run
+ /// use std::io;
+ /// use std::net::UdpSocket;
+ /// use std::time::Duration;
+ ///
+ /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+ /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+ /// let err = result.unwrap_err();
+ /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+ /// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_write_timeout(dur)
@@ -1024,6 +1054,23 @@ mod tests {
assert!(start.elapsed() > Duration::from_millis(400));
}
+ // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
+ // when passed zero Durations
+ #[test]
+ fn test_timeout_zero_duration() {
+ let addr = next_test_ip4();
+
+ let socket = t!(UdpSocket::bind(&addr));
+
+ let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+ let err = result.unwrap_err();
+ assert_eq!(err.kind(), ErrorKind::InvalidInput);
+
+ let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+ let err = result.unwrap_err();
+ assert_eq!(err.kind(), ErrorKind::InvalidInput);
+ }
+
#[test]
fn connect_send_recv() {
let addr = next_test_ip4();
diff --git a/ctr-std/src/num.rs b/ctr-std/src/num.rs
index a2c1339..4b975dd 100644
--- a/ctr-std/src/num.rs
+++ b/ctr-std/src/num.rs
@@ -21,6 +21,13 @@ pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError}
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::Wrapping;
+#[unstable(feature = "nonzero", issue = "49137")]
+#[allow(deprecated)]
+pub use core::num::{
+ NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
+ NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize,
+};
+
#[cfg(test)] use fmt;
#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
@@ -169,7 +176,6 @@ mod tests {
macro_rules! test_checked_next_power_of_two {
($test_name:ident, $T:ident) => (
- #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119)
fn $test_name() {
#![test]
assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
diff --git a/ctr-std/src/panic.rs b/ctr-std/src/panic.rs
index 5608760..28c1783 100644
--- a/ctr-std/src/panic.rs
+++ b/ctr-std/src/panic.rs
@@ -23,7 +23,10 @@ use sync::{Arc, Mutex, RwLock, atomic};
use thread::Result;
#[stable(feature = "panic_hooks", since = "1.10.0")]
-pub use panicking::{take_hook, set_hook, PanicInfo, Location};
+pub use panicking::{take_hook, set_hook};
+
+#[stable(feature = "panic_hooks", since = "1.10.0")]
+pub use core::panic::{PanicInfo, Location};
/// A marker trait which represents "panic safe" types in Rust.
///
@@ -185,7 +188,7 @@ pub struct AssertUnwindSafe<T>(
// * By default everything is unwind safe
// * pointers T contains mutability of some form are not unwind safe
// * Unique, an owning pointer, lifts an implementation
-// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
+// * Types like Mutex/RwLock which are explicitly poisoned are unwind safe
// * Our custom AssertUnwindSafe wrapper is indeed unwind safe
#[stable(feature = "catch_unwind", since = "1.9.0")]
@@ -198,7 +201,7 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
-#[stable(feature = "nonnull", since = "1.24.0")]
+#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: ?Sized> UnwindSafe for Mutex<T> {}
diff --git a/ctr-std/src/primitive_docs.rs b/ctr-std/src/primitive_docs.rs
index a2caf47..ce4bbff 100644
--- a/ctr-std/src/primitive_docs.rs
+++ b/ctr-std/src/primitive_docs.rs
@@ -79,7 +79,6 @@ mod prim_bool { }
/// write:
///
/// ```
-/// #![feature(never_type)]
/// # fn foo() -> u32 {
/// let x: ! = {
/// return 123
@@ -131,13 +130,15 @@ mod prim_bool { }
/// [`Result<String, !>`] which we can unpack like this:
///
/// ```ignore (string-from-str-error-type-is-not-never-yet)
+/// #[feature(exhaustive_patterns)]
/// // NOTE: This does not work today!
/// let Ok(s) = String::from_str("hello");
/// ```
///
-/// Since the [`Err`] variant contains a `!`, it can never occur. So we can exhaustively match on
-/// [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behaviour of `!` -
-/// it can be used to "delete" certain enum variants from generic types like `Result`.
+/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
+/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
+/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
+/// enum variants from generic types like `Result`.
///
/// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
/// [`Result<String, !>`]: result/enum.Result.html
@@ -154,7 +155,6 @@ mod prim_bool { }
/// for example:
///
/// ```
-/// # #![feature(never_type)]
/// # use std::fmt;
/// # trait Debug {
/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
@@ -192,7 +192,6 @@ mod prim_bool { }
/// [`Default`]: default/trait.Default.html
/// [`default()`]: default/trait.Default.html#tymethod.default
///
-#[unstable(feature = "never_type", issue = "35121")]
mod prim_never { }
#[doc(primitive = "char")]
@@ -720,10 +719,6 @@ mod prim_f64 { }
/// The 8-bit signed integer type.
///
/// *[See also the `std::i8` module](i8/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i64` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_i8 { }
@@ -732,10 +727,6 @@ mod prim_i8 { }
/// The 16-bit signed integer type.
///
/// *[See also the `std::i16` module](i16/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i32` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_i16 { }
@@ -744,10 +735,6 @@ mod prim_i16 { }
/// The 32-bit signed integer type.
///
/// *[See also the `std::i32` module](i32/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i16` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_i32 { }
@@ -756,10 +743,6 @@ mod prim_i32 { }
/// The 64-bit signed integer type.
///
/// *[See also the `std::i64` module](i64/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i8` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_i64 { }
@@ -768,11 +751,7 @@ mod prim_i64 { }
/// The 128-bit signed integer type.
///
/// *[See also the `std::i128` module](i128/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `i8` in there.
-///
-#[unstable(feature = "i128", issue="35118")]
+#[stable(feature = "i128", since="1.26.0")]
mod prim_i128 { }
#[doc(primitive = "u8")]
@@ -780,10 +759,6 @@ mod prim_i128 { }
/// The 8-bit unsigned integer type.
///
/// *[See also the `std::u8` module](u8/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u64` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_u8 { }
@@ -792,10 +767,6 @@ mod prim_u8 { }
/// The 16-bit unsigned integer type.
///
/// *[See also the `std::u16` module](u16/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u32` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_u16 { }
@@ -804,10 +775,6 @@ mod prim_u16 { }
/// The 32-bit unsigned integer type.
///
/// *[See also the `std::u32` module](u32/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u16` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_u32 { }
@@ -816,10 +783,6 @@ mod prim_u32 { }
/// The 64-bit unsigned integer type.
///
/// *[See also the `std::u64` module](u64/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u8` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_u64 { }
@@ -828,11 +791,7 @@ mod prim_u64 { }
/// The 128-bit unsigned integer type.
///
/// *[See also the `std::u128` module](u128/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `u8` in there.
-///
-#[unstable(feature = "i128", issue="35118")]
+#[stable(feature = "i128", since="1.26.0")]
mod prim_u128 { }
#[doc(primitive = "isize")]
@@ -844,10 +803,6 @@ mod prim_u128 { }
/// and on a 64 bit target, this is 8 bytes.
///
/// *[See also the `std::isize` module](isize/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `usize` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_isize { }
@@ -860,10 +815,6 @@ mod prim_isize { }
/// and on a 64 bit target, this is 8 bytes.
///
/// *[See also the `std::usize` module](usize/index.html).*
-///
-/// However, please note that examples are shared between primitive integer
-/// types. So it's normal if you see usage of types like `isize` in there.
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_usize { }
diff --git a/ctr-std/src/process.rs b/ctr-std/src/process.rs
index 5c66ac6..92f0406 100644
--- a/ctr-std/src/process.rs
+++ b/ctr-std/src/process.rs
@@ -1080,6 +1080,46 @@ impl fmt::Display for ExitStatus {
}
}
+/// This type represents the status code a process can return to its
+/// parent under normal termination.
+///
+/// Numeric values used in this type don't have portable meanings, and
+/// different platforms may mask different amounts of them.
+///
+/// For the platform's canonical successful and unsuccessful codes, see
+/// the [`SUCCESS`] and [`FAILURE`] associated items.
+///
+/// [`SUCCESS`]: #associatedconstant.SUCCESS
+/// [`FAILURE`]: #associatedconstant.FAILURE
+///
+/// **Warning**: While various forms of this were discussed in [RFC #1937],
+/// it was ultimately cut from that RFC, and thus this type is more subject
+/// to change even than the usual unstable item churn.
+///
+/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
+#[derive(Clone, Copy, Debug)]
+#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+pub struct ExitCode(imp::ExitCode);
+
+#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+impl ExitCode {
+ /// The canonical ExitCode for successful termination on this platform.
+ ///
+ /// Note that a `()`-returning `main` implicitly results in a successful
+ /// termination, so there's no need to return this from `main` unless
+ /// you're also returning other possible codes.
+ #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+ pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
+
+ /// The canonical ExitCode for unsuccessful termination on this platform.
+ ///
+ /// If you're only returning this and `SUCCESS` from `main`, consider
+ /// instead returning `Err(_)` and `Ok(())` respectively, which will
+ /// return the same codes (but will also `eprintln!` the error).
+ #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
+ pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
+}
+
impl Child {
/// Forces the child to exit. This is equivalent to sending a
/// SIGKILL on unix platforms.
@@ -1380,18 +1420,74 @@ pub fn abort() -> ! {
/// Basic usage:
///
/// ```no_run
-/// #![feature(getpid)]
/// use std::process;
///
/// println!("My pid is {}", process::id());
/// ```
///
///
-#[unstable(feature = "getpid", issue = "44971", reason = "recently added")]
+#[stable(feature = "getpid", since = "1.26.0")]
pub fn id() -> u32 {
::sys::os::getpid()
}
+/// A trait for implementing arbitrary return types in the `main` function.
+///
+/// The c-main function only supports to return integers as return type.
+/// So, every type implementing the `Termination` trait has to be converted
+/// to an integer.
+///
+/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
+/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
+#[cfg_attr(not(test), lang = "termination")]
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+#[rustc_on_unimplemented(
+ message="`main` has invalid return type `{Self}`",
+ label="`main` can only return types that implement `{Termination}`")]
+pub trait Termination {
+ /// Is called to get the representation of the value as status code.
+ /// This status code is returned to the operating system.
+ fn report(self) -> i32;
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for () {
+ #[inline]
+ fn report(self) -> i32 { ExitCode::SUCCESS.report() }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl<E: fmt::Debug> Termination for Result<(), E> {
+ fn report(self) -> i32 {
+ match self {
+ Ok(()) => ().report(),
+ Err(err) => Err::<!, _>(err).report(),
+ }
+ }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for ! {
+ fn report(self) -> i32 { self }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl<E: fmt::Debug> Termination for Result<!, E> {
+ fn report(self) -> i32 {
+ let Err(err) = self;
+ eprintln!("Error: {:?}", err);
+ ExitCode::FAILURE.report()
+ }
+}
+
+#[unstable(feature = "termination_trait_lib", issue = "43301")]
+impl Termination for ExitCode {
+ #[inline]
+ fn report(self) -> i32 {
+ self.0.as_i32()
+ }
+}
+
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
mod tests {
use io::prelude::*;
@@ -1843,4 +1939,10 @@ mod tests {
}
assert!(events > 0);
}
+
+ #[test]
+ fn test_command_implements_send() {
+ fn take_send_type<T: Send>(_: T) {}
+ take_send_type(Command::new(""))
+ }
}
diff --git a/ctr-std/src/rt.rs b/ctr-std/src/rt.rs
index 9dbaf78..e139276 100644
--- a/ctr-std/src/rt.rs
+++ b/ctr-std/src/rt.rs
@@ -68,7 +68,7 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
#[cfg(not(test))]
#[lang = "start"]
-fn lang_start<T: ::termination::Termination + 'static>
+fn lang_start<T: ::process::Termination + 'static>
(main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
{
lang_start_internal(&move || main().report(), argc, argv)
diff --git a/ctr-std/src/sync/condvar.rs b/ctr-std/src/sync/condvar.rs
index 5640217..3014283 100644
--- a/ctr-std/src/sync/condvar.rs
+++ b/ctr-std/src/sync/condvar.rs
@@ -14,7 +14,7 @@ use sync::{mutex, MutexGuard, PoisonError};
use sys_common::condvar as sys;
use sys_common::mutex as sys_mutex;
use sys_common::poison::{self, LockResult};
-use time::Duration;
+use time::{Duration, Instant};
/// A type indicating whether a timed wait on a condition variable returned
/// due to a time out or not.
@@ -47,11 +47,13 @@ impl WaitTimeoutResult {
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
+ ///
+ /// // Let's wait 20 milliseconds before notifying the condvar.
+ /// thread::sleep(Duration::from_millis(20));
+ ///
/// let mut started = lock.lock().unwrap();
/// // We update the boolean value.
/// *started = true;
- /// // Let's wait 20 milliseconds before notifying the condvar.
- /// thread::sleep(Duration::from_millis(20));
/// cvar.notify_one();
/// });
///
@@ -219,6 +221,64 @@ impl Condvar {
}
}
+ /// Blocks the current thread until this condition variable receives a
+ /// notification and the required condition is met. Spurious wakeups are
+ /// ignored and this function will only return once the condition has been
+ /// met.
+ ///
+ /// This function will atomically unlock the mutex specified (represented by
+ /// `guard`) and block the current thread. This means that any calls
+ /// to [`notify_one`] or [`notify_all`] which happen logically after the
+ /// mutex is unlocked are candidates to wake this thread up. When this
+ /// function call returns, the lock specified will have been re-acquired.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the mutex being waited on is
+ /// poisoned when this thread re-acquires the lock. For more information,
+ /// see information about [poisoning] on the [`Mutex`] type.
+ ///
+ /// [`notify_one`]: #method.notify_one
+ /// [`notify_all`]: #method.notify_all
+ /// [poisoning]: ../sync/struct.Mutex.html#poisoning
+ /// [`Mutex`]: ../sync/struct.Mutex.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(wait_until)]
+ ///
+ /// use std::sync::{Arc, Mutex, Condvar};
+ /// use std::thread;
+ ///
+ /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+ /// let pair2 = pair.clone();
+ ///
+ /// thread::spawn(move|| {
+ /// let &(ref lock, ref cvar) = &*pair2;
+ /// let mut started = lock.lock().unwrap();
+ /// *started = true;
+ /// // We notify the condvar that the value has changed.
+ /// cvar.notify_one();
+ /// });
+ ///
+ /// // Wait for the thread to start up.
+ /// let &(ref lock, ref cvar) = &*pair;
+ /// // As long as the value inside the `Mutex` is false, we wait.
+ /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
+ /// ```
+ #[unstable(feature = "wait_until", issue = "47960")]
+ pub fn wait_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
+ mut condition: F)
+ -> LockResult<MutexGuard<'a, T>>
+ where F: FnMut(&mut T) -> bool {
+ while !condition(&mut *guard) {
+ guard = self.wait(guard)?;
+ }
+ Ok(guard)
+ }
+
+
/// Waits on this condition variable for a notification, timing out after a
/// specified duration.
///
@@ -293,7 +353,15 @@ impl Condvar {
///
/// Note that the best effort is made to ensure that the time waited is
/// measured with a monotonic clock, and not affected by the changes made to
- /// the system time.
+ /// the system time. This function is susceptible to spurious wakeups.
+ /// Condition variables normally have a boolean predicate associated with
+ /// them, and the predicate must always be checked each time this function
+ /// returns to protect against spurious wakeups. Additionally, it is
+ /// typically desirable for the time-out to not exceed some duration in
+ /// spite of spurious wakes, thus the sleep-duration is decremented by the
+ /// amount slept. Alternatively, use the `wait_timeout_until` method
+ /// to wait until a condition is met with a total time-out regardless
+ /// of spurious wakes.
///
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
/// known to have elapsed.
@@ -302,6 +370,7 @@ impl Condvar {
/// returns, regardless of whether the timeout elapsed or not.
///
/// [`wait`]: #method.wait
+ /// [`wait_timeout_until`]: #method.wait_timeout_until
/// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
///
/// # Examples
@@ -353,6 +422,80 @@ impl Condvar {
}
}
+ /// Waits on this condition variable for a notification, timing out after a
+ /// specified duration. Spurious wakes will not cause this function to
+ /// return.
+ ///
+ /// The semantics of this function are equivalent to [`wait_until`] except
+ /// that the thread will be blocked for roughly no longer than `dur`. This
+ /// method should not be used for precise timing due to anomalies such as
+ /// preemption or platform differences that may not cause the maximum
+ /// amount of time waited to be precisely `dur`.
+ ///
+ /// Note that the best effort is made to ensure that the time waited is
+ /// measured with a monotonic clock, and not affected by the changes made to
+ /// the system time.
+ ///
+ /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
+ /// known to have elapsed without the condition being met.
+ ///
+ /// Like [`wait_until`], the lock specified will be re-acquired when this
+ /// function returns, regardless of whether the timeout elapsed or not.
+ ///
+ /// [`wait_until`]: #method.wait_until
+ /// [`wait_timeout`]: #method.wait_timeout
+ /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(wait_timeout_until)]
+ ///
+ /// use std::sync::{Arc, Mutex, Condvar};
+ /// use std::thread;
+ /// use std::time::Duration;
+ ///
+ /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
+ /// let pair2 = pair.clone();
+ ///
+ /// thread::spawn(move|| {
+ /// let &(ref lock, ref cvar) = &*pair2;
+ /// let mut started = lock.lock().unwrap();
+ /// *started = true;
+ /// // We notify the condvar that the value has changed.
+ /// cvar.notify_one();
+ /// });
+ ///
+ /// // wait for the thread to start up
+ /// let &(ref lock, ref cvar) = &*pair;
+ /// let result = cvar.wait_timeout_until(
+ /// lock.lock().unwrap(),
+ /// Duration::from_millis(100),
+ /// |&mut started| started,
+ /// ).unwrap();
+ /// if result.1.timed_out() {
+ /// // timed-out without the condition ever evaluating to true.
+ /// }
+ /// // access the locked mutex via result.0
+ /// ```
+ #[unstable(feature = "wait_timeout_until", issue = "47960")]
+ pub fn wait_timeout_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
+ dur: Duration, mut condition: F)
+ -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
+ where F: FnMut(&mut T) -> bool {
+ let start = Instant::now();
+ loop {
+ if condition(&mut *guard) {
+ return Ok((guard, WaitTimeoutResult(false)));
+ }
+ let timeout = match dur.checked_sub(start.elapsed()) {
+ Some(timeout) => timeout,
+ None => return Ok((guard, WaitTimeoutResult(true))),
+ };
+ guard = self.wait_timeout(guard, timeout)?.0;
+ }
+ }
+
/// Wakes up one blocked thread on this condvar.
///
/// If there is a blocked thread on this condition variable, then it will
@@ -478,6 +621,7 @@ impl Drop for Condvar {
#[cfg(test)]
mod tests {
+ /// #![feature(wait_until)]
use sync::mpsc::channel;
use sync::{Condvar, Mutex, Arc};
use sync::atomic::{AtomicBool, Ordering};
@@ -548,6 +692,29 @@ mod tests {
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
+ fn wait_until() {
+ let pair = Arc::new((Mutex::new(false), Condvar::new()));
+ let pair2 = pair.clone();
+
+ // Inside of our lock, spawn a new thread, and then wait for it to start.
+ thread::spawn(move|| {
+ let &(ref lock, ref cvar) = &*pair2;
+ let mut started = lock.lock().unwrap();
+ *started = true;
+ // We notify the condvar that the value has changed.
+ cvar.notify_one();
+ });
+
+ // Wait for the thread to start up.
+ let &(ref lock, ref cvar) = &*pair;
+ let guard = cvar.wait_until(lock.lock().unwrap(), |started| {
+ *started
+ });
+ assert!(*guard.unwrap());
+ }
+
+ #[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn wait_timeout_wait() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
@@ -567,6 +734,53 @@ mod tests {
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
+ fn wait_timeout_until_wait() {
+ let m = Arc::new(Mutex::new(()));
+ let c = Arc::new(Condvar::new());
+
+ let g = m.lock().unwrap();
+ let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| { false }).unwrap();
+ // no spurious wakeups. ensure it timed-out
+ assert!(wait.timed_out());
+ }
+
+ #[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
+ fn wait_timeout_until_instant_satisfy() {
+ let m = Arc::new(Mutex::new(()));
+ let c = Arc::new(Condvar::new());
+
+ let g = m.lock().unwrap();
+ let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| { true }).unwrap();
+ // ensure it didn't time-out even if we were not given any time.
+ assert!(!wait.timed_out());
+ }
+
+ #[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
+ fn wait_timeout_until_wake() {
+ let pair = Arc::new((Mutex::new(false), Condvar::new()));
+ let pair_copy = pair.clone();
+
+ let &(ref m, ref c) = &*pair;
+ let g = m.lock().unwrap();
+ let _t = thread::spawn(move || {
+ let &(ref lock, ref cvar) = &*pair_copy;
+ let mut started = lock.lock().unwrap();
+ thread::sleep(Duration::from_millis(1));
+ *started = true;
+ cvar.notify_one();
+ });
+ let (g2, wait) = c.wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| {
+ notified
+ }).unwrap();
+ // ensure it didn't time-out even if we were not given any time.
+ assert!(!wait.timed_out());
+ assert!(*g2);
+ }
+
+ #[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn wait_timeout_wake() {
let m = Arc::new(Mutex::new(()));
let c = Arc::new(Condvar::new());
diff --git a/ctr-std/src/sync/mod.rs b/ctr-std/src/sync/mod.rs
index 289b47b..642b284 100644
--- a/ctr-std/src/sync/mod.rs
+++ b/ctr-std/src/sync/mod.rs
@@ -18,7 +18,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::arc::{Arc, Weak};
+pub use alloc_crate::arc::{Arc, Weak};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;
diff --git a/ctr-std/src/sync/mpsc/mpsc_queue.rs b/ctr-std/src/sync/mpsc/mpsc_queue.rs
index 296773d..df945ac 100644
--- a/ctr-std/src/sync/mpsc/mpsc_queue.rs
+++ b/ctr-std/src/sync/mpsc/mpsc_queue.rs
@@ -23,10 +23,9 @@
pub use self::PopResult::*;
-use alloc::boxed::Box;
use core::ptr;
use core::cell::UnsafeCell;
-
+use boxed::Box;
use sync::atomic::{AtomicPtr, Ordering};
/// A result of the `pop` function.
diff --git a/ctr-std/src/sync/mpsc/spsc_queue.rs b/ctr-std/src/sync/mpsc/spsc_queue.rs
index cc4be92..9482f69 100644
--- a/ctr-std/src/sync/mpsc/spsc_queue.rs
+++ b/ctr-std/src/sync/mpsc/spsc_queue.rs
@@ -16,7 +16,7 @@
// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
-use alloc::boxed::Box;
+use boxed::Box;
use core::ptr;
use core::cell::UnsafeCell;
diff --git a/ctr-std/src/sync/rwlock.rs b/ctr-std/src/sync/rwlock.rs
index 2edf02e..f7fdedc 100644
--- a/ctr-std/src/sync/rwlock.rs
+++ b/ctr-std/src/sync/rwlock.rs
@@ -24,8 +24,8 @@ use sys_common::rwlock as sys;
/// typically allows for read-only access (shared access).
///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
-/// that aquire the lock, therefore blocking any threads waiting for the lock to
-/// become available. An `RwLock` will allow any number of readers to aquire the
+/// that acquire the lock, therefore blocking any threads waiting for the lock to
+/// become available. An `RwLock` will allow any number of readers to acquire the
/// lock as long as a writer is not holding the lock.
///
/// The priority policy of the lock is dependent on the underlying operating
diff --git a/ctr-std/src/sys/unix/os_str.rs b/ctr-std/src/sys/unix/os_str.rs
index 543c22e..e0da5bd 100644
--- a/ctr-std/src/sys/unix/os_str.rs
+++ b/ctr-std/src/sys/unix/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
use sync::Arc;
use sys_common::{AsInner, IntoInner};
use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)]
pub struct Buf {
@@ -104,6 +104,11 @@ impl Buf {
self.inner.shrink_to_fit()
}
+ #[inline]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.inner.shrink_to(min_capacity)
+ }
+
pub fn as_slice(&self) -> &Slice {
unsafe { mem::transmute(&*self.inner) }
}
diff --git a/ctr-std/src/sys/unix/process.rs b/ctr-std/src/sys/unix/process.rs
index f058aa9..06dafc6 100644
--- a/ctr-std/src/sys/unix/process.rs
+++ b/ctr-std/src/sys/unix/process.rs
@@ -16,6 +16,11 @@ use sys::pipe::AnonPipe;
use sys::{unsupported, Void};
use sys_common::process::{CommandEnv, DefaultEnvKey};
+use libc::c_int;
+
+const EXIT_SUCCESS: c_int = 0;
+const EXIT_FAILURE: c_int = 1;
+
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
@@ -149,3 +154,16 @@ impl Process {
match self.0 {}
}
}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(u8);
+
+impl ExitCode {
+ pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
+ pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
+
+ #[inline]
+ pub fn as_i32(&self) -> i32 {
+ self.0 as i32
+ }
+}
diff --git a/ctr-std/src/sys/unix/thread.rs b/ctr-std/src/sys/unix/thread.rs
index 76aa55a..694f85a 100644
--- a/ctr-std/src/sys/unix/thread.rs
+++ b/ctr-std/src/sys/unix/thread.rs
@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use alloc::boxed::FnBox;
+use alloc_crate::boxed::FnBox;
use libc;
use cmp;
use ffi::CStr;
diff --git a/ctr-std/src/sys_common/at_exit_imp.rs b/ctr-std/src/sys_common/at_exit_imp.rs
index ce6fd4c..f511981 100644
--- a/ctr-std/src/sys_common/at_exit_imp.rs
+++ b/ctr-std/src/sys_common/at_exit_imp.rs
@@ -12,7 +12,7 @@
//!
//! Documentation can be found on the `rt::at_exit` function.
-use alloc::boxed::FnBox;
+use alloc_crate::boxed::FnBox;
use ptr;
use sys_common::mutex::Mutex;
diff --git a/ctr-std/src/sys_common/bytestring.rs b/ctr-std/src/sys_common/bytestring.rs
index eb9cad0..971b839 100644
--- a/ctr-std/src/sys_common/bytestring.rs
+++ b/ctr-std/src/sys_common/bytestring.rs
@@ -11,7 +11,7 @@
#![allow(dead_code)]
use fmt::{Formatter, Result, Write};
-use std_unicode::lossy::{Utf8Lossy, Utf8LossyChunk};
+use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result {
// Writes out a valid unicode string with the correct escape sequences
diff --git a/ctr-std/src/sys_common/process.rs b/ctr-std/src/sys_common/process.rs
index fd1a5fd..0a64d78 100644
--- a/ctr-std/src/sys_common/process.rs
+++ b/ctr-std/src/sys_common/process.rs
@@ -14,7 +14,7 @@
use ffi::{OsStr, OsString};
use env;
use collections::BTreeMap;
-use alloc::borrow::Borrow;
+use alloc_crate::borrow::Borrow;
pub trait EnvKey:
From<OsString> + Into<OsString> +
diff --git a/ctr-std/src/sys_common/thread.rs b/ctr-std/src/sys_common/thread.rs
index f1379b6..cafa353 100644
--- a/ctr-std/src/sys_common/thread.rs
+++ b/ctr-std/src/sys_common/thread.rs
@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use alloc::boxed::FnBox;
+use alloc_crate::boxed::FnBox;
use env;
use sync::atomic::{self, Ordering};
use sys::stack_overflow;
diff --git a/ctr-std/src/sys_common/wtf8.rs b/ctr-std/src/sys_common/wtf8.rs
index 46d554d..dda4e1b 100644
--- a/ctr-std/src/sys_common/wtf8.rs
+++ b/ctr-std/src/sys_common/wtf8.rs
@@ -27,7 +27,6 @@
use core::str::next_code_point;
-use ascii::*;
use borrow::Cow;
use char;
use fmt;
@@ -254,6 +253,11 @@ impl Wtf8Buf {
self.bytes.shrink_to_fit()
}
+ #[inline]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.bytes.shrink_to(min_capacity)
+ }
+
/// Returns the number of bytes that this string buffer can hold without reallocating.
#[inline]
pub fn capacity(&self) -> usize {
@@ -428,20 +432,15 @@ impl fmt::Debug for Wtf8 {
formatter.write_str("\"")?;
let mut pos = 0;
- loop {
- match self.next_surrogate(pos) {
- None => break,
- Some((surrogate_pos, surrogate)) => {
- write_str_escaped(
- formatter,
- unsafe { str::from_utf8_unchecked(
- &self.bytes[pos .. surrogate_pos]
- )},
- )?;
- write!(formatter, "\\u{{{:x}}}", surrogate)?;
- pos = surrogate_pos + 3;
- }
- }
+ while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
+ write_str_escaped(
+ formatter,
+ unsafe { str::from_utf8_unchecked(
+ &self.bytes[pos .. surrogate_pos]
+ )},
+ )?;
+ write!(formatter, "\\u{{{:x}}}", surrogate)?;
+ pos = surrogate_pos + 3;
}
write_str_escaped(
formatter,
@@ -876,24 +875,22 @@ impl Hash for Wtf8 {
}
}
-impl AsciiExt for Wtf8 {
- type Owned = Wtf8Buf;
-
- fn is_ascii(&self) -> bool {
+impl Wtf8 {
+ pub fn is_ascii(&self) -> bool {
self.bytes.is_ascii()
}
- fn to_ascii_uppercase(&self) -> Wtf8Buf {
+ pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
}
- fn to_ascii_lowercase(&self) -> Wtf8Buf {
+ pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
}
- fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
+ pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
self.bytes.eq_ignore_ascii_case(&other.bytes)
}
- fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
- fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
+ pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
+ pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
}
#[cfg(test)]
diff --git a/ctr-std/src/termination.rs b/ctr-std/src/termination.rs
deleted file mode 100644
index e4a577e..0000000
--- a/ctr-std/src/termination.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use error::Error;
-// TODO: Add these consts to the libc crate for newlib
-mod exit {
- pub const SUCCESS: i32 = 0;
- pub const FAILURE: i32 = 1;
-}
-
-/// A trait for implementing arbitrary return types in the `main` function.
-///
-/// The c-main function only supports to return integers as return type.
-/// So, every type implementing the `Termination` trait has to be converted
-/// to an integer.
-///
-/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
-/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
-#[cfg_attr(not(test), lang = "termination")]
-#[unstable(feature = "termination_trait", issue = "43301")]
-#[rustc_on_unimplemented =
- "`main` can only return types that implement {Termination}, not `{Self}`"]
-pub trait Termination {
- /// Is called to get the representation of the value as status code.
- /// This status code is returned to the operating system.
- fn report(self) -> i32;
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for () {
- fn report(self) -> i32 { exit::SUCCESS }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl<T: Termination, E: Error> Termination for Result<T, E> {
- fn report(self) -> i32 {
- match self {
- Ok(val) => val.report(),
- Err(err) => {
- print_error(err);
- exit::FAILURE
- }
- }
- }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-fn print_error<E: Error>(err: E) {
- eprintln!("Error: {}", err.description());
-
- if let Some(ref err) = err.cause() {
- eprintln!("Caused by: {}", err.description());
- }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for ! {
- fn report(self) -> i32 { unreachable!(); }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for bool {
- fn report(self) -> i32 {
- if self { exit::SUCCESS } else { exit::FAILURE }
- }
-}
-
-#[unstable(feature = "termination_trait", issue = "43301")]
-impl Termination for i32 {
- fn report(self) -> i32 {
- self
- }
-}
diff --git a/ctr-std/src/thread/local.rs b/ctr-std/src/thread/local.rs
index fcbca38..99479bc 100644
--- a/ctr-std/src/thread/local.rs
+++ b/ctr-std/src/thread/local.rs
@@ -195,64 +195,20 @@ macro_rules! __thread_local_inner {
}
}
-/// Indicator of the state of a thread local storage key.
-#[unstable(feature = "thread_local_state",
- reason = "state querying was recently added",
- issue = "27716")]
-#[derive(Debug, Eq, PartialEq, Copy, Clone)]
-pub enum LocalKeyState {
- /// All keys are in this state whenever a thread starts. Keys will
- /// transition to the `Valid` state once the first call to [`with`] happens
- /// and the initialization expression succeeds.
- ///
- /// Keys in the `Uninitialized` state will yield a reference to the closure
- /// passed to [`with`] so long as the initialization routine does not panic.
- ///
- /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
- Uninitialized,
-
- /// Once a key has been accessed successfully, it will enter the `Valid`
- /// state. Keys in the `Valid` state will remain so until the thread exits,
- /// at which point the destructor will be run and the key will enter the
- /// `Destroyed` state.
- ///
- /// Keys in the `Valid` state will be guaranteed to yield a reference to the
- /// closure passed to [`with`].
- ///
- /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
- Valid,
-
- /// When a thread exits, the destructors for keys will be run (if
- /// necessary). While a destructor is running, and possibly after a
- /// destructor has run, a key is in the `Destroyed` state.
- ///
- /// Keys in the `Destroyed` states will trigger a panic when accessed via
- /// [`with`].
- ///
- /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
- Destroyed,
-}
-
/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
-#[unstable(feature = "thread_local_state",
- reason = "state querying was recently added",
- issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
pub struct AccessError {
_private: (),
}
-#[unstable(feature = "thread_local_state",
- reason = "state querying was recently added",
- issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
impl fmt::Debug for AccessError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("AccessError").finish()
}
}
-#[unstable(feature = "thread_local_state",
- reason = "state querying was recently added",
- issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
impl fmt::Display for AccessError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt("already destroyed", f)
@@ -312,64 +268,21 @@ impl<T: 'static> LocalKey<T> {
(*ptr).as_ref().unwrap()
}
- /// Query the current state of this key.
- ///
- /// A key is initially in the `Uninitialized` state whenever a thread
- /// starts. It will remain in this state up until the first call to [`with`]
- /// within a thread has run the initialization expression successfully.
- ///
- /// Once the initialization expression succeeds, the key transitions to the
- /// `Valid` state which will guarantee that future calls to [`with`] will
- /// succeed within the thread. Some keys might skip the `Uninitialized`
- /// state altogether and start in the `Valid` state as an optimization
- /// (e.g. keys initialized with a constant expression), but no guarantees
- /// are made.
- ///
- /// When a thread exits, each key will be destroyed in turn, and as keys are
- /// destroyed they will enter the `Destroyed` state just before the
- /// destructor starts to run. Keys may remain in the `Destroyed` state after
- /// destruction has completed. Keys without destructors (e.g. with types
- /// that are [`Copy`]), may never enter the `Destroyed` state.
- ///
- /// Keys in the `Uninitialized` state can be accessed so long as the
- /// initialization does not panic. Keys in the `Valid` state are guaranteed
- /// to be able to be accessed. Keys in the `Destroyed` state will panic on
- /// any call to [`with`].
- ///
- /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
- /// [`Copy`]: ../../std/marker/trait.Copy.html
- #[unstable(feature = "thread_local_state",
- reason = "state querying was recently added",
- issue = "27716")]
- pub fn state(&'static self) -> LocalKeyState {
- unsafe {
- match (self.inner)() {
- Some(cell) => {
- match *cell.get() {
- Some(..) => LocalKeyState::Valid,
- None => LocalKeyState::Uninitialized,
- }
- }
- None => LocalKeyState::Destroyed,
- }
- }
- }
-
/// Acquires a reference to the value in this TLS key.
///
/// This will lazily initialize the value if this thread has not referenced
/// this key yet. If the key has been destroyed (which may happen if this is called
- /// in a destructor), this function will return a ThreadLocalError.
+ /// in a destructor), this function will return a `ThreadLocalError`.
///
/// # Panics
///
/// This function will still `panic!()` if the key is uninitialized and the
/// key's initializer panics.
- #[unstable(feature = "thread_local_state",
- reason = "state querying was recently added",
- issue = "27716")]
+ #[stable(feature = "thread_local_try_with", since = "1.26.0")]
pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
- where F: FnOnce(&T) -> R {
+ where
+ F: FnOnce(&T) -> R,
+ {
unsafe {
let slot = (self.inner)().ok_or(AccessError {
_private: (),
@@ -530,7 +443,6 @@ pub mod os {
mod tests {
use sync::mpsc::{channel, Sender};
use cell::{Cell, UnsafeCell};
- use super::LocalKeyState;
use thread;
struct Foo(Sender<()>);
@@ -569,21 +481,13 @@ mod tests {
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
- assert!(FOO.state() == LocalKeyState::Destroyed);
+ assert!(FOO.try_with(|_| ()).is_err());
}
}
- fn foo() -> Foo {
- assert!(FOO.state() == LocalKeyState::Uninitialized);
- Foo
- }
- thread_local!(static FOO: Foo = foo());
+ thread_local!(static FOO: Foo = Foo);
thread::spawn(|| {
- assert!(FOO.state() == LocalKeyState::Uninitialized);
- FOO.with(|_| {
- assert!(FOO.state() == LocalKeyState::Valid);
- });
- assert!(FOO.state() == LocalKeyState::Valid);
+ assert!(FOO.try_with(|_| ()).is_ok());
}).join().ok().unwrap();
}
@@ -613,7 +517,7 @@ mod tests {
fn drop(&mut self) {
unsafe {
HITS += 1;
- if K2.state() == LocalKeyState::Destroyed {
+ if K2.try_with(|_| ()).is_err() {
assert_eq!(HITS, 3);
} else {
if HITS == 1 {
@@ -629,7 +533,7 @@ mod tests {
fn drop(&mut self) {
unsafe {
HITS += 1;
- assert!(K1.state() != LocalKeyState::Destroyed);
+ assert!(K1.try_with(|_| ()).is_ok());
assert_eq!(HITS, 2);
K1.with(|s| *s.get() = Some(S1));
}
@@ -648,7 +552,7 @@ mod tests {
impl Drop for S1 {
fn drop(&mut self) {
- assert!(K1.state() == LocalKeyState::Destroyed);
+ assert!(K1.try_with(|_| ()).is_err());
}
}
@@ -672,9 +576,7 @@ mod tests {
fn drop(&mut self) {
let S1(ref tx) = *self;
unsafe {
- if K2.state() != LocalKeyState::Destroyed {
- K2.with(|s| *s.get() = Some(Foo(tx.clone())));
- }
+ let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone())));
}
}
}
diff --git a/ctr-std/src/thread/mod.rs b/ctr-std/src/thread/mod.rs
index ee49bf7..71aee67 100644
--- a/ctr-std/src/thread/mod.rs
+++ b/ctr-std/src/thread/mod.rs
@@ -191,7 +191,7 @@ use time::Duration;
#[macro_use] mod local;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::local::{LocalKey, LocalKeyState, AccessError};
+pub use self::local::{LocalKey, AccessError};
// The types used by the thread_local! macro to access TLS keys. Note that there
// are two types, the "OS" type and the "fast" type. The OS thread local key
@@ -652,7 +652,7 @@ pub fn panicking() -> bool {
/// The thread may sleep longer than the duration specified due to scheduling
/// specifics or platform-dependent functionality.
///
-/// # Platform behavior
+/// # Platform-specific behavior
///
/// On Unix platforms this function will not return early due to a
/// signal being received or a spurious wakeup.
@@ -676,7 +676,7 @@ pub fn sleep_ms(ms: u32) {
/// The thread may sleep longer than the duration specified due to scheduling
/// specifics or platform-dependent functionality.
///
-/// # Platform behavior
+/// # Platform-specific behavior
///
/// On Unix platforms this function will not return early due to a
/// signal being received or a spurious wakeup. Platforms which do not support
@@ -837,7 +837,7 @@ pub fn park_timeout_ms(ms: u32) {
///
/// See the [park documentation][park] for more details.
///
-/// # Platform behavior
+/// # Platform-specific behavior
///
/// Platforms which do not support nanosecond precision for sleeping will have
/// `dur` rounded up to the nearest granularity of time they can sleep for.
diff --git a/ctr-std/src/time.rs b/ctr-std/src/time.rs
index 12f2a9b..1215302 100644
--- a/ctr-std/src/time.rs
+++ b/ctr-std/src/time.rs
@@ -49,6 +49,9 @@ pub use core::time::Duration;
/// allows measuring the duration between two instants (or comparing two
/// instants).
///
+/// The size of an `Instant` struct may vary depending on the target operating
+/// system.
+///
/// Example:
///
/// ```no_run
@@ -88,6 +91,9 @@ pub struct Instant(time::Instant);
/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
/// or perhaps some other string representation.
///
+/// The size of a `SystemTime` struct may vary depending on the target operating
+/// system.
+///
/// [`Instant`]: ../../std/time/struct.Instant.html
/// [`Result`]: ../../std/result/enum.Result.html
/// [`Duration`]: ../../std/time/struct.Duration.html
@@ -253,6 +259,29 @@ impl fmt::Debug for Instant {
}
impl SystemTime {
+ /// An anchor in time which can be used to create new `SystemTime` instances or
+ /// learn about where in time a `SystemTime` lies.
+ ///
+ /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
+ /// respect to the system clock. Using `duration_since` on an existing
+ /// `SystemTime` instance can tell how far away from this point in time a
+ /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
+ /// `SystemTime` instance to represent another fixed point in time.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(assoc_unix_epoch)]
+ /// use std::time::SystemTime;
+ ///
+ /// match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
+ /// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
+ /// Err(_) => panic!("SystemTime before UNIX EPOCH!"),
+ /// }
+ /// ```
+ #[unstable(feature = "assoc_unix_epoch", issue = "49502")]
+ pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH;
+
/// Returns the system time corresponding to "now".
///
/// # Examples