Browse Source

Update for Rust nightly 2018-04-19

pull/10/head
Fenrir 7 years ago
parent
commit
b330206f55
  1. 4
      .travis.yml
  2. 6
      ctr-std/Cargo.toml
  3. 121
      ctr-std/src/alloc.rs
  4. 498
      ctr-std/src/ascii.rs
  5. 365
      ctr-std/src/collections/hash/map.rs
  6. 46
      ctr-std/src/collections/hash/set.rs
  7. 91
      ctr-std/src/collections/hash/table.rs
  8. 28
      ctr-std/src/collections/mod.rs
  9. 16
      ctr-std/src/env.rs
  10. 36
      ctr-std/src/error.rs
  11. 60
      ctr-std/src/f32.rs
  12. 59
      ctr-std/src/f64.rs
  13. 34
      ctr-std/src/ffi/c_str.rs
  14. 30
      ctr-std/src/ffi/os_str.rs
  15. 422
      ctr-std/src/fs.rs
  16. 175
      ctr-std/src/heap.rs
  17. 149
      ctr-std/src/io/buffered.rs
  18. 20
      ctr-std/src/io/cursor.rs
  19. 8
      ctr-std/src/io/error.rs
  20. 312
      ctr-std/src/io/mod.rs
  21. 92
      ctr-std/src/io/stdio.rs
  22. 7
      ctr-std/src/io/util.rs
  23. 52
      ctr-std/src/lib.rs
  24. 98
      ctr-std/src/macros.rs
  25. 14
      ctr-std/src/net/addr.rs
  26. 95
      ctr-std/src/net/ip.rs
  27. 13
      ctr-std/src/net/mod.rs
  28. 19
      ctr-std/src/net/parser.rs
  29. 75
      ctr-std/src/net/tcp.rs
  30. 65
      ctr-std/src/net/udp.rs
  31. 8
      ctr-std/src/num.rs
  32. 9
      ctr-std/src/panic.rs
  33. 63
      ctr-std/src/primitive_docs.rs
  34. 106
      ctr-std/src/process.rs
  35. 2
      ctr-std/src/rt.rs
  36. 222
      ctr-std/src/sync/condvar.rs
  37. 2
      ctr-std/src/sync/mod.rs
  38. 3
      ctr-std/src/sync/mpsc/mpsc_queue.rs
  39. 2
      ctr-std/src/sync/mpsc/spsc_queue.rs
  40. 4
      ctr-std/src/sync/rwlock.rs
  41. 7
      ctr-std/src/sys/unix/os_str.rs
  42. 18
      ctr-std/src/sys/unix/process.rs
  43. 2
      ctr-std/src/sys/unix/thread.rs
  44. 2
      ctr-std/src/sys_common/at_exit_imp.rs
  45. 2
      ctr-std/src/sys_common/bytestring.rs
  46. 2
      ctr-std/src/sys_common/process.rs
  47. 2
      ctr-std/src/sys_common/thread.rs
  48. 29
      ctr-std/src/sys_common/wtf8.rs
  49. 80
      ctr-std/src/termination.rs
  50. 128
      ctr-std/src/thread/local.rs
  51. 8
      ctr-std/src/thread/mod.rs
  52. 29
      ctr-std/src/time.rs

4
.travis.yml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
language: rust
rust:
- nightly-2018-03-07
- nightly-2018-04-19
- nightly
matrix:
@ -16,6 +16,8 @@ install: @@ -16,6 +16,8 @@ install:
- export DEVKITPRO="$HOME/dkp"
- export DEVKITARM="$DEVKITPRO/devkitARM"
- export PATH="$PATH:$DEVKITARM/bin"
- export CC_3ds="$DEVKITARM/bin/arm-none-eabi-gcc"
- export TARGET_CFLAGS="-mfloat-abi=hard -march=armv6k"
- wget https://raw.githubusercontent.com/devkitPro/installer/master/perl/devkitARMupdate.pl
- chmod +x devkitARMupdate.pl
- ./devkitARMupdate.pl "$DEVKITPRO"

6
ctr-std/Cargo.toml

@ -3,9 +3,6 @@ name = "std" @@ -3,9 +3,6 @@ name = "std"
version = "0.0.0"
license = "MIT/Apache 2.0"
[dependencies.compiler_builtins]
git = "https://github.com/rust-lang-nursery/compiler-builtins"
[dependencies.alloc_system]
git = "https://github.com/rust3ds/alloc_system3ds"
@ -13,6 +10,3 @@ git = "https://github.com/rust3ds/alloc_system3ds" @@ -13,6 +10,3 @@ git = "https://github.com/rust3ds/alloc_system3ds"
path = "../ctru-sys"
default-features = false
features = ["stdbuild"]
[features]
citra = []

121
ctr-std/src/alloc.rs

@ -0,0 +1,121 @@ @@ -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!()
}
}
}

498
ctr-std/src/ascii.rs

@ -26,9 +26,8 @@ @@ -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; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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] { @@ -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 { @@ -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",
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
" ",
);
}
}

365
ctr-std/src/collections/hash/map.rs

@ -11,6 +11,7 @@ @@ -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}; @@ -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 { @@ -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> { @@ -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> { @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> { @@ -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> @@ -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> { @@ -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> { @@ -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> { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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);
map.entry(0) <- 10;
assert_eq!(map[&0], 10);
fn test_try_reserve() {
assert_eq!(map.len(), 11);
}
let mut empty_bytes: HashMap<u8,u8> = HashMap::new();
#[test]
fn test_placement_panic() {
let mut map = HashMap::new();
map.extend((0..10).map(|i| (i, i)));
const MAX_USIZE: usize = usize::MAX;
fn mkpanic() -> usize { panic!() }
// 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;
// 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));
if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!"); }
// add new key
let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); }));
assert_eq!(map.len(), 9);
assert!(!map.contains_key(&100));
}
#[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);
}
}

46
ctr-std/src/collections/hash/set.rs

@ -292,6 +292,34 @@ impl<T, S> HashSet<T, S> @@ -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> @@ -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> { @@ -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> { @@ -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> { @@ -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> @@ -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> @@ -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> @@ -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> { @@ -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 { @@ -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));

91
ctr-std/src/collections/hash/table.rs

@ -8,8 +8,7 @@ @@ -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> @@ -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>> { @@ -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() { @@ -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> { @@ -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> { @@ -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,7 +1183,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> { @@ -1188,7 +1183,7 @@ 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,
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.

28
ctr-std/src/collections/mod.rs

@ -64,11 +64,11 @@ @@ -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 @@ @@ -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;

16
ctr-std/src/env.rs

@ -552,17 +552,17 @@ pub fn home_dir() -> Option<PathBuf> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let mut dir = env::temp_dir();
/// dir.push("foo.txt");
///
/// let f = File::create(dir)?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "env", since = "1.0.0")]
pub fn temp_dir() -> PathBuf {
@ -723,10 +723,10 @@ pub fn args_os() -> ArgsOs { @@ -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 { @@ -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")]

36
ctr-std/src/error.rs

@ -51,14 +51,13 @@ @@ -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> { @@ -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 ! { @@ -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 { @@ -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 { @@ -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 { @@ -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`

60
ctr-std/src/f32.rs

@ -329,6 +329,57 @@ impl f32 { @@ -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 { @@ -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 { @@ -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;
///

59
ctr-std/src/f64.rs

@ -315,6 +315,56 @@ impl f64 { @@ -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 { @@ -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 { @@ -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;
///

34
ctr-std/src/ffi/c_str.rs

@ -91,7 +91,7 @@ use sys; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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

30
ctr-std/src/ffi/os_str.rs

@ -295,6 +295,36 @@ impl OsString { @@ -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

422
ctr-std/src/fs.rs

@ -41,11 +41,11 @@ use time::SystemTime; @@ -41,11 +41,11 @@ use time::SystemTime;
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut file = File::create("foo.txt")?;
/// file.write_all(b"Hello, world!")?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
///
/// Read the contents of a file into a [`String`]:
@ -54,13 +54,13 @@ use time::SystemTime; @@ -54,13 +54,13 @@ use time::SystemTime;
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// # fn foo() -> std::io::Result<()> {
/// 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(())
/// # }
/// Ok(())
/// }
/// ```
///
/// It can be more efficient to read the contents of a file with a buffered
@ -71,19 +71,28 @@ use time::SystemTime; @@ -71,19 +71,28 @@ use time::SystemTime;
/// use std::io::BufReader;
/// use std::io::prelude::*;
///
/// # fn foo() -> std::io::Result<()> {
/// 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(())
/// # }
/// 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 { @@ -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 { @@ -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>> {
/// fn main() -> Result<(), Box<std::error::Error + 'static>> {
/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
/// # Ok(())
/// # }
/// 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>> { @@ -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>> { @@ -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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::write("foo.txt", b"Lorem ipsum")?;
/// # Ok(())
/// # }
/// 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 { @@ -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 { @@ -371,10 +380,10 @@ impl File {
/// ```no_run
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
/// # Ok(())
/// # }
/// 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 { @@ -392,13 +401,13 @@ impl File {
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
/// f.write_all(b"Hello, world!")?;
///
/// f.sync_all()?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_all(&self) -> io::Result<()> {
@ -423,13 +432,13 @@ impl File { @@ -423,13 +432,13 @@ impl File {
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
/// f.write_all(b"Hello, world!")?;
///
/// f.sync_data()?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_data(&self) -> io::Result<()> {
@ -444,6 +453,10 @@ impl File { @@ -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 { @@ -453,12 +466,15 @@ impl File {
/// ```no_run
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
/// f.set_len(10)?;
/// # Ok(())
/// # }
/// 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 { @@ -471,33 +487,55 @@ 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")?;
/// let metadata = f.metadata()?;
/// # Ok(())
/// # }
/// 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 { @@ -524,17 +562,20 @@ impl File {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```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(())
/// # }
/// 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 { @@ -850,51 +891,63 @@ impl Metadata {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```no_run
/// fn main() -> std::io::Result<()> {
/// use std::fs;
///
/// let metadata = fs::metadata("foo.txt")?;
///
/// println!("{:?}", metadata.file_type());
/// # Ok(())
/// # }
/// 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<()> {
/// ```no_run
/// fn main() -> std::io::Result<()> {
/// use std::fs;
///
/// let metadata = fs::metadata("foo.txt")?;
///
/// assert!(!metadata.is_dir());
/// # Ok(())
/// # }
/// 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;
///
/// fn main() -> std::io::Result<()> {
/// let metadata = fs::metadata("foo.txt")?;
///
/// assert!(metadata.is_file());
/// # Ok(())
/// # }
/// 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 { @@ -903,15 +956,15 @@ impl Metadata {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```no_run
/// use std::fs;
///
/// fn main() -> std::io::Result<()> {
/// let metadata = fs::metadata("foo.txt")?;
///
/// assert_eq!(0, metadata.len());
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> u64 { self.0.size() }
@ -920,15 +973,15 @@ impl Metadata { @@ -920,15 +973,15 @@ impl Metadata {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```no_run
/// use std::fs;
///
/// fn main() -> std::io::Result<()> {
/// let metadata = fs::metadata("foo.txt")?;
///
/// assert!(!metadata.permissions().readonly());
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn permissions(&self) -> Permissions {
@ -947,10 +1000,10 @@ impl Metadata { @@ -947,10 +1000,10 @@ impl Metadata {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```no_run
/// use std::fs;
///
/// fn main() -> std::io::Result<()> {
/// let metadata = fs::metadata("foo.txt")?;
///
/// if let Ok(time) = metadata.modified() {
@ -958,8 +1011,8 @@ impl Metadata { @@ -958,8 +1011,8 @@ impl Metadata {
/// } 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,10 +1035,10 @@ impl Metadata { @@ -982,10 +1035,10 @@ impl Metadata {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```no_run
/// use std::fs;
///
/// fn main() -> std::io::Result<()> {
/// let metadata = fs::metadata("foo.txt")?;
///
/// if let Ok(time) = metadata.accessed() {
@ -993,15 +1046,15 @@ impl Metadata { @@ -993,15 +1046,15 @@ impl Metadata {
/// } 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,10 +1066,10 @@ impl Metadata { @@ -1013,10 +1066,10 @@ impl Metadata {
///
/// # Examples
///
/// ```
/// # fn foo() -> std::io::Result<()> {
/// ```no_run
/// use std::fs;
///
/// fn main() -> std::io::Result<()> {
/// let metadata = fs::metadata("foo.txt")?;
///
/// if let Ok(time) = metadata.created() {
@ -1024,8 +1077,8 @@ impl Metadata { @@ -1024,8 +1077,8 @@ impl Metadata {
/// } 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 { @@ -1057,16 +1110,16 @@ impl Permissions {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
/// let metadata = f.metadata()?;
///
/// assert_eq!(false, metadata.permissions().readonly());
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn readonly(&self) -> bool { self.0.readonly() }
@ -1082,10 +1135,10 @@ impl Permissions { @@ -1082,10 +1135,10 @@ impl Permissions {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let f = File::create("foo.txt")?;
/// let metadata = f.metadata()?;
/// let mut permissions = metadata.permissions();
@ -1097,8 +1150,8 @@ impl Permissions { @@ -1097,8 +1150,8 @@ impl Permissions {
///
/// // just this particular `permissions`.
/// assert_eq!(true, permissions.readonly());
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn set_readonly(&mut self, readonly: bool) {
@ -1107,43 +1160,58 @@ impl Permissions { @@ -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<()> {
/// ```no_run
/// fn main() -> std::io::Result<()> {
/// use std::fs;
///
/// let metadata = fs::metadata("foo.txt")?;
/// let file_type = metadata.file_type();
///
/// assert_eq!(file_type.is_dir(), false);
/// # Ok(())
/// # }
/// 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<()> {
/// ```no_run
/// fn main() -> std::io::Result<()> {
/// use std::fs;
///
/// let metadata = fs::metadata("foo.txt")?;
/// let file_type = metadata.file_type();
///
/// assert_eq!(file_type.is_file(), true);
/// # Ok(())
/// # }
/// 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 { @@ -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;
///
/// 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(())
/// # }
/// 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 { @@ -1204,15 +1274,16 @@ impl DirEntry {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::fs;
/// # fn foo() -> std::io::Result<()> {
///
/// 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 { @@ -1357,13 +1428,13 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::fs;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// fs::remove_file("a.txt")?;
/// # Ok(())
/// # }
/// 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<()> { @@ -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;
///
/// fn main() -> std::io::Result<()> {
/// let attr = fs::metadata("/some/file/path.txt")?;
/// // inspect attr ...
/// # Ok(())
/// # }
/// 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> { @@ -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;
///
/// fn main() -> std::io::Result<()> {
/// let attr = fs::symlink_metadata("/some/file/path.txt")?;
/// // inspect attr ...
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
/// # Ok(())
/// # }
/// 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<()> @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt
/// # Ok(()) }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
/// # Ok(())
/// # }
/// 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<( @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::soft_link("a.txt", "b.txt")?;
/// # Ok(())
/// # }
/// 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<( @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let path = fs::read_link("a.txt")?;
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let path = fs::canonicalize("../a/../foo.txt")?;
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::create_dir("/some/dir")?;
/// # Ok(())
/// # }
/// 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<()> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::create_dir_all("/some/dir")?;
/// # Ok(())
/// # }
/// 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<()> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::remove_dir("/some/dir")?;
/// # Ok(())
/// # }
/// 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<()> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// fs::remove_dir_all("/some/dir")?;
/// # Ok(())
/// # }
/// 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> { @@ -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;
///
/// fn main() -> std::io::Result<()> {
/// let mut perms = fs::metadata("foo.txt")?.permissions();
/// perms.set_readonly(true);
/// fs::set_permissions("foo.txt", perms)?;
/// # Ok(())
/// # }
/// 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 { @@ -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);
}

175
ctr-std/src/heap.rs

@ -1,175 +0,0 @@ @@ -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,
}
}
}

149
ctr-std/src/io/buffered.rs

@ -25,26 +25,32 @@ use memchr; @@ -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<()> {
/// 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(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufReader<R> {
@ -59,15 +65,15 @@ impl<R: Read> 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<()> {
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let reader = BufReader::new(f);
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> {
@ -80,15 +86,15 @@ impl<R: Read> 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<()> {
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let reader = BufReader::with_capacity(10, f);
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let reader = BufReader::new(f1);
///
/// let f2 = reader.get_ref();
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let mut reader = BufReader::new(f1);
///
/// let f2 = reader.get_mut();
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
@ -150,13 +156,14 @@ impl<R: Read> BufReader<R> { @@ -150,13 +156,14 @@ 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<()> {
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let mut reader = BufReader::new(f1);
/// assert!(reader.is_empty());
@ -164,12 +171,40 @@ impl<R: Read> BufReader<R> { @@ -164,12 +171,40 @@ impl<R: Read> BufReader<R> {
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let reader = BufReader::new(f1);
///
/// let f2 = reader.into_inner();
/// # Ok(())
/// # }
/// 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> { @@ -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> { @@ -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,12 +737,12 @@ impl<W> fmt::Display for IntoInnerError<W> { @@ -696,12 +737,12 @@ 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<()> {
/// 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 -
@ -722,8 +763,8 @@ impl<W> fmt::Display for IntoInnerError<W> { @@ -722,8 +763,8 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// file.read_to_string(&mut contents)?;
///
/// assert_eq!(contents.as_bytes(), &road_not_taken[..]);
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LineWriter<W: Write> {
@ -736,15 +777,15 @@ impl<W: Write> LineWriter<W> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let file = LineWriter::new(file);
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> LineWriter<W> {
@ -757,15 +798,15 @@ impl<W: Write> 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<()> {
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let file = LineWriter::with_capacity(100, file);
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let file = LineWriter::new(file);
///
/// let reference = file.get_ref();
/// # Ok(())
/// # }
/// 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> { @@ -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<()> {
/// 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(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
///
/// let writer: LineWriter<File> = LineWriter::new(file);
///
/// let file: File = writer.into_inner()?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {

20
ctr-std/src/io/cursor.rs

@ -10,7 +10,6 @@ @@ -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 @@ -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")
})?;

8
ctr-std/src/io/error.rs

@ -292,8 +292,8 @@ impl Error { @@ -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 { @@ -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")]

312
ctr-std/src/io/mod.rs

@ -24,12 +24,12 @@ @@ -24,12 +24,12 @@
//! 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<()> {
//! fn main() -> io::Result<()> {
//! let mut f = File::open("foo.txt")?;
//! let mut buffer = [0; 10];
//!
@ -37,8 +37,8 @@ @@ -37,8 +37,8 @@
//! f.read(&mut buffer)?;
//!
//! println!("The bytes: {:?}", buffer);
//! # Ok(())
//! # }
//! Ok(())
//! }
//! ```
//!
//! [`Read`] and [`Write`] are so important, implementors of the two traits have a
@ -52,13 +52,13 @@ @@ -52,13 +52,13 @@
//! 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<()> {
//! fn main() -> io::Result<()> {
//! let mut f = File::open("foo.txt")?;
//! let mut buffer = [0; 10];
//!
@ -69,8 +69,8 @@ @@ -69,8 +69,8 @@
//! f.read(&mut buffer)?;
//!
//! println!("The bytes: {:?}", buffer);
//! # Ok(())
//! # }
//! Ok(())
//! }
//! ```
//!
//! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but
@ -87,13 +87,13 @@ @@ -87,13 +87,13 @@
//! 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<()> {
//! fn main() -> io::Result<()> {
//! let f = File::open("foo.txt")?;
//! let mut reader = BufReader::new(f);
//! let mut buffer = String::new();
@ -102,20 +102,20 @@ @@ -102,20 +102,20 @@
//! reader.read_line(&mut buffer)?;
//!
//! println!("{}", buffer);
//! # Ok(())
//! # }
//! 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<()> {
//! fn main() -> io::Result<()> {
//! let f = File::create("foo.txt")?;
//! {
//! let mut writer = BufWriter::new(f);
@ -125,32 +125,32 @@ @@ -125,32 +125,32 @@
//!
//! } // 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<()> {
//! fn main() -> io::Result<()> {
//! let mut input = String::new();
//!
//! io::stdin().read_line(&mut input)?;
//!
//! println!("You typed: {}", input.trim());
//! # Ok(())
//! # }
//! 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 @@ @@ -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<()> {
//! fn main() -> io::Result<()> {
//! io::stdout().write(&[42])?;
//! # Ok(())
//! # }
//! Ok(())
//! }
//! ```
//!
//! Of course, using [`io::stdout`] directly is less common than something like
@ -179,22 +179,21 @@ @@ -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<()> {
//! fn main() -> io::Result<()> {
//! let f = File::open("foo.txt")?;
//! let reader = BufReader::new(f);
//!
//! for line in reader.lines() {
//! println!("{}", line?);
//! }
//!
//! # Ok(())
//! # }
//! Ok(())
//! }
//! ```
//!
//! ## Functions
@ -203,13 +202,13 @@ @@ -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<()> {
//! fn main() -> io::Result<()> {
//! io::copy(&mut io::stdin(), &mut io::stdout())?;
//! # Ok(())
//! # }
//! Ok(())
//! }
//! ```
//!
//! [functions-list]: #functions-1
@ -416,12 +415,12 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> @@ -416,12 +415,12 @@ 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<()> {
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// let mut buffer = [0; 10];
///
@ -437,17 +436,17 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> @@ -437,17 +436,17 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
/// f.read_to_string(&mut buffer)?;
///
/// // and more! See the other methods for more details.
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
///
/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`:
///
/// ```
/// ```no_run
/// # use std::io;
/// use std::io::prelude::*;
///
/// # fn foo() -> io::Result<()> {
/// fn main() -> io::Result<()> {
/// let mut b = "This string will be read".as_bytes();
/// let mut buffer = [0; 10];
///
@ -455,8 +454,8 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> @@ -455,8 +454,8 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
/// b.read(&mut buffer)?;
///
/// // etc... it works exactly as a File does!
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
///
/// [`read()`]: trait.Read.html#tymethod.read
@ -509,19 +508,19 @@ pub trait 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<()> {
/// 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(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
@ -582,20 +581,25 @@ pub trait Read { @@ -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<()> {
/// 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(())
/// # }
/// 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 { @@ -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<()> {
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// let mut buffer = String::new();
///
/// f.read_to_string(&mut buffer)?;
/// # Ok(())
/// # }
/// 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 { @@ -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<()> {
/// 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(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "read_exact", since = "1.6.0")]
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
@ -726,12 +735,12 @@ pub trait Read { @@ -726,12 +735,12 @@ 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<()> {
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// let mut buffer = Vec::new();
/// let mut other_buffer = Vec::new();
@ -746,8 +755,8 @@ pub trait Read { @@ -746,8 +755,8 @@ pub trait Read {
///
/// // original file still usable, read the rest
/// f.read_to_end(&mut other_buffer)?;
/// # Ok(())
/// # }
/// 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 { @@ -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<()> {
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
///
/// 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 { @@ -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<()> {
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
///
/// 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,12 +856,12 @@ pub trait Read { @@ -847,12 +856,12 @@ 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<()> {
/// fn main() -> io::Result<()> {
/// let mut f1 = File::open("foo.txt")?;
/// let mut f2 = File::open("bar.txt")?;
///
@ -862,8 +871,8 @@ pub trait Read { @@ -862,8 +871,8 @@ pub trait Read {
/// // 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(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
@ -885,12 +894,12 @@ pub trait Read { @@ -885,12 +894,12 @@ 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<()> {
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// let mut buffer = [0; 5];
///
@ -898,8 +907,8 @@ pub trait Read { @@ -898,8 +907,8 @@ pub trait Read {
/// let mut handle = f.take(5);
///
/// handle.read(&mut buffer)?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn take(self, limit: u64) -> Take<Self> where Self: Sized {
@ -974,16 +983,16 @@ impl Initializer { @@ -974,16 +983,16 @@ impl Initializer {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut buffer = File::create("foo.txt")?;
///
/// buffer.write(b"some bytes")?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(spotlight)]
@ -1022,17 +1031,17 @@ pub trait Write { @@ -1022,17 +1031,17 @@ pub trait Write {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// 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(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, buf: &[u8]) -> Result<usize>;
@ -1047,18 +1056,18 @@ pub trait Write { @@ -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<()> {
/// fn main() -> std::io::Result<()> {
/// let mut buffer = BufWriter::new(File::create("foo.txt")?);
///
/// buffer.write(b"some bytes")?;
/// buffer.flush()?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn flush(&mut self) -> Result<()>;
@ -1082,16 +1091,16 @@ pub trait Write { @@ -1082,16 +1091,16 @@ pub trait Write {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut buffer = File::create("foo.txt")?;
///
/// buffer.write_all(b"some bytes")?;
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
@ -1131,19 +1140,19 @@ pub trait Write { @@ -1131,19 +1140,19 @@ pub trait Write {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// 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(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
@ -1187,19 +1196,19 @@ pub trait Write { @@ -1187,19 +1196,19 @@ pub trait Write {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::Write;
/// use std::fs::File;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// let mut buffer = File::create("foo.txt")?;
///
/// let reference = buffer.by_ref();
///
/// // we can use reference just like our original buffer
/// reference.write_all(b"some bytes")?;
/// # Ok(())
/// # }
/// 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 { @@ -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<()> {
/// 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(())
/// # }
/// 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>) @@ -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,12 +1351,12 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) @@ -1342,12 +1351,12 @@ 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<()> {
/// fn main() -> io::Result<()> {
/// let f = File::open("foo.txt")?;
/// let f = BufReader::new(f);
///
@ -1355,8 +1364,8 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) @@ -1355,8 +1364,8 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
/// println!("{}", line.unwrap());
/// }
///
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
///
#[stable(feature = "rust1", since = "1.0.0")]
@ -1383,7 +1392,7 @@ pub trait BufRead: Read { @@ -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 { @@ -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 { @@ -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> { @@ -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<()> {
/// 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(())
/// # }
/// 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> { @@ -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<()> {
/// 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(())
/// # }
/// 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> { @@ -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<()> {
/// 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(())
/// # }
/// 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> { @@ -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<()> {
/// fn main() -> io::Result<()> {
/// let f = File::open("foo.txt")?;
///
/// // read at most five bytes
/// let handle = f.take(5);
///
/// println!("limit: {}", handle.limit());
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn limit(&self) -> u64 { self.limit }
@ -1819,13 +1828,12 @@ impl<T> Take<T> { @@ -1819,13 +1828,12 @@ 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<()> {
/// fn main() -> io::Result<()> {
/// let f = File::open("foo.txt")?;
///
/// // read at most five bytes
@ -1833,10 +1841,10 @@ impl<T> Take<T> { @@ -1833,10 +1841,10 @@ impl<T> Take<T> {
/// handle.set_limit(10);
///
/// assert_eq!(handle.limit(), 10);
/// # Ok(())
/// # }
/// 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,12 +1853,12 @@ impl<T> Take<T> { @@ -1845,12 +1853,12 @@ impl<T> Take<T> {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> io::Result<()> {
/// fn main() -> io::Result<()> {
/// let mut file = File::open("foo.txt")?;
///
/// let mut buffer = [0; 5];
@ -1858,8 +1866,8 @@ impl<T> Take<T> { @@ -1858,8 +1866,8 @@ impl<T> Take<T> {
/// handle.read(&mut buffer)?;
///
/// let file = handle.into_inner();
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "io_take_into_inner", since = "1.15.0")]
pub fn into_inner(self) -> T {
@ -1870,12 +1878,12 @@ impl<T> Take<T> { @@ -1870,12 +1878,12 @@ impl<T> Take<T> {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> io::Result<()> {
/// fn main() -> io::Result<()> {
/// let mut file = File::open("foo.txt")?;
///
/// let mut buffer = [0; 5];
@ -1883,8 +1891,8 @@ impl<T> Take<T> { @@ -1883,8 +1891,8 @@ impl<T> Take<T> {
/// handle.read(&mut buffer)?;
///
/// let file = handle.get_ref();
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn get_ref(&self) -> &T {
@ -1899,12 +1907,12 @@ impl<T> Take<T> { @@ -1899,12 +1907,12 @@ impl<T> Take<T> {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> io::Result<()> {
/// fn main() -> io::Result<()> {
/// let mut file = File::open("foo.txt")?;
///
/// let mut buffer = [0; 5];
@ -1912,8 +1920,8 @@ impl<T> Take<T> { @@ -1912,8 +1920,8 @@ impl<T> Take<T> {
/// handle.read(&mut buffer)?;
///
/// let file = handle.get_mut();
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "more_io_inner_methods", since = "1.20.0")]
pub fn get_mut(&mut self) -> &mut T {

92
ctr-std/src/io/stdio.rs

@ -17,7 +17,7 @@ use io::{self, Initializer, BufReader, LineWriter}; @@ -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> { @@ -171,29 +171,29 @@ pub struct StdinLock<'a> {
///
/// Using implicit synchronization:
///
/// ```
/// ```no_run
/// use std::io::{self, Read};
///
/// # fn foo() -> io::Result<String> {
/// fn main() -> io::Result<()> {
/// let mut buffer = String::new();
/// io::stdin().read_to_string(&mut buffer)?;
/// # Ok(buffer)
/// # }
/// Ok(())
/// }
/// ```
///
/// Using explicit synchronization:
///
/// ```
/// ```no_run
/// use std::io::{self, Read};
///
/// # fn foo() -> io::Result<String> {
/// 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)
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
@ -225,17 +225,17 @@ impl Stdin { @@ -225,17 +225,17 @@ impl Stdin {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::{self, Read};
///
/// # fn foo() -> io::Result<String> {
/// 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)
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdinLock {
@ -369,29 +369,29 @@ pub struct StdoutLock<'a> { @@ -369,29 +369,29 @@ pub struct StdoutLock<'a> {
///
/// Using implicit synchronization:
///
/// ```
/// ```no_run
/// use std::io::{self, Write};
///
/// # fn foo() -> io::Result<()> {
/// 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<()> {
/// fn main() -> io::Result<()> {
/// let stdout = io::stdout();
/// let mut handle = stdout.lock();
///
/// handle.write(b"hello world")?;
///
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
@ -419,17 +419,17 @@ impl Stdout { @@ -419,17 +419,17 @@ impl Stdout {
///
/// # Examples
///
/// ```
/// ```no_run
/// use std::io::{self, Write};
///
/// # fn foo() -> io::Result<()> {
/// fn main() -> io::Result<()> {
/// let stdout = io::stdout();
/// let mut handle = stdout.lock();
///
/// 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> { @@ -505,29 +505,29 @@ pub struct StderrLock<'a> {
///
/// Using implicit synchronization:
///
/// ```
/// ```no_run
/// use std::io::{self, Write};
///
/// # fn foo() -> io::Result<()> {
/// 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<()> {
/// fn main() -> io::Result<()> {
/// let stderr = io::stderr();
/// let mut handle = stderr.lock();
///
/// 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>> { @@ -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,
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| {
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);
}

7
ctr-std/src/io/util.rs

@ -34,16 +34,15 @@ use mem; @@ -34,16 +34,15 @@ use mem;
/// ```
/// use std::io;
///
/// # fn foo() -> io::Result<()> {
/// fn main() -> io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// io::copy(&mut reader, &mut writer)?;
///
/// assert_eq!(&b"hello"[..], &writer[..]);
/// # Ok(())
/// # }
/// # foo().unwrap();
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>

52
ctr-std/src/lib.rs

@ -259,6 +259,7 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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::*; @@ -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; @@ -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; @@ -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; @@ -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; @@ -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!`

98
ctr-std/src/macros.rs

@ -68,6 +68,9 @@ macro_rules! panic { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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.

14
ctr-std/src/net/addr.rs

@ -12,7 +12,9 @@ use fmt; @@ -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; @@ -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 { @@ -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 } @@ -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) { @@ -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();

95
ctr-std/src/net/ip.rs

@ -26,6 +26,9 @@ use sys_common::{AsInner, FromInner}; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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))
}

13
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> @@ -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 { @@ -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 { @@ -170,17 +175,19 @@ impl fmt::Debug for LookupHost {
///
/// use std::net;
///
/// # fn foo() -> std::io::Result<()> {
/// 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)
}

19
ctr-std/src/net/parser.rs

@ -372,6 +372,25 @@ impl FromStr for SocketAddr { @@ -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

75
ctr-std/src/net/tcp.rs

@ -72,7 +72,7 @@ pub struct TcpStream(net_imp::TcpStream); @@ -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); @@ -80,15 +80,15 @@ pub struct TcpStream(net_imp::TcpStream);
/// // ...
/// }
///
/// # fn process() -> io::Result<()> {
/// 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?);
/// }
/// # Ok(())
/// # }
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpListener(net_imp::TcpListener);
@ -259,19 +259,21 @@ impl TcpStream { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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();

65
ctr-std/src/net/udp.rs

@ -44,7 +44,7 @@ use time::Duration; @@ -44,7 +44,7 @@ use time::Duration;
/// ```no_run
/// use std::net::UdpSocket;
///
/// # fn foo() -> std::io::Result<()> {
/// fn main() -> std::io::Result<()> {
/// {
/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
///
@ -57,9 +57,9 @@ use time::Duration; @@ -57,9 +57,9 @@ use time::Duration;
/// let buf = &mut buf[..amt];
/// buf.reverse();
/// socket.send_to(buf, &src)?;
/// # Ok(())
/// } // 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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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();

8
ctr-std/src/num.rs

@ -21,6 +21,13 @@ pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError} @@ -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 { @@ -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));

9
ctr-std/src/panic.rs

@ -23,7 +23,10 @@ use sync::{Arc, Mutex, RwLock, atomic}; @@ -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>( @@ -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 {} @@ -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> {}

63
ctr-std/src/primitive_docs.rs

@ -79,7 +79,6 @@ mod prim_bool { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { } @@ -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 { }

106
ctr-std/src/process.rs

@ -1080,6 +1080,46 @@ impl fmt::Display for ExitStatus { @@ -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() -> ! { @@ -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 { @@ -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(""))
}
}

2
ctr-std/src/rt.rs

@ -68,7 +68,7 @@ fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe), @@ -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)

222
ctr-std/src/sync/condvar.rs

@ -14,7 +14,7 @@ use sync::{mutex, MutexGuard, PoisonError}; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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};
@ -546,6 +690,29 @@ mod tests { @@ -546,6 +690,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() {
@ -565,6 +732,53 @@ mod tests { @@ -565,6 +732,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() {

2
ctr-std/src/sync/mod.rs

@ -18,7 +18,7 @@ @@ -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;

3
ctr-std/src/sync/mpsc/mpsc_queue.rs

@ -23,10 +23,9 @@ @@ -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.

2
ctr-std/src/sync/mpsc/spsc_queue.rs

@ -16,7 +16,7 @@ @@ -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;

4
ctr-std/src/sync/rwlock.rs

@ -24,8 +24,8 @@ use sys_common::rwlock as sys; @@ -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

7
ctr-std/src/sys/unix/os_str.rs

@ -19,7 +19,7 @@ use rc::Rc; @@ -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 { @@ -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) }
}

18
ctr-std/src/sys/unix/process.rs

@ -16,6 +16,11 @@ use sys::pipe::AnonPipe; @@ -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 { @@ -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
}
}

2
ctr-std/src/sys/unix/thread.rs

@ -8,7 +8,7 @@ @@ -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;

2
ctr-std/src/sys_common/at_exit_imp.rs

@ -12,7 +12,7 @@ @@ -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;

2
ctr-std/src/sys_common/bytestring.rs

@ -11,7 +11,7 @@ @@ -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

2
ctr-std/src/sys_common/process.rs

@ -14,7 +14,7 @@ @@ -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> +

2
ctr-std/src/sys_common/thread.rs

@ -8,7 +8,7 @@ @@ -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;

29
ctr-std/src/sys_common/wtf8.rs

@ -27,7 +27,6 @@ @@ -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 { @@ -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,10 +432,7 @@ impl fmt::Debug for Wtf8 { @@ -428,10 +432,7 @@ impl fmt::Debug for Wtf8 {
formatter.write_str("\"")?;
let mut pos = 0;
loop {
match self.next_surrogate(pos) {
None => break,
Some((surrogate_pos, surrogate)) => {
while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
write_str_escaped(
formatter,
unsafe { str::from_utf8_unchecked(
@ -441,8 +442,6 @@ impl fmt::Debug for Wtf8 { @@ -441,8 +442,6 @@ impl fmt::Debug for Wtf8 {
write!(formatter, "\\u{{{:x}}}", surrogate)?;
pos = surrogate_pos + 3;
}
}
}
write_str_escaped(
formatter,
unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) },
@ -876,24 +875,22 @@ impl Hash for Wtf8 { @@ -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)]

80
ctr-std/src/termination.rs

@ -1,80 +0,0 @@ @@ -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
}
}

128
ctr-std/src/thread/local.rs

@ -195,64 +195,20 @@ macro_rules! __thread_local_inner { @@ -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> { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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())));
}
}
}

8
ctr-std/src/thread/mod.rs

@ -191,7 +191,7 @@ use time::Duration; @@ -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 { @@ -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) { @@ -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) { @@ -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.

29
ctr-std/src/time.rs

@ -49,6 +49,9 @@ pub use core::time::Duration; @@ -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); @@ -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 { @@ -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

Loading…
Cancel
Save