Browse Source

We stdlib now

pull/10/head
Fenrir 8 years ago
parent
commit
08b71a18cd
  1. 5
      3ds.json
  2. 5
      Cargo.toml
  3. 12
      Xargo.toml
  4. 4
      build.rs
  5. 14
      ctr-libc/Cargo.toml
  6. 1
      ctr-libc/README.md
  7. 122
      ctr-libc/src/constants.rs
  8. 39
      ctr-libc/src/functions.rs
  9. 190
      ctr-libc/src/lib.rs
  10. 31
      ctr-std/3ds.json
  11. 13
      ctr-std/Cargo.toml
  12. 1
      ctr-std/README.md
  13. 6
      ctr-std/Xargo.toml
  14. 30
      ctr-std/src/ascii.rs
  15. 53
      ctr-std/src/error.rs
  16. 181
      ctr-std/src/f32.rs
  17. 216
      ctr-std/src/f64.rs
  18. 74
      ctr-std/src/ffi/c_str.rs
  19. 24
      ctr-std/src/ffi/mod.rs
  20. 166
      ctr-std/src/ffi/os_str.rs
  21. 72
      ctr-std/src/io/buffered.rs
  22. 70
      ctr-std/src/io/cursor.rs
  23. 315
      ctr-std/src/io/error.rs
  24. 25
      ctr-std/src/io/impls.rs
  25. 297
      ctr-std/src/io/mod.rs
  26. 2
      ctr-std/src/io/prelude.rs
  27. 3
      ctr-std/src/io/print.rs
  28. 11
      ctr-std/src/io/util.rs
  29. 174
      ctr-std/src/lib.rs
  30. 481
      ctr-std/src/macros.rs
  31. 143
      ctr-std/src/memchr.rs
  32. 44
      ctr-std/src/num.rs
  33. 17
      ctr-std/src/os/mod.rs
  34. 11
      ctr-std/src/panicking.rs
  35. 510
      ctr-std/src/path.rs
  36. 146
      ctr-std/src/prelude/mod.rs
  37. 53
      ctr-std/src/prelude/v1.rs
  38. 6
      ctr-std/src/rt.rs
  39. 29
      ctr-std/src/sync/mod.rs
  40. 37
      ctr-std/src/sys/mod.rs
  41. 61
      ctr-std/src/sys/unix/ext/ffi.rs
  42. 41
      ctr-std/src/sys/unix/ext/mod.rs
  43. 51
      ctr-std/src/sys/unix/memchr.rs
  44. 50
      ctr-std/src/sys/unix/mod.rs
  45. 123
      ctr-std/src/sys/unix/os.rs
  46. 119
      ctr-std/src/sys/unix/os_str.rs
  47. 29
      ctr-std/src/sys/unix/path.rs
  48. 179
      ctr-std/src/sys_common/io.rs
  49. 76
      ctr-std/src/sys_common/mod.rs
  50. 5
      ctru-sys/Cargo.toml
  51. 1
      ctru-sys/src/applets/mod.rs
  52. 258
      ctru-sys/src/applets/swkbd.rs
  53. 7
      ctru-sys/src/lib.rs
  54. 82
      ctru-sys/src/ndsp/channel.rs
  55. 2
      ctru-sys/src/ndsp/mod.rs
  56. 112
      ctru-sys/src/ndsp/ndsp.rs
  57. 62
      ctru-sys/src/os.rs
  58. 64
      ctru-sys/src/romfs.rs
  59. 24
      ctru-sys/src/sdmc.rs
  60. 28
      ctru-sys/src/services/apt.rs
  61. 1
      ctru-sys/src/services/mod.rs
  62. 6
      ctru-sys/src/services/nfc.rs
  63. 2
      ctru-sys/src/services/ps.rs
  64. 2
      ctru-sys/src/services/soc.rs
  65. 4
      ctru-sys/src/services/sslc.rs
  66. 244
      ctru-sys/src/svc.rs
  67. 6
      ctru-sys/src/sys/inaddr.rs
  68. 6
      ctru-sys/src/sys/libc.rs
  69. 3
      ctru-sys/src/sys/mod.rs
  70. 20
      ctru-sys/src/sys/socket.rs
  71. 4
      ctru-sys/src/types.rs
  72. 1
      src/lib.rs
  73. 15
      src/services/fs.rs
  74. 15
      std/Cargo.toml
  75. 5
      std/src/ffi/mod.rs
  76. 100
      std/src/lib.rs
  77. 105
      std/src/macros.rs
  78. 397
      std/src/memchr.rs
  79. 1
      std/src/prelude/mod.rs
  80. 49
      std/src/prelude/v1.rs
  81. 5
      std/src/sync/mod.rs
  82. 92
      std/src/sync/mutex.rs
  83. 25
      std/src/sys/mod.rs
  84. 1204
      std/src/sys/wtf8.rs

5
3ds.json

@ -5,15 +5,16 @@
"ar": "arm-none-eabi-ar", "ar": "arm-none-eabi-ar",
"target-endian": "little", "target-endian": "little",
"target-pointer-width": "32", "target-pointer-width": "32",
"target-family": "unix",
"arch": "arm", "arch": "arm",
"os": "linux", "os": "linux",
"env": "newlib",
"cpu": "mpcore", "cpu": "mpcore",
"features": "+vfp2", "features": "+vfp2",
"relocation-model": "static", "relocation-model": "static",
"disable-redzone": true,
"executables": true, "executables": true,
"no-compiler-rt": true,
"exe-suffix": ".elf", "exe-suffix": ".elf",
"panic-strategy": "abort",
"pre-link-args": [ "pre-link-args": [
"-specs=3dsx.specs", "-specs=3dsx.specs",
"-march=armv6k", "-march=armv6k",

5
Cargo.toml

@ -12,7 +12,10 @@ crate-type = ["rlib"]
name = "ctru" name = "ctru"
[dependencies.ctru-sys] [dependencies.ctru-sys]
path = "ctru-sys" path = "../ctru-sys"
[dependencies.bitflags] [dependencies.bitflags]
version = "0.7.0" version = "0.7.0"
[dependencies.widestring]
widestring = "0.2.2"

12
Xargo.toml

@ -1,2 +1,10 @@
[target.3ds.dependencies] [dependencies.collections]
collections = {}
[dependencies.ctr-libc]
path = "ctr-libc"
default-features = false
stage = 0
[dependencies.std]
path = "ctr-std"
stage = 1

4
build.rs

@ -4,12 +4,12 @@ use std::fs;
use std::option::Option::{self, Some, None}; use std::option::Option::{self, Some, None};
const ENV_DKP: &'static str = "CTRULIB"; const ENV_DKP: &'static str = "DEVKITPRO";
fn find_libctru() -> Option<PathBuf> { fn find_libctru() -> Option<PathBuf> {
if let Ok(value) = env::var(ENV_DKP) { if let Ok(value) = env::var(ENV_DKP) {
let mut path = PathBuf::from(value); let mut path = PathBuf::from(value);
path.push("lib"); path.push("libctru/lib");
// metadata returns Err if the dir does not exist // metadata returns Err if the dir does not exist
if let Ok(metadata) = fs::metadata(path.as_path()) { if let Ok(metadata) = fs::metadata(path.as_path()) {
if metadata.is_dir() { if metadata.is_dir() {

14
ctr-libc/Cargo.toml

@ -0,0 +1,14 @@
[package]
name = "ctr-libc"
version = "0.1.0"
authors = ["Fenrir <fenrirwolf@gmail.com>", "The Rust Project Developers"]
license = "MIT/Apache 2.0"
description = """
A library for types and bindings to native C functions found in newlib
for devkitARM
"""
[features]
default = ["use_std"]
use_std = []

1
ctr-libc/README.md

@ -0,0 +1 @@
Extended libc bindings for use with ctr-std. This library is experimental. Use of some functions might result in undefined symbols.

122
ctr-libc/src/constants.rs

@ -0,0 +1,122 @@
// Many of these constants are unused/unnecessary. But let's keep them around for now.
pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;
pub const EPERM: ::c_int = 1;
pub const ENOENT: ::c_int = 2;
pub const ESRCH: ::c_int = 3;
pub const EINTR: ::c_int = 4;
pub const EIO: ::c_int = 5;
pub const ENXIO: ::c_int = 6;
pub const E2BIG: ::c_int = 7;
pub const ENOEXEC: ::c_int = 8;
pub const EBADF: ::c_int = 9;
pub const ECHILD: ::c_int = 10;
pub const EAGAIN: ::c_int = 11;
pub const ENOMEM: ::c_int = 12;
pub const EACCES: ::c_int = 13;
pub const EFAULT: ::c_int = 14;
pub const EBUSY: ::c_int = 16;
pub const EEXIST: ::c_int = 17;
pub const EXDEV: ::c_int = 18;
pub const ENODEV: ::c_int = 19;
pub const ENOTDIR: ::c_int = 20;
pub const EISDIR: ::c_int = 21;
pub const EINVAL: ::c_int = 22;
pub const ENFILE: ::c_int = 23;
pub const EMFILE: ::c_int = 24;
pub const ENOTTY: ::c_int = 25;
pub const ETXTBSY: ::c_int = 26;
pub const EFBIG: ::c_int = 27;
pub const ENOSPC: ::c_int = 28;
pub const ESPIPE: ::c_int = 29;
pub const EROFS: ::c_int = 30;
pub const EMLINK: ::c_int = 31;
pub const EPIPE: ::c_int = 32;
pub const EDOM: ::c_int = 33;
pub const ERANGE: ::c_int = 34;
pub const ENOMSG: ::c_int = 35;
pub const EIDRM: ::c_int = 36;
pub const EDEADLK: ::c_int = 45;
pub const ENOLCK: ::c_int = 46;
pub const ENOSTR: ::c_int = 60;
pub const ENODATA: ::c_int = 61;
pub const ETIME: ::c_int = 62;
pub const ENOSR: ::c_int = 63;
pub const ENOLINK: ::c_int = 67;
pub const EPROTO: ::c_int = 71;
pub const EMULTIHOP: ::c_int = 74;
pub const EBADMSG: ::c_int = 77;
pub const EFTYPE: ::c_int = 79;
pub const ENOSYS: ::c_int = 88;
pub const ENOTEMPTY: ::c_int = 90;
pub const ENAMETOOLONG: ::c_int = 91;
pub const ELOOP: ::c_int = 92;
pub const EOPNOTSUPP: ::c_int = 95;
pub const EPFNOSUPPORT: ::c_int = 96;
pub const ECONNRESET: ::c_int = 104;
pub const ENOBUFS: ::c_int = 105;
pub const EAFNOSUPPORT: ::c_int = 106;
pub const EPROTOTYPE: ::c_int = 107;
pub const ENOTSOCK: ::c_int = 108;
pub const ENOPROTOOPT: ::c_int = 109;
pub const ECONNREFUSED: ::c_int = 111;
pub const EADDRINUSE: ::c_int = 112;
pub const ECONNABORTED: ::c_int = 113;
pub const ENETUNREACH: ::c_int = 114;
pub const ENETDOWN: ::c_int = 115;
pub const ETIMEDOUT: ::c_int = 116;
pub const EHOSTDOWN: ::c_int = 117;
pub const EHOSTUNREACH: ::c_int = 118;
pub const EINPROGRESS: ::c_int = 119;
pub const EALREADY: ::c_int = 120;
pub const EDESTADDRREQ: ::c_int = 121;
pub const EMSGSIZE: ::c_int = 122;
pub const EPROTONOSUPPORT: ::c_int = 123;
pub const EADDRNOTAVAIL: ::c_int = 125;
pub const ENETRESET: ::c_int = 126;
pub const EISCONN: ::c_int = 127;
pub const ENOTCONN: ::c_int = 128;
pub const ETOOMANYREFS: ::c_int = 129;
pub const EDQUOT: ::c_int = 132;
pub const ESTALE: ::c_int = 133;
pub const ENOTSUP: ::c_int = 134;
pub const EILSEQ: ::c_int = 138;
pub const EOVERFLOW: ::c_int = 139;
pub const ECANCELED: ::c_int = 140;
pub const ENOTRECOVERABLE: ::c_int = 141;
pub const EOWNERDEAD: ::c_int = 142;
pub const EWOULDBLOCK: ::c_int = 11;
pub const __ELASTERROR: ::c_int = 2000;
pub const O_RDONLY: ::c_int = 0;
pub const O_WRONLY: ::c_int = 1;
pub const O_RDWR: ::c_int = 2;
pub const O_APPEND: ::c_int = 8;
pub const O_CREAT: ::c_int = 512;
pub const O_TRUNC: ::c_int = 1024;
pub const O_EXCL: ::c_int = 2048;
pub const O_SYNC: ::c_int = 8192;
pub const O_NONBLOCK: ::c_int = 16384;
pub const O_NOCTTY: ::c_int = 32768;
pub const FD_CLOEXEC: ::c_int = 1;
pub const DT_FIFO: u8 = 1;
pub const DT_CHR: u8 = 2;
pub const DT_DIR: u8 = 4;
pub const DT_BLK: u8 = 6;
pub const DT_REG: u8 = 8;
pub const DT_LNK: u8 = 10;
pub const DT_SOCK: u8 = 12;
pub const O_CLOEXEC: ::c_int = 0x80000;
pub const O_ACCMODE: ::c_int = 3;
pub const SEEK_SET: ::c_int = 0;
pub const SEEK_CUR: ::c_int = 1;
pub const SEEK_END: ::c_int = 2;
pub const SIG_IGN: ::sighandler_t = 1 as ::sighandler_t;
pub const SIGPIPE: ::c_int = 13;

39
ctr-libc/src/functions.rs

@ -0,0 +1,39 @@
extern "C" {
pub fn abort() -> !;
pub fn chdir(dir: *const ::c_char) -> ::c_int;
pub fn chmod(path: *const ::c_char, mode: ::mode_t) -> ::c_int;
pub fn close(fd: ::c_int) -> ::c_int;
pub fn closedir(dirp: *mut ::DIR) -> ::c_int;
pub fn exit(status: ::c_int) -> !;
pub fn fchmod(fd: ::c_int, mode: ::mode_t) -> ::c_int;
pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
pub fn fdatasync(fd: ::c_int) -> ::c_int;
pub fn free(p: *mut ::c_void);
pub fn fstat(fildes: ::c_int, buf: *mut ::stat) -> ::c_int;
pub fn ftruncate(fd: ::c_int, length: ::off_t) -> ::c_int;
pub fn fsync(fd: ::c_int) -> ::c_int;
pub fn getcwd(buf: *mut ::c_char, size: ::size_t) -> *mut ::c_char;
pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int;
pub fn link(src: *const ::c_char, dst: *const ::c_char) -> ::c_int;
pub fn lstat(path: *const ::c_char, buf: *mut ::stat) -> ::c_int;
pub fn lseek(fd: ::c_int, offset: ::off_t, whence: ::c_int) -> ::off_t;
pub fn memchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void;
pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void;
pub fn mkdir(path: *const ::c_char, mode: ::mode_t) -> ::c_int;
pub fn open(path: *const ::c_char, oflag: ::c_int, ...) -> ::c_int;
pub fn opendir(dirname: *const ::c_char) -> *mut ::DIR;
pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: ::off_t) -> ::ssize_t;
pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: ::off_t) -> ::ssize_t;
pub fn read(fd: ::c_int, puf: *mut ::c_void, count: ::size_t) -> ::ssize_t;
pub fn readlink(path: *const ::c_char, buf: *mut ::c_char, bufsz: ::size_t) -> ::ssize_t;
pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) -> ::c_int;
pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) -> *mut ::c_char;
pub fn rename(oldname: *const ::c_char, newname: *const ::c_char) -> ::c_int;
pub fn rmdir(path: *const ::c_char) -> ::c_int;
pub fn signal(signum: ::c_int, handler: ::sighandler_t) -> ::sighandler_t;
pub fn stat(path: *const ::c_char, buf: *mut ::stat) -> ::c_int;
pub fn strlen(cs: *const ::c_char) -> ::size_t;
pub fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int;
pub fn unlink(c: *const ::c_char) -> ::c_int;
pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t;
}

190
ctr-libc/src/lib.rs

@ -0,0 +1,190 @@
// Copyright 2012-2015 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.
#![allow(bad_style, overflowing_literals, improper_ctypes, non_camel_case_types)]
// Attributes needed when building as part of the standard library
#![cfg_attr(stdbuild, feature(no_std, core, core_slice_ext, staged_api, custom_attribute, cfg_target_vendor))]
#![cfg_attr(stdbuild, feature(link_cfg))]
#![cfg_attr(stdbuild, no_std)]
#![cfg_attr(stdbuild, staged_api)]
#![cfg_attr(stdbuild, allow(warnings))]
#![cfg_attr(stdbuild, unstable(feature = "libc",
reason = "use `libc` from crates.io",
issue = "27783"))]
#![cfg_attr(not(feature = "use_std"), no_std)]
#[cfg(all(not(stdbuild), not(dox), feature = "use_std"))]
extern crate std as core;
mod constants;
mod functions;
pub use constants::*;
pub use functions::*;
#[link(name = "c")]
#[link(name = "m")]
extern {}
#[repr(u8)]
pub enum c_void {
__variant1,
__variant2,
}
// char is u8 on ARM
pub type c_char = u8;
pub type c_schar = i8;
pub type c_uchar = u8;
pub type c_short = i16;
pub type c_ushort = u16;
pub type c_int = i32;
pub type c_uint = u32;
pub type c_float = f32;
pub type c_double = f64;
pub type c_longlong = i64;
pub type c_ulonglong = u64;
// 4 bytes on ARM
pub type c_long = i32;
pub type c_ulong = u32;
pub type size_t = usize;
pub type ptrdiff_t = isize;
pub type intptr_t = isize;
pub type uintptr_t = usize;
pub type ssize_t = isize;
// devkitARM says wchar_t is 4 bytes. Nintendo's API says it's 2 bytes.
// hope you never have to interact between the two...
pub type wchar_t = c_int;
pub type int8_t = i8;
pub type uint8_t = u8;
pub type int16_t = i16;
pub type uint16_t = u16;
pub type int32_t = i32;
pub type uint32_t = u32;
pub type int64_t = i64;
pub type uint64_t = u64;
pub type time_t = i32;
pub type clockid_t = c_int;
pub type mode_t = u32;
pub type sighandler_t = size_t;
pub type dev_t = u32;
pub type nlink_t = u32;
pub type uid_t = u32;
pub type gid_t = u32;
pub type off_t = i64;
pub type blksize_t = i32;
pub type blkcnt_t = c_ulong;
pub type fsblkcnt_t = uint64_t;
pub type fsfilcnt_t = uint32_t;
pub type ino_t = u32;
pub type suseconds_t = i32;
pub type error_t = c_int;
pub enum timezone {}
pub enum _reent {}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct timeval {
pub tv_sec: time_t,
pub tv_usec: suseconds_t,
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct timespec {
pub tv_sec: time_t,
pub tv_nsec: c_long,
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct itimerspec {
pub it_interval: timespec,
pub it_value: timespec,
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct tm {
pub tm_sec: c_int,
pub tm_min: c_int,
pub tm_hour: c_int,
pub tm_mday: c_int,
pub tm_mon: c_int,
pub tm_year: c_int,
pub tm_wday: c_int,
pub tm_yday: c_int,
pub tm_isdst: c_int,
}
pub enum DIR {}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct stat {
pub st_dev: dev_t,
pub st_ino: ino_t,
pub st_mode: mode_t,
pub st_nlink: nlink_t,
pub st_uid: uid_t,
pub st_gid: gid_t,
pub st_rdev: dev_t,
pub st_size: off_t,
pub st_atime: time_t,
pub st_spare1: c_long,
pub st_mtime: time_t,
pub st_spare2: c_long,
pub st_ctime: time_t,
pub st_spare3: c_long,
pub st_blksize: blksize_t,
pub st_blocks: blkcnt_t,
pub st_spare4: [c_long; 2usize],
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct statvfs {
pub f_bsize: c_ulong,
pub f_frsize: c_ulong,
pub f_blocks: fsblkcnt_t,
pub f_bfree: fsblkcnt_t,
pub f_bavail: fsblkcnt_t,
pub f_files: fsfilcnt_t,
pub f_ffree: fsfilcnt_t,
pub f_favail: fsfilcnt_t,
pub f_fsid: c_ulong,
pub f_flag: c_ulong,
pub f_namemax: c_ulong,
}
#[repr(C)]
#[derive(Copy)]
pub struct dirent {
pub d_ino: ino_t,
pub d_type: c_uchar,
pub d_name: [c_char; 256usize],
}
impl Clone for dirent {
fn clone(&self) -> Self { *self }
}

31
ctr-std/3ds.json

@ -0,0 +1,31 @@
{
"data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64",
"llvm-target": "arm-none-eabihf",
"linker": "arm-none-eabi-gcc",
"ar": "arm-none-eabi-ar",
"target-endian": "little",
"target-pointer-width": "32",
"target-family": "unix",
"arch": "arm",
"os": "linux",
"env": "newlib",
"cpu": "mpcore",
"features": "+vfp2",
"relocation-model": "static",
"executables": true,
"exe-suffix": ".elf",
"panic-strategy": "abort",
"pre-link-args": [
"-specs=3dsx.specs",
"-march=armv6k",
"-mtune=mpcore",
"-mfloat-abi=hard",
"-mtp=soft"
],
"post-link-args": [
"-lc",
"-lm",
"-lsysbase",
"-lc"
]
}

13
ctr-std/Cargo.toml

@ -0,0 +1,13 @@
[package]
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]
version = "0.1.1"
[dependencies.spin]
version = "0.4"

1
ctr-std/README.md

@ -0,0 +1 @@
A work-in-progress port of the Rust Standard Library for the Nintendo 3DS, based on [ctrulib](https://github.com/smealum/ctrulib/) and the [devkitARM](http://devkitPro.org) toolchain.

6
ctr-std/Xargo.toml

@ -0,0 +1,6 @@
[dependencies.collections]
[dependencies.ctr-libc]
path = "../ctr-libc"
default-features = false
stage = 1

30
std/src/ascii.rs → ctr-std/src/ascii.rs

@ -10,8 +10,11 @@
//! Operations on ASCII strings and characters. //! Operations on ASCII strings and characters.
#![stable(feature = "rust1", since = "1.0.0")]
use mem; use mem;
use ops::Range; use ops::Range;
use iter::FusedIterator;
/// Extension methods for ASCII-subset only operations on string slices. /// Extension methods for ASCII-subset only operations on string slices.
/// ///
@ -35,8 +38,10 @@ use ops::Range;
/// it will not get mapped to an uppercase variant, resulting in `"CAF\u{e9}"`. /// it will not get mapped to an uppercase variant, resulting in `"CAF\u{e9}"`.
/// ///
/// [combining character]: https://en.wikipedia.org/wiki/Combining_character /// [combining character]: https://en.wikipedia.org/wiki/Combining_character
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsciiExt { pub trait AsciiExt {
/// Container type for copied ASCII characters. /// Container type for copied ASCII characters.
#[stable(feature = "rust1", since = "1.0.0")]
type Owned; type Owned;
/// Checks if the value is within the ASCII range. /// Checks if the value is within the ASCII range.
@ -52,6 +57,7 @@ pub trait AsciiExt {
/// assert!(ascii.is_ascii()); /// assert!(ascii.is_ascii());
/// assert!(!utf8.is_ascii()); /// assert!(!utf8.is_ascii());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn is_ascii(&self) -> bool; fn is_ascii(&self) -> bool;
/// Makes a copy of the string in ASCII upper case. /// Makes a copy of the string in ASCII upper case.
@ -70,6 +76,7 @@ pub trait AsciiExt {
/// assert_eq!('A', ascii.to_ascii_uppercase()); /// assert_eq!('A', ascii.to_ascii_uppercase());
/// assert_eq!('❤', utf8.to_ascii_uppercase()); /// assert_eq!('❤', utf8.to_ascii_uppercase());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn to_ascii_uppercase(&self) -> Self::Owned; fn to_ascii_uppercase(&self) -> Self::Owned;
/// Makes a copy of the string in ASCII lower case. /// Makes a copy of the string in ASCII lower case.
@ -88,6 +95,7 @@ pub trait AsciiExt {
/// assert_eq!('a', ascii.to_ascii_lowercase()); /// assert_eq!('a', ascii.to_ascii_lowercase());
/// assert_eq!('❤', utf8.to_ascii_lowercase()); /// assert_eq!('❤', utf8.to_ascii_lowercase());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn to_ascii_lowercase(&self) -> Self::Owned; fn to_ascii_lowercase(&self) -> Self::Owned;
/// Checks that two strings are an ASCII case-insensitive match. /// Checks that two strings are an ASCII case-insensitive match.
@ -109,6 +117,7 @@ pub trait AsciiExt {
/// assert!(ascii1.eq_ignore_ascii_case(&ascii3)); /// assert!(ascii1.eq_ignore_ascii_case(&ascii3));
/// assert!(!ascii1.eq_ignore_ascii_case(&ascii4)); /// assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn eq_ignore_ascii_case(&self, other: &Self) -> bool; fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
/// Converts this type to its ASCII upper case equivalent in-place. /// Converts this type to its ASCII upper case equivalent in-place.
@ -126,6 +135,7 @@ pub trait AsciiExt {
/// ///
/// assert_eq!('A', ascii); /// assert_eq!('A', ascii);
/// ``` /// ```
#[stable(feature = "ascii", since = "1.9.0")]
fn make_ascii_uppercase(&mut self); fn make_ascii_uppercase(&mut self);
/// Converts this type to its ASCII lower case equivalent in-place. /// Converts this type to its ASCII lower case equivalent in-place.
@ -143,9 +153,11 @@ pub trait AsciiExt {
/// ///
/// assert_eq!('a', ascii); /// assert_eq!('a', ascii);
/// ``` /// ```
#[stable(feature = "ascii", since = "1.9.0")]
fn make_ascii_lowercase(&mut self); fn make_ascii_lowercase(&mut self);
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for str { impl AsciiExt for str {
type Owned = String; type Owned = String;
@ -186,6 +198,7 @@ impl AsciiExt for str {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for [u8] { impl AsciiExt for [u8] {
type Owned = Vec<u8>; type Owned = Vec<u8>;
#[inline] #[inline]
@ -228,6 +241,7 @@ impl AsciiExt for [u8] {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for u8 { impl AsciiExt for u8 {
type Owned = u8; type Owned = u8;
#[inline] #[inline]
@ -246,6 +260,7 @@ impl AsciiExt for u8 {
fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); } fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for char { impl AsciiExt for char {
type Owned = char; type Owned = char;
#[inline] #[inline]
@ -284,6 +299,7 @@ impl AsciiExt for char {
/// An iterator over the escaped version of a byte, constructed via /// An iterator over the escaped version of a byte, constructed via
/// `std::ascii::escape_default`. /// `std::ascii::escape_default`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct EscapeDefault { pub struct EscapeDefault {
range: Range<usize>, range: Range<usize>,
data: [u8; 4], data: [u8; 4],
@ -314,6 +330,7 @@ pub struct EscapeDefault {
/// assert_eq!(b'\\', escaped.next().unwrap()); /// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b't', escaped.next().unwrap()); /// assert_eq!(b't', escaped.next().unwrap());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn escape_default(c: u8) -> EscapeDefault { pub fn escape_default(c: u8) -> EscapeDefault {
let (data, len) = match c { let (data, len) = match c {
b'\t' => ([b'\\', b't', 0, 0], 2), b'\t' => ([b'\\', b't', 0, 0], 2),
@ -336,17 +353,23 @@ pub fn escape_default(c: u8) -> EscapeDefault {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for EscapeDefault { impl Iterator for EscapeDefault {
type Item = u8; type Item = u8;
fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) } 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() } fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault { impl DoubleEndedIterator for EscapeDefault {
fn next_back(&mut self) -> Option<u8> { fn next_back(&mut self) -> Option<u8> {
self.range.next_back().map(|i| self.data[i]) self.range.next_back().map(|i| self.data[i])
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {} impl ExactSizeIterator for EscapeDefault {}
#[unstable(feature = "fused", issue = "35602")]
impl FusedIterator for EscapeDefault {}
static ASCII_LOWERCASE_MAP: [u8; 256] = [ static ASCII_LOWERCASE_MAP: [u8; 256] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@ -430,8 +453,7 @@ static ASCII_UPPERCASE_MAP: [u8; 256] = [
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std_unicode::char::from_u32; use char::from_u32;
use collections::string::ToString;
#[test] #[test]
fn test_is_ascii() { fn test_is_ascii() {
@ -446,9 +468,7 @@ mod tests {
assert!("banana\0\u{7F}".is_ascii()); assert!("banana\0\u{7F}".is_ascii());
assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii())); assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii())); assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
// NOTE: This test fails for some reason.
assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
} }
#[test] #[test]

53
std/src/error.rs → ctr-std/src/error.rs

@ -38,6 +38,8 @@
//! [`Display`]: ../fmt/trait.Display.html //! [`Display`]: ../fmt/trait.Display.html
//! [`cause`]: trait.Error.html#method.cause //! [`cause`]: trait.Error.html#method.cause
#![stable(feature = "rust1", since = "1.0.0")]
// A note about crates and the facade: // A note about crates and the facade:
// //
// Originally, the `Error` trait was defined in libcore, and the impls // Originally, the `Error` trait was defined in libcore, and the impls
@ -59,12 +61,17 @@ use str;
use string; use string;
/// Base functionality for all errors in Rust. /// Base functionality for all errors in Rust.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display { pub trait Error: Debug + Display {
/// A short description of the error. /// A short description of the error.
/// ///
/// The description should not contain newlines or sentence-ending /// The description should only be used for a simple message.
/// punctuation, to facilitate embedding in larger user-facing /// It should not contain newlines or sentence-ending punctuation,
/// strings. /// to facilitate embedding in larger user-facing strings.
/// For showing formatted error messages with more information see
/// [`Display`].
///
/// [`Display`]: ../fmt/trait.Display.html
/// ///
/// # Examples /// # Examples
/// ///
@ -78,6 +85,7 @@ pub trait Error: Debug + Display {
/// _ => println!("No error"), /// _ => println!("No error"),
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn description(&self) -> &str; fn description(&self) -> &str;
/// The lower-level cause of this error, if any. /// The lower-level cause of this error, if any.
@ -138,27 +146,34 @@ pub trait Error: Debug + Display {
/// } /// }
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cause(&self) -> Option<&Error> { None } fn cause(&self) -> Option<&Error> { None }
/// Get the `TypeId` of `self` /// Get the `TypeId` of `self`
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "error_type_id",
reason = "unclear whether to commit to this public implementation detail",
issue = "27745")]
fn type_id(&self) -> TypeId where Self: 'static { fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<Self>() TypeId::of::<Self>()
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> { impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
fn from(err: E) -> Box<Error + 'a> { fn from(err: E) -> Box<Error + 'a> {
Box::new(err) Box::new(err)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> { impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> {
fn from(err: E) -> Box<Error + Send + Sync + 'a> { fn from(err: E) -> Box<Error + Send + Sync + 'a> {
Box::new(err) Box::new(err)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for Box<Error + Send + Sync> { impl From<String> for Box<Error + Send + Sync> {
fn from(err: String) -> Box<Error + Send + Sync> { fn from(err: String) -> Box<Error + Send + Sync> {
#[derive(Debug)] #[derive(Debug)]
@ -178,6 +193,7 @@ impl From<String> for Box<Error + Send + Sync> {
} }
} }
#[stable(feature = "string_box_error", since = "1.7.0")]
impl From<String> for Box<Error> { impl From<String> for Box<Error> {
fn from(str_err: String) -> Box<Error> { fn from(str_err: String) -> Box<Error> {
let err1: Box<Error + Send + Sync> = From::from(str_err); let err1: Box<Error + Send + Sync> = From::from(str_err);
@ -186,70 +202,82 @@ impl From<String> for Box<Error> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> { impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> {
fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> { fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
From::from(String::from(err)) From::from(String::from(err))
} }
} }
#[stable(feature = "string_box_error", since = "1.7.0")]
impl<'a> From<&'a str> for Box<Error> { impl<'a> From<&'a str> for Box<Error> {
fn from(err: &'a str) -> Box<Error> { fn from(err: &'a str) -> Box<Error> {
From::from(String::from(err)) From::from(String::from(err))
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for str::ParseBoolError { impl Error for str::ParseBoolError {
fn description(&self) -> &str { "failed to parse bool" } fn description(&self) -> &str { "failed to parse bool" }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for str::Utf8Error { impl Error for str::Utf8Error {
fn description(&self) -> &str { fn description(&self) -> &str {
"invalid utf-8: corrupt contents" "invalid utf-8: corrupt contents"
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for num::ParseIntError { impl Error for num::ParseIntError {
fn description(&self) -> &str { fn description(&self) -> &str {
self.__description() self.__description()
} }
} }
#[unstable(feature = "try_from", issue = "33417")]
impl Error for num::TryFromIntError { impl Error for num::TryFromIntError {
fn description(&self) -> &str { fn description(&self) -> &str {
self.__description() self.__description()
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for num::ParseFloatError { impl Error for num::ParseFloatError {
fn description(&self) -> &str { fn description(&self) -> &str {
self.__description() self.__description()
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for string::FromUtf8Error { impl Error for string::FromUtf8Error {
fn description(&self) -> &str { fn description(&self) -> &str {
"invalid utf-8" "invalid utf-8"
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for string::FromUtf16Error { impl Error for string::FromUtf16Error {
fn description(&self) -> &str { fn description(&self) -> &str {
"invalid utf-16" "invalid utf-16"
} }
} }
#[stable(feature = "str_parse_error2", since = "1.8.0")]
impl Error for string::ParseError { impl Error for string::ParseError {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self {} match *self {}
} }
} }
#[stable(feature = "decode_utf16", since = "1.9.0")]
impl Error for char::DecodeUtf16Error { impl Error for char::DecodeUtf16Error {
fn description(&self) -> &str { fn description(&self) -> &str {
"unpaired surrogate found" "unpaired surrogate found"
} }
} }
#[stable(feature = "box_error", since = "1.7.0")]
impl<T: Error> Error for Box<T> { impl<T: Error> Error for Box<T> {
fn description(&self) -> &str { fn description(&self) -> &str {
Error::description(&**self) Error::description(&**self)
@ -260,24 +288,28 @@ impl<T: Error> Error for Box<T> {
} }
} }
#[stable(feature = "fmt_error", since = "1.11.0")]
impl Error for fmt::Error { impl Error for fmt::Error {
fn description(&self) -> &str { fn description(&self) -> &str {
"an error occurred when formatting an argument" "an error occurred when formatting an argument"
} }
} }
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Error for cell::BorrowError { impl Error for cell::BorrowError {
fn description(&self) -> &str { fn description(&self) -> &str {
"already mutably borrowed" "already mutably borrowed"
} }
} }
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Error for cell::BorrowMutError { impl Error for cell::BorrowMutError {
fn description(&self) -> &str { fn description(&self) -> &str {
"already borrowed" "already borrowed"
} }
} }
#[unstable(feature = "try_from", issue = "33417")]
impl Error for char::CharTryFromError { impl Error for char::CharTryFromError {
fn description(&self) -> &str { fn description(&self) -> &str {
"converted integer out of range for `char`" "converted integer out of range for `char`"
@ -287,6 +319,7 @@ impl Error for char::CharTryFromError {
// copied from any.rs // copied from any.rs
impl Error + 'static { impl Error + 'static {
/// Returns true if the boxed type is the same as `T` /// Returns true if the boxed type is the same as `T`
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn is<T: Error + 'static>(&self) -> bool { pub fn is<T: Error + 'static>(&self) -> bool {
// Get TypeId of the type this function is instantiated with // Get TypeId of the type this function is instantiated with
@ -301,6 +334,7 @@ impl Error + 'static {
/// Returns some reference to the boxed value if it is of type `T`, or /// Returns some reference to the boxed value if it is of type `T`, or
/// `None` if it isn't. /// `None` if it isn't.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
if self.is::<T>() { if self.is::<T>() {
@ -314,6 +348,7 @@ impl Error + 'static {
/// Returns some mutable reference to the boxed value if it is of type `T`, or /// Returns some mutable reference to the boxed value if it is of type `T`, or
/// `None` if it isn't. /// `None` if it isn't.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
if self.is::<T>() { if self.is::<T>() {
@ -328,18 +363,21 @@ impl Error + 'static {
impl Error + 'static + Send { impl Error + 'static + Send {
/// Forwards to the method defined on the type `Any`. /// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn is<T: Error + 'static>(&self) -> bool { pub fn is<T: Error + 'static>(&self) -> bool {
<Error + 'static>::is::<T>(self) <Error + 'static>::is::<T>(self)
} }
/// Forwards to the method defined on the type `Any`. /// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
<Error + 'static>::downcast_ref::<T>(self) <Error + 'static>::downcast_ref::<T>(self)
} }
/// Forwards to the method defined on the type `Any`. /// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
<Error + 'static>::downcast_mut::<T>(self) <Error + 'static>::downcast_mut::<T>(self)
@ -348,18 +386,21 @@ impl Error + 'static + Send {
impl Error + 'static + Send + Sync { impl Error + 'static + Send + Sync {
/// Forwards to the method defined on the type `Any`. /// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn is<T: Error + 'static>(&self) -> bool { pub fn is<T: Error + 'static>(&self) -> bool {
<Error + 'static>::is::<T>(self) <Error + 'static>::is::<T>(self)
} }
/// Forwards to the method defined on the type `Any`. /// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> { pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
<Error + 'static>::downcast_ref::<T>(self) <Error + 'static>::downcast_ref::<T>(self)
} }
/// Forwards to the method defined on the type `Any`. /// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline] #[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
<Error + 'static>::downcast_mut::<T>(self) <Error + 'static>::downcast_mut::<T>(self)
@ -368,6 +409,7 @@ impl Error + 'static + Send + Sync {
impl Error { impl Error {
#[inline] #[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type. /// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> { pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> {
if self.is::<T>() { if self.is::<T>() {
@ -383,6 +425,7 @@ impl Error {
impl Error + Send { impl Error + Send {
#[inline] #[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type. /// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) pub fn downcast<T: Error + 'static>(self: Box<Self>)
-> Result<Box<T>, Box<Error + Send>> { -> Result<Box<T>, Box<Error + Send>> {
@ -396,6 +439,7 @@ impl Error + Send {
impl Error + Send + Sync { impl Error + Send + Sync {
#[inline] #[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type. /// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) pub fn downcast<T: Error + 'static>(self: Box<Self>)
-> Result<Box<T>, Box<Self>> { -> Result<Box<T>, Box<Self>> {
@ -410,8 +454,7 @@ impl Error + Send + Sync {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Error; use super::Error;
use core::fmt; use fmt;
use alloc::boxed::Box;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct A; struct A;

181
std/src/num/f32.rs → ctr-std/src/f32.rs

@ -12,6 +12,7 @@
//! //!
//! *[See also the `f32` primitive type](../primitive.f32.html).* //! *[See also the `f32` primitive type](../primitive.f32.html).*
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)] #![allow(missing_docs)]
#[cfg(not(test))] #[cfg(not(test))]
@ -19,22 +20,27 @@ use core::num;
#[cfg(not(test))] #[cfg(not(test))]
use intrinsics; use intrinsics;
#[cfg(not(test))] #[cfg(not(test))]
use libctru::libc::c_int; use libc::c_int;
#[cfg(not(test))] #[cfg(not(test))]
use num::FpCategory; use num::FpCategory;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP}; pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY}; pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MIN, MIN_POSITIVE, MAX}; pub use core::f32::{MIN, MIN_POSITIVE, MAX};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::consts; pub use core::f32::consts;
#[allow(dead_code)] #[allow(dead_code)]
mod cmath { mod cmath {
use libctru::libc::{c_float, c_int}; use libc::{c_float, c_int};
extern "C" { extern {
pub fn cbrtf(n: c_float) -> c_float; pub fn cbrtf(n: c_float) -> c_float;
pub fn erff(n: c_float) -> c_float; pub fn erff(n: c_float) -> c_float;
pub fn erfcf(n: c_float) -> c_float; pub fn erfcf(n: c_float) -> c_float;
@ -59,7 +65,7 @@ mod cmath {
// See the comments in the `floor` function for why MSVC is special // See the comments in the `floor` function for why MSVC is special
// here. // here.
#[cfg(not(target_env = "msvc"))] #[cfg(not(target_env = "msvc"))]
extern "C" { extern {
pub fn acosf(n: c_float) -> c_float; pub fn acosf(n: c_float) -> c_float;
pub fn asinf(n: c_float) -> c_float; pub fn asinf(n: c_float) -> c_float;
pub fn atan2f(a: c_float, b: c_float) -> c_float; pub fn atan2f(a: c_float, b: c_float) -> c_float;
@ -76,7 +82,7 @@ mod cmath {
pub use self::shims::*; pub use self::shims::*;
#[cfg(target_env = "msvc")] #[cfg(target_env = "msvc")]
mod shims { mod shims {
use libctru::libc::{c_float, c_int}; use libc::{c_float, c_int};
#[inline] #[inline]
pub unsafe fn acosf(n: c_float) -> c_float { pub unsafe fn acosf(n: c_float) -> c_float {
@ -148,10 +154,9 @@ impl f32 {
/// assert!(nan.is_nan()); /// assert!(nan.is_nan());
/// assert!(!f.is_nan()); /// assert!(!f.is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_nan(self) -> bool { pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
num::Float::is_nan(self)
}
/// Returns `true` if this value is positive infinity or negative infinity and /// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise. /// false otherwise.
@ -170,10 +175,9 @@ impl f32 {
/// assert!(inf.is_infinite()); /// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite()); /// assert!(neg_inf.is_infinite());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_infinite(self) -> bool { pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
num::Float::is_infinite(self)
}
/// Returns `true` if this number is neither infinite nor `NaN`. /// Returns `true` if this number is neither infinite nor `NaN`.
/// ///
@ -191,10 +195,9 @@ impl f32 {
/// assert!(!inf.is_finite()); /// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite()); /// assert!(!neg_inf.is_finite());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_finite(self) -> bool { pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
num::Float::is_finite(self)
}
/// Returns `true` if the number is neither zero, infinite, /// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`. /// [subnormal][subnormal], or `NaN`.
@ -217,10 +220,9 @@ impl f32 {
/// assert!(!lower_than_min.is_normal()); /// assert!(!lower_than_min.is_normal());
/// ``` /// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_normal(self) -> bool { pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
num::Float::is_normal(self)
}
/// Returns the floating point category of the number. If only one property /// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific /// is going to be tested, it is generally faster to use the specific
@ -236,10 +238,9 @@ impl f32 {
/// assert_eq!(num.classify(), FpCategory::Normal); /// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite); /// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn classify(self) -> FpCategory { pub fn classify(self) -> FpCategory { num::Float::classify(self) }
num::Float::classify(self)
}
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively. /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
@ -264,6 +265,11 @@ impl f32 {
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
/// [floating-point]: ../reference.html#machine-types /// [floating-point]: ../reference.html#machine-types
#[unstable(feature = "float_extras", reason = "signature is undecided",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
#[allow(deprecated)] #[allow(deprecated)]
pub fn integer_decode(self) -> (u64, i16, i8) { pub fn integer_decode(self) -> (u64, i16, i8) {
@ -279,6 +285,7 @@ impl f32 {
/// assert_eq!(f.floor(), 3.0); /// assert_eq!(f.floor(), 3.0);
/// assert_eq!(g.floor(), 3.0); /// assert_eq!(g.floor(), 3.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn floor(self) -> f32 { pub fn floor(self) -> f32 {
// On MSVC LLVM will lower many math intrinsics to a call to the // On MSVC LLVM will lower many math intrinsics to a call to the
@ -309,6 +316,7 @@ impl f32 {
/// assert_eq!(f.ceil(), 4.0); /// assert_eq!(f.ceil(), 4.0);
/// assert_eq!(g.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ceil(self) -> f32 { pub fn ceil(self) -> f32 {
// see notes above in `floor` // see notes above in `floor`
@ -328,6 +336,7 @@ impl f32 {
/// assert_eq!(f.round(), 3.0); /// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0); /// assert_eq!(g.round(), -3.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn round(self) -> f32 { pub fn round(self) -> f32 {
unsafe { intrinsics::roundf32(self) } unsafe { intrinsics::roundf32(self) }
@ -342,6 +351,7 @@ impl f32 {
/// assert_eq!(f.trunc(), 3.0); /// assert_eq!(f.trunc(), 3.0);
/// assert_eq!(g.trunc(), -3.0); /// assert_eq!(g.trunc(), -3.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn trunc(self) -> f32 { pub fn trunc(self) -> f32 {
unsafe { intrinsics::truncf32(self) } unsafe { intrinsics::truncf32(self) }
@ -360,10 +370,9 @@ impl f32 {
/// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_x <= f32::EPSILON);
/// assert!(abs_difference_y <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn fract(self) -> f32 { pub fn fract(self) -> f32 { self - self.trunc() }
self - self.trunc()
}
/// Computes the absolute value of `self`. Returns `NAN` if the /// Computes the absolute value of `self`. Returns `NAN` if the
/// number is `NAN`. /// number is `NAN`.
@ -382,10 +391,9 @@ impl f32 {
/// ///
/// assert!(f32::NAN.abs().is_nan()); /// assert!(f32::NAN.abs().is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn abs(self) -> f32 { pub fn abs(self) -> f32 { num::Float::abs(self) }
num::Float::abs(self)
}
/// Returns a number that represents the sign of `self`. /// Returns a number that represents the sign of `self`.
/// ///
@ -403,10 +411,9 @@ impl f32 {
/// ///
/// assert!(f32::NAN.signum().is_nan()); /// assert!(f32::NAN.signum().is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn signum(self) -> f32 { pub fn signum(self) -> f32 { num::Float::signum(self) }
num::Float::signum(self)
}
/// Returns `true` if `self`'s sign bit is positive, including /// Returns `true` if `self`'s sign bit is positive, including
/// `+0.0` and `INFINITY`. /// `+0.0` and `INFINITY`.
@ -423,10 +430,9 @@ impl f32 {
/// // Requires both tests to determine if is `NaN` /// // Requires both tests to determine if is `NaN`
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_sign_positive(self) -> bool { pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
num::Float::is_sign_positive(self)
}
/// Returns `true` if `self`'s sign is negative, including `-0.0` /// Returns `true` if `self`'s sign is negative, including `-0.0`
/// and `NEG_INFINITY`. /// and `NEG_INFINITY`.
@ -443,10 +449,9 @@ impl f32 {
/// // Requires both tests to determine if is `NaN`. /// // Requires both tests to determine if is `NaN`.
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_sign_negative(self) -> bool { pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
num::Float::is_sign_negative(self)
}
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than /// error. This produces a more accurate result with better performance than
@ -464,6 +469,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn mul_add(self, a: f32, b: f32) -> f32 { pub fn mul_add(self, a: f32, b: f32) -> f32 {
unsafe { intrinsics::fmaf32(self, a, b) } unsafe { intrinsics::fmaf32(self, a, b) }
@ -479,10 +485,9 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn recip(self) -> f32 { pub fn recip(self) -> f32 { num::Float::recip(self) }
num::Float::recip(self)
}
/// Raises a number to an integer power. /// Raises a number to an integer power.
/// ///
@ -496,10 +501,9 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn powi(self, n: i32) -> f32 { pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
num::Float::powi(self, n)
}
/// Raises a number to a floating point power. /// Raises a number to a floating point power.
/// ///
@ -511,6 +515,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn powf(self, n: f32) -> f32 { pub fn powf(self, n: f32) -> f32 {
// see notes above in `floor` // see notes above in `floor`
@ -535,6 +540,7 @@ impl f32 {
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// assert!(negative.sqrt().is_nan()); /// assert!(negative.sqrt().is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sqrt(self) -> f32 { pub fn sqrt(self) -> f32 {
if self < 0.0 { if self < 0.0 {
@ -558,6 +564,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn exp(self) -> f32 { pub fn exp(self) -> f32 {
// see notes above in `floor` // see notes above in `floor`
@ -579,6 +586,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn exp2(self) -> f32 { pub fn exp2(self) -> f32 {
unsafe { intrinsics::exp2f32(self) } unsafe { intrinsics::exp2f32(self) }
@ -598,6 +606,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ln(self) -> f32 { pub fn ln(self) -> f32 {
// see notes above in `floor` // see notes above in `floor`
@ -624,10 +633,9 @@ impl f32 {
/// assert!(abs_difference_10 <= f32::EPSILON); /// assert!(abs_difference_10 <= f32::EPSILON);
/// assert!(abs_difference_2 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log(self, base: f32) -> f32 { pub fn log(self, base: f32) -> f32 { self.ln() / base.ln() }
self.ln() / base.ln()
}
/// Returns the base 2 logarithm of the number. /// Returns the base 2 logarithm of the number.
/// ///
@ -641,6 +649,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log2(self) -> f32 { pub fn log2(self) -> f32 {
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
@ -661,6 +670,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log10(self) -> f32 { pub fn log10(self) -> f32 {
// see notes above in `floor` // see notes above in `floor`
@ -681,10 +691,9 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline] #[inline]
pub fn to_degrees(self) -> f32 { pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
num::Float::to_degrees(self)
}
/// Converts degrees to radians. /// Converts degrees to radians.
/// ///
@ -697,10 +706,9 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline] #[inline]
pub fn to_radians(self) -> f32 { pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
num::Float::to_radians(self)
}
/// Constructs a floating point number of `x*2^exp`. /// Constructs a floating point number of `x*2^exp`.
/// ///
@ -713,6 +721,12 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[unstable(feature = "float_extras",
reason = "pending integer conventions",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
pub fn ldexp(x: f32, exp: isize) -> f32 { pub fn ldexp(x: f32, exp: isize) -> f32 {
unsafe { cmath::ldexpf(x, exp as c_int) } unsafe { cmath::ldexpf(x, exp as c_int) }
@ -739,6 +753,12 @@ impl f32 {
/// assert!(abs_difference_0 <= f32::EPSILON); /// assert!(abs_difference_0 <= f32::EPSILON);
/// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON);
/// ``` /// ```
#[unstable(feature = "float_extras",
reason = "pending integer conventions",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
pub fn frexp(self) -> (f32, isize) { pub fn frexp(self) -> (f32, isize) {
unsafe { unsafe {
@ -762,6 +782,12 @@ impl f32 {
/// ///
/// assert!(abs_diff <= f32::EPSILON); /// assert!(abs_diff <= f32::EPSILON);
/// ``` /// ```
#[unstable(feature = "float_extras",
reason = "unsure about its place in the world",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
pub fn next_after(self, other: f32) -> f32 { pub fn next_after(self, other: f32) -> f32 {
unsafe { cmath::nextafterf(self, other) } unsafe { cmath::nextafterf(self, other) }
@ -777,6 +803,7 @@ impl f32 {
/// ``` /// ```
/// ///
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn max(self, other: f32) -> f32 { pub fn max(self, other: f32) -> f32 {
unsafe { cmath::fmaxf(self, other) } unsafe { cmath::fmaxf(self, other) }
@ -792,6 +819,7 @@ impl f32 {
/// ``` /// ```
/// ///
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn min(self, other: f32) -> f32 { pub fn min(self, other: f32) -> f32 {
unsafe { cmath::fminf(self, other) } unsafe { cmath::fminf(self, other) }
@ -814,6 +842,15 @@ impl f32 {
/// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_x <= f32::EPSILON);
/// assert!(abs_difference_y <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#[rustc_deprecated(since = "1.10.0",
reason = "you probably meant `(self - other).abs()`: \
this operation is `(self - other).max(0.0)` (also \
known as `fdimf` in C). If you truly need the positive \
difference, consider using that expression or the C function \
`fdimf`, depending on how you wish to handle NaN (please consider \
filing an issue describing your use-case too).")]
pub fn abs_sub(self, other: f32) -> f32 { pub fn abs_sub(self, other: f32) -> f32 {
unsafe { cmath::fdimf(self, other) } unsafe { cmath::fdimf(self, other) }
} }
@ -830,6 +867,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn cbrt(self) -> f32 { pub fn cbrt(self) -> f32 {
unsafe { cmath::cbrtf(self) } unsafe { cmath::cbrtf(self) }
@ -849,6 +887,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn hypot(self, other: f32) -> f32 { pub fn hypot(self, other: f32) -> f32 {
unsafe { cmath::hypotf(self, other) } unsafe { cmath::hypotf(self, other) }
@ -865,6 +904,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sin(self) -> f32 { pub fn sin(self) -> f32 {
// see notes in `core::f32::Float::floor` // see notes in `core::f32::Float::floor`
@ -885,6 +925,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn cos(self) -> f32 { pub fn cos(self) -> f32 {
// see notes in `core::f32::Float::floor` // see notes in `core::f32::Float::floor`
@ -904,6 +945,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn tan(self) -> f32 { pub fn tan(self) -> f32 {
unsafe { cmath::tanf(self) } unsafe { cmath::tanf(self) }
@ -923,6 +965,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn asin(self) -> f32 { pub fn asin(self) -> f32 {
unsafe { cmath::asinf(self) } unsafe { cmath::asinf(self) }
@ -942,6 +985,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn acos(self) -> f32 { pub fn acos(self) -> f32 {
unsafe { cmath::acosf(self) } unsafe { cmath::acosf(self) }
@ -960,6 +1004,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn atan(self) -> f32 { pub fn atan(self) -> f32 {
unsafe { cmath::atanf(self) } unsafe { cmath::atanf(self) }
@ -991,6 +1036,7 @@ impl f32 {
/// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON);
/// assert!(abs_difference_2 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn atan2(self, other: f32) -> f32 { pub fn atan2(self, other: f32) -> f32 {
unsafe { cmath::atan2f(self, other) } unsafe { cmath::atan2f(self, other) }
@ -1011,6 +1057,7 @@ impl f32 {
/// assert!(abs_difference_0 <= f32::EPSILON); /// assert!(abs_difference_0 <= f32::EPSILON);
/// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sin_cos(self) -> (f32, f32) { pub fn sin_cos(self) -> (f32, f32) {
(self.sin(), self.cos()) (self.sin(), self.cos())
@ -1029,6 +1076,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn exp_m1(self) -> f32 { pub fn exp_m1(self) -> f32 {
unsafe { cmath::expm1f(self) } unsafe { cmath::expm1f(self) }
@ -1047,6 +1095,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ln_1p(self) -> f32 { pub fn ln_1p(self) -> f32 {
unsafe { cmath::log1pf(self) } unsafe { cmath::log1pf(self) }
@ -1067,6 +1116,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sinh(self) -> f32 { pub fn sinh(self) -> f32 {
unsafe { cmath::sinhf(self) } unsafe { cmath::sinhf(self) }
@ -1087,6 +1137,7 @@ impl f32 {
/// // Same result /// // Same result
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn cosh(self) -> f32 { pub fn cosh(self) -> f32 {
unsafe { cmath::coshf(self) } unsafe { cmath::coshf(self) }
@ -1107,6 +1158,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn tanh(self) -> f32 { pub fn tanh(self) -> f32 {
unsafe { cmath::tanhf(self) } unsafe { cmath::tanhf(self) }
@ -1124,6 +1176,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn asinh(self) -> f32 { pub fn asinh(self) -> f32 {
if self == NEG_INFINITY { if self == NEG_INFINITY {
@ -1145,6 +1198,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= f32::EPSILON); /// assert!(abs_difference <= f32::EPSILON);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn acosh(self) -> f32 { pub fn acosh(self) -> f32 {
match self { match self {
@ -1165,6 +1219,7 @@ impl f32 {
/// ///
/// assert!(abs_difference <= 1e-5); /// assert!(abs_difference <= 1e-5);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn atanh(self) -> f32 { pub fn atanh(self) -> f32 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
@ -1438,7 +1493,7 @@ mod tests {
assert_eq!((-0f32).abs(), 0f32); assert_eq!((-0f32).abs(), 0f32);
assert_eq!((-1f32).abs(), 1f32); assert_eq!((-1f32).abs(), 1f32);
assert_eq!(NEG_INFINITY.abs(), INFINITY); assert_eq!(NEG_INFINITY.abs(), INFINITY);
assert_eq!((1f32 / NEG_INFINITY).abs(), 0f32); assert_eq!((1f32/NEG_INFINITY).abs(), 0f32);
assert!(NAN.abs().is_nan()); assert!(NAN.abs().is_nan());
} }
@ -1450,7 +1505,7 @@ mod tests {
assert_eq!((-0f32).signum(), -1f32); assert_eq!((-0f32).signum(), -1f32);
assert_eq!((-1f32).signum(), -1f32); assert_eq!((-1f32).signum(), -1f32);
assert_eq!(NEG_INFINITY.signum(), -1f32); assert_eq!(NEG_INFINITY.signum(), -1f32);
assert_eq!((1f32 / NEG_INFINITY).signum(), -1f32); assert_eq!((1f32/NEG_INFINITY).signum(), -1f32);
assert!(NAN.signum().is_nan()); assert!(NAN.signum().is_nan());
} }
@ -1462,7 +1517,7 @@ mod tests {
assert!(!(-0f32).is_sign_positive()); assert!(!(-0f32).is_sign_positive());
assert!(!(-1f32).is_sign_positive()); assert!(!(-1f32).is_sign_positive());
assert!(!NEG_INFINITY.is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive());
assert!(!(1f32 / NEG_INFINITY).is_sign_positive()); assert!(!(1f32/NEG_INFINITY).is_sign_positive());
assert!(!NAN.is_sign_positive()); assert!(!NAN.is_sign_positive());
} }
@ -1474,7 +1529,7 @@ mod tests {
assert!((-0f32).is_sign_negative()); assert!((-0f32).is_sign_negative());
assert!((-1f32).is_sign_negative()); assert!((-1f32).is_sign_negative());
assert!(NEG_INFINITY.is_sign_negative()); assert!(NEG_INFINITY.is_sign_negative());
assert!((1f32 / NEG_INFINITY).is_sign_negative()); assert!((1f32/NEG_INFINITY).is_sign_negative());
assert!(!NAN.is_sign_negative()); assert!(!NAN.is_sign_negative());
} }
@ -1712,25 +1767,15 @@ mod tests {
assert_eq!((-0f32).frexp(), (-0f32, 0)); assert_eq!((-0f32).frexp(), (-0f32, 0));
} }
#[test] #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
#[cfg_attr(windows, ignore)]
// FIXME #8755
#[allow(deprecated)] #[allow(deprecated)]
fn test_frexp_nowin() { fn test_frexp_nowin() {
let inf: f32 = f32::INFINITY; let inf: f32 = f32::INFINITY;
let neg_inf: f32 = f32::NEG_INFINITY; let neg_inf: f32 = f32::NEG_INFINITY;
let nan: f32 = f32::NAN; let nan: f32 = f32::NAN;
assert_eq!(match inf.frexp() { assert_eq!(match inf.frexp() { (x, _) => x }, inf);
(x, _) => x, assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
}, assert!(match nan.frexp() { (x, _) => x.is_nan() })
inf);
assert_eq!(match neg_inf.frexp() {
(x, _) => x,
},
neg_inf);
assert!(match nan.frexp() {
(x, _) => x.is_nan(),
})
} }
#[test] #[test]

216
std/src/num/f64.rs → ctr-std/src/f64.rs

@ -2,8 +2,9 @@
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
// Licensed under the Apache License, Version 2.0 or the MIT license // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// , at your // 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 // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
@ -11,29 +12,35 @@
//! //!
//! *[See also the `f64` primitive type](../primitive.f64.html).* //! *[See also the `f64` primitive type](../primitive.f64.html).*
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)] #![allow(missing_docs)]
#[cfg(not(test))] #[cfg(not(test))]
use core::num; use core::num;
#[cfg(not(test))] #[cfg(not(test))]
use core::intrinsics; use intrinsics;
#[cfg(not(test))] #[cfg(not(test))]
use libctru::libc::c_int; use libc::c_int;
#[cfg(not(test))] #[cfg(not(test))]
use core::num::FpCategory; use num::FpCategory;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP}; pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY}; pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MIN, MIN_POSITIVE, MAX}; pub use core::f64::{MIN, MIN_POSITIVE, MAX};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::consts; pub use core::f64::consts;
#[allow(dead_code)] #[allow(dead_code)]
mod cmath { mod cmath {
use libctru::libc::{c_double, c_int}; use libc::{c_double, c_int};
#[link_name = "m"] #[link_name = "m"]
extern "C" { extern {
pub fn acos(n: c_double) -> c_double; pub fn acos(n: c_double) -> c_double;
pub fn asin(n: c_double) -> c_double; pub fn asin(n: c_double) -> c_double;
pub fn atan(n: c_double) -> c_double; pub fn atan(n: c_double) -> c_double;
@ -91,10 +98,9 @@ impl f64 {
/// assert!(nan.is_nan()); /// assert!(nan.is_nan());
/// assert!(!f.is_nan()); /// assert!(!f.is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_nan(self) -> bool { pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
num::Float::is_nan(self)
}
/// Returns `true` if this value is positive infinity or negative infinity and /// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise. /// false otherwise.
@ -113,10 +119,9 @@ impl f64 {
/// assert!(inf.is_infinite()); /// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite()); /// assert!(neg_inf.is_infinite());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_infinite(self) -> bool { pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
num::Float::is_infinite(self)
}
/// Returns `true` if this number is neither infinite nor `NaN`. /// Returns `true` if this number is neither infinite nor `NaN`.
/// ///
@ -134,10 +139,9 @@ impl f64 {
/// assert!(!inf.is_finite()); /// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite()); /// assert!(!neg_inf.is_finite());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_finite(self) -> bool { pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
num::Float::is_finite(self)
}
/// Returns `true` if the number is neither zero, infinite, /// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`. /// [subnormal][subnormal], or `NaN`.
@ -160,10 +164,9 @@ impl f64 {
/// assert!(!lower_than_min.is_normal()); /// assert!(!lower_than_min.is_normal());
/// ``` /// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_normal(self) -> bool { pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
num::Float::is_normal(self)
}
/// Returns the floating point category of the number. If only one property /// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific /// is going to be tested, it is generally faster to use the specific
@ -179,10 +182,9 @@ impl f64 {
/// assert_eq!(num.classify(), FpCategory::Normal); /// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite); /// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn classify(self) -> FpCategory { pub fn classify(self) -> FpCategory { num::Float::classify(self) }
num::Float::classify(self)
}
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively. /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
@ -205,11 +207,14 @@ impl f64 {
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
/// [floating-point]: ../reference.html#machine-types /// [floating-point]: ../reference.html#machine-types
#[unstable(feature = "float_extras", reason = "signature is undecided",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
#[allow(deprecated)] #[allow(deprecated)]
pub fn integer_decode(self) -> (u64, i16, i8) { pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
num::Float::integer_decode(self)
}
/// Returns the largest integer less than or equal to a number. /// Returns the largest integer less than or equal to a number.
/// ///
@ -220,6 +225,7 @@ impl f64 {
/// assert_eq!(f.floor(), 3.0); /// assert_eq!(f.floor(), 3.0);
/// assert_eq!(g.floor(), 3.0); /// assert_eq!(g.floor(), 3.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn floor(self) -> f64 { pub fn floor(self) -> f64 {
unsafe { intrinsics::floorf64(self) } unsafe { intrinsics::floorf64(self) }
@ -234,6 +240,7 @@ impl f64 {
/// assert_eq!(f.ceil(), 4.0); /// assert_eq!(f.ceil(), 4.0);
/// assert_eq!(g.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ceil(self) -> f64 { pub fn ceil(self) -> f64 {
unsafe { intrinsics::ceilf64(self) } unsafe { intrinsics::ceilf64(self) }
@ -249,6 +256,7 @@ impl f64 {
/// assert_eq!(f.round(), 3.0); /// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0); /// assert_eq!(g.round(), -3.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn round(self) -> f64 { pub fn round(self) -> f64 {
unsafe { intrinsics::roundf64(self) } unsafe { intrinsics::roundf64(self) }
@ -263,6 +271,7 @@ impl f64 {
/// assert_eq!(f.trunc(), 3.0); /// assert_eq!(f.trunc(), 3.0);
/// assert_eq!(g.trunc(), -3.0); /// assert_eq!(g.trunc(), -3.0);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn trunc(self) -> f64 { pub fn trunc(self) -> f64 {
unsafe { intrinsics::truncf64(self) } unsafe { intrinsics::truncf64(self) }
@ -279,10 +288,9 @@ impl f64 {
/// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10); /// assert!(abs_difference_y < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn fract(self) -> f64 { pub fn fract(self) -> f64 { self - self.trunc() }
self - self.trunc()
}
/// Computes the absolute value of `self`. Returns `NAN` if the /// Computes the absolute value of `self`. Returns `NAN` if the
/// number is `NAN`. /// number is `NAN`.
@ -301,10 +309,9 @@ impl f64 {
/// ///
/// assert!(f64::NAN.abs().is_nan()); /// assert!(f64::NAN.abs().is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn abs(self) -> f64 { pub fn abs(self) -> f64 { num::Float::abs(self) }
num::Float::abs(self)
}
/// Returns a number that represents the sign of `self`. /// Returns a number that represents the sign of `self`.
/// ///
@ -322,10 +329,9 @@ impl f64 {
/// ///
/// assert!(f64::NAN.signum().is_nan()); /// assert!(f64::NAN.signum().is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn signum(self) -> f64 { pub fn signum(self) -> f64 { num::Float::signum(self) }
num::Float::signum(self)
}
/// Returns `true` if `self`'s sign bit is positive, including /// Returns `true` if `self`'s sign bit is positive, including
/// `+0.0` and `INFINITY`. /// `+0.0` and `INFINITY`.
@ -343,15 +349,14 @@ impl f64 {
/// // Requires both tests to determine if is `NaN` /// // Requires both tests to determine if is `NaN`
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_sign_positive(self) -> bool { pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
num::Float::is_sign_positive(self)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
#[inline] #[inline]
pub fn is_positive(self) -> bool { pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
num::Float::is_sign_positive(self)
}
/// Returns `true` if `self`'s sign is negative, including `-0.0` /// Returns `true` if `self`'s sign is negative, including `-0.0`
/// and `NEG_INFINITY`. /// and `NEG_INFINITY`.
@ -369,15 +374,14 @@ impl f64 {
/// // Requires both tests to determine if is `NaN`. /// // Requires both tests to determine if is `NaN`.
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_sign_negative(self) -> bool { pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
num::Float::is_sign_negative(self)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
#[inline] #[inline]
pub fn is_negative(self) -> bool { pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) }
num::Float::is_sign_negative(self)
}
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than /// error. This produces a more accurate result with better performance than
@ -393,6 +397,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn mul_add(self, a: f64, b: f64) -> f64 { pub fn mul_add(self, a: f64, b: f64) -> f64 {
unsafe { intrinsics::fmaf64(self, a, b) } unsafe { intrinsics::fmaf64(self, a, b) }
@ -406,10 +411,9 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn recip(self) -> f64 { pub fn recip(self) -> f64 { num::Float::recip(self) }
num::Float::recip(self)
}
/// Raises a number to an integer power. /// Raises a number to an integer power.
/// ///
@ -421,10 +425,9 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn powi(self, n: i32) -> f64 { pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
num::Float::powi(self, n)
}
/// Raises a number to a floating point power. /// Raises a number to a floating point power.
/// ///
@ -434,6 +437,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn powf(self, n: f64) -> f64 { pub fn powf(self, n: f64) -> f64 {
unsafe { intrinsics::powf64(self, n) } unsafe { intrinsics::powf64(self, n) }
@ -452,6 +456,7 @@ impl f64 {
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// assert!(negative.sqrt().is_nan()); /// assert!(negative.sqrt().is_nan());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sqrt(self) -> f64 { pub fn sqrt(self) -> f64 {
if self < 0.0 { if self < 0.0 {
@ -473,6 +478,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn exp(self) -> f64 { pub fn exp(self) -> f64 {
unsafe { intrinsics::expf64(self) } unsafe { intrinsics::expf64(self) }
@ -488,6 +494,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn exp2(self) -> f64 { pub fn exp2(self) -> f64 {
unsafe { intrinsics::exp2f64(self) } unsafe { intrinsics::exp2f64(self) }
@ -505,6 +512,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ln(self) -> f64 { pub fn ln(self) -> f64 {
self.log_wrapper(|n| { unsafe { intrinsics::logf64(n) } }) self.log_wrapper(|n| { unsafe { intrinsics::logf64(n) } })
@ -525,10 +533,9 @@ impl f64 {
/// assert!(abs_difference_10 < 1e-10); /// assert!(abs_difference_10 < 1e-10);
/// assert!(abs_difference_2 < 1e-10); /// assert!(abs_difference_2 < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log(self, base: f64) -> f64 { pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() }
self.ln() / base.ln()
}
/// Returns the base 2 logarithm of the number. /// Returns the base 2 logarithm of the number.
/// ///
@ -540,9 +547,13 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log2(self) -> f64 { pub fn log2(self) -> f64 {
self.log_wrapper(|n| { self.log_wrapper(|n| {
#[cfg(target_os = "android")]
return ::sys::android::log2f64(n);
#[cfg(not(target_os = "android"))]
return unsafe { intrinsics::log2f64(n) }; return unsafe { intrinsics::log2f64(n) };
}) })
} }
@ -557,6 +568,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn log10(self) -> f64 { pub fn log10(self) -> f64 {
self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } }) self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
@ -573,10 +585,9 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn to_degrees(self) -> f64 { pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
num::Float::to_degrees(self)
}
/// Converts degrees to radians. /// Converts degrees to radians.
/// ///
@ -589,10 +600,9 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn to_radians(self) -> f64 { pub fn to_radians(self) -> f64 { num::Float::to_radians(self) }
num::Float::to_radians(self)
}
/// Constructs a floating point number of `x*2^exp`. /// Constructs a floating point number of `x*2^exp`.
/// ///
@ -604,6 +614,12 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[unstable(feature = "float_extras",
reason = "pending integer conventions",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
pub fn ldexp(x: f64, exp: isize) -> f64 { pub fn ldexp(x: f64, exp: isize) -> f64 {
unsafe { cmath::ldexp(x, exp as c_int) } unsafe { cmath::ldexp(x, exp as c_int) }
@ -628,6 +644,12 @@ impl f64 {
/// assert!(abs_difference_0 < 1e-10); /// assert!(abs_difference_0 < 1e-10);
/// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_1 < 1e-10);
/// ``` /// ```
#[unstable(feature = "float_extras",
reason = "pending integer conventions",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
pub fn frexp(self) -> (f64, isize) { pub fn frexp(self) -> (f64, isize) {
unsafe { unsafe {
@ -649,6 +671,12 @@ impl f64 {
/// ///
/// assert!(abs_diff < 1e-10); /// assert!(abs_diff < 1e-10);
/// ``` /// ```
#[unstable(feature = "float_extras",
reason = "unsure about its place in the world",
issue = "27752")]
#[rustc_deprecated(since = "1.11.0",
reason = "never really came to fruition and easily \
implementable outside the standard library")]
#[inline] #[inline]
pub fn next_after(self, other: f64) -> f64 { pub fn next_after(self, other: f64) -> f64 {
unsafe { cmath::nextafter(self, other) } unsafe { cmath::nextafter(self, other) }
@ -664,6 +692,7 @@ impl f64 {
/// ``` /// ```
/// ///
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn max(self, other: f64) -> f64 { pub fn max(self, other: f64) -> f64 {
unsafe { cmath::fmax(self, other) } unsafe { cmath::fmax(self, other) }
@ -679,6 +708,7 @@ impl f64 {
/// ``` /// ```
/// ///
/// If one of the arguments is NaN, then the other argument is returned. /// If one of the arguments is NaN, then the other argument is returned.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn min(self, other: f64) -> f64 { pub fn min(self, other: f64) -> f64 {
unsafe { cmath::fmin(self, other) } unsafe { cmath::fmin(self, other) }
@ -699,10 +729,18 @@ impl f64 {
/// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10); /// assert!(abs_difference_y < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn abs_sub(self, other: f64) -> f64 { #[rustc_deprecated(since = "1.10.0",
unsafe { cmath::fdim(self, other) } reason = "you probably meant `(self - other).abs()`: \
} this operation is `(self - other).max(0.0)` (also \
known as `fdim` in C). If you truly need the positive \
difference, consider using that expression or the C function \
`fdim`, depending on how you wish to handle NaN (please consider \
filing an issue describing your use-case too).")]
pub fn abs_sub(self, other: f64) -> f64 {
unsafe { cmath::fdim(self, other) }
}
/// Takes the cubic root of a number. /// Takes the cubic root of a number.
/// ///
@ -714,6 +752,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn cbrt(self) -> f64 { pub fn cbrt(self) -> f64 {
unsafe { cmath::cbrt(self) } unsafe { cmath::cbrt(self) }
@ -731,6 +770,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn hypot(self, other: f64) -> f64 { pub fn hypot(self, other: f64) -> f64 {
unsafe { cmath::hypot(self, other) } unsafe { cmath::hypot(self, other) }
@ -747,6 +787,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sin(self) -> f64 { pub fn sin(self) -> f64 {
unsafe { intrinsics::sinf64(self) } unsafe { intrinsics::sinf64(self) }
@ -763,6 +804,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn cos(self) -> f64 { pub fn cos(self) -> f64 {
unsafe { intrinsics::cosf64(self) } unsafe { intrinsics::cosf64(self) }
@ -778,6 +820,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-14); /// assert!(abs_difference < 1e-14);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn tan(self) -> f64 { pub fn tan(self) -> f64 {
unsafe { cmath::tan(self) } unsafe { cmath::tan(self) }
@ -797,6 +840,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn asin(self) -> f64 { pub fn asin(self) -> f64 {
unsafe { cmath::asin(self) } unsafe { cmath::asin(self) }
@ -816,6 +860,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn acos(self) -> f64 { pub fn acos(self) -> f64 {
unsafe { cmath::acos(self) } unsafe { cmath::acos(self) }
@ -832,6 +877,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn atan(self) -> f64 { pub fn atan(self) -> f64 {
unsafe { cmath::atan(self) } unsafe { cmath::atan(self) }
@ -863,6 +909,7 @@ impl f64 {
/// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_1 < 1e-10);
/// assert!(abs_difference_2 < 1e-10); /// assert!(abs_difference_2 < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn atan2(self, other: f64) -> f64 { pub fn atan2(self, other: f64) -> f64 {
unsafe { cmath::atan2(self, other) } unsafe { cmath::atan2(self, other) }
@ -883,6 +930,7 @@ impl f64 {
/// assert!(abs_difference_0 < 1e-10); /// assert!(abs_difference_0 < 1e-10);
/// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_1 < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sin_cos(self) -> (f64, f64) { pub fn sin_cos(self) -> (f64, f64) {
(self.sin(), self.cos()) (self.sin(), self.cos())
@ -899,6 +947,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn exp_m1(self) -> f64 { pub fn exp_m1(self) -> f64 {
unsafe { cmath::expm1(self) } unsafe { cmath::expm1(self) }
@ -917,6 +966,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn ln_1p(self) -> f64 { pub fn ln_1p(self) -> f64 {
unsafe { cmath::log1p(self) } unsafe { cmath::log1p(self) }
@ -937,6 +987,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1e-10); /// assert!(abs_difference < 1e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sinh(self) -> f64 { pub fn sinh(self) -> f64 {
unsafe { cmath::sinh(self) } unsafe { cmath::sinh(self) }
@ -957,6 +1008,7 @@ impl f64 {
/// // Same result /// // Same result
/// assert!(abs_difference < 1.0e-10); /// assert!(abs_difference < 1.0e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn cosh(self) -> f64 { pub fn cosh(self) -> f64 {
unsafe { cmath::cosh(self) } unsafe { cmath::cosh(self) }
@ -977,6 +1029,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1.0e-10); /// assert!(abs_difference < 1.0e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn tanh(self) -> f64 { pub fn tanh(self) -> f64 {
unsafe { cmath::tanh(self) } unsafe { cmath::tanh(self) }
@ -992,6 +1045,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1.0e-10); /// assert!(abs_difference < 1.0e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn asinh(self) -> f64 { pub fn asinh(self) -> f64 {
if self == NEG_INFINITY { if self == NEG_INFINITY {
@ -1011,6 +1065,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1.0e-10); /// assert!(abs_difference < 1.0e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn acosh(self) -> f64 { pub fn acosh(self) -> f64 {
match self { match self {
@ -1031,6 +1086,7 @@ impl f64 {
/// ///
/// assert!(abs_difference < 1.0e-10); /// assert!(abs_difference < 1.0e-10);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn atanh(self) -> f64 { pub fn atanh(self) -> f64 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
@ -1236,10 +1292,8 @@ mod tests {
#[test] #[test]
#[allow(deprecated)] #[allow(deprecated)]
fn test_integer_decode() { fn test_integer_decode() {
assert_eq!(3.14159265359f64.integer_decode(), assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
(7074237752028906, -51, 1)); assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1));
assert_eq!((-8573.5918555f64).integer_decode(),
(4713381968463931, -39, -1));
assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1)); assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1));
assert_eq!(0f64.integer_decode(), (0, -1075, 1)); assert_eq!(0f64.integer_decode(), (0, -1075, 1));
assert_eq!((-0f64).integer_decode(), (0, -1075, -1)); assert_eq!((-0f64).integer_decode(), (0, -1075, -1));
@ -1330,7 +1384,7 @@ mod tests {
assert_eq!((-0f64).abs(), 0f64); assert_eq!((-0f64).abs(), 0f64);
assert_eq!((-1f64).abs(), 1f64); assert_eq!((-1f64).abs(), 1f64);
assert_eq!(NEG_INFINITY.abs(), INFINITY); assert_eq!(NEG_INFINITY.abs(), INFINITY);
assert_eq!((1f64 / NEG_INFINITY).abs(), 0f64); assert_eq!((1f64/NEG_INFINITY).abs(), 0f64);
assert!(NAN.abs().is_nan()); assert!(NAN.abs().is_nan());
} }
@ -1342,7 +1396,7 @@ mod tests {
assert_eq!((-0f64).signum(), -1f64); assert_eq!((-0f64).signum(), -1f64);
assert_eq!((-1f64).signum(), -1f64); assert_eq!((-1f64).signum(), -1f64);
assert_eq!(NEG_INFINITY.signum(), -1f64); assert_eq!(NEG_INFINITY.signum(), -1f64);
assert_eq!((1f64 / NEG_INFINITY).signum(), -1f64); assert_eq!((1f64/NEG_INFINITY).signum(), -1f64);
assert!(NAN.signum().is_nan()); assert!(NAN.signum().is_nan());
} }
@ -1354,7 +1408,7 @@ mod tests {
assert!(!(-0f64).is_sign_positive()); assert!(!(-0f64).is_sign_positive());
assert!(!(-1f64).is_sign_positive()); assert!(!(-1f64).is_sign_positive());
assert!(!NEG_INFINITY.is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive());
assert!(!(1f64 / NEG_INFINITY).is_sign_positive()); assert!(!(1f64/NEG_INFINITY).is_sign_positive());
assert!(!NAN.is_sign_positive()); assert!(!NAN.is_sign_positive());
} }
@ -1366,7 +1420,7 @@ mod tests {
assert!((-0f64).is_sign_negative()); assert!((-0f64).is_sign_negative());
assert!((-1f64).is_sign_negative()); assert!((-1f64).is_sign_negative());
assert!(NEG_INFINITY.is_sign_negative()); assert!(NEG_INFINITY.is_sign_negative());
assert!((1f64 / NEG_INFINITY).is_sign_negative()); assert!((1f64/NEG_INFINITY).is_sign_negative());
assert!(!NAN.is_sign_negative()); assert!(!NAN.is_sign_negative());
} }
@ -1604,25 +1658,15 @@ mod tests {
assert_eq!((-0f64).frexp(), (-0f64, 0)); assert_eq!((-0f64).frexp(), (-0f64, 0));
} }
#[test] #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
#[cfg_attr(windows, ignore)]
// FIXME #8755
#[allow(deprecated)] #[allow(deprecated)]
fn test_frexp_nowin() { fn test_frexp_nowin() {
let inf: f64 = INFINITY; let inf: f64 = INFINITY;
let neg_inf: f64 = NEG_INFINITY; let neg_inf: f64 = NEG_INFINITY;
let nan: f64 = NAN; let nan: f64 = NAN;
assert_eq!(match inf.frexp() { assert_eq!(match inf.frexp() { (x, _) => x }, inf);
(x, _) => x, assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
}, assert!(match nan.frexp() { (x, _) => x.is_nan() })
inf);
assert_eq!(match neg_inf.frexp() {
(x, _) => x,
},
neg_inf);
assert!(match nan.frexp() {
(x, _) => x.is_nan(),
})
} }
#[test] #[test]

74
std/src/ffi/c_str.rs → ctr-std/src/ffi/c_str.rs

@ -14,7 +14,7 @@ use cmp::Ordering;
use error::Error; use error::Error;
use fmt::{self, Write}; use fmt::{self, Write};
use io; use io;
use libctru::libc::{self, c_char}; use libc::{self, c_char};
use mem; use mem;
use memchr; use memchr;
use ops; use ops;
@ -66,6 +66,7 @@ use str::{self, Utf8Error};
/// and other memory errors. /// and other memory errors.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString { pub struct CString {
// Invariant 1: the slice ends with a zero byte and has a length of at least one. // Invariant 1: the slice ends with a zero byte and has a length of at least one.
// Invariant 2: the slice contains only one zero byte. // Invariant 2: the slice contains only one zero byte.
@ -133,6 +134,7 @@ pub struct CString {
/// println!("string: {}", my_string_safe()); /// println!("string: {}", my_string_safe());
/// ``` /// ```
#[derive(Hash)] #[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr { pub struct CStr {
// FIXME: this should not be represented with a DST slice but rather with // FIXME: this should not be represented with a DST slice but rather with
// just a raw `c_char` along with some form of marker to make // just a raw `c_char` along with some form of marker to make
@ -144,16 +146,19 @@ pub struct CStr {
/// An error returned from `CString::new` to indicate that a nul byte was found /// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided. /// in the vector provided.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>); pub struct NulError(usize, Vec<u8>);
/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul /// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
/// byte was found too early in the slice provided or one wasn't found at all. /// byte was found too early in the slice provided or one wasn't found at all.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub struct FromBytesWithNulError { _a: () } pub struct FromBytesWithNulError { _a: () }
/// An error returned from `CString::into_string` to indicate that a UTF-8 error /// An error returned from `CString::into_string` to indicate that a UTF-8 error
/// was encountered during the conversion. /// was encountered during the conversion.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstring_into", since = "1.7.0")]
pub struct IntoStringError { pub struct IntoStringError {
inner: CString, inner: CString,
error: Utf8Error, error: Utf8Error,
@ -184,6 +189,7 @@ impl CString {
/// This function will return an error if the bytes yielded contain an /// This function will return an error if the bytes yielded contain an
/// internal 0 byte. The error returned will contain the bytes as well as /// internal 0 byte. The error returned will contain the bytes as well as
/// the position of the nul byte. /// the position of the nul byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> { pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
Self::_new(t.into()) Self::_new(t.into())
} }
@ -212,6 +218,7 @@ impl CString {
/// let c_string = CString::from_vec_unchecked(raw); /// let c_string = CString::from_vec_unchecked(raw);
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString { pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
v.reserve_exact(1); v.reserve_exact(1);
v.push(0); v.push(0);
@ -228,6 +235,7 @@ impl CString {
/// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take /// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take
/// ownership of a string that was allocated by foreign code) is likely to lead /// ownership of a string that was allocated by foreign code) is likely to lead
/// to undefined behavior or allocator corruption. /// to undefined behavior or allocator corruption.
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString { pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = libc::strlen(ptr) + 1; // Including the NUL byte let len = libc::strlen(ptr) + 1; // Including the NUL byte
let slice = slice::from_raw_parts(ptr, len as usize); let slice = slice::from_raw_parts(ptr, len as usize);
@ -242,6 +250,7 @@ impl CString {
/// this string. /// this string.
/// ///
/// Failure to call `from_raw` will lead to a memory leak. /// Failure to call `from_raw` will lead to a memory leak.
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub fn into_raw(self) -> *mut c_char { pub fn into_raw(self) -> *mut c_char {
Box::into_raw(self.into_inner()) as *mut c_char Box::into_raw(self.into_inner()) as *mut c_char
} }
@ -249,6 +258,7 @@ impl CString {
/// Converts the `CString` into a `String` if it contains valid Unicode data. /// Converts the `CString` into a `String` if it contains valid Unicode data.
/// ///
/// On failure, ownership of the original `CString` is returned. /// On failure, ownership of the original `CString` is returned.
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_string(self) -> Result<String, IntoStringError> { pub fn into_string(self) -> Result<String, IntoStringError> {
String::from_utf8(self.into_bytes()) String::from_utf8(self.into_bytes())
.map_err(|e| IntoStringError { .map_err(|e| IntoStringError {
@ -261,6 +271,7 @@ impl CString {
/// ///
/// The returned buffer does **not** contain the trailing nul separator and /// The returned buffer does **not** contain the trailing nul separator and
/// it is guaranteed to not have any interior nul bytes. /// it is guaranteed to not have any interior nul bytes.
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_bytes(self) -> Vec<u8> { pub fn into_bytes(self) -> Vec<u8> {
let mut vec = self.into_inner().into_vec(); let mut vec = self.into_inner().into_vec();
let _nul = vec.pop(); let _nul = vec.pop();
@ -270,6 +281,7 @@ impl CString {
/// Equivalent to the `into_bytes` function except that the returned vector /// Equivalent to the `into_bytes` function except that the returned vector
/// includes the trailing nul byte. /// includes the trailing nul byte.
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_bytes_with_nul(self) -> Vec<u8> { pub fn into_bytes_with_nul(self) -> Vec<u8> {
self.into_inner().into_vec() self.into_inner().into_vec()
} }
@ -278,12 +290,14 @@ impl CString {
/// ///
/// The returned slice does **not** contain the trailing nul separator and /// The returned slice does **not** contain the trailing nul separator and
/// it is guaranteed to not have any interior nul bytes. /// it is guaranteed to not have any interior nul bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes(&self) -> &[u8] { pub fn as_bytes(&self) -> &[u8] {
&self.inner[..self.inner.len() - 1] &self.inner[..self.inner.len() - 1]
} }
/// Equivalent to the `as_bytes` function except that the returned slice /// Equivalent to the `as_bytes` function except that the returned slice
/// includes the trailing nul byte. /// includes the trailing nul byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes_with_nul(&self) -> &[u8] { pub fn as_bytes_with_nul(&self) -> &[u8] {
&self.inner &self.inner
} }
@ -301,6 +315,7 @@ impl CString {
// Turns this `CString` into an empty string to prevent // Turns this `CString` into an empty string to prevent
// memory unsafe code from working by accident. Inline // memory unsafe code from working by accident. Inline
// to prevent LLVM from optimizing it away in debug builds. // to prevent LLVM from optimizing it away in debug builds.
#[stable(feature = "cstring_drop", since = "1.13.0")]
impl Drop for CString { impl Drop for CString {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
@ -308,6 +323,7 @@ impl Drop for CString {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for CString { impl ops::Deref for CString {
type Target = CStr; type Target = CStr;
@ -316,18 +332,21 @@ impl ops::Deref for CString {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString { impl fmt::Debug for CString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f) fmt::Debug::fmt(&**self, f)
} }
} }
#[stable(feature = "cstring_into", since = "1.7.0")]
impl From<CString> for Vec<u8> { impl From<CString> for Vec<u8> {
fn from(s: CString) -> Vec<u8> { fn from(s: CString) -> Vec<u8> {
s.into_bytes() s.into_bytes()
} }
} }
#[stable(feature = "cstr_debug", since = "1.3.0")]
impl fmt::Debug for CStr { impl fmt::Debug for CStr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\"")?; write!(f, "\"")?;
@ -338,6 +357,7 @@ impl fmt::Debug for CStr {
} }
} }
#[stable(feature = "cstr_default", since = "1.10.0")]
impl<'a> Default for &'a CStr { impl<'a> Default for &'a CStr {
fn default() -> &'a CStr { fn default() -> &'a CStr {
static SLICE: &'static [c_char] = &[0]; static SLICE: &'static [c_char] = &[0];
@ -345,6 +365,7 @@ impl<'a> Default for &'a CStr {
} }
} }
#[stable(feature = "cstr_default", since = "1.10.0")]
impl Default for CString { impl Default for CString {
/// Creates an empty `CString`. /// Creates an empty `CString`.
fn default() -> CString { fn default() -> CString {
@ -353,6 +374,7 @@ impl Default for CString {
} }
} }
#[stable(feature = "cstr_borrow", since = "1.3.0")]
impl Borrow<CStr> for CString { impl Borrow<CStr> for CString {
fn borrow(&self) -> &CStr { self } fn borrow(&self) -> &CStr { self }
} }
@ -372,6 +394,7 @@ impl NulError {
/// let nul_error = CString::new("foo bar\0").unwrap_err(); /// let nul_error = CString::new("foo bar\0").unwrap_err();
/// assert_eq!(nul_error.nul_position(), 7); /// assert_eq!(nul_error.nul_position(), 7);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn nul_position(&self) -> usize { self.0 } pub fn nul_position(&self) -> usize { self.0 }
/// Consumes this error, returning the underlying vector of bytes which /// Consumes this error, returning the underlying vector of bytes which
@ -385,19 +408,23 @@ impl NulError {
/// let nul_error = CString::new("foo\0bar").unwrap_err(); /// let nul_error = CString::new("foo\0bar").unwrap_err();
/// assert_eq!(nul_error.into_vec(), b"foo\0bar"); /// assert_eq!(nul_error.into_vec(), b"foo\0bar");
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_vec(self) -> Vec<u8> { self.1 } pub fn into_vec(self) -> Vec<u8> { self.1 }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError { impl Error for NulError {
fn description(&self) -> &str { "nul byte found in data" } fn description(&self) -> &str { "nul byte found in data" }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError { impl fmt::Display for NulError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "nul byte found in provided data at position: {}", self.0) write!(f, "nul byte found in provided data at position: {}", self.0)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error { impl From<NulError> for io::Error {
fn from(_: NulError) -> io::Error { fn from(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, io::Error::new(io::ErrorKind::InvalidInput,
@ -408,16 +435,19 @@ impl From<NulError> for io::Error {
impl IntoStringError { impl IntoStringError {
/// Consumes this error, returning original `CString` which generated the /// Consumes this error, returning original `CString` which generated the
/// error. /// error.
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_cstring(self) -> CString { pub fn into_cstring(self) -> CString {
self.inner self.inner
} }
/// Access the underlying UTF-8 error that was the cause of this error. /// Access the underlying UTF-8 error that was the cause of this error.
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn utf8_error(&self) -> Utf8Error { pub fn utf8_error(&self) -> Utf8Error {
self.error self.error
} }
} }
#[stable(feature = "cstring_into", since = "1.7.0")]
impl Error for IntoStringError { impl Error for IntoStringError {
fn description(&self) -> &str { fn description(&self) -> &str {
"C string contained non-utf8 bytes" "C string contained non-utf8 bytes"
@ -428,6 +458,7 @@ impl Error for IntoStringError {
} }
} }
#[stable(feature = "cstring_into", since = "1.7.0")]
impl fmt::Display for IntoStringError { impl fmt::Display for IntoStringError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f) self.description().fmt(f)
@ -468,6 +499,7 @@ impl CStr {
/// } /// }
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
let len = libc::strlen(ptr); let len = libc::strlen(ptr);
mem::transmute(slice::from_raw_parts(ptr, len as usize + 1)) mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
@ -487,6 +519,7 @@ impl CStr {
/// let cstr = CStr::from_bytes_with_nul(b"hello\0"); /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
/// assert!(cstr.is_ok()); /// assert!(cstr.is_ok());
/// ``` /// ```
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub fn from_bytes_with_nul(bytes: &[u8]) pub fn from_bytes_with_nul(bytes: &[u8])
-> Result<&CStr, FromBytesWithNulError> { -> Result<&CStr, FromBytesWithNulError> {
if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) { if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) {
@ -513,6 +546,7 @@ impl CStr {
/// assert_eq!(cstr, &*cstring); /// assert_eq!(cstr, &*cstring);
/// } /// }
/// ``` /// ```
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
mem::transmute(bytes) mem::transmute(bytes)
} }
@ -554,6 +588,7 @@ impl CStr {
/// *ptr; /// *ptr;
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_ptr(&self) -> *const c_char { pub fn as_ptr(&self) -> *const c_char {
self.inner.as_ptr() self.inner.as_ptr()
} }
@ -570,6 +605,7 @@ impl CStr {
/// > **Note**: This method is currently implemented as a 0-cost cast, but /// > **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 /// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called. /// > length calculation whenever this method is called.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes(&self) -> &[u8] { pub fn to_bytes(&self) -> &[u8] {
let bytes = self.to_bytes_with_nul(); let bytes = self.to_bytes_with_nul();
&bytes[..bytes.len() - 1] &bytes[..bytes.len() - 1]
@ -583,6 +619,7 @@ impl CStr {
/// > **Note**: This method is currently implemented as a 0-cost cast, but /// > **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 /// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called. /// > length calculation whenever this method is called.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] { pub fn to_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute(&self.inner) } unsafe { mem::transmute(&self.inner) }
} }
@ -596,6 +633,7 @@ impl CStr {
/// > after a 0-cost cast, but it is planned to alter its definition in the /// > 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 /// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called. /// > check whenever this method is called.
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> { pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
// NB: When CStr is changed to perform the length check in .to_bytes() // NB: When CStr is changed to perform the length check in .to_bytes()
// instead of in from_ptr(), it may be worth considering if this should // instead of in from_ptr(), it may be worth considering if this should
@ -615,28 +653,34 @@ impl CStr {
/// > after a 0-cost cast, but it is planned to alter its definition in the /// > 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 /// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called. /// > check whenever this method is called.
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_string_lossy(&self) -> Cow<str> { pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.to_bytes()) String::from_utf8_lossy(self.to_bytes())
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr { impl PartialEq for CStr {
fn eq(&self, other: &CStr) -> bool { fn eq(&self, other: &CStr) -> bool {
self.to_bytes().eq(other.to_bytes()) self.to_bytes().eq(other.to_bytes())
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {} impl Eq for CStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr { impl PartialOrd for CStr {
fn partial_cmp(&self, other: &CStr) -> Option<Ordering> { fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
self.to_bytes().partial_cmp(&other.to_bytes()) self.to_bytes().partial_cmp(&other.to_bytes())
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr { impl Ord for CStr {
fn cmp(&self, other: &CStr) -> Ordering { fn cmp(&self, other: &CStr) -> Ordering {
self.to_bytes().cmp(&other.to_bytes()) self.to_bytes().cmp(&other.to_bytes())
} }
} }
#[stable(feature = "cstr_borrow", since = "1.3.0")]
impl ToOwned for CStr { impl ToOwned for CStr {
type Owned = CString; type Owned = CString;
@ -645,12 +689,14 @@ impl ToOwned for CStr {
} }
} }
#[stable(feature = "cstring_asref", since = "1.7.0")]
impl<'a> From<&'a CStr> for CString { impl<'a> From<&'a CStr> for CString {
fn from(s: &'a CStr) -> CString { fn from(s: &'a CStr) -> CString {
s.to_owned() s.to_owned()
} }
} }
#[stable(feature = "cstring_asref", since = "1.7.0")]
impl ops::Index<ops::RangeFull> for CString { impl ops::Index<ops::RangeFull> for CString {
type Output = CStr; type Output = CStr;
@ -660,12 +706,14 @@ impl ops::Index<ops::RangeFull> for CString {
} }
} }
#[stable(feature = "cstring_asref", since = "1.7.0")]
impl AsRef<CStr> for CStr { impl AsRef<CStr> for CStr {
fn as_ref(&self) -> &CStr { fn as_ref(&self) -> &CStr {
self self
} }
} }
#[stable(feature = "cstring_asref", since = "1.7.0")]
impl AsRef<CStr> for CString { impl AsRef<CStr> for CString {
fn as_ref(&self) -> &CStr { fn as_ref(&self) -> &CStr {
self self
@ -675,10 +723,10 @@ impl AsRef<CStr> for CString {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use libc::c_char; use os::raw::c_char;
use collections::borrow::Cow::{Borrowed, Owned}; use borrow::Cow::{Borrowed, Owned};
use collections::borrow::ToOwned; use hash::{Hash, Hasher};
use core::hash::{Hash, Hasher}; use collections::hash_map::DefaultHasher;
#[test] #[test]
fn c_to_rust() { fn c_to_rust() {
@ -754,6 +802,22 @@ mod tests {
assert_eq!(owned.as_bytes_with_nul(), data); assert_eq!(owned.as_bytes_with_nul(), data);
} }
#[test]
fn equal_hash() {
let data = b"123\xE2\xFA\xA6\0";
let ptr = data.as_ptr() as *const c_char;
let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) };
let mut s = DefaultHasher::new();
cstr.hash(&mut s);
let cstr_hash = s.finish();
let mut s = DefaultHasher::new();
CString::new(&data[..data.len() - 1]).unwrap().hash(&mut s);
let cstring_hash = s.finish();
assert_eq!(cstr_hash, cstring_hash);
}
#[test] #[test]
fn from_bytes_with_nul() { fn from_bytes_with_nul() {
let data = b"123\0"; let data = b"123\0";

24
ctr-std/src/ffi/mod.rs

@ -0,0 +1,24 @@
// Copyright 2015 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.
//! Utilities related to FFI bindings.
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};
mod c_str;
mod os_str;

166
std/src/ffi/os_str.rs → ctr-std/src/ffi/os_str.rs

@ -15,9 +15,8 @@ use ops;
use cmp; use cmp;
use hash::{Hash, Hasher}; use hash::{Hash, Hasher};
use sys::wtf8::{Wtf8, Wtf8Buf}; use sys::os_str::{Buf, Slice};
use sys::{AsInner, IntoInner, FromInner}; use sys_common::{AsInner, IntoInner, FromInner};
pub use sys::wtf8::EncodeWide;
/// A type that can represent owned, mutable platform-native strings, but is /// A type that can represent owned, mutable platform-native strings, but is
/// cheaply inter-convertible with Rust strings. /// cheaply inter-convertible with Rust strings.
@ -36,26 +35,26 @@ pub use sys::wtf8::EncodeWide;
/// and platform-native string values, and in particular allowing a Rust string /// and platform-native string values, and in particular allowing a Rust string
/// to be converted into an "OS" string with no cost. /// to be converted into an "OS" string with no cost.
#[derive(Clone)] #[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsString { pub struct OsString {
inner: Wtf8Buf inner: Buf
} }
/// Slices into OS strings (see `OsString`). /// Slices into OS strings (see `OsString`).
#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsStr { pub struct OsStr {
inner: Wtf8 inner: Slice
} }
impl OsString { impl OsString {
/// Constructs a new empty `OsString`. /// Constructs a new empty `OsString`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> OsString { pub fn new() -> OsString {
OsString { inner: Wtf8Buf::from_string(String::new()) } OsString { inner: Buf::from_string(String::new()) }
}
fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
String::from_utf8(vec).ok().map(OsString::from)
} }
/// Converts to an `OsStr` slice. /// Converts to an `OsStr` slice.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_os_str(&self) -> &OsStr { pub fn as_os_str(&self) -> &OsStr {
self self
} }
@ -63,13 +62,15 @@ impl OsString {
/// Converts the `OsString` into a `String` if it contains valid Unicode data. /// Converts the `OsString` into a `String` if it contains valid Unicode data.
/// ///
/// On failure, ownership of the original `OsString` is returned. /// On failure, ownership of the original `OsString` is returned.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_string(self) -> Result<String, OsString> { pub fn into_string(self) -> Result<String, OsString> {
self.inner.into_string().map_err(|buf| OsString { inner: buf} ) self.inner.into_string().map_err(|buf| OsString { inner: buf} )
} }
/// Extends the string with the given `&OsStr` slice. /// Extends the string with the given `&OsStr` slice.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn push<T: AsRef<OsStr>>(&mut self, s: T) { pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
self.inner.push_wtf8(&s.as_ref().inner) self.inner.push_slice(&s.as_ref().inner)
} }
/// Creates a new `OsString` with the given capacity. /// Creates a new `OsString` with the given capacity.
@ -79,13 +80,15 @@ impl OsString {
/// allocate. /// allocate.
/// ///
/// See main `OsString` documentation information about encoding. /// See main `OsString` documentation information about encoding.
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn with_capacity(capacity: usize) -> OsString { pub fn with_capacity(capacity: usize) -> OsString {
OsString { OsString {
inner: Wtf8Buf::with_capacity(capacity) inner: Buf::with_capacity(capacity)
} }
} }
/// Truncates the `OsString` to zero length. /// Truncates the `OsString` to zero length.
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.inner.clear() self.inner.clear()
} }
@ -93,6 +96,7 @@ impl OsString {
/// Returns the capacity this `OsString` can hold without reallocating. /// Returns the capacity this `OsString` can hold without reallocating.
/// ///
/// See `OsString` introduction for information about encoding. /// See `OsString` introduction for information about encoding.
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
self.inner.capacity() self.inner.capacity()
} }
@ -101,6 +105,7 @@ impl OsString {
/// in the given `OsString`. /// in the given `OsString`.
/// ///
/// The collection may reserve more space to avoid frequent reallocations. /// The collection may reserve more space to avoid frequent reallocations.
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn reserve(&mut self, additional: usize) { pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional) self.inner.reserve(additional)
} }
@ -112,34 +117,27 @@ impl OsString {
/// Note that the allocator may give the collection more space than it /// Note that the allocator may give the collection more space than it
/// requests. Therefore capacity can not be relied upon to be precisely /// requests. Therefore capacity can not be relied upon to be precisely
/// minimal. Prefer reserve if future insertions are expected. /// minimal. Prefer reserve if future insertions are expected.
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn reserve_exact(&mut self, additional: usize) { pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional) self.inner.reserve_exact(additional)
} }
/// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
/// 16-bit code units.
///
/// This is lossless: calling `.encode_wide()` on the resulting string
/// will always return the original code units.
///
/// NOTE: This function was copied from the windows implementation of OsStringExt
pub fn from_wide(wide: &[u16]) -> OsString {
OsString { inner: Wtf8Buf::from_wide(wide) }
}
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for OsString { impl From<String> for OsString {
fn from(s: String) -> OsString { fn from(s: String) -> OsString {
OsString { inner: Wtf8Buf::from_string(s) } OsString { inner: Buf::from_string(s) }
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString { impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
fn from(s: &'a T) -> OsString { fn from(s: &'a T) -> OsString {
s.as_ref().to_os_string() s.as_ref().to_os_string()
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Index<ops::RangeFull> for OsString { impl ops::Index<ops::RangeFull> for OsString {
type Output = OsStr; type Output = OsStr;
@ -149,6 +147,7 @@ impl ops::Index<ops::RangeFull> for OsString {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for OsString { impl ops::Deref for OsString {
type Target = OsStr; type Target = OsStr;
@ -158,39 +157,47 @@ impl ops::Deref for OsString {
} }
} }
#[stable(feature = "osstring_default", since = "1.9.0")]
impl Default for OsString { impl Default for OsString {
/// Constructs an empty `OsString`.
#[inline] #[inline]
fn default() -> OsString { fn default() -> OsString {
OsString::new() OsString::new()
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for OsString { impl Debug for OsString {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fmt::Debug::fmt(&**self, formatter) fmt::Debug::fmt(&**self, formatter)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for OsString { impl PartialEq for OsString {
fn eq(&self, other: &OsString) -> bool { fn eq(&self, other: &OsString) -> bool {
&**self == &**other &**self == &**other
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<str> for OsString { impl PartialEq<str> for OsString {
fn eq(&self, other: &str) -> bool { fn eq(&self, other: &str) -> bool {
&**self == other &**self == other
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<OsString> for str { impl PartialEq<OsString> for str {
fn eq(&self, other: &OsString) -> bool { fn eq(&self, other: &OsString) -> bool {
&**other == self &**other == self
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for OsString {} impl Eq for OsString {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for OsString { impl PartialOrd for OsString {
#[inline] #[inline]
fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
@ -206,6 +213,7 @@ impl PartialOrd for OsString {
fn ge(&self, other: &OsString) -> bool { &**self >= &**other } fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd<str> for OsString { impl PartialOrd<str> for OsString {
#[inline] #[inline]
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
@ -213,6 +221,7 @@ impl PartialOrd<str> for OsString {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for OsString { impl Ord for OsString {
#[inline] #[inline]
fn cmp(&self, other: &OsString) -> cmp::Ordering { fn cmp(&self, other: &OsString) -> cmp::Ordering {
@ -220,6 +229,7 @@ impl Ord for OsString {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for OsString { impl Hash for OsString {
#[inline] #[inline]
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
@ -229,38 +239,61 @@ impl Hash for OsString {
impl OsStr { impl OsStr {
/// Coerces into an `OsStr` slice. /// Coerces into an `OsStr` slice.
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
///
/// let os_str = OsStr::new("foo");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr { pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
s.as_ref() s.as_ref()
} }
fn from_inner(inner: &Wtf8) -> &OsStr { fn from_inner(inner: &Slice) -> &OsStr {
unsafe { mem::transmute(inner) } unsafe { mem::transmute(inner) }
} }
/// Yields a `&str` slice if the `OsStr` is valid Unicode. /// Yields a `&str` slice if the `OsStr` is valid Unicode.
/// ///
/// This conversion may entail doing a check for UTF-8 validity. /// This conversion may entail doing a check for UTF-8 validity.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_str(&self) -> Option<&str> { pub fn to_str(&self) -> Option<&str> {
self.inner.as_str() self.inner.to_str()
} }
/// Converts an `OsStr` to a `Cow<str>`. /// Converts an `OsStr` to a `Cow<str>`.
/// ///
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_string_lossy(&self) -> Cow<str> { pub fn to_string_lossy(&self) -> Cow<str> {
self.inner.to_string_lossy() self.inner.to_string_lossy()
} }
/// Copies the slice into an owned `OsString`. /// Copies the slice into an owned `OsString`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_os_string(&self) -> OsString { pub fn to_os_string(&self) -> OsString {
let mut buf = Wtf8Buf::with_capacity(self.inner.len()); OsString { inner: self.inner.to_owned() }
buf.push_wtf8(&self.inner);
OsString { inner: buf }
} }
/// Checks whether the `OsStr` is empty. /// Checks whether the `OsStr` is empty.
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
///
/// let os_str = OsStr::new("");
/// assert!(os_str.is_empty());
///
/// let os_str = OsStr::new("foo");
/// assert!(!os_str.is_empty());
/// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.inner.is_empty() self.inner.inner.is_empty()
} }
/// Returns the length of this `OsStr`. /// Returns the length of this `OsStr`.
@ -271,8 +304,21 @@ impl OsStr {
/// other methods like `OsString::with_capacity` to avoid reallocations. /// other methods like `OsString::with_capacity` to avoid reallocations.
/// ///
/// See `OsStr` introduction for more information about encoding. /// See `OsStr` introduction for more information about encoding.
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
///
/// let os_str = OsStr::new("");
/// assert_eq!(os_str.len(), 0);
///
/// let os_str = OsStr::new("foo");
/// assert_eq!(os_str.len(), 3);
/// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.inner.len() self.inner.inner.len()
} }
/// Gets the underlying byte representation. /// Gets the underlying byte representation.
@ -282,46 +328,42 @@ impl OsStr {
fn bytes(&self) -> &[u8] { fn bytes(&self) -> &[u8] {
unsafe { mem::transmute(&self.inner) } unsafe { mem::transmute(&self.inner) }
} }
/// Re-encodes an `OsStr` as a wide character sequence,
/// i.e. potentially ill-formed UTF-16.
/// This is lossless. Note that the encoding does not include a final
/// null.
///
/// NOTE: This function was copied from the windows implementation of OsStrExt
pub fn encode_wide(&self) -> EncodeWide {
self.inner.encode_wide()
}
} }
#[stable(feature = "osstring_default", since = "1.9.0")]
impl<'a> Default for &'a OsStr { impl<'a> Default for &'a OsStr {
/// Creates an empty `OsStr`.
#[inline] #[inline]
fn default() -> &'a OsStr { fn default() -> &'a OsStr {
OsStr::new("") OsStr::new("")
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for OsStr { impl PartialEq for OsStr {
fn eq(&self, other: &OsStr) -> bool { fn eq(&self, other: &OsStr) -> bool {
self.bytes().eq(other.bytes()) self.bytes().eq(other.bytes())
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<str> for OsStr { impl PartialEq<str> for OsStr {
fn eq(&self, other: &str) -> bool { fn eq(&self, other: &str) -> bool {
*self == *OsStr::new(other) *self == *OsStr::new(other)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<OsStr> for str { impl PartialEq<OsStr> for str {
fn eq(&self, other: &OsStr) -> bool { fn eq(&self, other: &OsStr) -> bool {
*other == *OsStr::new(self) *other == *OsStr::new(self)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for OsStr {} impl Eq for OsStr {}
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for OsStr { impl PartialOrd for OsStr {
#[inline] #[inline]
fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
@ -337,6 +379,7 @@ impl PartialOrd for OsStr {
fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) } fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd<str> for OsStr { impl PartialOrd<str> for OsStr {
#[inline] #[inline]
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
@ -347,6 +390,7 @@ impl PartialOrd<str> for OsStr {
// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
// have more flexible coherence rules. // have more flexible coherence rules.
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for OsStr { impl Ord for OsStr {
#[inline] #[inline]
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) } fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
@ -354,16 +398,19 @@ impl Ord for OsStr {
macro_rules! impl_cmp { macro_rules! impl_cmp {
($lhs:ty, $rhs: ty) => { ($lhs:ty, $rhs: ty) => {
#[stable(feature = "cmp_os_str", since = "1.8.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs { impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline] #[inline]
fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) } fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
} }
#[stable(feature = "cmp_os_str", since = "1.8.0")]
impl<'a, 'b> PartialEq<$lhs> for $rhs { impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline] #[inline]
fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) } fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
} }
#[stable(feature = "cmp_os_str", since = "1.8.0")]
impl<'a, 'b> PartialOrd<$rhs> for $lhs { impl<'a, 'b> PartialOrd<$rhs> for $lhs {
#[inline] #[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
@ -371,6 +418,7 @@ macro_rules! impl_cmp {
} }
} }
#[stable(feature = "cmp_os_str", since = "1.8.0")]
impl<'a, 'b> PartialOrd<$lhs> for $rhs { impl<'a, 'b> PartialOrd<$lhs> for $rhs {
#[inline] #[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
@ -386,6 +434,7 @@ impl_cmp!(Cow<'a, OsStr>, OsStr);
impl_cmp!(Cow<'a, OsStr>, &'b OsStr); impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
impl_cmp!(Cow<'a, OsStr>, OsString); impl_cmp!(Cow<'a, OsStr>, OsString);
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for OsStr { impl Hash for OsStr {
#[inline] #[inline]
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
@ -393,59 +442,66 @@ impl Hash for OsStr {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for OsStr { impl Debug for OsStr {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.inner.fmt(formatter) self.inner.fmt(formatter)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<OsStr> for OsString { impl Borrow<OsStr> for OsString {
fn borrow(&self) -> &OsStr { &self[..] } fn borrow(&self) -> &OsStr { &self[..] }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for OsStr { impl ToOwned for OsStr {
type Owned = OsString; type Owned = OsString;
fn to_owned(&self) -> OsString { self.to_os_string() } fn to_owned(&self) -> OsString { self.to_os_string() }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for OsStr { impl AsRef<OsStr> for OsStr {
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
self self
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for OsString { impl AsRef<OsStr> for OsString {
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
self self
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for str { impl AsRef<OsStr> for str {
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
OsStr::from_inner(Wtf8::from_str(self)) OsStr::from_inner(Slice::from_str(self))
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for String { impl AsRef<OsStr> for String {
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
(&**self).as_ref() (&**self).as_ref()
} }
} }
impl FromInner<Wtf8Buf> for OsString { impl FromInner<Buf> for OsString {
fn from_inner(buf: Wtf8Buf) -> OsString { fn from_inner(buf: Buf) -> OsString {
OsString { inner: buf } OsString { inner: buf }
} }
} }
impl IntoInner<Wtf8Buf> for OsString { impl IntoInner<Buf> for OsString {
fn into_inner(self) -> Wtf8Buf { fn into_inner(self) -> Buf {
self.inner self.inner
} }
} }
impl AsInner<Wtf8> for OsStr { impl AsInner<Slice> for OsStr {
fn as_inner(&self) -> &Wtf8 { fn as_inner(&self) -> &Slice {
&self.inner &self.inner
} }
} }
@ -453,29 +509,29 @@ impl AsInner<Wtf8> for OsStr {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use sys::{AsInner, IntoInner}; use sys_common::{AsInner, IntoInner};
#[test] #[test]
fn test_os_string_with_capacity() { fn test_os_string_with_capacity() {
let os_string = OsString::with_capacity(0); let os_string = OsString::with_capacity(0);
assert_eq!(0, os_string.inner.capacity()); assert_eq!(0, os_string.inner.into_inner().capacity());
let os_string = OsString::with_capacity(10); let os_string = OsString::with_capacity(10);
assert_eq!(10, os_string.inner.capacity()); assert_eq!(10, os_string.inner.into_inner().capacity());
let mut os_string = OsString::with_capacity(0); let mut os_string = OsString::with_capacity(0);
os_string.push("abc"); os_string.push("abc");
assert!(os_string.inner.capacity() >= 3); assert!(os_string.inner.into_inner().capacity() >= 3);
} }
#[test] #[test]
fn test_os_string_clear() { fn test_os_string_clear() {
let mut os_string = OsString::from("abc"); let mut os_string = OsString::from("abc");
assert_eq!(3, os_string.inner.len()); assert_eq!(3, os_string.inner.as_inner().len());
os_string.clear(); os_string.clear();
assert_eq!(&os_string, ""); assert_eq!(&os_string, "");
assert_eq!(0, os_string.inner.len()); assert_eq!(0, os_string.inner.as_inner().len());
} }
#[test] #[test]

72
std/src/io/buffered.rs → ctr-std/src/io/buffered.rs

@ -20,11 +20,15 @@ use memchr;
/// The `BufReader` struct adds buffering to any reader. /// The `BufReader` struct adds buffering to any reader.
/// ///
/// It can be excessively inefficient to work directly with a `Read` instance. /// It can be excessively inefficient to work directly with a [`Read`] instance.
/// For example, every call to `read` on `TcpStream` results in a system call. /// For example, every call to [`read`] on [`TcpStream`] results in a system call.
/// A `BufReader` performs large, infrequent reads on the underlying `Read` /// A `BufReader` performs large, infrequent reads on the underlying [`Read`]
/// and maintains an in-memory buffer of the results. /// and maintains an in-memory buffer of the results.
/// ///
/// [`Read`]: ../../std/io/trait.Read.html
/// [`read`]: ../../std/net/struct.TcpStream.html#method.read
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -42,6 +46,7 @@ use memchr;
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufReader<R> { pub struct BufReader<R> {
inner: R, inner: R,
buf: Box<[u8]>, buf: Box<[u8]>,
@ -64,6 +69,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> { pub fn new(inner: R) -> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
} }
@ -84,6 +90,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> { pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
BufReader { BufReader {
inner: inner, inner: inner,
@ -111,6 +118,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &R { &self.inner } pub fn get_ref(&self) -> &R { &self.inner }
/// Gets a mutable reference to the underlying reader. /// Gets a mutable reference to the underlying reader.
@ -131,6 +139,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner } pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
/// Unwraps this `BufReader`, returning the underlying reader. /// Unwraps this `BufReader`, returning the underlying reader.
@ -151,9 +160,11 @@ impl<R: Read> BufReader<R> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> R { self.inner } pub fn into_inner(self) -> R { self.inner }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Read for BufReader<R> { impl<R: Read> Read for BufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
// If we don't have any buffered data and we're doing a massive read // If we don't have any buffered data and we're doing a massive read
@ -171,6 +182,7 @@ impl<R: Read> Read for BufReader<R> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> BufRead for BufReader<R> { impl<R: Read> BufRead for BufReader<R> {
fn fill_buf(&mut self) -> io::Result<&[u8]> { fn fill_buf(&mut self) -> io::Result<&[u8]> {
// If we've reached the end of our internal buffer then we need to fetch // If we've reached the end of our internal buffer then we need to fetch
@ -187,6 +199,7 @@ impl<R: Read> BufRead for BufReader<R> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug { impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BufReader") fmt.debug_struct("BufReader")
@ -196,6 +209,7 @@ impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Seek> Seek for BufReader<R> { impl<R: Seek> Seek for BufReader<R> {
/// Seek to an offset, in bytes, in the underlying reader. /// Seek to an offset, in bytes, in the underlying reader.
/// ///
@ -205,8 +219,8 @@ impl<R: Seek> Seek for BufReader<R> {
/// ///
/// Seeking always discards the internal buffer, even if the seek position /// Seeking always discards the internal buffer, even if the seek position
/// would otherwise fall within it. This guarantees that calling /// would otherwise fall within it. This guarantees that calling
/// `.unwrap()` immediately after a seek yields the underlying reader at /// `.into_inner()` immediately after a seek yields the underlying reader
/// the same position. /// at the same position.
/// ///
/// See `std::io::Seek` for more details. /// See `std::io::Seek` for more details.
/// ///
@ -220,7 +234,7 @@ impl<R: Seek> Seek for BufReader<R> {
if let SeekFrom::Current(n) = pos { if let SeekFrom::Current(n) = pos {
let remainder = (self.cap - self.pos) as i64; let remainder = (self.cap - self.pos) as i64;
// it should be safe to assume that remainder fits within an i64 as the alternative // it should be safe to assume that remainder fits within an i64 as the alternative
// means we managed to allocate 8 ebibytes and that's absurd. // means we managed to allocate 8 exbibytes and that's absurd.
// But it's not out of the realm of possibility for some weird underlying reader to // But it's not out of the realm of possibility for some weird underlying reader to
// support seeking by i64::min_value() so we need to handle underflow when subtracting // support seeking by i64::min_value() so we need to handle underflow when subtracting
// remainder. // remainder.
@ -244,7 +258,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// Wraps a writer and buffers its output. /// Wraps a writer and buffers its output.
/// ///
/// It can be excessively inefficient to work directly with something that /// It can be excessively inefficient to work directly with something that
/// implements `Write`. For example, every call to `write` on `TcpStream` /// implements [`Write`]. For example, every call to [`write`] on [`TcpStream`]
/// results in a system call. A `BufWriter` keeps an in-memory buffer of data /// results in a system call. A `BufWriter` keeps an in-memory buffer of data
/// and writes it to an underlying writer in large, infrequent batches. /// and writes it to an underlying writer in large, infrequent batches.
/// ///
@ -252,7 +266,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// ///
/// # Examples /// # Examples
/// ///
/// Let's write the numbers one through ten to a `TcpStream`: /// Let's write the numbers one through ten to a [`TcpStream`]:
/// ///
/// ```no_run /// ```no_run
/// use std::io::prelude::*; /// use std::io::prelude::*;
@ -284,6 +298,11 @@ impl<R: Seek> Seek for BufReader<R> {
/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped
/// together by the buffer, and will all be written out in one system call when /// together by the buffer, and will all be written out in one system call when
/// the `stream` is dropped. /// the `stream` is dropped.
///
/// [`Write`]: ../../std/io/trait.Write.html
/// [`write`]: ../../std/net/struct.TcpStream.html#method.write
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufWriter<W: Write> { pub struct BufWriter<W: Write> {
inner: Option<W>, inner: Option<W>,
buf: Vec<u8>, buf: Vec<u8>,
@ -318,6 +337,7 @@ pub struct BufWriter<W: Write> {
/// }; /// };
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoInnerError<W>(W, Error); pub struct IntoInnerError<W>(W, Error);
impl<W: Write> BufWriter<W> { impl<W: Write> BufWriter<W> {
@ -331,6 +351,7 @@ impl<W: Write> BufWriter<W> {
/// ///
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> BufWriter<W> { pub fn new(inner: W) -> BufWriter<W> {
BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
} }
@ -348,6 +369,7 @@ impl<W: Write> BufWriter<W> {
/// let stream = TcpStream::connect("127.0.0.1:34254").unwrap(); /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
/// let mut buffer = BufWriter::with_capacity(100, stream); /// let mut buffer = BufWriter::with_capacity(100, stream);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> { pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> {
BufWriter { BufWriter {
inner: Some(inner), inner: Some(inner),
@ -396,6 +418,7 @@ impl<W: Write> BufWriter<W> {
/// // we can use reference just like buffer /// // we can use reference just like buffer
/// let reference = buffer.get_ref(); /// let reference = buffer.get_ref();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() }
/// Gets a mutable reference to the underlying writer. /// Gets a mutable reference to the underlying writer.
@ -413,6 +436,7 @@ impl<W: Write> BufWriter<W> {
/// // we can use reference just like buffer /// // we can use reference just like buffer
/// let reference = buffer.get_mut(); /// let reference = buffer.get_mut();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() }
/// Unwraps this `BufWriter`, returning the underlying writer. /// Unwraps this `BufWriter`, returning the underlying writer.
@ -430,6 +454,7 @@ impl<W: Write> BufWriter<W> {
/// // unwrap the TcpStream and flush the buffer /// // unwrap the TcpStream and flush the buffer
/// let stream = buffer.into_inner().unwrap(); /// let stream = buffer.into_inner().unwrap();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> { pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
match self.flush_buf() { match self.flush_buf() {
Err(e) => Err(IntoInnerError(self, e)), Err(e) => Err(IntoInnerError(self, e)),
@ -438,6 +463,7 @@ impl<W: Write> BufWriter<W> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for BufWriter<W> { impl<W: Write> Write for BufWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.buf.len() + buf.len() > self.buf.capacity() { if self.buf.len() + buf.len() > self.buf.capacity() {
@ -449,8 +475,7 @@ impl<W: Write> Write for BufWriter<W> {
self.panicked = false; self.panicked = false;
r r
} else { } else {
let amt = cmp::min(buf.len(), self.buf.capacity()); Write::write(&mut self.buf, buf)
Write::write(&mut self.buf, &buf[..amt])
} }
} }
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
@ -458,6 +483,7 @@ impl<W: Write> Write for BufWriter<W> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug { impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BufWriter") fmt.debug_struct("BufWriter")
@ -467,6 +493,7 @@ impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + Seek> Seek for BufWriter<W> { impl<W: Write + Seek> Seek for BufWriter<W> {
/// Seek to the offset, in bytes, in the underlying writer. /// Seek to the offset, in bytes, in the underlying writer.
/// ///
@ -476,6 +503,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Drop for BufWriter<W> { impl<W: Write> Drop for BufWriter<W> {
fn drop(&mut self) { fn drop(&mut self) {
if self.inner.is_some() && !self.panicked { if self.inner.is_some() && !self.panicked {
@ -514,6 +542,7 @@ impl<W> IntoInnerError<W> {
/// } /// }
/// }; /// };
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn error(&self) -> &Error { &self.1 } pub fn error(&self) -> &Error { &self.1 }
/// Returns the buffered writer instance which generated the error. /// Returns the buffered writer instance which generated the error.
@ -546,19 +575,23 @@ impl<W> IntoInnerError<W> {
/// } /// }
/// }; /// };
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> W { self.0 } pub fn into_inner(self) -> W { self.0 }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W> From<IntoInnerError<W>> for Error { impl<W> From<IntoInnerError<W>> for Error {
fn from(iie: IntoInnerError<W>) -> Error { iie.1 } fn from(iie: IntoInnerError<W>) -> Error { iie.1 }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> { impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
fn description(&self) -> &str { fn description(&self) -> &str {
error::Error::description(self.error()) error::Error::description(self.error())
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W> fmt::Display for IntoInnerError<W> { impl<W> fmt::Display for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.error().fmt(f) self.error().fmt(f)
@ -613,6 +646,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LineWriter<W: Write> { pub struct LineWriter<W: Write> {
inner: BufWriter<W>, inner: BufWriter<W>,
} }
@ -632,6 +666,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> LineWriter<W> { pub fn new(inner: W) -> LineWriter<W> {
// Lines typically aren't that long, don't use a giant buffer // Lines typically aren't that long, don't use a giant buffer
LineWriter::with_capacity(1024, inner) LineWriter::with_capacity(1024, inner)
@ -652,6 +687,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> { pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
LineWriter { inner: BufWriter::with_capacity(cap, inner) } LineWriter { inner: BufWriter::with_capacity(cap, inner) }
} }
@ -672,6 +708,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.get_ref() } pub fn get_ref(&self) -> &W { self.inner.get_ref() }
/// Gets a mutable reference to the underlying writer. /// Gets a mutable reference to the underlying writer.
@ -694,6 +731,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() }
/// Unwraps this `LineWriter`, returning the underlying writer. /// Unwraps this `LineWriter`, returning the underlying writer.
@ -715,6 +753,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> { pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
self.inner.into_inner().map_err(|IntoInnerError(buf, e)| { self.inner.into_inner().map_err(|IntoInnerError(buf, e)| {
IntoInnerError(LineWriter { inner: buf }, e) IntoInnerError(LineWriter { inner: buf }, e)
@ -722,6 +761,7 @@ impl<W: Write> LineWriter<W> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for LineWriter<W> { impl<W: Write> Write for LineWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match memchr::memrchr(b'\n', buf) { match memchr::memrchr(b'\n', buf) {
@ -740,6 +780,7 @@ impl<W: Write> Write for LineWriter<W> {
fn flush(&mut self) -> io::Result<()> { self.inner.flush() } fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug { impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("LineWriter") fmt.debug_struct("LineWriter")
@ -754,13 +795,10 @@ impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
mod tests { mod tests {
use io::prelude::*; use io::prelude::*;
use io::{self, BufReader, BufWriter, LineWriter, SeekFrom}; use io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
//use sync::atomic::{AtomicUsize, Ordering}; use sync::atomic::{AtomicUsize, Ordering};
//use thread; use thread;
use test; use test;
use collections::{Vec, String};
use collections::string::ToString;
/// A dummy reader intended at testing short-reads propagation. /// A dummy reader intended at testing short-reads propagation.
pub struct ShortReader { pub struct ShortReader {
lengths: Vec<usize>, lengths: Vec<usize>,
@ -1075,9 +1113,8 @@ mod tests {
panic!(); panic!();
} }
// NOTE: These tests are for threading stuff that is not yet implemented
/*
#[test] #[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn panic_in_write_doesnt_flush_in_drop() { fn panic_in_write_doesnt_flush_in_drop() {
static WRITES: AtomicUsize = AtomicUsize::new(0); static WRITES: AtomicUsize = AtomicUsize::new(0);
@ -1113,5 +1150,4 @@ mod tests {
BufWriter::new(io::sink()) BufWriter::new(io::sink())
}); });
} }
*/
} }

70
std/src/io/cursor.rs → ctr-std/src/io/cursor.rs

@ -10,26 +10,33 @@
use io::prelude::*; use io::prelude::*;
use core::convert::TryInto;
use cmp; use cmp;
use io::{self, SeekFrom, Error, ErrorKind}; use io::{self, SeekFrom, Error, ErrorKind};
/// A `Cursor` wraps another type and provides it with a /// A `Cursor` wraps another type and provides it with a
/// [`Seek`](trait.Seek.html) implementation. /// [`Seek`] implementation.
/// ///
/// Cursors are typically used with in-memory buffers to allow them to /// `Cursor`s are typically used with in-memory buffers to allow them to
/// implement `Read` and/or `Write`, allowing these buffers to be used /// implement [`Read`] and/or [`Write`], allowing these buffers to be used
/// anywhere you might use a reader or writer that does actual I/O. /// anywhere you might use a reader or writer that does actual I/O.
/// ///
/// The standard library implements some I/O traits on various types which /// The standard library implements some I/O traits on various types which
/// are commonly used as a buffer, like `Cursor<Vec<u8>>` and `Cursor<&[u8]>`. /// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
/// `Cursor<`[`&[u8]`][bytes]`>`.
/// ///
/// # Examples /// # Examples
/// ///
/// We may want to write bytes to a [`File`][file] in our production /// We may want to write bytes to a [`File`] in our production
/// code, but use an in-memory buffer in our tests. We can do this with /// code, but use an in-memory buffer in our tests. We can do this with
/// `Cursor`: /// `Cursor`:
/// ///
/// [file]: ../fs/struct.File.html /// [`Seek`]: trait.Seek.html
/// [`Read`]: ../../std/io/trait.Read.html
/// [`Write`]: ../../std/io/trait.Write.html
/// [`Vec`]: ../../std/vec/struct.Vec.html
/// [bytes]: ../../std/primitive.slice.html
/// [`File`]: ../fs/struct.File.html
/// ///
/// ```no_run /// ```no_run
/// use std::io::prelude::*; /// use std::io::prelude::*;
@ -72,6 +79,7 @@ use io::{self, SeekFrom, Error, ErrorKind};
/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Cursor<T> { pub struct Cursor<T> {
inner: T, inner: T,
@ -90,6 +98,7 @@ impl<T> Cursor<T> {
/// # fn force_inference(_: &Cursor<Vec<u8>>) {} /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
/// # force_inference(&buff); /// # force_inference(&buff);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: T) -> Cursor<T> { pub fn new(inner: T) -> Cursor<T> {
Cursor { pos: 0, inner: inner } Cursor { pos: 0, inner: inner }
} }
@ -107,6 +116,7 @@ impl<T> Cursor<T> {
/// ///
/// let vec = buff.into_inner(); /// let vec = buff.into_inner();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> T { self.inner } pub fn into_inner(self) -> T { self.inner }
/// Gets a reference to the underlying value in this cursor. /// Gets a reference to the underlying value in this cursor.
@ -122,6 +132,7 @@ impl<T> Cursor<T> {
/// ///
/// let reference = buff.get_ref(); /// let reference = buff.get_ref();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &T { &self.inner } pub fn get_ref(&self) -> &T { &self.inner }
/// Gets a mutable reference to the underlying value in this cursor. /// Gets a mutable reference to the underlying value in this cursor.
@ -140,6 +151,7 @@ impl<T> Cursor<T> {
/// ///
/// let reference = buff.get_mut(); /// let reference = buff.get_mut();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut T { &mut self.inner } pub fn get_mut(&mut self) -> &mut T { &mut self.inner }
/// Returns the current position of this cursor. /// Returns the current position of this cursor.
@ -161,6 +173,7 @@ impl<T> Cursor<T> {
/// buff.seek(SeekFrom::Current(-1)).unwrap(); /// buff.seek(SeekFrom::Current(-1)).unwrap();
/// assert_eq!(buff.position(), 1); /// assert_eq!(buff.position(), 1);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn position(&self) -> u64 { self.pos } pub fn position(&self) -> u64 { self.pos }
/// Sets the position of this cursor. /// Sets the position of this cursor.
@ -180,9 +193,11 @@ impl<T> Cursor<T> {
/// buff.set_position(4); /// buff.set_position(4);
/// assert_eq!(buff.position(), 4); /// assert_eq!(buff.position(), 4);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn set_position(&mut self, pos: u64) { self.pos = pos; } pub fn set_position(&mut self, pos: u64) { self.pos = pos; }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> { impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
fn seek(&mut self, style: SeekFrom) -> io::Result<u64> { fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
let pos = match style { let pos = match style {
@ -201,6 +216,7 @@ impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Read for Cursor<T> where T: AsRef<[u8]> { impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let n = Read::read(&mut self.fill_buf()?, buf)?; let n = Read::read(&mut self.fill_buf()?, buf)?;
@ -209,6 +225,7 @@ impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> { impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> {
fn fill_buf(&mut self) -> io::Result<&[u8]> { fn fill_buf(&mut self) -> io::Result<&[u8]> {
let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64); let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
@ -217,6 +234,7 @@ impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> {
fn consume(&mut self, amt: usize) { self.pos += amt as u64; } fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> { impl<'a> Write for Cursor<&'a mut [u8]> {
#[inline] #[inline]
fn write(&mut self, data: &[u8]) -> io::Result<usize> { fn write(&mut self, data: &[u8]) -> io::Result<usize> {
@ -228,20 +246,23 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> { Ok(()) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Cursor<Vec<u8>> { impl Write for Cursor<Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let pos: usize = self.position().try_into().map_err(|_| {
Error::new(ErrorKind::InvalidInput,
"cursor position exceeds maximum possible vector length")
})?;
// Make sure the internal buffer is as least as big as where we // Make sure the internal buffer is as least as big as where we
// currently are // currently are
let pos = self.position();
let amt = pos.saturating_sub(self.inner.len() as u64);
// use `resize` so that the zero filling is as efficient as possible
let len = self.inner.len(); let len = self.inner.len();
self.inner.resize(len + amt as usize, 0); if len < pos {
// use `resize` so that the zero filling is as efficient as possible
self.inner.resize(pos, 0);
}
// Figure out what bytes will be used to overwrite what's currently // Figure out what bytes will be used to overwrite what's currently
// there (left), and what will be appended on the end (right) // there (left), and what will be appended on the end (right)
{ {
let pos = pos as usize;
let space = self.inner.len() - pos; let space = self.inner.len() - pos;
let (left, right) = buf.split_at(cmp::min(space, buf.len())); let (left, right) = buf.split_at(cmp::min(space, buf.len()));
self.inner[pos..pos + left.len()].copy_from_slice(left); self.inner[pos..pos + left.len()].copy_from_slice(left);
@ -249,12 +270,13 @@ impl Write for Cursor<Vec<u8>> {
} }
// Bump us forward // Bump us forward
self.set_position(pos + buf.len() as u64); self.set_position((pos + buf.len()) as u64);
Ok(buf.len()) Ok(buf.len())
} }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> { Ok(()) }
} }
#[stable(feature = "cursor_box_slice", since = "1.5.0")]
impl Write for Cursor<Box<[u8]>> { impl Write for Cursor<Box<[u8]>> {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@ -271,8 +293,6 @@ mod tests {
use io::prelude::*; use io::prelude::*;
use io::{Cursor, SeekFrom}; use io::{Cursor, SeekFrom};
use collections::Vec;
#[test] #[test]
fn test_vec_writer() { fn test_vec_writer() {
let mut writer = Vec::new(); let mut writer = Vec::new();
@ -372,7 +392,7 @@ mod tests {
#[test] #[test]
fn test_mem_reader() { fn test_mem_reader() {
let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
let mut buf = []; let mut buf = [];
assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.read(&mut buf).unwrap(), 0);
assert_eq!(reader.position(), 0); assert_eq!(reader.position(), 0);
@ -394,7 +414,7 @@ mod tests {
#[test] #[test]
fn test_boxed_slice_reader() { fn test_boxed_slice_reader() {
let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7).into_boxed_slice()); let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
let mut buf = []; let mut buf = [];
assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.read(&mut buf).unwrap(), 0);
assert_eq!(reader.position(), 0); assert_eq!(reader.position(), 0);
@ -416,7 +436,7 @@ mod tests {
#[test] #[test]
fn read_to_end() { fn read_to_end() {
let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
let mut v = Vec::new(); let mut v = Vec::new();
reader.read_to_end(&mut v).unwrap(); reader.read_to_end(&mut v).unwrap();
assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]); assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]);
@ -492,7 +512,7 @@ mod tests {
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
assert_eq!(r.read(&mut [0]).unwrap(), 0); assert_eq!(r.read(&mut [0]).unwrap(), 0);
let mut r = Cursor::new(vec!(10)); let mut r = Cursor::new(vec![10]);
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
assert_eq!(r.read(&mut [0]).unwrap(), 0); assert_eq!(r.read(&mut [0]).unwrap(), 0);
@ -512,14 +532,14 @@ mod tests {
let mut r = Cursor::new(&buf[..]); let mut r = Cursor::new(&buf[..]);
assert!(r.seek(SeekFrom::End(-2)).is_err()); assert!(r.seek(SeekFrom::End(-2)).is_err());
let mut r = Cursor::new(vec!(10)); let mut r = Cursor::new(vec![10]);
assert!(r.seek(SeekFrom::End(-2)).is_err()); assert!(r.seek(SeekFrom::End(-2)).is_err());
let mut buf = [0]; let mut buf = [0];
let mut r = Cursor::new(&mut buf[..]); let mut r = Cursor::new(&mut buf[..]);
assert!(r.seek(SeekFrom::End(-2)).is_err()); assert!(r.seek(SeekFrom::End(-2)).is_err());
let mut r = Cursor::new(vec!(10).into_boxed_slice()); let mut r = Cursor::new(vec![10].into_boxed_slice());
assert!(r.seek(SeekFrom::End(-2)).is_err()); assert!(r.seek(SeekFrom::End(-2)).is_err());
} }
@ -569,4 +589,12 @@ mod tests {
let mut r = Cursor::new(Vec::new()); let mut r = Cursor::new(Vec::new());
assert!(r.seek(SeekFrom::End(-2)).is_err()); assert!(r.seek(SeekFrom::End(-2)).is_err());
} }
#[test]
#[cfg(target_pointer_width = "32")]
fn vec_seek_and_write_past_usize_max() {
let mut c = Cursor::new(Vec::new());
c.set_position(<usize>::max_value() as u64 + 1);
assert!(c.write_all(&[1, 2, 3]).is_err());
}
} }

315
std/src/io/error.rs → ctr-std/src/io/error.rs

@ -8,10 +8,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use error; use error;
use fmt; use fmt;
use result; use result;
use sys;
use convert::From;
/// A specialized [`Result`](../result/enum.Result.html) type for I/O /// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations. /// operations.
@ -43,6 +44,7 @@ use result;
/// Ok(buffer) /// Ok(buffer)
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = result::Result<T, Error>; pub type Result<T> = result::Result<T, Error>;
/// The error type for I/O operations of the `Read`, `Write`, `Seek`, and /// The error type for I/O operations of the `Read`, `Write`, `Seek`, and
@ -50,14 +52,18 @@ pub type Result<T> = result::Result<T, Error>;
/// ///
/// Errors mostly originate from the underlying OS, but custom instances of /// Errors mostly originate from the underlying OS, but custom instances of
/// `Error` can be created with crafted error messages and a particular value of /// `Error` can be created with crafted error messages and a particular value of
/// `ErrorKind`. /// [`ErrorKind`].
///
/// [`ErrorKind`]: enum.ErrorKind.html
#[derive(Debug)] #[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error { pub struct Error {
repr: Repr, repr: Repr,
} }
enum Repr { enum Repr {
Os(i32), Os(i32),
Simple(ErrorKind),
Custom(Box<Custom>), Custom(Box<Custom>),
} }
@ -71,59 +77,86 @@ struct Custom {
/// ///
/// This list is intended to grow over time and it is not recommended to /// This list is intended to grow over time and it is not recommended to
/// exhaustively match against it. /// exhaustively match against it.
#[derive(Copy, PartialEq, Eq, Clone, Debug)] ///
/// It is used with the [`io::Error`] type.
///
/// [`io::Error`]: struct.Error.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)] #[allow(deprecated)]
pub enum ErrorKind { pub enum ErrorKind {
/// An entity was not found, often a file. /// An entity was not found, often a file.
#[stable(feature = "rust1", since = "1.0.0")]
NotFound, NotFound,
/// The operation lacked the necessary privileges to complete. /// The operation lacked the necessary privileges to complete.
#[stable(feature = "rust1", since = "1.0.0")]
PermissionDenied, PermissionDenied,
/// The connection was refused by the remote server. /// The connection was refused by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionRefused, ConnectionRefused,
/// The connection was reset by the remote server. /// The connection was reset by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionReset, ConnectionReset,
/// The connection was aborted (terminated) by the remote server. /// The connection was aborted (terminated) by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionAborted, ConnectionAborted,
/// The network operation failed because it was not connected yet. /// The network operation failed because it was not connected yet.
#[stable(feature = "rust1", since = "1.0.0")]
NotConnected, NotConnected,
/// A socket address could not be bound because the address is already in /// A socket address could not be bound because the address is already in
/// use elsewhere. /// use elsewhere.
#[stable(feature = "rust1", since = "1.0.0")]
AddrInUse, AddrInUse,
/// A nonexistent interface was requested or the requested address was not /// A nonexistent interface was requested or the requested address was not
/// local. /// local.
#[stable(feature = "rust1", since = "1.0.0")]
AddrNotAvailable, AddrNotAvailable,
/// The operation failed because a pipe was closed. /// The operation failed because a pipe was closed.
#[stable(feature = "rust1", since = "1.0.0")]
BrokenPipe, BrokenPipe,
/// An entity already exists, often a file. /// An entity already exists, often a file.
#[stable(feature = "rust1", since = "1.0.0")]
AlreadyExists, AlreadyExists,
/// The operation needs to block to complete, but the blocking operation was /// The operation needs to block to complete, but the blocking operation was
/// requested to not occur. /// requested to not occur.
#[stable(feature = "rust1", since = "1.0.0")]
WouldBlock, WouldBlock,
/// A parameter was incorrect. /// A parameter was incorrect.
#[stable(feature = "rust1", since = "1.0.0")]
InvalidInput, InvalidInput,
/// Data not valid for the operation were encountered. /// Data not valid for the operation were encountered.
/// ///
/// Unlike `InvalidInput`, this typically means that the operation /// Unlike [`InvalidInput`], this typically means that the operation
/// parameters were valid, however the error was caused by malformed /// parameters were valid, however the error was caused by malformed
/// input data. /// input data.
/// ///
/// For example, a function that reads a file into a string will error with /// For example, a function that reads a file into a string will error with
/// `InvalidData` if the file's contents are not valid UTF-8. /// `InvalidData` if the file's contents are not valid UTF-8.
///
/// [`InvalidInput`]: #variant.InvalidInput
#[stable(feature = "io_invalid_data", since = "1.2.0")]
InvalidData, InvalidData,
/// The I/O operation's timeout expired, causing it to be canceled. /// The I/O operation's timeout expired, causing it to be canceled.
#[stable(feature = "rust1", since = "1.0.0")]
TimedOut, TimedOut,
/// An error returned when an operation could not be completed because a /// An error returned when an operation could not be completed because a
/// call to `write` returned `Ok(0)`. /// call to [`write()`] returned [`Ok(0)`].
/// ///
/// This typically means that an operation could only succeed if it wrote a /// This typically means that an operation could only succeed if it wrote a
/// particular number of bytes but only a smaller number of bytes could be /// particular number of bytes but only a smaller number of bytes could be
/// written. /// written.
///
/// [`write()`]: ../../std/io/trait.Write.html#tymethod.write
/// [`Ok(0)`]: ../../std/io/type.Result.html
#[stable(feature = "rust1", since = "1.0.0")]
WriteZero, WriteZero,
/// This operation was interrupted. /// This operation was interrupted.
/// ///
/// Interrupted operations can typically be retried. /// Interrupted operations can typically be retried.
#[stable(feature = "rust1", since = "1.0.0")]
Interrupted, Interrupted,
/// Any I/O error not part of this list. /// Any I/O error not part of this list.
#[stable(feature = "rust1", since = "1.0.0")]
Other, Other,
/// An error returned when an operation could not be completed because an /// An error returned when an operation could not be completed because an
@ -132,13 +165,56 @@ pub enum ErrorKind {
/// This typically means that an operation could only succeed if it read a /// This typically means that an operation could only succeed if it read a
/// particular number of bytes but only a smaller number of bytes could be /// particular number of bytes but only a smaller number of bytes could be
/// read. /// read.
#[stable(feature = "read_exact", since = "1.6.0")]
UnexpectedEof, UnexpectedEof,
/// Any I/O error not part of this list. /// A marker variant that tells the compiler that users of this enum cannot
/// match it exhaustively.
#[unstable(feature = "io_error_internals",
reason = "better expressed through extensible enums that this \
enum cannot be exhaustively matched against",
issue = "0")]
#[doc(hidden)] #[doc(hidden)]
__Nonexhaustive, __Nonexhaustive,
} }
impl ErrorKind {
fn as_str(&self) -> &'static str {
match *self {
ErrorKind::NotFound => "entity not found",
ErrorKind::PermissionDenied => "permission denied",
ErrorKind::ConnectionRefused => "connection refused",
ErrorKind::ConnectionReset => "connection reset",
ErrorKind::ConnectionAborted => "connection aborted",
ErrorKind::NotConnected => "not connected",
ErrorKind::AddrInUse => "address in use",
ErrorKind::AddrNotAvailable => "address not available",
ErrorKind::BrokenPipe => "broken pipe",
ErrorKind::AlreadyExists => "entity already exists",
ErrorKind::WouldBlock => "operation would block",
ErrorKind::InvalidInput => "invalid input parameter",
ErrorKind::InvalidData => "invalid data",
ErrorKind::TimedOut => "timed out",
ErrorKind::WriteZero => "write zero",
ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file",
ErrorKind::__Nonexhaustive => unreachable!()
}
}
}
/// Intended for use for errors not exposed to the user, where allocating onto
/// the heap (for normal construction via Error::new) is too costly.
#[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
repr: Repr::Simple(kind)
}
}
}
impl Error { impl Error {
/// Creates a new I/O error from a known kind of error as well as an /// Creates a new I/O error from a known kind of error as well as an
/// arbitrary error payload. /// arbitrary error payload.
@ -158,6 +234,7 @@ impl Error {
/// // errors can also be created from other errors /// // errors can also be created from other errors
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<Box<error::Error+Send+Sync>> where E: Into<Box<error::Error+Send+Sync>>
{ {
@ -173,7 +250,50 @@ impl Error {
} }
} }
/// Returns an error representing the last OS error which occurred.
///
/// This function reads the value of `errno` for the target platform (e.g.
/// `GetLastError` on Windows) and will return a corresponding instance of
/// `Error` for the error code.
///
/// # Examples
///
/// ```
/// use std::io::Error;
///
/// println!("last OS error: {:?}", Error::last_os_error());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn last_os_error() -> Error {
Error::from_raw_os_error(sys::os::errno() as i32)
}
/// Creates a new instance of an `Error` from a particular OS error code. /// Creates a new instance of an `Error` from a particular OS error code.
///
/// # Examples
///
/// On Linux:
///
/// ```
/// # if cfg!(target_os = "linux") {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(98);
/// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
/// # }
/// ```
///
/// On Windows:
///
/// ```
/// # if cfg!(windows) {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(10048);
/// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_raw_os_error(code: i32) -> Error { pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) } Error { repr: Repr::Os(code) }
} }
@ -183,10 +303,33 @@ impl Error {
/// If this `Error` was constructed via `last_os_error` or /// If this `Error` was constructed via `last_os_error` or
/// `from_raw_os_error`, then this function will return `Some`, otherwise /// `from_raw_os_error`, then this function will return `Some`, otherwise
/// it will return `None`. /// it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_os_error(err: &Error) {
/// if let Some(raw_os_err) = err.raw_os_error() {
/// println!("raw OS error: {:?}", raw_os_err);
/// } else {
/// println!("Not an OS error");
/// }
/// }
///
/// fn main() {
/// // Will print "raw OS error: ...".
/// print_os_error(&Error::last_os_error());
/// // Will print "Not an OS error".
/// print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn raw_os_error(&self) -> Option<i32> { pub fn raw_os_error(&self) -> Option<i32> {
match self.repr { match self.repr {
Repr::Os(i) => Some(i), Repr::Os(i) => Some(i),
Repr::Custom(..) => None, Repr::Custom(..) => None,
Repr::Simple(..) => None,
} }
} }
@ -194,9 +337,32 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: &Error) {
/// if let Some(inner_err) = err.get_ref() {
/// println!("Inner error: {:?}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(&Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(&Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> { pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(ref c) => Some(&*c.error), Repr::Custom(ref c) => Some(&*c.error),
} }
} }
@ -206,9 +372,68 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
/// use std::{error, fmt};
/// use std::fmt::Display;
///
/// #[derive(Debug)]
/// struct MyError {
/// v: String,
/// }
///
/// impl MyError {
/// fn new() -> MyError {
/// MyError {
/// v: "oh no!".to_owned()
/// }
/// }
///
/// fn change_message(&mut self, new_message: &str) {
/// self.v = new_message.to_owned();
/// }
/// }
///
/// impl error::Error for MyError {
/// fn description(&self) -> &str { &self.v }
/// }
///
/// impl Display for MyError {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// write!(f, "MyError: {}", &self.v)
/// }
/// }
///
/// fn change_error(mut err: Error) -> Error {
/// if let Some(inner_err) = err.get_mut() {
/// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
/// }
/// err
/// }
///
/// fn print_error(err: &Error) {
/// if let Some(inner_err) = err.get_ref() {
/// println!("Inner error: {}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(&change_error(Error::last_os_error()));
/// // Will print "Inner error: ...".
/// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> { pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(ref mut c) => Some(&mut *c.error), Repr::Custom(ref mut c) => Some(&mut *c.error),
} }
} }
@ -217,18 +442,60 @@ impl Error {
/// ///
/// If this `Error` was constructed via `new` then this function will /// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`. /// return `Some`, otherwise it will return `None`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: Error) {
/// if let Some(inner_err) = err.into_inner() {
/// println!("Inner error: {}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> { pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(c) => Some(c.error) Repr::Custom(c) => Some(c.error)
} }
} }
/// Returns the corresponding `ErrorKind` for this error. /// Returns the corresponding `ErrorKind` for this error.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: Error) {
/// println!("{:?}", err.kind());
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn kind(&self) -> ErrorKind { pub fn kind(&self) -> ErrorKind {
match self.repr { match self.repr {
Repr::Os(_code) => ErrorKind::Other, Repr::Os(code) => sys::decode_error_kind(code),
Repr::Custom(ref c) => c.kind, Repr::Custom(ref c) => c.kind,
Repr::Simple(kind) => kind,
} }
} }
} }
@ -237,47 +504,33 @@ impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
Repr::Os(ref code) => Repr::Os(ref code) =>
fmt.debug_struct("Os").field("code", code).finish(), fmt.debug_struct("Os").field("code", code)
.field("message", &sys::os::error_string(*code)).finish(),
Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(), Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
} }
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.repr { match self.repr {
Repr::Os(code) => { Repr::Os(code) => {
write!(fmt, "os error {}", code) let detail = sys::os::error_string(code);
write!(fmt, "{} (os error {})", detail, code)
} }
Repr::Custom(ref c) => c.error.fmt(fmt), Repr::Custom(ref c) => c.error.fmt(fmt),
Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
} }
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl error::Error for Error { impl error::Error for Error {
fn description(&self) -> &str { fn description(&self) -> &str {
match self.repr { match self.repr {
Repr::Os(..) => match self.kind() { Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
ErrorKind::NotFound => "entity not found",
ErrorKind::PermissionDenied => "permission denied",
ErrorKind::ConnectionRefused => "connection refused",
ErrorKind::ConnectionReset => "connection reset",
ErrorKind::ConnectionAborted => "connection aborted",
ErrorKind::NotConnected => "not connected",
ErrorKind::AddrInUse => "address in use",
ErrorKind::AddrNotAvailable => "address not available",
ErrorKind::BrokenPipe => "broken pipe",
ErrorKind::AlreadyExists => "entity already exists",
ErrorKind::WouldBlock => "operation would block",
ErrorKind::InvalidInput => "invalid input parameter",
ErrorKind::InvalidData => "invalid data",
ErrorKind::TimedOut => "timed out",
ErrorKind::WriteZero => "write zero",
ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file",
ErrorKind::__Nonexhaustive => unreachable!()
},
Repr::Custom(ref c) => c.error.description(), Repr::Custom(ref c) => c.error.description(),
} }
} }
@ -285,6 +538,7 @@ impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&error::Error> {
match self.repr { match self.repr {
Repr::Os(..) => None, Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(ref c) => c.error.cause(), Repr::Custom(ref c) => c.error.cause(),
} }
} }
@ -297,7 +551,6 @@ fn _assert_error_is_sync_send() {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use prelude::v1::*;
use super::{Error, ErrorKind}; use super::{Error, ErrorKind};
use error; use error;
use fmt; use fmt;

25
std/src/io/impls.rs → ctr-std/src/io/impls.rs

@ -16,6 +16,7 @@ use mem;
// ============================================================================= // =============================================================================
// Forwarding implementations // Forwarding implementations
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, R: Read + ?Sized> Read for &'a mut R { impl<'a, R: Read + ?Sized> Read for &'a mut R {
#[inline] #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
@ -37,6 +38,7 @@ impl<'a, R: Read + ?Sized> Read for &'a mut R {
(**self).read_exact(buf) (**self).read_exact(buf)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, W: Write + ?Sized> Write for &'a mut W { impl<'a, W: Write + ?Sized> Write for &'a mut W {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
@ -54,10 +56,12 @@ impl<'a, W: Write + ?Sized> Write for &'a mut W {
(**self).write_fmt(fmt) (**self).write_fmt(fmt)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, S: Seek + ?Sized> Seek for &'a mut S { impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
#[inline] #[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) } fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
@ -76,6 +80,7 @@ impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read + ?Sized> Read for Box<R> { impl<R: Read + ?Sized> Read for Box<R> {
#[inline] #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
@ -97,6 +102,7 @@ impl<R: Read + ?Sized> Read for Box<R> {
(**self).read_exact(buf) (**self).read_exact(buf)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + ?Sized> Write for Box<W> { impl<W: Write + ?Sized> Write for Box<W> {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
@ -114,10 +120,12 @@ impl<W: Write + ?Sized> Write for Box<W> {
(**self).write_fmt(fmt) (**self).write_fmt(fmt)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<S: Seek + ?Sized> Seek for Box<S> { impl<S: Seek + ?Sized> Seek for Box<S> {
#[inline] #[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) } fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for Box<B> { impl<B: BufRead + ?Sized> BufRead for Box<B> {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
@ -139,6 +147,11 @@ impl<B: BufRead + ?Sized> BufRead for Box<B> {
// ============================================================================= // =============================================================================
// In-memory buffer implementations // In-memory buffer implementations
/// Read is implemented for `&[u8]` by copying from the slice.
///
/// Note that reading updates the slice to point to the yet unread part.
/// The slice will be empty when EOF is reached.
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Read for &'a [u8] { impl<'a> Read for &'a [u8] {
#[inline] #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
@ -162,6 +175,7 @@ impl<'a> Read for &'a [u8] {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> BufRead for &'a [u8] { impl<'a> BufRead for &'a [u8] {
#[inline] #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) }
@ -170,6 +184,12 @@ impl<'a> BufRead for &'a [u8] {
fn consume(&mut self, amt: usize) { *self = &self[amt..]; } fn consume(&mut self, amt: usize) { *self = &self[amt..]; }
} }
/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting
/// its data.
///
/// Note that writing updates the slice to point to the yet unwritten part.
/// The slice will be empty when it has been completely overwritten.
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for &'a mut [u8] { impl<'a> Write for &'a mut [u8] {
#[inline] #[inline]
fn write(&mut self, data: &[u8]) -> io::Result<usize> { fn write(&mut self, data: &[u8]) -> io::Result<usize> {
@ -193,6 +213,9 @@ impl<'a> Write for &'a mut [u8] {
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> { Ok(()) }
} }
/// Write is implemented for `Vec<u8>` by appending to the vector.
/// The vector will grow as needed.
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Vec<u8> { impl Write for Vec<u8> {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@ -215,8 +238,6 @@ mod tests {
use io::prelude::*; use io::prelude::*;
use test; use test;
use collections::Vec;
#[bench] #[bench]
fn bench_read_slice(b: &mut test::Bencher) { fn bench_read_slice(b: &mut test::Bencher) {
let buf = [5; 1024]; let buf = [5; 1024];

297
std/src/io/mod.rs → ctr-std/src/io/mod.rs

@ -12,18 +12,15 @@
//! //!
//! The `std::io` module contains a number of common things you'll need //! The `std::io` module contains a number of common things you'll need
//! when doing input and output. The most core part of this module is //! when doing input and output. The most core part of this module is
//! the [`Read`][read] and [`Write`][write] traits, which provide the //! the [`Read`] and [`Write`] traits, which provide the
//! most general interface for reading and writing input and output. //! most general interface for reading and writing input and output.
//! //!
//! [read]: trait.Read.html
//! [write]: trait.Write.html
//!
//! # Read and Write //! # Read and Write
//! //!
//! Because they are traits, `Read` and `Write` are implemented by a number //! Because they are traits, [`Read`] and [`Write`] are implemented by a number
//! of other types, and you can implement them for your types too. As such, //! of other types, and you can implement them for your types too. As such,
//! you'll see a few different types of I/O throughout the documentation in //! you'll see a few different types of I/O throughout the documentation in
//! this module: `File`s, `TcpStream`s, and sometimes even `Vec<T>`s. For //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For
//! example, `Read` adds a `read()` method, which we can use on `File`s: //! example, `Read` adds a `read()` method, which we can use on `File`s:
//! //!
//! ``` //! ```
@ -43,15 +40,15 @@
//! # } //! # }
//! ``` //! ```
//! //!
//! `Read` and `Write` are so important, implementors of the two traits have a //! [`Read`] and [`Write`] are so important, implementors of the two traits have a
//! nickname: readers and writers. So you'll sometimes see 'a reader' instead //! nickname: readers and writers. So you'll sometimes see 'a reader' instead
//! of 'a type that implements the `Read` trait'. Much easier! //! of 'a type that implements the [`Read`] trait'. Much easier!
//! //!
//! ## Seek and BufRead //! ## Seek and BufRead
//! //!
//! Beyond that, there are two important traits that are provided: [`Seek`][seek] //! Beyond that, there are two important traits that are provided: [`Seek`]
//! and [`BufRead`][bufread]. Both of these build on top of a reader to control //! and [`BufRead`]. Both of these build on top of a reader to control
//! how the reading happens. `Seek` lets you control where the next byte is //! how the reading happens. [`Seek`] lets you control where the next byte is
//! coming from: //! coming from:
//! //!
//! ``` //! ```
@ -75,21 +72,18 @@
//! # } //! # }
//! ``` //! ```
//! //!
//! [seek]: trait.Seek.html //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but
//! [bufread]: trait.BufRead.html
//!
//! `BufRead` uses an internal buffer to provide a number of other ways to read, but
//! to show it off, we'll need to talk about buffers in general. Keep reading! //! to show it off, we'll need to talk about buffers in general. Keep reading!
//! //!
//! ## BufReader and BufWriter //! ## BufReader and BufWriter
//! //!
//! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be
//! making near-constant calls to the operating system. To help with this, //! making near-constant calls to the operating system. To help with this,
//! `std::io` comes with two structs, `BufReader` and `BufWriter`, which wrap //! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap
//! readers and writers. The wrapper uses a buffer, reducing the number of //! readers and writers. The wrapper uses a buffer, reducing the number of
//! calls and providing nicer methods for accessing exactly what you want. //! calls and providing nicer methods for accessing exactly what you want.
//! //!
//! For example, `BufReader` works with the `BufRead` trait to add extra //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra
//! methods to any reader: //! methods to any reader:
//! //!
//! ``` //! ```
@ -111,8 +105,8 @@
//! # } //! # }
//! ``` //! ```
//! //!
//! `BufWriter` doesn't add any new ways of writing; it just buffers every call //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
//! to [`write()`][write()]: //! to [`write()`]:
//! //!
//! ``` //! ```
//! use std::io; //! use std::io;
@ -134,8 +128,6 @@
//! # } //! # }
//! ``` //! ```
//! //!
//! [write()]: trait.Write.html#tymethod.write
//!
//! ## Standard input and output //! ## Standard input and output
//! //!
//! A very common source of input is standard input: //! A very common source of input is standard input:
@ -165,13 +157,13 @@
//! # } //! # }
//! ``` //! ```
//! //!
//! Of course, using `io::stdout()` directly is less common than something like //! Of course, using [`io::stdout()`] directly is less common than something like
//! `println!`. //! [`println!`].
//! //!
//! ## Iterator types //! ## Iterator types
//! //!
//! A large number of the structures provided by `std::io` are for various //! A large number of the structures provided by `std::io` are for various
//! ways of iterating over I/O. For example, `Lines` is used to split over //! ways of iterating over I/O. For example, [`Lines`] is used to split over
//! lines: //! lines:
//! //!
//! ``` //! ```
@ -211,10 +203,10 @@
//! //!
//! ## io::Result //! ## io::Result
//! //!
//! Last, but certainly not least, is [`io::Result`][result]. This type is used //! Last, but certainly not least, is [`io::Result`]. This type is used
//! as the return type of many `std::io` functions that can cause an error, and //! as the return type of many `std::io` functions that can cause an error, and
//! can be returned from your own functions as well. Many of the examples in this //! can be returned from your own functions as well. Many of the examples in this
//! module use the [`try!`][try] macro: //! module use the [`try!`] macro:
//! //!
//! ``` //! ```
//! use std::io; //! use std::io;
@ -230,14 +222,11 @@
//! } //! }
//! ``` //! ```
//! //!
//! The return type of `read_input()`, `io::Result<()>`, is a very common type //! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very
//! for functions which don't have a 'real' return value, but do want to return //! common type for functions which don't have a 'real' return value, but do want to
//! errors if they happen. In this case, the only purpose of this function is //! return errors if they happen. In this case, the only purpose of this function is
//! to read the line and print it, so we use `()`. //! to read the line and print it, so we use `()`.
//! //!
//! [result]: type.Result.html
//! [try]: ../macro.try.html
//!
//! ## Platform-specific behavior //! ## Platform-specific behavior
//! //!
//! Many I/O functions throughout the standard library are documented to indicate //! Many I/O functions throughout the standard library are documented to indicate
@ -246,6 +235,24 @@
//! any possibly unclear semantics. Note, however, that this is informative, not a binding //! any possibly unclear semantics. Note, however, that this is informative, not a binding
//! contract. The implementation of many of these functions are subject to change over //! contract. The implementation of many of these functions are subject to change over
//! time and may call fewer or more syscalls/library functions. //! time and may call fewer or more syscalls/library functions.
//!
//! [`Read`]: trait.Read.html
//! [`Write`]: trait.Write.html
//! [`Seek`]: trait.Seek.html
//! [`BufRead`]: trait.BufRead.html
//! [`File`]: ../fs/struct.File.html
//! [`TcpStream`]: ../net/struct.TcpStream.html
//! [`Vec<T>`]: ../vec/struct.Vec.html
//! [`BufReader`]: struct.BufReader.html
//! [`BufWriter`]: struct.BufWriter.html
//! [`write()`]: trait.Write.html#tymethod.write
//! [`io::stdout()`]: fn.stdout.html
//! [`println!`]: ../macro.println.html
//! [`Lines`]: struct.Lines.html
//! [`io::Result`]: type.Result.html
//! [`try!`]: ../macro.try.html
#![stable(feature = "rust1", since = "1.0.0")]
use cmp; use cmp;
use std_unicode::str as core_str; use std_unicode::str as core_str;
@ -255,17 +262,19 @@ use result;
use str; use str;
use memchr; use memchr;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::{BufReader, BufWriter, LineWriter}; pub use self::buffered::{BufReader, BufWriter, LineWriter};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::IntoInnerError; pub use self::buffered::IntoInnerError;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::cursor::Cursor; pub use self::cursor::Cursor;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::error::{Result, Error, ErrorKind}; pub use self::error::{Result, Error, ErrorKind};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::print::{STDOUT, _print}; pub use self::print::{STDOUT, _print};
//pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr};
//pub use self::stdio::{StdoutLock, StderrLock, StdinLock};
#[doc(no_inline, hidden)]
//pub use self::stdio::{set_panic, set_print};
pub mod prelude; pub mod prelude;
mod buffered; mod buffered;
@ -275,10 +284,7 @@ mod impls;
mod util; mod util;
mod print; mod print;
//mod lazy; const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
//mod stdio;
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
// A few methods below (read_to_string, read_line) will append data into a // A few methods below (read_to_string, read_line) will append data into a
// `String` buffer, but we need to be pretty careful when doing this. The // `String` buffer, but we need to be pretty careful when doing this. The
@ -411,6 +417,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Read { pub trait Read {
/// Pull some bytes from this source into the specified buffer, returning /// Pull some bytes from this source into the specified buffer, returning
/// how many bytes were read. /// how many bytes were read.
@ -460,6 +467,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read(&mut self, buf: &mut [u8]) -> Result<usize>; fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
/// Read all bytes until EOF in this source, placing them into `buf`. /// Read all bytes until EOF in this source, placing them into `buf`.
@ -501,6 +509,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
read_to_end(self, buf) read_to_end(self, buf)
} }
@ -538,6 +547,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> { fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
// Note that we do *not* call `.read_to_end()` here. We are passing // Note that we do *not* call `.read_to_end()` here. We are passing
// `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end` // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end`
@ -598,6 +608,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "read_exact", since = "1.6.0")]
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() { while !buf.is_empty() {
match self.read(buf) { match self.read(buf) {
@ -649,6 +660,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self } fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
/// Transforms this `Read` instance to an `Iterator` over its bytes. /// Transforms this `Read` instance to an `Iterator` over its bytes.
@ -678,6 +690,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn bytes(self) -> Bytes<Self> where Self: Sized { fn bytes(self) -> Bytes<Self> where Self: Sized {
Bytes { inner: self } Bytes { inner: self }
} }
@ -714,6 +727,10 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
of where errors happen is currently \
unclear and may change",
issue = "27802")]
fn chars(self) -> Chars<Self> where Self: Sized { fn chars(self) -> Chars<Self> where Self: Sized {
Chars { inner: self } Chars { inner: self }
} }
@ -748,6 +765,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized { fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
Chain { first: self, second: next, done_first: false } Chain { first: self, second: next, done_first: false }
} }
@ -781,6 +799,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn take(self, limit: u64) -> Take<Self> where Self: Sized { fn take(self, limit: u64) -> Take<Self> where Self: Sized {
Take { inner: self, limit: limit } Take { inner: self, limit: limit }
} }
@ -816,6 +835,7 @@ pub trait Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Write { pub trait Write {
/// Write a buffer into this object, returning how many bytes were written. /// Write a buffer into this object, returning how many bytes were written.
/// ///
@ -855,6 +875,7 @@ pub trait Write {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, buf: &[u8]) -> Result<usize>; fn write(&mut self, buf: &[u8]) -> Result<usize>;
/// Flush this output stream, ensuring that all intermediately buffered /// Flush this output stream, ensuring that all intermediately buffered
@ -880,6 +901,7 @@ pub trait Write {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn flush(&mut self) -> Result<()>; fn flush(&mut self) -> Result<()>;
/// Attempts to write an entire buffer into this write. /// Attempts to write an entire buffer into this write.
@ -906,6 +928,7 @@ pub trait Write {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
while !buf.is_empty() { while !buf.is_empty() {
match self.write(buf) { match self.write(buf) {
@ -957,6 +980,7 @@ pub trait Write {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
// Create a shim which translates a Write to a fmt::Write and saves // Create a shim which translates a Write to a fmt::Write and saves
// off I/O errors. instead of discarding them // off I/O errors. instead of discarding them
@ -1012,6 +1036,7 @@ pub trait Write {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self } fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
} }
@ -1041,6 +1066,7 @@ pub trait Write {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Seek { pub trait Seek {
/// Seek to an offset, in bytes, in a stream. /// Seek to an offset, in bytes, in a stream.
/// ///
@ -1056,6 +1082,7 @@ pub trait Seek {
/// Seeking to a negative offset is considered an error. /// Seeking to a negative offset is considered an error.
/// ///
/// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start /// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
#[stable(feature = "rust1", since = "1.0.0")]
fn seek(&mut self, pos: SeekFrom) -> Result<u64>; fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
} }
@ -1065,23 +1092,27 @@ pub trait Seek {
/// ///
/// [`Seek`]: trait.Seek.html /// [`Seek`]: trait.Seek.html
#[derive(Copy, PartialEq, Eq, Clone, Debug)] #[derive(Copy, PartialEq, Eq, Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum SeekFrom { pub enum SeekFrom {
/// Set the offset to the provided number of bytes. /// Set the offset to the provided number of bytes.
Start(u64), #[stable(feature = "rust1", since = "1.0.0")]
Start(#[stable(feature = "rust1", since = "1.0.0")] u64),
/// Set the offset to the size of this object plus the specified number of /// Set the offset to the size of this object plus the specified number of
/// bytes. /// bytes.
/// ///
/// It is possible to seek beyond the end of an object, but it's an error to /// It is possible to seek beyond the end of an object, but it's an error to
/// seek before byte 0. /// seek before byte 0.
End(i64), #[stable(feature = "rust1", since = "1.0.0")]
End(#[stable(feature = "rust1", since = "1.0.0")] i64),
/// Set the offset to the current position plus the specified number of /// Set the offset to the current position plus the specified number of
/// bytes. /// bytes.
/// ///
/// It is possible to seek beyond the end of an object, but it's an error to /// It is possible to seek beyond the end of an object, but it's an error to
/// seek before byte 0. /// seek before byte 0.
Current(i64), #[stable(feature = "rust1", since = "1.0.0")]
Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
} }
fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
@ -1118,10 +1149,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
/// ///
/// For example, reading line-by-line is inefficient without using a buffer, so /// For example, reading line-by-line is inefficient without using a buffer, so
/// if you want to read by line, you'll need `BufRead`, which includes a /// if you want to read by line, you'll need `BufRead`, which includes a
/// [`read_line()`][readline] method as well as a [`lines()`][lines] iterator. /// [`read_line()`] method as well as a [`lines()`] iterator.
///
/// [readline]: #method.read_line
/// [lines]: #method.lines
/// ///
/// # Examples /// # Examples
/// ///
@ -1137,14 +1165,17 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
/// } /// }
/// ``` /// ```
/// ///
/// If you have something that implements `Read`, you can use the [`BufReader` /// If you have something that implements [`Read`], you can use the [`BufReader`
/// type][bufreader] to turn it into a `BufRead`. /// type][`BufReader`] to turn it into a `BufRead`.
/// ///
/// For example, [`File`][file] implements `Read`, but not `BufRead`. /// For example, [`File`] implements [`Read`], but not `BufRead`.
/// `BufReader` to the rescue! /// [`BufReader`] to the rescue!
/// ///
/// [bufreader]: struct.BufReader.html /// [`BufReader`]: struct.BufReader.html
/// [file]: ../fs/struct.File.html /// [`File`]: ../fs/struct.File.html
/// [`read_line()`]: #method.read_line
/// [`lines()`]: #method.lines
/// [`Read`]: trait.Read.html
/// ///
/// ``` /// ```
/// use std::io::{self, BufReader}; /// use std::io::{self, BufReader};
@ -1163,17 +1194,18 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
/// # } /// # }
/// ``` /// ```
/// ///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BufRead: Read { pub trait BufRead: Read {
/// Fills the internal buffer of this object, returning the buffer contents. /// Fills the internal buffer of this object, returning the buffer contents.
/// ///
/// This function is a lower-level call. It needs to be paired with the /// This function is a lower-level call. It needs to be paired with the
/// [`consume`][consume] method to function properly. When calling this /// [`consume()`] method to function properly. When calling this
/// method, none of the contents will be "read" in the sense that later /// method, none of the contents will be "read" in the sense that later
/// calling `read` may return the same contents. As such, `consume` must be /// calling `read` may return the same contents. As such, [`consume()`] must
/// called with the number of bytes that are consumed from this buffer to /// be called with the number of bytes that are consumed from this buffer to
/// ensure that the bytes are never returned twice. /// ensure that the bytes are never returned twice.
/// ///
/// [consume]: #tymethod.consume /// [`consume()`]: #tymethod.consume
/// ///
/// An empty buffer returned indicates that the stream has reached EOF. /// An empty buffer returned indicates that the stream has reached EOF.
/// ///
@ -1207,43 +1239,43 @@ pub trait BufRead: Read {
/// // ensure the bytes we worked with aren't returned again later /// // ensure the bytes we worked with aren't returned again later
/// stdin.consume(length); /// stdin.consume(length);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn fill_buf(&mut self) -> Result<&[u8]>; fn fill_buf(&mut self) -> Result<&[u8]>;
/// Tells this buffer that `amt` bytes have been consumed from the buffer, /// Tells this buffer that `amt` bytes have been consumed from the buffer,
/// so they should no longer be returned in calls to `read`. /// so they should no longer be returned in calls to `read`.
/// ///
/// This function is a lower-level call. It needs to be paired with the /// This function is a lower-level call. It needs to be paired with the
/// [`fill_buf`][fillbuf] method to function properly. This function does /// [`fill_buf()`] method to function properly. This function does
/// not perform any I/O, it simply informs this object that some amount of /// not perform any I/O, it simply informs this object that some amount of
/// its buffer, returned from `fill_buf`, has been consumed and should no /// its buffer, returned from [`fill_buf()`], has been consumed and should
/// longer be returned. As such, this function may do odd things if /// no longer be returned. As such, this function may do odd things if
/// `fill_buf` isn't called before calling it. /// [`fill_buf()`] isn't called before calling it.
///
/// [fillbuf]: #tymethod.fill_buf
/// ///
/// The `amt` must be `<=` the number of bytes in the buffer returned by /// The `amt` must be `<=` the number of bytes in the buffer returned by
/// `fill_buf`. /// [`fill_buf()`].
/// ///
/// # Examples /// # Examples
/// ///
/// Since `consume()` is meant to be used with [`fill_buf()`][fillbuf], /// Since `consume()` is meant to be used with [`fill_buf()`],
/// that method's example includes an example of `consume()`. /// that method's example includes an example of `consume()`.
///
/// [`fill_buf()`]: #tymethod.fill_buf
#[stable(feature = "rust1", since = "1.0.0")]
fn consume(&mut self, amt: usize); fn consume(&mut self, amt: usize);
/// Read all bytes into `buf` until the delimiter `byte` is reached. /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
/// ///
/// This function will read bytes from the underlying stream until the /// This function will read bytes from the underlying stream until the
/// delimiter or EOF is found. Once found, all bytes up to, and including, /// delimiter or EOF is found. Once found, all bytes up to, and including,
/// the delimiter (if found) will be appended to `buf`. /// the delimiter (if found) will be appended to `buf`.
/// ///
/// If this reader is currently at EOF then this function will not modify /// If successful, this function will return the total number of bytes read.
/// `buf` and will return `Ok(n)` where `n` is the number of bytes which
/// were read.
/// ///
/// # Errors /// # Errors
/// ///
/// This function will ignore all instances of `ErrorKind::Interrupted` and /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
/// will otherwise return any errors returned by `fill_buf`. /// will otherwise return any errors returned by [`fill_buf()`].
/// ///
/// If an I/O error is encountered then all bytes read so far will be /// If an I/O error is encountered then all bytes read so far will be
/// present in `buf` and its length will have been adjusted appropriately. /// present in `buf` and its length will have been adjusted appropriately.
@ -1253,6 +1285,9 @@ pub trait BufRead: Read {
/// A locked standard input implements `BufRead`. In this example, we'll /// A locked standard input implements `BufRead`. In this example, we'll
/// read from standard input until we see an `a` byte. /// read from standard input until we see an `a` byte.
/// ///
/// [`fill_buf()`]: #tymethod.fill_buf
/// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
///
/// ``` /// ```
/// use std::io; /// use std::io;
/// use std::io::prelude::*; /// use std::io::prelude::*;
@ -1268,6 +1303,7 @@ pub trait BufRead: Read {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> { fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
read_until(self, byte, buf) read_until(self, byte, buf)
} }
@ -1280,25 +1316,24 @@ pub trait BufRead: Read {
/// up to, and including, the delimiter (if found) will be appended to /// up to, and including, the delimiter (if found) will be appended to
/// `buf`. /// `buf`.
/// ///
/// If this reader is currently at EOF then this function will not modify /// If successful, this function will return the total number of bytes read.
/// `buf` and will return `Ok(n)` where `n` is the number of bytes which
/// were read.
/// ///
/// # Errors /// # Errors
/// ///
/// This function has the same error semantics as `read_until` and will also /// This function has the same error semantics as [`read_until()`] and will
/// return an error if the read bytes are not valid UTF-8. If an I/O error /// also return an error if the read bytes are not valid UTF-8. If an I/O
/// is encountered then `buf` may contain some bytes already read in the /// error is encountered then `buf` may contain some bytes already read in
/// event that all data read so far was valid UTF-8. /// the event that all data read so far was valid UTF-8.
/// ///
/// # Examples /// # Examples
/// ///
/// A locked standard input implements `BufRead`. In this example, we'll /// A locked standard input implements `BufRead`. In this example, we'll
/// read all of the lines from standard input. If we were to do this in /// read all of the lines from standard input. If we were to do this in
/// an actual project, the [`lines()`][lines] method would be easier, of /// an actual project, the [`lines()`] method would be easier, of
/// course. /// course.
/// ///
/// [lines]: #method.lines /// [`lines()`]: #method.lines
/// [`read_until()`]: #method.read_until
/// ///
/// ``` /// ```
/// use std::io; /// use std::io;
@ -1315,6 +1350,7 @@ pub trait BufRead: Read {
/// buffer.clear(); /// buffer.clear();
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn read_line(&mut self, buf: &mut String) -> Result<usize> { fn read_line(&mut self, buf: &mut String) -> Result<usize> {
// Note that we are not calling the `.read_until` method here, but // Note that we are not calling the `.read_until` method here, but
// rather our hardcoded implementation. For more details as to why, see // rather our hardcoded implementation. For more details as to why, see
@ -1326,17 +1362,21 @@ pub trait BufRead: Read {
/// `byte`. /// `byte`.
/// ///
/// The iterator returned from this function will return instances of /// The iterator returned from this function will return instances of
/// `io::Result<Vec<u8>>`. Each vector returned will *not* have the /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
/// delimiter byte at the end. /// the delimiter byte at the end.
/// ///
/// This function will yield errors whenever `read_until` would have also /// This function will yield errors whenever [`read_until()`] would have
/// yielded an error. /// also yielded an error.
/// ///
/// # Examples /// # Examples
/// ///
/// A locked standard input implements `BufRead`. In this example, we'll /// A locked standard input implements `BufRead`. In this example, we'll
/// read some input from standard input, splitting on commas. /// read some input from standard input, splitting on commas.
/// ///
/// [`io::Result`]: type.Result.html
/// [`Vec<u8>`]: ../vec/struct.Vec.html
/// [`read_until()`]: #method.read_until
///
/// ``` /// ```
/// use std::io; /// use std::io;
/// use std::io::prelude::*; /// use std::io::prelude::*;
@ -1347,6 +1387,7 @@ pub trait BufRead: Read {
/// println!("{:?}", content.unwrap()); /// println!("{:?}", content.unwrap());
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn split(self, byte: u8) -> Split<Self> where Self: Sized { fn split(self, byte: u8) -> Split<Self> where Self: Sized {
Split { buf: self, delim: byte } Split { buf: self, delim: byte }
} }
@ -1354,9 +1395,12 @@ pub trait BufRead: Read {
/// Returns an iterator over the lines of this reader. /// Returns an iterator over the lines of this reader.
/// ///
/// The iterator returned from this function will yield instances of /// The iterator returned from this function will yield instances of
/// `io::Result<String>`. Each string returned will *not* have a newline /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
/// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
/// ///
/// [`io::Result`]: type.Result.html
/// [`String`]: ../string/struct.String.html
///
/// # Examples /// # Examples
/// ///
/// A locked standard input implements `BufRead`: /// A locked standard input implements `BufRead`:
@ -1371,6 +1415,7 @@ pub trait BufRead: Read {
/// println!("{}", line.unwrap()); /// println!("{}", line.unwrap());
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn lines(self) -> Lines<Self> where Self: Sized { fn lines(self) -> Lines<Self> where Self: Sized {
Lines { buf: self } Lines { buf: self }
} }
@ -1378,21 +1423,23 @@ pub trait BufRead: Read {
/// Adaptor to chain together two readers. /// Adaptor to chain together two readers.
/// ///
/// This struct is generally created by calling [`chain()`][chain] on a reader. /// This struct is generally created by calling [`chain()`] on a reader.
/// Please see the documentation of `chain()` for more details. /// Please see the documentation of [`chain()`] for more details.
/// ///
/// [chain]: trait.Read.html#method.chain /// [`chain()`]: trait.Read.html#method.chain
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chain<T, U> { pub struct Chain<T, U> {
first: T, first: T,
second: U, second: U,
done_first: bool, done_first: bool,
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Read, U: Read> Read for Chain<T, U> { impl<T: Read, U: Read> Read for Chain<T, U> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> { fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if !self.done_first { if !self.done_first {
match self.first.read(buf)? { match self.first.read(buf)? {
0 => { self.done_first = true; } 0 if buf.len() != 0 => { self.done_first = true; }
n => return Ok(n), n => return Ok(n),
} }
} }
@ -1400,6 +1447,7 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
} }
} }
#[stable(feature = "chain_bufread", since = "1.9.0")]
impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> { impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
fn fill_buf(&mut self) -> Result<&[u8]> { fn fill_buf(&mut self) -> Result<&[u8]> {
if !self.done_first { if !self.done_first {
@ -1426,6 +1474,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
/// Please see the documentation of `take()` for more details. /// Please see the documentation of `take()` for more details.
/// ///
/// [take]: trait.Read.html#method.take /// [take]: trait.Read.html#method.take
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Take<T> { pub struct Take<T> {
inner: T, inner: T,
limit: u64, limit: u64,
@ -1457,9 +1506,38 @@ impl<T> Take<T> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn limit(&self) -> u64 { self.limit } pub fn limit(&self) -> u64 { self.limit }
/// Consumes the `Take`, returning the wrapped reader.
///
/// # Examples
///
/// ```
/// #![feature(io_take_into_inner)]
///
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// # fn foo() -> io::Result<()> {
/// let mut file = try!(File::open("foo.txt"));
///
/// let mut buffer = [0; 5];
/// let mut handle = file.take(5);
/// try!(handle.read(&mut buffer));
///
/// let file = handle.into_inner();
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "io_take_into_inner", issue = "23755")]
pub fn into_inner(self) -> T {
self.inner
}
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Read> Read for Take<T> { impl<T: Read> Read for Take<T> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> { fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
// Don't call into inner reader at all at EOF because it may still block // Don't call into inner reader at all at EOF because it may still block
@ -1474,6 +1552,7 @@ impl<T: Read> Read for Take<T> {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: BufRead> BufRead for Take<T> { impl<T: BufRead> BufRead for Take<T> {
fn fill_buf(&mut self) -> Result<&[u8]> { fn fill_buf(&mut self) -> Result<&[u8]> {
// Don't call into inner reader at all at EOF because it may still block // Don't call into inner reader at all at EOF because it may still block
@ -1508,14 +1587,16 @@ fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
/// An iterator over `u8` values of a reader. /// An iterator over `u8` values of a reader.
/// ///
/// This struct is generally created by calling [`bytes()`][bytes] on a reader. /// This struct is generally created by calling [`bytes()`] on a reader.
/// Please see the documentation of `bytes()` for more details. /// Please see the documentation of [`bytes()`] for more details.
/// ///
/// [bytes]: trait.Read.html#method.bytes /// [`bytes()`]: trait.Read.html#method.bytes
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Bytes<R> { pub struct Bytes<R> {
inner: R, inner: R,
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Iterator for Bytes<R> { impl<R: Read> Iterator for Bytes<R> {
type Item = Result<u8>; type Item = Result<u8>;
@ -1530,6 +1611,8 @@ impl<R: Read> Iterator for Bytes<R> {
/// Please see the documentation of `chars()` for more details. /// Please see the documentation of `chars()` for more details.
/// ///
/// [chars]: trait.Read.html#method.chars /// [chars]: trait.Read.html#method.chars
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
pub struct Chars<R> { pub struct Chars<R> {
inner: R, inner: R,
} }
@ -1537,6 +1620,8 @@ pub struct Chars<R> {
/// An enumeration of possible errors that can be generated from the `Chars` /// An enumeration of possible errors that can be generated from the `Chars`
/// adapter. /// adapter.
#[derive(Debug)] #[derive(Debug)]
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
pub enum CharsError { pub enum CharsError {
/// Variant representing that the underlying stream was read successfully /// Variant representing that the underlying stream was read successfully
/// but it did not contain valid utf8 data. /// but it did not contain valid utf8 data.
@ -1546,6 +1631,8 @@ pub enum CharsError {
Other(Error), Other(Error),
} }
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
impl<R: Read> Iterator for Chars<R> { impl<R: Read> Iterator for Chars<R> {
type Item = result::Result<char, CharsError>; type Item = result::Result<char, CharsError>;
@ -1577,6 +1664,8 @@ impl<R: Read> Iterator for Chars<R> {
} }
} }
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
impl std_error::Error for CharsError { impl std_error::Error for CharsError {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
@ -1592,6 +1681,8 @@ impl std_error::Error for CharsError {
} }
} }
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
impl fmt::Display for CharsError { impl fmt::Display for CharsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
@ -1610,11 +1701,13 @@ impl fmt::Display for CharsError {
/// `BufRead`. Please see the documentation of `split()` for more details. /// `BufRead`. Please see the documentation of `split()` for more details.
/// ///
/// [split]: trait.BufRead.html#method.split /// [split]: trait.BufRead.html#method.split
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Split<B> { pub struct Split<B> {
buf: B, buf: B,
delim: u8, delim: u8,
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead> Iterator for Split<B> { impl<B: BufRead> Iterator for Split<B> {
type Item = Result<Vec<u8>>; type Item = Result<Vec<u8>>;
@ -1639,10 +1732,12 @@ impl<B: BufRead> Iterator for Split<B> {
/// `BufRead`. Please see the documentation of `lines()` for more details. /// `BufRead`. Please see the documentation of `lines()` for more details.
/// ///
/// [lines]: trait.BufRead.html#method.lines /// [lines]: trait.BufRead.html#method.lines
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Lines<B> { pub struct Lines<B> {
buf: B, buf: B,
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead> Iterator for Lines<B> { impl<B: BufRead> Iterator for Lines<B> {
type Item = Result<String>; type Item = Result<String>;
@ -1669,13 +1764,11 @@ mod tests {
use io::prelude::*; use io::prelude::*;
use io; use io;
use super::Cursor; use super::Cursor;
use super::repeat;
use test; use test;
use super::repeat;
use collections::{Vec, String};
use collections::string::ToString;
#[test] #[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn read_until() { fn read_until() {
let mut buf = Cursor::new(&b"12"[..]); let mut buf = Cursor::new(&b"12"[..]);
let mut v = Vec::new(); let mut v = Vec::new();
@ -1874,7 +1967,19 @@ mod tests {
cmp_bufread(chain1, chain2, &testdata[..]); cmp_bufread(chain1, chain2, &testdata[..]);
} }
#[test]
fn chain_zero_length_read_is_not_eof() {
let a = b"A";
let b = b"B";
let mut s = String::new();
let mut chain = (&a[..]).chain(&b[..]);
chain.read(&mut []).unwrap();
chain.read_to_string(&mut s).unwrap();
assert_eq!("AB", s);
}
#[bench] #[bench]
#[cfg_attr(target_os = "emscripten", ignore)]
fn bench_read_to_end(b: &mut test::Bencher) { fn bench_read_to_end(b: &mut test::Bencher) {
b.iter(|| { b.iter(|| {
let mut lr = repeat(1).take(10000000); let mut lr = repeat(1).take(10000000);

2
std/src/io/prelude.rs → ctr-std/src/io/prelude.rs

@ -18,5 +18,7 @@
//! use std::io::prelude::*; //! use std::io::prelude::*;
//! ``` //! ```
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub use super::{Read, Write, BufRead, Seek}; pub use super::{Read, Write, BufRead, Seek};

3
std/src/io/print.rs → ctr-std/src/io/print.rs

@ -4,12 +4,13 @@ use io::{self, Write};
// NOTE: We're just gonna use the spin mutex until we figure out how to properly // NOTE: We're just gonna use the spin mutex until we figure out how to properly
// implement mutexes with ctrulib functions // implement mutexes with ctrulib functions
use spin::Mutex; use spin::Mutex;
use libctru::libc; use libc;
pub static STDOUT: Mutex<StdoutRaw> = Mutex::new(StdoutRaw(())); pub static STDOUT: Mutex<StdoutRaw> = Mutex::new(StdoutRaw(()));
pub struct StdoutRaw(()); pub struct StdoutRaw(());
#[stable(feature = "3ds", since = "1.0.0")]
impl Write for StdoutRaw { impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
unsafe { unsafe {

11
std/src/io/util.rs → ctr-std/src/io/util.rs

@ -42,6 +42,7 @@ use io::{self, Read, Write, ErrorKind, BufRead};
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
where R: Read, W: Write where R: Read, W: Write
{ {
@ -65,6 +66,7 @@ pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<
/// the documentation of `empty()` for more details. /// the documentation of `empty()` for more details.
/// ///
/// [empty]: fn.empty.html /// [empty]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () } pub struct Empty { _priv: () }
/// Constructs a new handle to an empty reader. /// Constructs a new handle to an empty reader.
@ -82,11 +84,14 @@ pub struct Empty { _priv: () }
/// io::empty().read_to_string(&mut buffer).unwrap(); /// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty()); /// assert!(buffer.is_empty());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } } pub fn empty() -> Empty { Empty { _priv: () } }
#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty { impl Read for Empty {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty { impl BufRead for Empty {
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
fn consume(&mut self, _n: usize) {} fn consume(&mut self, _n: usize) {}
@ -98,6 +103,7 @@ impl BufRead for Empty {
/// see the documentation of `repeat()` for more details. /// see the documentation of `repeat()` for more details.
/// ///
/// [repeat]: fn.repeat.html /// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 } pub struct Repeat { byte: u8 }
/// Creates an instance of a reader that infinitely repeats one byte. /// Creates an instance of a reader that infinitely repeats one byte.
@ -114,8 +120,10 @@ pub struct Repeat { byte: u8 }
/// io::repeat(0b101).read_exact(&mut buffer).unwrap(); /// io::repeat(0b101).read_exact(&mut buffer).unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]); /// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }
#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat { impl Read for Repeat {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
for slot in &mut *buf { for slot in &mut *buf {
@ -131,6 +139,7 @@ impl Read for Repeat {
/// see the documentation of `sink()` for more details. /// see the documentation of `sink()` for more details.
/// ///
/// [sink]: fn.sink.html /// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () } pub struct Sink { _priv: () }
/// Creates an instance of a writer which will successfully consume all data. /// Creates an instance of a writer which will successfully consume all data.
@ -147,8 +156,10 @@ pub struct Sink { _priv: () }
/// let num_bytes = io::sink().write(&buffer).unwrap(); /// let num_bytes = io::sink().write(&buffer).unwrap();
/// assert_eq!(num_bytes, 5); /// assert_eq!(num_bytes, 5);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } } pub fn sink() -> Sink { Sink { _priv: () } }
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink { impl Write for Sink {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> { Ok(()) }

174
ctr-std/src/lib.rs

@ -0,0 +1,174 @@
#![feature(alloc)]
#![feature(allow_internal_unstable)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(const_fn)]
#![feature(compiler_builtins_lib)]
#![feature(core_intrinsics)]
#![feature(char_escape_debug)]
#![feature(float_extras)]
#![feature(fused)]
#![feature(int_error_internals)]
#![feature(lang_items)]
#![feature(macro_reexport)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(raw)]
#![feature(slice_concat_ext)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(str_internals)]
#![feature(thread_local)]
#![feature(try_from)]
#![feature(unicode)]
#![feature(zero_one)]
#![allow(non_camel_case_types, dead_code, unused_features)]
#![no_std]
#![stable(feature = "rust1", since = "1.0.0")]
#[prelude_import]
#[allow(unused)]
use prelude::v1::*;
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
unreachable, unimplemented, write, writeln, try)]
extern crate core as __core;
#[macro_use]
#[macro_reexport(vec, format)]
extern crate collections as core_collections;
extern crate alloc;
extern crate std_unicode;
extern crate alloc_system;
// compiler-rt intrinsics
extern crate compiler_builtins;
// 3ds-specific dependencies
extern crate ctr_libc as libc;
// stealing spin's mutex implementation for now
extern crate spin;
// The standard macros that are not built-in to the compiler.
#[macro_use]
mod macros;
// The Rust prelude
pub mod prelude;
// Public module declarations and reexports
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::any;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::cell;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::clone;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::cmp;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::convert;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::default;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::hash;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::intrinsics;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::iter;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::marker;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::mem;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::ops;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::ptr;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::raw;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::result;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::option;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::isize;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::i8;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::i16;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::i32;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::i64;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::usize;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::u8;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::u16;
#[stable(feature = "rust1", since = "1.0.0")]
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;
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc::rc;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::borrow;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::fmt;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::slice;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::str;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::string;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::vec;
#[stable(feature = "rust1", since = "1.0.0")]
pub use std_unicode::char;
pub mod f32;
pub mod f64;
pub mod ascii;
pub mod error;
pub mod ffi;
pub mod io;
pub mod num;
pub mod os;
pub mod path;
pub mod sync;
// Platform-abstraction modules
#[macro_use]
mod sys_common;
mod sys;
// Private support modules
mod panicking;
mod memchr;
// The runtime entry point and a few unstable public functions used by the
// compiler
pub mod rt;
// NOTE: These two are "undefined" symbols that LLVM emits but that
// we never actually use
#[doc(hidden)]
#[stable(feature = "3ds", since = "1.0.0")]
#[no_mangle]
pub unsafe extern "C" fn __aeabi_unwind_cpp_pr0() {
intrinsics::unreachable()
}
#[stable(feature = "3ds", since = "1.0.0")]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn __aeabi_unwind_cpp_pr1() {
intrinsics::unreachable()
}

481
ctr-std/src/macros.rs

@ -0,0 +1,481 @@
// Copyright 2014 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.
//! Standard library macros
//!
//! This modules contains a set of macros which are exported from the standard
//! library. Each macro is available for use when linking against the standard
//! library.
/// The entry point for panic of Rust threads.
///
/// This macro is used to inject panic into a Rust thread, causing the thread to
/// panic entirely. Each thread's panic can be reaped as the `Box<Any>` type,
/// and the single-argument form of the `panic!` macro will be the value which
/// is transmitted.
///
/// The multi-argument form of this macro panics with a string and has the
/// `format!` syntax for building a string.
///
/// # Examples
///
/// ```should_panic
/// # #![allow(unreachable_code)]
/// panic!();
/// panic!("this is a terrible mistake!");
/// panic!(4); // panic with the value of 4 to be collected elsewhere
/// panic!("this is a {} {message}", "fancy", message = "message");
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
macro_rules! panic {
() => ({
panic!("explicit panic")
});
($msg:expr) => ({
$crate::rt::begin_panic($msg, {
// static requires less code at runtime, more constant data
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
&_FILE_LINE
})
});
($fmt:expr, $($arg:tt)+) => ({
$crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+), {
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
// insufficient, since the user may have
// `#[forbid(dead_code)]` and which cannot be overridden.
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
&_FILE_LINE
})
});
}
/// Macro for printing to the standard output.
///
/// Equivalent to the `println!` macro except that a newline is not printed at
/// the end of the message.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use `io::stdout().flush()` to ensure the output is emitted
/// immediately.
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
/// Macro for printing to the standard output, with a newline. On all
/// platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
///
/// Use the `format!` syntax to write data to the standard output.
/// See `std::fmt` for more information.
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// println!();
/// println!("hello there!");
/// println!("format {} arguments", "some");
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! println {
() => (print!("\n"));
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}
/// A macro to select an event from a number of receivers.
///
/// This macro is used to wait for the first event to occur on a number of
/// receivers. It places no restrictions on the types of receivers given to
/// this macro, this can be viewed as a heterogeneous select.
///
/// # Examples
///
/// ```
/// #![feature(mpsc_select)]
///
/// use std::thread;
/// use std::sync::mpsc;
///
/// // two placeholder functions for now
/// fn long_running_thread() {}
/// fn calculate_the_answer() -> u32 { 42 }
///
/// let (tx1, rx1) = mpsc::channel();
/// let (tx2, rx2) = mpsc::channel();
///
/// thread::spawn(move|| { long_running_thread(); tx1.send(()).unwrap(); });
/// thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
///
/// select! {
/// _ = rx1.recv() => println!("the long running thread finished first"),
/// answer = rx2.recv() => {
/// println!("the answer was: {}", answer.unwrap());
/// }
/// }
/// # drop(rx1.recv());
/// # drop(rx2.recv());
/// ```
///
/// For more information about select, see the `std::sync::mpsc::Select` structure.
#[macro_export]
#[unstable(feature = "mpsc_select", issue = "27800")]
macro_rules! select {
(
$($name:pat = $rx:ident.$meth:ident() => $code:expr),+
) => ({
use $crate::sync::mpsc::Select;
let sel = Select::new();
$( let mut $rx = sel.handle(&$rx); )+
unsafe {
$( $rx.add(); )+
}
let ret = sel.wait();
$( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
{ unreachable!() }
})
}
#[cfg(test)]
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
})
}
/// Built-in macros to the compiler itself.
///
/// These macros do not have any corresponding definition with a `macro_rules!`
/// macro, but are documented here. Their implementations can be found hardcoded
/// into libsyntax itself.
#[cfg(dox)]
pub mod builtin {
/// The core macro for formatted string creation & output.
///
/// This macro produces a value of type [`fmt::Arguments`]. This value can be
/// passed to the functions in [`std::fmt`] for performing useful functions.
/// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are
/// proxied through this one.
///
/// For more information, see the documentation in [`std::fmt`].
///
/// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
/// [`std::fmt`]: ../std/fmt/index.html
/// [`format!`]: ../std/macro.format.html
/// [`write!`]: ../std/macro.write.html
/// [`println!`]: ../std/macro.println.html
///
/// # Examples
///
/// ```
/// use std::fmt;
///
/// let s = fmt::format(format_args!("hello {}", "world"));
/// assert_eq!(s, format!("hello {}", "world"));
///
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! format_args { ($fmt:expr, $($args:tt)*) => ({
/* compiler built-in */
}) }
/// Inspect an environment variable at compile time.
///
/// This macro will expand to the value of the named environment variable at
/// compile time, yielding an expression of type `&'static str`.
///
/// If the environment variable is not defined, then a compilation error
/// will be emitted. To not emit a compile error, use the `option_env!`
/// macro instead.
///
/// # Examples
///
/// ```
/// let path: &'static str = env!("PATH");
/// println!("the $PATH variable at the time of compiling was: {}", path);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) }
/// Optionally inspect an environment variable at compile time.
///
/// If the named environment variable is present at compile time, this will
/// expand into an expression of type `Option<&'static str>` whose value is
/// `Some` of the value of the environment variable. If the environment
/// variable is not present, then this will expand to `None`.
///
/// A compile time error is never emitted when using this macro regardless
/// of whether the environment variable is present or not.
///
/// # Examples
///
/// ```
/// let key: Option<&'static str> = option_env!("SECRET_KEY");
/// println!("the secret key might be: {:?}", key);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
/// Concatenate identifiers into one identifier.
///
/// This macro takes any number of comma-separated identifiers, and
/// concatenates them all into one, yielding an expression which is a new
/// identifier. Note that hygiene makes it such that this macro cannot
/// capture local variables. Also, as a general rule, macros are only
/// allowed in item, statement or expression position. That means while
/// you may use this macro for referring to existing variables, functions or
/// modules etc, you cannot define a new one with it.
///
/// # Examples
///
/// ```
/// #![feature(concat_idents)]
///
/// # fn main() {
/// fn foobar() -> u32 { 23 }
///
/// let f = concat_idents!(foo, bar);
/// println!("{}", f());
///
/// // fn concat_idents!(new, fun, name) { } // not usable in this way!
/// # }
/// ```
#[unstable(feature = "concat_idents_macro", issue = "29599")]
#[macro_export]
macro_rules! concat_idents {
($($e:ident),*) => ({ /* compiler built-in */ })
}
/// Concatenates literals into a static string slice.
///
/// This macro takes any number of comma-separated literals, yielding an
/// expression of type `&'static str` which represents all of the literals
/// concatenated left-to-right.
///
/// Integer and floating point literals are stringified in order to be
/// concatenated.
///
/// # Examples
///
/// ```
/// let s = concat!("test", 10, 'b', true);
/// assert_eq!(s, "test10btrue");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) }
/// A macro which expands to the line number on which it was invoked.
///
/// The expanded expression has type `u32`, and the returned line is not
/// the invocation of the `line!()` macro itself, but rather the first macro
/// invocation leading up to the invocation of the `line!()` macro.
///
/// # Examples
///
/// ```
/// let current_line = line!();
/// println!("defined on line: {}", current_line);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! line { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the column number on which it was invoked.
///
/// The expanded expression has type `u32`, and the returned column is not
/// the invocation of the `column!()` macro itself, but rather the first macro
/// invocation leading up to the invocation of the `column!()` macro.
///
/// # Examples
///
/// ```
/// let current_col = column!();
/// println!("defined on column: {}", current_col);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! column { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the file name from which it was invoked.
///
/// The expanded expression has type `&'static str`, and the returned file
/// is not the invocation of the `file!()` macro itself, but rather the
/// first macro invocation leading up to the invocation of the `file!()`
/// macro.
///
/// # Examples
///
/// ```
/// let this_file = file!();
/// println!("defined in file: {}", this_file);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! file { () => ({ /* compiler built-in */ }) }
/// A macro which stringifies its argument.
///
/// This macro will yield an expression of type `&'static str` which is the
/// stringification of all the tokens passed to the macro. No restrictions
/// are placed on the syntax of the macro invocation itself.
///
/// Note that the expanded results of the input tokens may change in the
/// future. You should be careful if you rely on the output.
///
/// # Examples
///
/// ```
/// let one_plus_one = stringify!(1 + 1);
/// assert_eq!(one_plus_one, "1 + 1");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) }
/// Includes a utf8-encoded file as a string.
///
/// The file is located relative to the current file. (similarly to how
/// modules are found)
///
/// This macro will yield an expression of type `&'static str` which is the
/// contents of the file.
///
/// # Examples
///
/// ```rust,ignore
/// let secret_key = include_str!("secret-key.ascii");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
/// Includes a file as a reference to a byte array.
///
/// The file is located relative to the current file. (similarly to how
/// modules are found)
///
/// This macro will yield an expression of type `&'static [u8; N]` which is
/// the contents of the file.
///
/// # Examples
///
/// ```rust,ignore
/// let secret_key = include_bytes!("secret-key.bin");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) }
/// Expands to a string that represents the current module path.
///
/// The current module path can be thought of as the hierarchy of modules
/// leading back up to the crate root. The first component of the path
/// returned is the name of the crate currently being compiled.
///
/// # Examples
///
/// ```
/// mod test {
/// pub fn foo() {
/// assert!(module_path!().ends_with("test"));
/// }
/// }
///
/// test::foo();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! module_path { () => ({ /* compiler built-in */ }) }
/// Boolean evaluation of configuration flags.
///
/// In addition to the `#[cfg]` attribute, this macro is provided to allow
/// boolean expression evaluation of configuration flags. This frequently
/// leads to less duplicated code.
///
/// The syntax given to this macro is the same syntax as [the `cfg`
/// attribute](../reference.html#conditional-compilation).
///
/// # Examples
///
/// ```
/// let my_directory = if cfg!(windows) {
/// "windows-specific-directory"
/// } else {
/// "unix-directory"
/// };
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
/// Parse a file as an expression or an item according to the context.
///
/// The file is located relative to the current file. (similarly to how
/// modules are found)
///
/// Using this macro is often a bad idea, because if the file is
/// parsed as an expression, it is going to be placed in the
/// surrounding code unhygenically. This could result in variables
/// or functions being different from what the file expected if
/// there are variables or functions that have the same name in
/// the current file.
///
/// # Examples
///
/// ```ignore
/// fn foo() {
/// include!("/path/to/a/file")
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
}

143
ctr-std/src/memchr.rs

@ -0,0 +1,143 @@
// Copyright 2015 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.
//
// Original implementation taken from rust-memchr
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
/// A safe interface to `memchr`.
///
/// Returns the index corresponding to the first occurrence of `needle` in
/// `haystack`, or `None` if one is not found.
///
/// memchr reduces to super-optimized machine code at around an order of
/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
/// (See benchmarks.)
///
/// # Example
///
/// This shows how to find the first position of a byte in a byte string.
///
/// ```rust,ignore
/// use memchr::memchr;
///
/// let haystack = b"the quick brown fox";
/// assert_eq!(memchr(b'k', haystack), Some(8));
/// ```
#[inline]
pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
::sys::memchr::memchr(needle, haystack)
}
/// A safe interface to `memrchr`.
///
/// Returns the index corresponding to the last occurrence of `needle` in
/// `haystack`, or `None` if one is not found.
///
/// # Example
///
/// This shows how to find the last position of a byte in a byte string.
///
/// ```rust,ignore
/// use memchr::memrchr;
///
/// let haystack = b"the quick brown fox";
/// assert_eq!(memrchr(b'o', haystack), Some(17));
/// ```
#[inline]
pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
::sys::memchr::memrchr(needle, haystack)
}
#[cfg(test)]
mod tests {
// test the implementations for the current plattform
use super::{memchr, memrchr};
#[test]
fn matches_one() {
assert_eq!(Some(0), memchr(b'a', b"a"));
}
#[test]
fn matches_begin() {
assert_eq!(Some(0), memchr(b'a', b"aaaa"));
}
#[test]
fn matches_end() {
assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
}
#[test]
fn matches_nul() {
assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
}
#[test]
fn matches_past_nul() {
assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
}
#[test]
fn no_match_empty() {
assert_eq!(None, memchr(b'a', b""));
}
#[test]
fn no_match() {
assert_eq!(None, memchr(b'a', b"xyz"));
}
#[test]
fn matches_one_reversed() {
assert_eq!(Some(0), memrchr(b'a', b"a"));
}
#[test]
fn matches_begin_reversed() {
assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
}
#[test]
fn matches_end_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
}
#[test]
fn matches_nul_reversed() {
assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
}
#[test]
fn matches_past_nul_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
}
#[test]
fn no_match_empty_reversed() {
assert_eq!(None, memrchr(b'a', b""));
}
#[test]
fn no_match_reversed() {
assert_eq!(None, memrchr(b'a', b"xyz"));
}
#[test]
fn each_alignment() {
let mut data = [1u8; 64];
let needle = 2;
let pos = 40;
data[pos] = needle;
for start in 0..16 {
assert_eq!(Some(pos - start), memchr(needle, &data[start..]));
}
}
}

44
std/src/num/mod.rs → ctr-std/src/num.rs

@ -13,17 +13,19 @@
//! This module provides some extra types that are useful when doing numerical //! This module provides some extra types that are useful when doing numerical
//! work. See the individual documentation for each piece for more information. //! work. See the individual documentation for each piece for more information.
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)] #![allow(missing_docs)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)] #[allow(deprecated)]
pub use core::num::{Zero, One}; pub use core::num::{Zero, One};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError}; pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::Wrapping; pub use core::num::Wrapping;
#[cfg(test)] #[cfg(test)] use fmt;
use fmt; #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
#[cfg(test)]
use ops::{Add, Sub, Mul, Div, Rem};
/// Helper function for testing numeric operations /// Helper function for testing numeric operations
#[cfg(test)] #[cfg(test)]
@ -34,11 +36,11 @@ pub fn test_num<T>(ten: T, two: T) where
+ Rem<Output=T> + fmt::Debug + Rem<Output=T> + fmt::Debug
+ Copy + Copy
{ {
assert_eq!(ten.add(two), ten + two); assert_eq!(ten.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two); assert_eq!(ten.sub(two), ten - two);
assert_eq!(ten.mul(two), ten * two); assert_eq!(ten.mul(two), ten * two);
assert_eq!(ten.div(two), ten / two); assert_eq!(ten.div(two), ten / two);
assert_eq!(ten.rem(two), ten % two); assert_eq!(ten.rem(two), ten % two);
} }
#[cfg(test)] #[cfg(test)]
@ -54,9 +56,9 @@ mod tests {
fn test_saturating_add_uint() { fn test_saturating_add_uint() {
use usize::MAX; use usize::MAX;
assert_eq!(3_usize.saturating_add(5_usize), 8_usize); assert_eq!(3_usize.saturating_add(5_usize), 8_usize);
assert_eq!(3_usize.saturating_add(MAX - 1), MAX); assert_eq!(3_usize.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX); assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX - 2).saturating_add(1), MAX - 1); assert_eq!((MAX-2).saturating_add(1), MAX-1);
} }
#[test] #[test]
@ -65,16 +67,16 @@ mod tests {
assert_eq!(5_usize.saturating_sub(3_usize), 2_usize); assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
assert_eq!(3_usize.saturating_sub(5_usize), 0_usize); assert_eq!(3_usize.saturating_sub(5_usize), 0_usize);
assert_eq!(0_usize.saturating_sub(1_usize), 0_usize); assert_eq!(0_usize.saturating_sub(1_usize), 0_usize);
assert_eq!((MAX - 1).saturating_sub(MAX), 0); assert_eq!((MAX-1).saturating_sub(MAX), 0);
} }
#[test] #[test]
fn test_saturating_add_int() { fn test_saturating_add_int() {
use isize::{MIN, MAX}; use isize::{MIN,MAX};
assert_eq!(3i32.saturating_add(5), 8); assert_eq!(3i32.saturating_add(5), 8);
assert_eq!(3isize.saturating_add(MAX - 1), MAX); assert_eq!(3isize.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX); assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX - 2).saturating_add(1), MAX - 1); assert_eq!((MAX-2).saturating_add(1), MAX-1);
assert_eq!(3i32.saturating_add(-5), -2); assert_eq!(3i32.saturating_add(-5), -2);
assert_eq!(MIN.saturating_add(-1), MIN); assert_eq!(MIN.saturating_add(-1), MIN);
assert_eq!((-2isize).saturating_add(-MAX), MIN); assert_eq!((-2isize).saturating_add(-MAX), MIN);
@ -82,14 +84,14 @@ mod tests {
#[test] #[test]
fn test_saturating_sub_int() { fn test_saturating_sub_int() {
use isize::{MIN, MAX}; use isize::{MIN,MAX};
assert_eq!(3i32.saturating_sub(5), -2); assert_eq!(3i32.saturating_sub(5), -2);
assert_eq!(MIN.saturating_sub(1), MIN); assert_eq!(MIN.saturating_sub(1), MIN);
assert_eq!((-2isize).saturating_sub(MAX), MIN); assert_eq!((-2isize).saturating_sub(MAX), MIN);
assert_eq!(3i32.saturating_sub(-5), 8); assert_eq!(3i32.saturating_sub(-5), 8);
assert_eq!(3isize.saturating_sub(-(MAX - 1)), MAX); assert_eq!(3isize.saturating_sub(-(MAX-1)), MAX);
assert_eq!(MAX.saturating_sub(-MAX), MAX); assert_eq!(MAX.saturating_sub(-MAX), MAX);
assert_eq!((MAX - 2).saturating_sub(-1), MAX - 1); assert_eq!((MAX-2).saturating_sub(-1), MAX-1);
} }
#[test] #[test]
@ -193,7 +195,7 @@ mod tests {
#[test] #[test]
fn test_pow() { fn test_pow() {
fn naive_pow<T: Mul<Output = T> + Copy>(one: T, base: T, exp: usize) -> T { fn naive_pow<T: Mul<Output=T> + Copy>(one: T, base: T, exp: usize) -> T {
(0..exp).fold(one, |acc, _| acc * base) (0..exp).fold(one, |acc, _| acc * base)
} }
macro_rules! assert_pow { macro_rules! assert_pow {
@ -286,8 +288,6 @@ mod bench {
#[bench] #[bench]
fn bench_pow_function(b: &mut Bencher) { fn bench_pow_function(b: &mut Bencher) {
let v = (0..1024).collect::<Vec<u32>>(); let v = (0..1024).collect::<Vec<u32>>();
b.iter(|| { b.iter(|| {v.iter().fold(0u32, |old, new| old.pow(*new as u32));});
v.iter().fold(0u32, |old, new| old.pow(*new as u32));
});
} }
} }

17
ctr-std/src/os/mod.rs

@ -0,0 +1,17 @@
// Copyright 2012-2015 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.
//! OS-specific functionality.
#![stable(feature = "os", since = "1.0.0")]
#![allow(missing_docs, bad_style)]
#[stable(feature = "rust1", since = "1.0.0")]
pub use sys::ext as unix;

11
std/src/panicking.rs → ctr-std/src/panicking.rs

@ -11,8 +11,9 @@
//! Implementation of various bits and pieces of the `panic!` macro and //! Implementation of various bits and pieces of the `panic!` macro and
//! associated runtime pieces. //! associated runtime pieces.
use fmt::{self, Display};
use any::Any; use any::Any;
use fmt;
use __core::fmt::Display;
///The compiler wants this to be here. Otherwise it won't be happy. And we like happy compilers. ///The compiler wants this to be here. Otherwise it won't be happy. And we like happy compilers.
#[lang = "eh_personality"] #[lang = "eh_personality"]
@ -20,7 +21,7 @@ extern fn eh_personality() {}
/// Entry point of panic from the libcore crate. /// Entry point of panic from the libcore crate.
#[lang = "panic_fmt"] #[lang = "panic_fmt"]
extern fn panic_fmt(msg: fmt::Arguments, file: &'static str, line: u32) -> ! { extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, line: u32) -> ! {
begin_panic_fmt(&msg, &(file, line)) begin_panic_fmt(&msg, &(file, line))
} }
@ -30,8 +31,10 @@ extern fn panic_fmt(msg: fmt::Arguments, file: &'static str, line: u32) -> ! {
/// site as much as possible (so that `panic!()` has as low an impact /// site as much as possible (so that `panic!()` has as low an impact
/// on (e.g.) the inlining of other functions as possible), by moving /// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place. /// the actual formatting into this shared place.
#[inline(never)] #[unstable(feature = "libstd_sys_internals",
#[cold] reason = "used by the panic! macro",
issue = "0")]
#[inline(never)] #[cold]
pub fn begin_panic_fmt(msg: &fmt::Arguments, file_line: &(&'static str, u32)) -> ! { pub fn begin_panic_fmt(msg: &fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
use fmt::Write; use fmt::Write;

510
std/src/path.rs → ctr-std/src/path.rs

File diff suppressed because it is too large Load Diff

146
ctr-std/src/prelude/mod.rs

@ -0,0 +1,146 @@
// Copyright 2014 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.
//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```ignore
//! extern crate std;
//! ```
//!
//! into the crate root of every crate, and
//!
//! ```ignore
//! use std::prelude::v1::*;
//! ```
//!
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and reexports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
//! traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//! operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`], a convenience function for explicitly dropping a
//! value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//! [`to_owned()`], the generic method for creating an owned type from a
//! borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`],
//! the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//! comparison traits, which implement the comparison operators and are often
//! seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//! conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//! [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//! kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//! expresses the presence or absence of a value. This type is so commonly
//! used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//! that may succeed or fail. Like [`Option`], its variants are exported as
//! well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//! reasons, but shouldn't have to exist. It provides a few useful methods on
//! slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//! vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone
//! [`drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/closures.html
//! [book-dtor]: ../../book/drop.html
//! [book-enums]: ../../book/enums.html
//! [book-iter]: ../../book/iterators.html
#![stable(feature = "rust1", since = "1.0.0")]
pub mod v1;

53
ctr-std/src/prelude/v1.rs

@ -0,0 +1,53 @@
// Copyright 2013 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.
//! The first version of the prelude of The Rust Standard Library.
//!
//! See the [module-level documentation](../index.html) for more.
#![stable(feature = "rust1", since = "1.0.0")]
// Reexported core operators
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
// Reexported functions
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use mem::drop;
// Reexported types and traits
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use borrow::ToOwned;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use clone::Clone;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use default::Default;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use option::Option::{self, Some, None};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use result::Result::{self, Ok, Err};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use slice::SliceConcatExt;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use string::{String, ToString};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use vec::Vec;

6
std/src/rt.rs → ctr-std/src/rt.rs

@ -16,6 +16,12 @@
//! and should be considered as private implementation details for the //! and should be considered as private implementation details for the
//! time being. //! time being.
#![unstable(feature = "rt",
reason = "this public module should not exist and is highly likely \
to disappear",
issue = "0")]
#![doc(hidden)]
use mem; use mem;
// Reexport some of our utilities which are expected by other crates. // Reexport some of our utilities which are expected by other crates.

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

@ -0,0 +1,29 @@
// Copyright 2013 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.
//! Useful synchronization primitives.
//!
//! This module contains useful safe and unsafe synchronization primitives.
//! Most of the primitives in this module do not provide any sort of locking
//! and/or blocking at all, but rather provide the necessary tools to build
//! other types of concurrent primitives.
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc::arc::{Arc, Weak};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;
// Easy cheat until we get proper locks based on libctru code
#[stable(feature = "3ds", since = "1.0.0")]
pub use spin::{Mutex, MutexGuard};
#[stable(feature = "3ds", since = "1.0.0")]
pub use spin::{RwLock, RwLockReadGuard, RwLockWriteGuard};

37
ctr-std/src/sys/mod.rs

@ -0,0 +1,37 @@
// Copyright 2016 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.
//! Platform-dependent platform abstraction
//!
//! The `std::sys` module is the abstracted interface through which
//! `std` talks to the underlying operating system. It has different
//! implementations for different operating system families, today
//! just Unix and Windows.
//!
//! The centralization of platform-specific code in this module is
//! enforced by the "platform abstraction layer" tidy script in
//! `tools/tidy/pal.rs`.
//!
//! This module is closely related to the platform-independent system
//! integration code in `std::sys_common`. See that module's
//! documentation for details.
//!
//! In the future it would be desirable for the indepedent
//! implementations of this module to be extracted to their own crates
//! that `std` can link to, thus enabling their implementation
//! out-of-tree via crate replacement. Though due to the complex
//! inter-dependencies within `std` that will be a challenging goal to
//! achieve.
pub use self::imp::*;
#[cfg(unix)]
#[path = "unix/mod.rs"]
mod imp;

61
ctr-std/src/sys/unix/ext/ffi.rs

@ -0,0 +1,61 @@
// Copyright 2015 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.
//! Unix-specific extension to the primitives in the `std::ffi` module
#![stable(feature = "rust1", since = "1.0.0")]
use ffi::{OsStr, OsString};
use mem;
use sys::os_str::Buf;
use sys_common::{FromInner, IntoInner, AsInner};
/// Unix-specific extensions to `OsString`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait OsStringExt {
/// Creates an `OsString` from a byte vector.
#[stable(feature = "rust1", since = "1.0.0")]
fn from_vec(vec: Vec<u8>) -> Self;
/// Yields the underlying byte vector of this `OsString`.
#[stable(feature = "rust1", since = "1.0.0")]
fn into_vec(self) -> Vec<u8>;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl OsStringExt for OsString {
fn from_vec(vec: Vec<u8>) -> OsString {
FromInner::from_inner(Buf { inner: vec })
}
fn into_vec(self) -> Vec<u8> {
self.into_inner().inner
}
}
/// Unix-specific extensions to `OsStr`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait OsStrExt {
#[stable(feature = "rust1", since = "1.0.0")]
fn from_bytes(slice: &[u8]) -> &Self;
/// Gets the underlying byte view of the `OsStr` slice.
#[stable(feature = "rust1", since = "1.0.0")]
fn as_bytes(&self) -> &[u8];
}
#[stable(feature = "rust1", since = "1.0.0")]
impl OsStrExt for OsStr {
fn from_bytes(slice: &[u8]) -> &OsStr {
unsafe { mem::transmute(slice) }
}
fn as_bytes(&self) -> &[u8] {
&self.as_inner().inner
}
}

41
ctr-std/src/sys/unix/ext/mod.rs

@ -0,0 +1,41 @@
// Copyright 2014 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.
//! Experimental extensions to `std` for Unix platforms.
//!
//! For now, this module is limited to extracting file descriptors,
//! but its functionality will grow over time.
//!
//! # Example
//!
//! ```no_run
//! use std::fs::File;
//! use std::os::unix::prelude::*;
//!
//! fn main() {
//! let f = File::create("foo.txt").unwrap();
//! let fd = f.as_raw_fd();
//!
//! // use fd with native unix bindings
//! }
//! ```
#![stable(feature = "rust1", since = "1.0.0")]
pub mod ffi;
/// A prelude for conveniently writing platform-specific code.
///
/// Includes all extension traits, and some important type definitions.
#[stable(feature = "rust1", since = "1.0.0")]
pub mod prelude {
#[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
pub use super::ffi::{OsStrExt, OsStringExt};
}

51
ctr-std/src/sys/unix/memchr.rs

@ -0,0 +1,51 @@
// Copyright 2015 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.
//
// Original implementation taken from rust-memchr
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
use libc;
let p = unsafe {
libc::memchr(
haystack.as_ptr() as *const libc::c_void,
needle as libc::c_int,
haystack.len())
};
if p.is_null() {
None
} else {
Some(p as usize - (haystack.as_ptr() as usize))
}
}
pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
#[cfg(target_os = "linux")]
fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
use libc;
// GNU's memrchr() will - unlike memchr() - error if haystack is empty.
if haystack.is_empty() {return None}
let p = unsafe {
libc::memrchr(
haystack.as_ptr() as *const libc::c_void,
needle as libc::c_int,
haystack.len())
};
if p.is_null() {
None
} else {
Some(p as usize - (haystack.as_ptr() as usize))
}
}
memrchr_specific(needle, haystack)
}

50
ctr-std/src/sys/unix/mod.rs

@ -0,0 +1,50 @@
// Copyright 2014 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.
#![allow(missing_docs, bad_style)]
pub mod ext;
pub mod memchr;
pub mod os;
pub mod os_str;
pub mod path;
use io::ErrorKind;
use libc;
pub fn decode_error_kind(errno: i32) -> ErrorKind {
match errno as libc::c_int {
libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
libc::ECONNRESET => ErrorKind::ConnectionReset,
libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
libc::EPIPE => ErrorKind::BrokenPipe,
libc::ENOTCONN => ErrorKind::NotConnected,
libc::ECONNABORTED => ErrorKind::ConnectionAborted,
libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
libc::EADDRINUSE => ErrorKind::AddrInUse,
libc::ENOENT => ErrorKind::NotFound,
libc::EINTR => ErrorKind::Interrupted,
libc::EINVAL => ErrorKind::InvalidInput,
libc::ETIMEDOUT => ErrorKind::TimedOut,
libc::EEXIST => ErrorKind::AlreadyExists,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
ErrorKind::WouldBlock,
_ => ErrorKind::Other,
}
}
pub unsafe fn abort_internal() -> ! {
::libc::abort()
}

123
ctr-std/src/sys/unix/os.rs

@ -0,0 +1,123 @@
// Copyright 2015 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.
//! Implementation of `std::os` functionality for unix systems
#![allow(unused_imports)] // lots of cfg code here
use os::unix::prelude::*;
use error::Error as StdError;
use ffi::{CString, CStr, OsString, OsStr};
use fmt;
use io;
use iter;
use libc::{self, c_int, c_char, c_void};
use marker::PhantomData;
use mem;
use memchr;
use path::{self, PathBuf};
use ptr;
use slice;
use str;
use vec;
const TMPBUF_SZ: usize = 128;
extern "C" {
fn __errno() -> *mut c_int;
}
/// Returns the platform-specific value of errno
pub fn errno() -> i32 {
unsafe {
(*__errno()) as i32
}
}
/// Gets a detailed string description for the given error number.
pub fn error_string(errno: i32) -> String {
extern {
#[cfg_attr(any(target_os = "linux", target_env = "newlib"),
link_name = "__xpg_strerror_r")]
fn strerror_r(errnum: c_int, buf: *mut c_char,
buflen: libc::size_t) -> c_int;
}
let mut buf = [0 as c_char; TMPBUF_SZ];
let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errno as c_int, p, buf.len()) < 0 {
panic!("strerror_r failure");
}
let p = p as *const _;
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
}
}
pub struct SplitPaths<'a> {
iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
fn(&'a [u8]) -> PathBuf>,
}
pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
fn bytes_to_path(b: &[u8]) -> PathBuf {
PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
}
fn is_colon(b: &u8) -> bool { *b == b':' }
let unparsed = unparsed.as_bytes();
SplitPaths {
iter: unparsed.split(is_colon as fn(&u8) -> bool)
.map(bytes_to_path as fn(&[u8]) -> PathBuf)
}
}
impl<'a> Iterator for SplitPaths<'a> {
type Item = PathBuf;
fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}
#[derive(Debug)]
pub struct JoinPathsError;
pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
where I: Iterator<Item=T>, T: AsRef<OsStr>
{
let mut joined = Vec::new();
let sep = b':';
for (i, path) in paths.enumerate() {
let path = path.as_ref().as_bytes();
if i > 0 { joined.push(sep) }
if path.contains(&sep) {
return Err(JoinPathsError)
}
joined.extend_from_slice(path);
}
Ok(OsStringExt::from_vec(joined))
}
impl fmt::Display for JoinPathsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"path segment contains separator `:`".fmt(f)
}
}
impl StdError for JoinPathsError {
fn description(&self) -> &str { "failed to join paths" }
}
pub fn exit(code: i32) -> ! {
unsafe { libc::exit(code as c_int) }
}

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

@ -0,0 +1,119 @@
// Copyright 2015 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.
/// The underlying OsString/OsStr implementation on Unix systems: just
/// a `Vec<u8>`/`[u8]`.
use borrow::Cow;
use fmt::{self, Debug};
use str;
use mem;
use sys_common::{AsInner, IntoInner};
#[derive(Clone, Hash)]
pub struct Buf {
pub inner: Vec<u8>
}
pub struct Slice {
pub inner: [u8]
}
impl Debug for Slice {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.to_string_lossy().fmt(formatter)
}
}
impl Debug for Buf {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.as_slice().fmt(formatter)
}
}
impl IntoInner<Vec<u8>> for Buf {
fn into_inner(self) -> Vec<u8> {
self.inner
}
}
impl AsInner<[u8]> for Buf {
fn as_inner(&self) -> &[u8] {
&self.inner
}
}
impl Buf {
pub fn from_string(s: String) -> Buf {
Buf { inner: s.into_bytes() }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Buf {
Buf {
inner: Vec::with_capacity(capacity)
}
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear()
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional)
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional)
}
pub fn as_slice(&self) -> &Slice {
unsafe { mem::transmute(&*self.inner) }
}
pub fn into_string(self) -> Result<String, Buf> {
String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
}
pub fn push_slice(&mut self, s: &Slice) {
self.inner.extend_from_slice(&s.inner)
}
}
impl Slice {
fn from_u8_slice(s: &[u8]) -> &Slice {
unsafe { mem::transmute(s) }
}
pub fn from_str(s: &str) -> &Slice {
Slice::from_u8_slice(s.as_bytes())
}
pub fn to_str(&self) -> Option<&str> {
str::from_utf8(&self.inner).ok()
}
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(&self.inner)
}
pub fn to_owned(&self) -> Buf {
Buf { inner: self.inner.to_vec() }
}
}

29
ctr-std/src/sys/unix/path.rs

@ -0,0 +1,29 @@
// Copyright 2015 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 path::Prefix;
use ffi::OsStr;
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/'
}
#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
b == b'/'
}
pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
None
}
pub const MAIN_SEP_STR: &'static str = "/";
pub const MAIN_SEP: char = '/';

179
ctr-std/src/sys_common/io.rs

@ -0,0 +1,179 @@
// Copyright 2015 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 io;
use io::ErrorKind;
use io::Read;
use slice::from_raw_parts_mut;
pub const DEFAULT_BUF_SIZE: usize = 8 * 1024;
// Provides read_to_end functionality over an uninitialized buffer.
// This function is unsafe because it calls the underlying
// read function with a slice into uninitialized memory. The default
// implementation of read_to_end for readers will zero out new memory in
// the buf before passing it to read, but avoiding this zero can often
// lead to a fairly significant performance win.
//
// Implementations using this method have to adhere to two guarantees:
// * The implementation of read never reads the buffer provided.
// * The implementation of read correctly reports how many bytes were written.
pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec<u8>) -> io::Result<usize> {
let start_len = buf.len();
buf.reserve(16);
// Always try to read into the empty space of the vector (from the length to the capacity).
// If the vector ever fills up then we reserve an extra byte which should trigger the normal
// reallocation routines for the vector, which will likely double the size.
//
// This function is similar to the read_to_end function in std::io, but the logic about
// reservations and slicing is different enough that this is duplicated here.
loop {
if buf.len() == buf.capacity() {
buf.reserve(1);
}
let buf_slice = from_raw_parts_mut(buf.as_mut_ptr().offset(buf.len() as isize),
buf.capacity() - buf.len());
match r.read(buf_slice) {
Ok(0) => { return Ok(buf.len() - start_len); }
Ok(n) => { let len = buf.len() + n; buf.set_len(len); },
Err(ref e) if e.kind() == ErrorKind::Interrupted => { }
Err(e) => { return Err(e); }
}
}
}
#[cfg(test)]
#[allow(dead_code)] // not used on emscripten
pub mod test {
use path::{Path, PathBuf};
use env;
use rand::{self, Rng};
use fs;
pub struct TempDir(PathBuf);
impl TempDir {
pub fn join(&self, path: &str) -> PathBuf {
let TempDir(ref p) = *self;
p.join(path)
}
pub fn path<'a>(&'a self) -> &'a Path {
let TempDir(ref p) = *self;
p
}
}
impl Drop for TempDir {
fn drop(&mut self) {
// Gee, seeing how we're testing the fs module I sure hope that we
// at least implement this correctly!
let TempDir(ref p) = *self;
fs::remove_dir_all(p).unwrap();
}
}
pub fn tmpdir() -> TempDir {
let p = env::temp_dir();
let mut r = rand::thread_rng();
let ret = p.join(&format!("rust-{}", r.next_u32()));
fs::create_dir(&ret).unwrap();
TempDir(ret)
}
}
#[cfg(test)]
mod tests {
use io::prelude::*;
use super::*;
use io;
use io::{ErrorKind, Take, Repeat, repeat};
use slice::from_raw_parts;
struct ErrorRepeat {
lr: Take<Repeat>
}
fn error_repeat(byte: u8, limit: u64) -> ErrorRepeat {
ErrorRepeat { lr: repeat(byte).take(limit) }
}
impl Read for ErrorRepeat {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let ret = self.lr.read(buf);
if let Ok(0) = ret {
return Err(io::Error::new(ErrorKind::Other, ""))
}
ret
}
}
fn init_vec_data() -> Vec<u8> {
let mut vec = vec![10u8; 200];
unsafe { vec.set_len(0); }
vec
}
fn assert_all_eq(buf: &[u8], value: u8) {
for n in buf {
assert_eq!(*n, value);
}
}
fn validate(buf: &Vec<u8>, good_read_len: usize) {
assert_all_eq(buf, 1u8);
let cap = buf.capacity();
let end_slice = unsafe { from_raw_parts(buf.as_ptr().offset(good_read_len as isize),
cap - good_read_len) };
assert_all_eq(end_slice, 10u8);
}
#[test]
fn read_to_end_uninit_error() {
let mut er = error_repeat(1,100);
let mut vec = init_vec_data();
if let Err(_) = unsafe { read_to_end_uninitialized(&mut er, &mut vec) } {
validate(&vec, 100);
} else {
assert!(false);
}
}
#[test]
fn read_to_end_uninit_zero_len_vec() {
let mut er = repeat(1).take(100);
let mut vec = Vec::new();
let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() };
assert_all_eq(&vec, 1u8);
assert_eq!(vec.len(), n);
}
#[test]
fn read_to_end_uninit_good() {
let mut er = repeat(1).take(100);
let mut vec = init_vec_data();
let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() };
validate(&vec, 100);
assert_eq!(vec.len(), n);
}
#[bench]
#[cfg_attr(target_os = "emscripten", ignore)]
fn bench_uninitialized(b: &mut ::test::Bencher) {
b.iter(|| {
let mut lr = repeat(1).take(10000000);
let mut vec = Vec::with_capacity(1024);
unsafe { read_to_end_uninitialized(&mut lr, &mut vec) }
});
}
}

76
ctr-std/src/sys_common/mod.rs

@ -0,0 +1,76 @@
// Copyright 2014 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.
//! Platform-independent platform abstraction
//!
//! This is the platform-independent portion of the standard libraries
//! platform abstraction layer, whereas `std::sys` is the
//! platform-specific portion.
//!
//! The relationship between `std::sys_common`, `std::sys` and the
//! rest of `std` is complex, with dependencies going in all
//! directions: `std` depending on `sys_common`, `sys_common`
//! depending on `sys`, and `sys` depending on `sys_common` and `std`.
//! Ideally `sys_common` would be split into two and the dependencies
//! between them all would form a dag, facilitating the extraction of
//! `std::sys` from the standard library.
#![allow(missing_docs)]
pub mod io;
// common error constructors
/// A trait for viewing representations from std types
#[doc(hidden)]
pub trait AsInner<Inner: ?Sized> {
fn as_inner(&self) -> &Inner;
}
/// A trait for viewing representations from std types
#[doc(hidden)]
pub trait AsInnerMut<Inner: ?Sized> {
fn as_inner_mut(&mut self) -> &mut Inner;
}
/// A trait for extracting representations from std types
#[doc(hidden)]
pub trait IntoInner<Inner> {
fn into_inner(self) -> Inner;
}
/// A trait for creating std types from internal representations
#[doc(hidden)]
pub trait FromInner<Inner> {
fn from_inner(inner: Inner) -> Self;
}
macro_rules! rtabort {
($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*)))
}
// Computes (value*numer)/denom without overflow, as long as both
// (numer*denom) and the overall result fit into i64 (which is the case
// for our time conversions).
#[allow(dead_code)] // not used on all platforms
pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
let q = value / denom;
let r = value % denom;
// Decompose value as (value/denom*denom + value%denom),
// substitute into (value*numer)/denom and simplify.
// r < denom, so (denom*numer) is the upper bound of (r*numer)
q * numer + r * numer / denom
}
#[test]
fn test_muldiv() {
assert_eq!(mul_div_u64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
1_000_000_000_001_000);
}

5
ctru-sys/Cargo.toml

@ -1,5 +1,8 @@
[package] [package]
name = "ctru-sys" name = "ctru-sys"
version = "0.2.0" version = "0.3.0"
authors = ["Ronald Kinard <furyhunter600@gmail.com>"] authors = ["Ronald Kinard <furyhunter600@gmail.com>"]
license = "https://en.wikipedia.org/wiki/Zlib_License" license = "https://en.wikipedia.org/wiki/Zlib_License"
[dependencies]
ctr-libc = { path = "../ctr-libc", default-features = false }

1
ctru-sys/src/applets/mod.rs

@ -0,0 +1 @@
pub mod swkbd;

258
ctru-sys/src/applets/swkbd.rs

@ -0,0 +1,258 @@
// automatically generated by rust-bindgen
#![allow(dead_code,
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum SwkbdType {
SWKBD_TYPE_NORMAL = 0,
SWKBD_TYPE_QWERTY = 1,
SWKBD_TYPE_NUMPAD = 2,
SWKBD_TYPE_WESTERN = 3,
}
pub const SWKBD_NOTBLANK_NOTEMPTY: SwkbdValidInput = SwkbdValidInput::SWKBD_NOTEMPTY_NOTBLANK;
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum SwkbdValidInput {
SWKBD_ANYTHING = 0,
SWKBD_NOTEMPTY = 1,
SWKBD_NOTEMPTY_NOTBLANK = 2,
SWKBD_NOTBLANK = 3,
SWKBD_FIXEDLEN = 4,
}
pub const SWKBD_BUTTON_CONFIRM: SwkbdButton = SwkbdButton::SWKBD_BUTTON_RIGHT;
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum SwkbdButton {
SWKBD_BUTTON_LEFT = 0,
SWKBD_BUTTON_MIDDLE = 1,
SWKBD_BUTTON_RIGHT = 2,
SWKBD_BUTTON_NONE = 3,
}
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum SwkbdPasswordMode {
SWKBD_PASSWORD_NONE = 0,
SWKBD_PASSWORD_HIDE = 1,
SWKBD_PASSWORD_HIDE_DELAY = 2,
}
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum Enum_Unnamed1 {
SWKBD_FILTER_DIGITS = 1,
SWKBD_FILTER_AT = 2,
SWKBD_FILTER_PERCENT = 4,
SWKBD_FILTER_BACKSLASH = 8,
SWKBD_FILTER_PROFANITY = 16,
SWKBD_FILTER_CALLBACK = 32,
}
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum Enum_Unnamed2 {
SWKBD_PARENTAL = 1,
SWKBD_DARKEN_TOP_SCREEN = 2,
SWKBD_PREDICTIVE_INPUT = 4,
SWKBD_MULTILINE = 8,
SWKBD_FIXED_WIDTH = 16,
SWKBD_ALLOW_HOME = 32,
SWKBD_ALLOW_RESET = 64,
SWKBD_ALLOW_POWER = 128,
SWKBD_DEFAULT_QWERTY = 512,
}
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum SwkbdCallbackResult {
SWKBD_CALLBACK_OK = 0,
SWKBD_CALLBACK_CLOSE = 1,
SWKBD_CALLBACK_CONTINUE = 2,
}
#[derive(Copy, Clone)]
#[repr(i32)]
#[derive(Debug)]
pub enum SwkbdResult {
SWKBD_NONE = -1,
SWKBD_INVALID_INPUT = -2,
SWKBD_OUTOFMEM = -3,
SWKBD_D0_CLICK = 0,
SWKBD_D1_CLICK0 = 1,
SWKBD_D1_CLICK1 = 2,
SWKBD_D2_CLICK0 = 3,
SWKBD_D2_CLICK1 = 4,
SWKBD_D2_CLICK2 = 5,
SWKBD_HOMEPRESSED = 10,
SWKBD_RESETPRESSED = 11,
SWKBD_POWERPRESSED = 12,
SWKBD_PARENTAL_OK = 20,
SWKBD_PARENTAL_FAIL = 21,
SWKBD_BANNED_INPUT = 30,
}
#[repr(C)]
#[derive(Copy)]
pub struct SwkbdDictWord {
pub reading: [u16; 41usize],
pub word: [u16; 41usize],
pub language: u8,
pub all_languages: u8,
}
impl ::core::clone::Clone for SwkbdDictWord {
fn clone(&self) -> Self {
*self
}
}
impl ::core::default::Default for SwkbdDictWord {
fn default() -> Self {
unsafe { ::core::mem::zeroed() }
}
}
pub type SwkbdCallbackFn =
::core::option::Option<unsafe extern "C" fn(user: *mut ::libc::c_void,
ppMessage: *mut *const u8,
text: *const u8,
textlen: usize)
-> SwkbdCallbackResult>;
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct SwkbdStatusData {
pub data: [u32; 17usize],
}
impl ::core::default::Default for SwkbdStatusData {
fn default() -> Self {
unsafe { ::core::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy)]
pub struct SwkbdLearningData {
pub data: [u32; 10523usize],
}
impl ::core::clone::Clone for SwkbdLearningData {
fn clone(&self) -> Self {
*self
}
}
impl ::core::default::Default for SwkbdLearningData {
fn default() -> Self {
unsafe { ::core::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct SwkbdExtra {
pub initial_text: *const u8,
pub dict: *const SwkbdDictWord,
pub status_data: *mut SwkbdStatusData,
pub learning_data: *mut SwkbdLearningData,
pub callback: SwkbdCallbackFn,
pub callback_user: *mut ::libc::c_void,
}
impl ::core::default::Default for SwkbdExtra {
fn default() -> Self {
unsafe { ::core::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy)]
pub struct SwkbdState {
pub type_: i32,
pub num_buttons_m1: i32,
pub valid_input: i32,
pub password_mode: i32,
pub is_parental_screen: i32,
pub darken_top_screen: i32,
pub filter_flags: u32,
pub save_state_flags: u32,
pub max_text_len: u16,
pub dict_word_count: u16,
pub max_digits: u16,
pub button_text: [[u16; 17usize]; 3usize],
pub numpad_keys: [u16; 2usize],
pub hint_text: [u16; 65usize],
pub predictive_input: u8,
pub multiline: u8,
pub fixed_width: u8,
pub allow_home: u8,
pub allow_reset: u8,
pub allow_power: u8,
pub unknown: u8,
pub default_qwerty: u8,
pub button_submits_text: [u8; 4usize],
pub language: u16,
pub initial_text_offset: i32,
pub dict_offset: i32,
pub initial_status_offset: i32,
pub initial_learning_offset: i32,
pub shared_memory_size: usize,
pub version: u32,
pub result: SwkbdResult,
pub status_offset: i32,
pub learning_offset: i32,
pub text_offset: i32,
pub text_length: u16,
pub callback_result: i32,
pub callback_msg: [u16; 257usize],
pub skip_at_check: u8,
pub union: _bindgen_data_1_,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union _bindgen_data_1_ {
pub reserved: [u8; 171usize],
pub extra: SwkbdExtra,
}
impl ::core::clone::Clone for SwkbdState {
fn clone(&self) -> Self {
*self
}
}
impl ::core::default::Default for SwkbdState {
fn default() -> Self {
unsafe { ::core::mem::zeroed() }
}
}
extern "C" {
pub fn swkbdInit(swkbd: *mut SwkbdState,
type_: SwkbdType,
numButtons: i32,
maxTextLength: i32);
pub fn swkbdSetFeatures(swkbd: *mut SwkbdState, features: u32);
pub fn swkbdSetHintText(swkbd: *mut SwkbdState, text: *const u8);
pub fn swkbdSetButton(swkbd: *mut SwkbdState,
button: SwkbdButton,
text: *const u8,
submit: u8);
pub fn swkbdSetInitialText(swkbd: *mut SwkbdState, text: *const u8);
pub fn swkbdSetDictWord(word: *mut SwkbdDictWord,
reading: *const u8,
text: *const u8);
pub fn swkbdSetDictionary(swkbd: *mut SwkbdState,
dict: *const SwkbdDictWord,
wordCount: i32);
pub fn swkbdSetStatusData(swkbd: *mut SwkbdState,
data: *mut SwkbdStatusData,
in_: u8,
out: u8);
pub fn swkbdSetLearningData(swkbd: *mut SwkbdState,
data: *mut SwkbdLearningData,
in_: u8,
out: u8);
pub fn swkbdSetFilterCallback(swkbd: *mut SwkbdState,
callback: SwkbdCallbackFn,
user: *mut ::libc::c_void);
pub fn swkbdInputText(swkbd: *mut SwkbdState,
buf: *mut u8,
bufsize: usize)
-> SwkbdButton;
}

7
ctru-sys/src/lib.rs

@ -2,18 +2,23 @@
* C bindings generation: * C bindings generation:
* bindgen --match=file.h --use-core --ctypes-prefix=libc -- --sysroot=$DEVKITARM/arm-none-eabi -I$CTRULIB/include $CTRULIB/include/3ds.h * bindgen --match=file.h --use-core --ctypes-prefix=libc -- --sysroot=$DEVKITARM/arm-none-eabi -I$CTRULIB/include $CTRULIB/include/3ds.h
* *
* bindgen --sysroot=$DEVKITARM/arm-none-eabi -I$CTRULIB/include $CTRULIB/include/3ds.h
*/ */
#![no_std] #![no_std]
#![allow(non_camel_case_types, non_snake_case, overflowing_literals)] #![allow(non_camel_case_types, non_snake_case, overflowing_literals)]
#![feature(untagged_unions)]
extern crate ctr_libc as libc;
pub mod applets;
pub mod console; pub mod console;
pub mod env; pub mod env;
pub mod gfx; pub mod gfx;
pub mod gpu; pub mod gpu;
pub mod ipc; pub mod ipc;
pub mod ndsp;
pub mod os; pub mod os;
pub mod romfs;
pub mod sdmc; pub mod sdmc;
pub mod services; pub mod services;
pub mod svc; pub mod svc;

82
ctru-sys/src/ndsp/channel.rs

@ -0,0 +1,82 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code,
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
use ::types::*;
use super::ndsp::ndspWaveBuf;
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum Enum_Unnamed1 {
NDSP_ENCODING_PCM8 = 0,
NDSP_ENCODING_PCM16 = 1,
NDSP_ENCODING_ADPCM = 2,
}
pub const NDSP_FORMAT_PCM8: Enum_Unnamed2 =
Enum_Unnamed2::NDSP_FORMAT_MONO_PCM8;
pub const NDSP_FORMAT_PCM16: Enum_Unnamed2 =
Enum_Unnamed2::NDSP_FORMAT_MONO_PCM16;
pub const NDSP_FORMAT_ADPCM: Enum_Unnamed2 =
Enum_Unnamed2::NDSP_FORMAT_MONO_ADPCM;
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum Enum_Unnamed2 {
NDSP_FORMAT_MONO_PCM8 = 1,
NDSP_FORMAT_MONO_PCM16 = 5,
NDSP_FORMAT_MONO_ADPCM = 9,
NDSP_FORMAT_STEREO_PCM8 = 2,
NDSP_FORMAT_STEREO_PCM16 = 6,
NDSP_FRONT_BYPASS = 16,
NDSP_3D_SURROUND_PREPROCESSED = 64,
}
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum ndspInterpType {
NDSP_INTERP_POLYPHASE = 0,
NDSP_INTERP_LINEAR = 1,
NDSP_INTERP_NONE = 2,
}
extern "C" {
pub fn ndspChnReset(id: ::libc::c_int);
pub fn ndspChnInitParams(id: ::libc::c_int);
pub fn ndspChnIsPlaying(id: ::libc::c_int) -> u8;
pub fn ndspChnGetSamplePos(id: ::libc::c_int) -> u32_;
pub fn ndspChnGetWaveBufSeq(id: ::libc::c_int) -> u16_;
pub fn ndspChnIsPaused(id: ::libc::c_int) -> u8;
pub fn ndspChnSetPaused(id: ::libc::c_int, paused: u8);
pub fn ndspChnSetFormat(id: ::libc::c_int, format: u16_);
pub fn ndspChnSetInterp(id: ::libc::c_int, type_: ndspInterpType);
pub fn ndspChnSetRate(id: ::libc::c_int, rate: f32);
pub fn ndspChnSetMix(id: ::libc::c_int, mix: *mut f32);
pub fn ndspChnSetAdpcmCoefs(id: ::libc::c_int, coefs: *mut u16_);
pub fn ndspChnWaveBufClear(id: ::libc::c_int);
pub fn ndspChnWaveBufAdd(id: ::libc::c_int, buf: *mut ndspWaveBuf);
pub fn ndspChnIirMonoSetEnable(id: ::libc::c_int, enable: u8);
pub fn ndspChnIirMonoSetParamsCustomFilter(id: ::libc::c_int, a0: f32,
a1: f32, b0: f32) -> u8;
pub fn ndspChnIirMonoSetParamsLowPassFilter(id: ::libc::c_int, f0: f32)
-> u8;
pub fn ndspChnIirMonoSetParamsHighPassFilter(id: ::libc::c_int, f0: f32)
-> u8;
pub fn ndspChnIirBiquadSetEnable(id: ::libc::c_int, enable: u8);
pub fn ndspChnIirBiquadSetParamsCustomFilter(id: ::libc::c_int, a0: f32,
a1: f32, a2: f32, b0: f32,
b1: f32, b2: f32) -> u8;
pub fn ndspChnIirBiquadSetParamsLowPassFilter(id: ::libc::c_int, f0: f32,
Q: f32) -> u8;
pub fn ndspChnIirBiquadSetParamsHighPassFilter(id: ::libc::c_int, f0: f32,
Q: f32) -> u8;
pub fn ndspChnIirBiquadSetParamsBandPassFilter(id: ::libc::c_int, f0: f32,
Q: f32) -> u8;
pub fn ndspChnIirBiquadSetParamsNotchFilter(id: ::libc::c_int, f0: f32,
Q: f32) -> u8;
pub fn ndspChnIirBiquadSetParamsPeakingEqualizer(id: ::libc::c_int,
f0: f32, Q: f32,
gain: f32) -> u8;
}

2
ctru-sys/src/ndsp/mod.rs

@ -0,0 +1,2 @@
pub mod channel;
pub mod ndsp;

112
ctru-sys/src/ndsp/ndsp.rs

@ -0,0 +1,112 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code,
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum ndspOutputMode {
NDSP_OUTPUT_MONO = 0,
NDSP_OUTPUT_STEREO = 1,
NDSP_OUTPUT_SURROUND = 2,
}
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum ndspClippingMode { NDSP_CLIP_NORMAL = 0, NDSP_CLIP_SOFT = 1, }
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum ndspSpeakerPos {
NDSP_SPKPOS_SQUARE = 0,
NDSP_SPKPOS_WIDE = 1,
NDSP_SPKPOS_NUM = 2,
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct ndspAdpcmData {
pub index: u16_,
pub history0: s16,
pub history1: s16,
}
impl ::core::default::Default for ndspAdpcmData {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
pub type ndspWaveBuf = tag_ndspWaveBuf;
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
pub enum Enum_Unnamed1 {
NDSP_WBUF_FREE = 0,
NDSP_WBUF_QUEUED = 1,
NDSP_WBUF_PLAYING = 2,
NDSP_WBUF_DONE = 3,
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct tag_ndspWaveBuf {
pub _bindgen_data_1_: [u64; 1usize],
pub nsamples: u32_,
pub adpcm_data: *mut ndspAdpcmData,
pub offset: u32_,
pub looping: u8,
pub status: u8_,
pub sequence_id: u16_,
pub next: *mut ndspWaveBuf,
}
impl tag_ndspWaveBuf {
pub unsafe fn data_pcm8(&mut self) -> *mut *mut s8 {
let raw: *mut u8 = ::core::mem::transmute(&self._bindgen_data_1_);
::core::mem::transmute(raw.offset(0))
}
pub unsafe fn data_pcm16(&mut self) -> *mut *mut s16 {
let raw: *mut u8 = ::core::mem::transmute(&self._bindgen_data_1_);
::core::mem::transmute(raw.offset(0))
}
pub unsafe fn data_adpcm(&mut self) -> *mut *mut u8_ {
let raw: *mut u8 = ::core::mem::transmute(&self._bindgen_data_1_);
::core::mem::transmute(raw.offset(0))
}
pub unsafe fn data_vaddr(&mut self) -> *mut *const ::libc::c_void {
let raw: *mut u8 = ::core::mem::transmute(&self._bindgen_data_1_);
::core::mem::transmute(raw.offset(0))
}
}
impl ::core::default::Default for tag_ndspWaveBuf {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
pub type ndspCallback =
::core::option::Option<unsafe extern "C" fn(data: *mut ::libc::c_void)>;
pub type ndspAuxCallback =
::core::option::Option<unsafe extern "C" fn(data: *mut ::libc::c_void,
nsamples: ::libc::c_int,
samples:
*mut *mut ::libc::c_void)>;
extern "C" {
pub fn ndspUseComponent(binary: *const ::libc::c_void, size: u32_,
progMask: u16_, dataMask: u16_);
pub fn ndspInit() -> Result;
pub fn ndspExit();
pub fn ndspGetDroppedFrames() -> u32_;
pub fn ndspGetFrameCount() -> u32_;
pub fn ndspSetMasterVol(volume: f32);
pub fn ndspSetOutputMode(mode: ndspOutputMode);
pub fn ndspSetClippingMode(mode: ndspClippingMode);
pub fn ndspSetOutputCount(count: ::libc::c_int);
pub fn ndspSetCapture(capture: *mut ndspWaveBuf);
pub fn ndspSetCallback(callback: ndspCallback, data: *mut ::libc::c_void);
pub fn ndspSurroundSetDepth(depth: u16_);
pub fn ndspSurroundSetPos(pos: ndspSpeakerPos);
pub fn ndspSurroundSetRearRatio(ratio: u16_);
pub fn ndspAuxSetEnable(id: ::libc::c_int, enable: u8);
pub fn ndspAuxSetFrontBypass(id: ::libc::c_int, bypass: u8);
pub fn ndspAuxSetVolume(id: ::libc::c_int, volume: f32);
pub fn ndspAuxSetCallback(id: ::libc::c_int, callback: ndspAuxCallback,
data: *mut ::libc::c_void);
}
use ::types::*;

62
ctru-sys/src/os.rs

@ -1,53 +1,47 @@
//TODO: Fix Bindgen's issues again. /* automatically generated by rust-bindgen */
use libc::c_void; #![allow(dead_code,
use types::*; non_camel_case_types,
non_upper_case_globals,
#[inline] non_snake_case)]
pub fn SYSTEM_VERSION(major: i32, minor: i32, revision: i32) { #[derive(Copy, Clone)]
(((major)<<24)|((minor)<<16)|((revision)<<8)); #[repr(u32)]
} #[derive(Debug)]
pub enum MemRegion {
#[derive(Clone, Copy)]
#[repr(C)]
pub enum Enum_Unnamed1 {
MEMREGION_ALL = 0, MEMREGION_ALL = 0,
MEMREGION_APPLICATION = 1, MEMREGION_APPLICATION = 1,
MEMREGION_SYSTEM = 2, MEMREGION_SYSTEM = 2,
MEMREGION_BASE = 3, MEMREGION_BASE = 3,
} }
pub type MemRegion = Enum_Unnamed1;
#[repr(C)] #[repr(C)]
#[derive(Copy)] #[derive(Copy, Clone)]
pub struct Struct_Unnamed2 { #[derive(Debug)]
pub build: u8, pub struct OS_VersionBin {
pub minor: u8, pub build: u8_,
pub mainver: u8, pub minor: u8_,
pub reserved_x3: u8, pub mainver: u8_,
pub region: u8, pub reserved_x3: u8_,
pub reserved_x5: [u8; 3usize], pub region: ::libc::c_char,
} pub reserved_x5: [u8_; 3usize],
impl ::core::clone::Clone for Struct_Unnamed2 {
fn clone(&self) -> Self { *self }
} }
impl ::core::default::Default for Struct_Unnamed2 { impl ::core::default::Default for OS_VersionBin {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
} }
pub type OS_VersionBin = Struct_Unnamed2;
extern "C" { extern "C" {
pub fn osConvertVirtToPhys(vaddr: *const c_void) -> u32; pub fn osConvertVirtToPhys(vaddr: *const ::libc::c_void) -> u32_;
pub fn osConvertOldLINEARMemToNew(vaddr: *const c_void) pub fn osConvertOldLINEARMemToNew(vaddr: *const ::libc::c_void)
-> *mut c_void; -> *mut ::libc::c_void;
pub fn osStrError(error: u32) -> *const u8; pub fn osStrError(error: u32_) -> *const ::libc::c_char;
pub fn osGetMemRegionUsed(region: MemRegion) -> s64; pub fn osGetMemRegionUsed(region: MemRegion) -> s64;
pub fn osGetTime() -> u64; pub fn osGetTime() -> u64_;
pub fn osSetSpeedupEnable(enable: u8); pub fn osSetSpeedupEnable(enable: u8);
pub fn osGetSystemVersionData(nver_versionbin: *mut OS_VersionBin, pub fn osGetSystemVersionData(nver_versionbin: *mut OS_VersionBin,
cver_versionbin: *mut OS_VersionBin) cver_versionbin: *mut OS_VersionBin)
-> Result; -> Result;
pub fn osGetSystemVersionDataString(nver_versionbin: *mut OS_VersionBin, pub fn osGetSystemVersionDataString(nver_versionbin: *mut OS_VersionBin,
cver_versionbin: *mut OS_VersionBin, cver_versionbin: *mut OS_VersionBin,
sysverstr: sysverstr: *mut ::libc::c_char,
*mut u8, sysverstr_maxsize: u32_) -> Result;
sysverstr_maxsize: u32) -> Result;
} }
use ::types::*;

64
ctru-sys/src/romfs.rs

@ -0,0 +1,64 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code,
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct romfs_header {
pub headerSize: u32_,
pub dirHashTableOff: u32_,
pub dirHashTableSize: u32_,
pub dirTableOff: u32_,
pub dirTableSize: u32_,
pub fileHashTableOff: u32_,
pub fileHashTableSize: u32_,
pub fileTableOff: u32_,
pub fileTableSize: u32_,
pub fileDataOff: u32_,
}
impl ::core::default::Default for romfs_header {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct romfs_dir {
pub parent: u32_,
pub sibling: u32_,
pub childDir: u32_,
pub childFile: u32_,
pub nextHash: u32_,
pub nameLen: u32_,
pub name: [u16_; 0usize],
}
impl ::core::default::Default for romfs_dir {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct romfs_file {
pub parent: u32_,
pub sibling: u32_,
pub dataOff: u64_,
pub dataSize: u64_,
pub nextHash: u32_,
pub nameLen: u32_,
pub name: [u16_; 0usize],
}
impl ::core::default::Default for romfs_file {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
pub enum romfs_mount { }
extern "C" {
pub fn romfsMount(mount: *mut *mut romfs_mount) -> Result;
pub fn romfsMountFromFile(file: Handle, offset: u32_,
mount: *mut *mut romfs_mount) -> Result;
pub fn romfsBind(mount: *mut romfs_mount) -> Result;
pub fn romfsUnmount(mount: *mut romfs_mount) -> Result;
}
use ::types::*;

24
ctru-sys/src/sdmc.rs

@ -1,7 +1,29 @@
use Result; /* automatically generated by rust-bindgen */
#![allow(dead_code,
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
use ::types::*;
use services::fs::FS_DirectoryEntry;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sdmc_dir_t {
pub magic: u32_,
pub fd: Handle,
pub index: ::libc::ssize_t,
pub size: ::libc::size_t,
pub entry_data: [FS_DirectoryEntry; 32usize],
}
impl ::core::default::Default for sdmc_dir_t {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
extern "C" { extern "C" {
pub fn sdmcInit() -> Result; pub fn sdmcInit() -> Result;
pub fn sdmcWriteSafe(enable: u8);
pub fn sdmcExit() -> Result; pub fn sdmcExit() -> Result;
pub fn sdmc_getmtime(name: *const ::libc::c_char, mtime: *mut u64_)
-> Result;
} }

28
ctru-sys/src/services/apt.rs

@ -143,7 +143,7 @@ pub type aptMessageCb =
::core::option::Option<unsafe extern "C" fn(user: *mut ::libc::c_void, ::core::option::Option<unsafe extern "C" fn(user: *mut ::libc::c_void,
sender: NS_APPID, sender: NS_APPID,
msg: *mut ::libc::c_void, msg: *mut ::libc::c_void,
msgsize: size_t)>; msgsize: ::libc::size_t)>;
extern "C" { extern "C" {
pub fn aptInit() -> Result; pub fn aptInit() -> Result;
pub fn aptExit(); pub fn aptExit();
@ -157,7 +157,7 @@ extern "C" {
pub fn aptSetMessageCallback(callback: aptMessageCb, pub fn aptSetMessageCallback(callback: aptMessageCb,
user: *mut ::libc::c_void); user: *mut ::libc::c_void);
pub fn aptLaunchLibraryApplet(appId: NS_APPID, buf: *mut ::libc::c_void, pub fn aptLaunchLibraryApplet(appId: NS_APPID, buf: *mut ::libc::c_void,
bufsize: size_t, handle: Handle) -> u8; bufsize: ::libc::size_t, handle: Handle) -> u8;
pub fn APT_GetLockHandle(flags: u16_, lockHandle: *mut Handle) -> Result; pub fn APT_GetLockHandle(flags: u16_, lockHandle: *mut Handle) -> Result;
pub fn APT_Initialize(appId: NS_APPID, attr: APT_AppletAttr, pub fn APT_Initialize(appId: NS_APPID, attr: APT_AppletAttr,
signalEvent: *mut Handle, resumeEvent: *mut Handle) signalEvent: *mut Handle, resumeEvent: *mut Handle)
@ -178,31 +178,31 @@ extern "C" {
titleversion: *mut u16_) -> Result; titleversion: *mut u16_) -> Result;
pub fn APT_GetProgramID(pProgramID: *mut u64_) -> Result; pub fn APT_GetProgramID(pProgramID: *mut u64_) -> Result;
pub fn APT_PrepareToJumpToHomeMenu() -> Result; pub fn APT_PrepareToJumpToHomeMenu() -> Result;
pub fn APT_JumpToHomeMenu(param: *const ::libc::c_void, paramSize: size_t, pub fn APT_JumpToHomeMenu(param: *const ::libc::c_void, paramSize: ::libc::size_t,
handle: Handle) -> Result; handle: Handle) -> Result;
pub fn APT_PrepareToJumpToApplication(exiting: u8) -> Result; pub fn APT_PrepareToJumpToApplication(exiting: u8) -> Result;
pub fn APT_JumpToApplication(param: *const ::libc::c_void, pub fn APT_JumpToApplication(param: *const ::libc::c_void,
paramSize: size_t, handle: Handle) -> Result; paramSize: ::libc::size_t, handle: Handle) -> Result;
pub fn APT_IsRegistered(appID: NS_APPID, out: *mut u8) -> Result; pub fn APT_IsRegistered(appID: NS_APPID, out: *mut u8) -> Result;
pub fn APT_InquireNotification(appID: u32_, signalType: *mut APT_Signal) pub fn APT_InquireNotification(appID: u32_, signalType: *mut APT_Signal)
-> Result; -> Result;
pub fn APT_NotifyToWait(appID: NS_APPID) -> Result; pub fn APT_NotifyToWait(appID: NS_APPID) -> Result;
pub fn APT_AppletUtility(id: ::libc::c_int, out: *mut ::libc::c_void, pub fn APT_AppletUtility(id: ::libc::c_int, out: *mut ::libc::c_void,
outSize: size_t, in_: *const ::libc::c_void, outSize: ::libc::size_t, in_: *const ::libc::c_void,
inSize: size_t) -> Result; inSize: ::libc::size_t) -> Result;
pub fn APT_SleepIfShellClosed() -> Result; pub fn APT_SleepIfShellClosed() -> Result;
pub fn APT_TryLockTransition(transition: u32_, succeeded: *mut u8) pub fn APT_TryLockTransition(transition: u32_, succeeded: *mut u8)
-> Result; -> Result;
pub fn APT_UnlockTransition(transition: u32_) -> Result; pub fn APT_UnlockTransition(transition: u32_) -> Result;
pub fn APT_GlanceParameter(appID: NS_APPID, buffer: *mut ::libc::c_void, pub fn APT_GlanceParameter(appID: NS_APPID, buffer: *mut ::libc::c_void,
bufferSize: size_t, sender: *mut NS_APPID, bufferSize: ::libc::size_t, sender: *mut NS_APPID,
command: *mut APT_Command, command: *mut APT_Command,
actualSize: *mut size_t, actualSize: *mut ::libc::size_t,
parameter: *mut Handle) -> Result; parameter: *mut Handle) -> Result;
pub fn APT_ReceiveParameter(appID: NS_APPID, buffer: *mut ::libc::c_void, pub fn APT_ReceiveParameter(appID: NS_APPID, buffer: *mut ::libc::c_void,
bufferSize: size_t, sender: *mut NS_APPID, bufferSize: ::libc::size_t, sender: *mut NS_APPID,
command: *mut APT_Command, command: *mut APT_Command,
actualSize: *mut size_t, actualSize: *mut ::libc::size_t,
parameter: *mut Handle) -> Result; parameter: *mut Handle) -> Result;
pub fn APT_SendParameter(source: NS_APPID, dest: NS_APPID, pub fn APT_SendParameter(source: NS_APPID, dest: NS_APPID,
command: APT_Command, command: APT_Command,
@ -217,24 +217,24 @@ extern "C" {
pub fn APT_ReplySleepNotificationComplete(appID: NS_APPID) -> Result; pub fn APT_ReplySleepNotificationComplete(appID: NS_APPID) -> Result;
pub fn APT_PrepareToCloseApplication(cancelPreload: u8) -> Result; pub fn APT_PrepareToCloseApplication(cancelPreload: u8) -> Result;
pub fn APT_CloseApplication(param: *const ::libc::c_void, pub fn APT_CloseApplication(param: *const ::libc::c_void,
paramSize: size_t, handle: Handle) -> Result; paramSize: ::libc::size_t, handle: Handle) -> Result;
pub fn APT_SetAppCpuTimeLimit(percent: u32_) -> Result; pub fn APT_SetAppCpuTimeLimit(percent: u32_) -> Result;
pub fn APT_GetAppCpuTimeLimit(percent: *mut u32_) -> Result; pub fn APT_GetAppCpuTimeLimit(percent: *mut u32_) -> Result;
pub fn APT_CheckNew3DS(out: *mut u8) -> Result; pub fn APT_CheckNew3DS(out: *mut u8) -> Result;
pub fn APT_PrepareToDoApplicationJump(flags: u8_, programID: u64_, pub fn APT_PrepareToDoApplicationJump(flags: u8_, programID: u64_,
mediatype: u8_) -> Result; mediatype: u8_) -> Result;
pub fn APT_DoApplicationJump(param: *const ::libc::c_void, pub fn APT_DoApplicationJump(param: *const ::libc::c_void,
paramSize: size_t, paramSize: ::libc::size_t,
hmac: *const ::libc::c_void) -> Result; hmac: *const ::libc::c_void) -> Result;
pub fn APT_PrepareToStartLibraryApplet(appID: NS_APPID) -> Result; pub fn APT_PrepareToStartLibraryApplet(appID: NS_APPID) -> Result;
pub fn APT_StartLibraryApplet(appID: NS_APPID, pub fn APT_StartLibraryApplet(appID: NS_APPID,
param: *const ::libc::c_void, param: *const ::libc::c_void,
paramSize: size_t, handle: Handle) paramSize: ::libc::size_t, handle: Handle)
-> Result; -> Result;
pub fn APT_PrepareToStartSystemApplet(appID: NS_APPID) -> Result; pub fn APT_PrepareToStartSystemApplet(appID: NS_APPID) -> Result;
pub fn APT_StartSystemApplet(appID: NS_APPID, pub fn APT_StartSystemApplet(appID: NS_APPID,
param: *const ::libc::c_void, param: *const ::libc::c_void,
paramSize: size_t, handle: Handle) -> Result; paramSize: ::libc::size_t, handle: Handle) -> Result;
pub fn APT_GetSharedFont(fontHandle: *mut Handle, mapAddr: *mut u32_) pub fn APT_GetSharedFont(fontHandle: *mut Handle, mapAddr: *mut u32_)
-> Result; -> Result;
} }

1
ctru-sys/src/services/mod.rs

@ -25,7 +25,6 @@ pub mod ptmsysm;
pub mod ptmu; pub mod ptmu;
pub mod pxidev; pub mod pxidev;
pub mod qtm; pub mod qtm;
pub mod soc;
pub mod srvpm; pub mod srvpm;
pub mod sslc; pub mod sslc;
pub mod uds; pub mod uds;

6
ctru-sys/src/services/nfc.rs

@ -116,10 +116,10 @@ extern "C" {
pub fn nfcGetTagInfo(out: *mut NFC_TagInfo) -> Result; pub fn nfcGetTagInfo(out: *mut NFC_TagInfo) -> Result;
pub fn nfcOpenAppData(amiibo_appid: u32_) -> Result; pub fn nfcOpenAppData(amiibo_appid: u32_) -> Result;
pub fn nfcInitializeWriteAppData(amiibo_appid: u32_, pub fn nfcInitializeWriteAppData(amiibo_appid: u32_,
buf: *const ::libc::c_void, size: size_t) buf: *const ::libc::c_void, size: ::libc::size_t)
-> Result; -> Result;
pub fn nfcReadAppData(buf: *mut ::libc::c_void, size: size_t) -> Result; pub fn nfcReadAppData(buf: *mut ::libc::c_void, size: ::libc::size_t) -> Result;
pub fn nfcWriteAppData(buf: *const ::libc::c_void, size: size_t, pub fn nfcWriteAppData(buf: *const ::libc::c_void, size: ::libc::size_t,
taginfo: *mut NFC_TagInfo) -> Result; taginfo: *mut NFC_TagInfo) -> Result;
pub fn nfcGetAmiiboSettings(out: *mut NFC_AmiiboSettings) -> Result; pub fn nfcGetAmiiboSettings(out: *mut NFC_AmiiboSettings) -> Result;
pub fn nfcGetAmiiboConfig(out: *mut NFC_AmiiboConfig) -> Result; pub fn nfcGetAmiiboConfig(out: *mut NFC_AmiiboConfig) -> Result;

2
ctru-sys/src/services/ps.rs

@ -47,7 +47,7 @@ extern "C" {
nonce: *mut u8_) -> Result; nonce: *mut u8_) -> Result;
pub fn PS_GetLocalFriendCodeSeed(seed: *mut u64_) -> Result; pub fn PS_GetLocalFriendCodeSeed(seed: *mut u64_) -> Result;
pub fn PS_GetDeviceId(device_id: *mut u32_) -> Result; pub fn PS_GetDeviceId(device_id: *mut u32_) -> Result;
pub fn PS_GenerateRandomBytes(out: *mut ::libc::c_void, len: size_t) pub fn PS_GenerateRandomBytes(out: *mut ::libc::c_void, len: ::libc::size_t)
-> Result; -> Result;
} }
use ::types::*; use ::types::*;

2
ctru-sys/src/services/soc.rs

@ -92,7 +92,7 @@ extern "C" {
pub fn socInit(context_addr: *mut u32_, context_size: u32_) -> Result; pub fn socInit(context_addr: *mut u32_, context_size: u32_) -> Result;
pub fn socExit() -> Result; pub fn socExit() -> Result;
pub fn gethostid() -> ::libc::c_long; pub fn gethostid() -> ::libc::c_long;
pub fn gethostname(name: *mut ::libc::c_char, namelen: size_t) pub fn gethostname(name: *mut ::libc::c_char, namelen: ::libc::size_t)
-> ::libc::c_int; -> ::libc::c_int;
pub fn SOCU_ShutdownSockets() -> ::libc::c_int; pub fn SOCU_ShutdownSockets() -> ::libc::c_int;
pub fn SOCU_CloseSockets() -> ::libc::c_int; pub fn SOCU_CloseSockets() -> ::libc::c_int;

4
ctru-sys/src/services/sslc.rs

@ -89,9 +89,9 @@ extern "C" {
internal_retval: *mut ::libc::c_int, internal_retval: *mut ::libc::c_int,
out: *mut u32_) -> Result; out: *mut u32_) -> Result;
pub fn sslcRead(context: *mut sslcContext, buf: *mut ::libc::c_void, pub fn sslcRead(context: *mut sslcContext, buf: *mut ::libc::c_void,
len: size_t, peek: u8) -> Result; len: ::libc::size_t, peek: u8) -> Result;
pub fn sslcWrite(context: *mut sslcContext, buf: *const ::libc::c_void, pub fn sslcWrite(context: *mut sslcContext, buf: *const ::libc::c_void,
len: size_t) -> Result; len: ::libc::size_t) -> Result;
pub fn sslcContextSetRootCertChain(context: *mut sslcContext, pub fn sslcContextSetRootCertChain(context: *mut sslcContext,
handle: u32_) -> Result; handle: u32_) -> Result;
pub fn sslcContextSetClientCert(context: *mut sslcContext, handle: u32_) pub fn sslcContextSetClientCert(context: *mut sslcContext, handle: u32_)

244
ctru-sys/src/svc.rs

@ -4,10 +4,6 @@
non_camel_case_types, non_camel_case_types,
non_upper_case_globals, non_upper_case_globals,
non_snake_case)] non_snake_case)]
use ::{Handle, Result};
use ::ThreadFunc;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(u32)] #[repr(u32)]
#[derive(Debug)] #[derive(Debug)]
@ -56,10 +52,10 @@ pub enum MemPerm {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct MemInfo { pub struct MemInfo {
pub base_addr: u32, pub base_addr: u32_,
pub size: u32, pub size: u32_,
pub perm: u32, pub perm: u32_,
pub state: u32, pub state: u32_,
} }
impl ::core::default::Default for MemInfo { impl ::core::default::Default for MemInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -68,7 +64,7 @@ impl ::core::default::Default for MemInfo {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct PageInfo { pub struct PageInfo {
pub flags: u32, pub flags: u32_,
} }
impl ::core::default::Default for PageInfo { impl ::core::default::Default for PageInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -99,10 +95,10 @@ pub enum ProcessEventReason { REASON_CREATE = 1, REASON_ATTACH = 2, }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct ProcessEvent { pub struct ProcessEvent {
pub program_id: u64, pub program_id: u64_,
pub process_name: [u8; 8usize], pub process_name: [u8_; 8usize],
pub process_id: u32, pub process_id: u32_,
pub reason: u32, pub reason: u32_,
} }
impl ::core::default::Default for ProcessEvent { impl ::core::default::Default for ProcessEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -119,7 +115,7 @@ pub enum ExitProcessEventReason {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct ExitProcessEvent { pub struct ExitProcessEvent {
pub reason: u32, pub reason: u32_,
} }
impl ::core::default::Default for ExitProcessEvent { impl ::core::default::Default for ExitProcessEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -128,9 +124,9 @@ impl ::core::default::Default for ExitProcessEvent {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct CreateThreadEvent { pub struct CreateThreadEvent {
pub creator_thread_id: u32, pub creator_thread_id: u32_,
pub base_addr: u32, pub base_addr: u32_,
pub entry_point: u32, pub entry_point: u32_,
} }
impl ::core::default::Default for CreateThreadEvent { impl ::core::default::Default for CreateThreadEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -148,7 +144,7 @@ pub enum ExitThreadEventReason {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct ExitThreadEvent { pub struct ExitThreadEvent {
pub reason: u32, pub reason: u32_,
} }
impl ::core::default::Default for ExitThreadEvent { impl ::core::default::Default for ExitThreadEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -179,9 +175,9 @@ pub enum ExceptionEventType {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct ExceptionEvent { pub struct ExceptionEvent {
pub type_: u32, pub type_: u32_,
pub address: u32, pub address: u32_,
pub argument: u32, pub argument: u32_,
} }
impl ::core::default::Default for ExceptionEvent { impl ::core::default::Default for ExceptionEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -190,7 +186,7 @@ impl ::core::default::Default for ExceptionEvent {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct SchedulerInOutEvent { pub struct SchedulerInOutEvent {
pub clock_tick: u64, pub clock_tick: u64_,
} }
impl ::core::default::Default for SchedulerInOutEvent { impl ::core::default::Default for SchedulerInOutEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -199,8 +195,8 @@ impl ::core::default::Default for SchedulerInOutEvent {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct SyscallInOutEvent { pub struct SyscallInOutEvent {
pub clock_tick: u64, pub clock_tick: u64_,
pub syscall: u32, pub syscall: u32_,
_bindgen_padding_0_: [u8; 4usize], _bindgen_padding_0_: [u8; 4usize],
} }
impl ::core::default::Default for SyscallInOutEvent { impl ::core::default::Default for SyscallInOutEvent {
@ -210,8 +206,8 @@ impl ::core::default::Default for SyscallInOutEvent {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct OutputStringEvent { pub struct OutputStringEvent {
pub string_addr: u32, pub string_addr: u32_,
pub string_size: u32, pub string_size: u32_,
} }
impl ::core::default::Default for OutputStringEvent { impl ::core::default::Default for OutputStringEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -220,10 +216,10 @@ impl ::core::default::Default for OutputStringEvent {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct MapEvent { pub struct MapEvent {
pub mapped_addr: u32, pub mapped_addr: u32_,
pub mapped_size: u32, pub mapped_size: u32_,
pub memperm: u32, pub memperm: u32_,
pub memstate: u32, pub memstate: u32_,
} }
impl ::core::default::Default for MapEvent { impl ::core::default::Default for MapEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -250,9 +246,9 @@ pub enum DebugEventType {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct DebugEventInfo { pub struct DebugEventInfo {
pub type_: u32, pub type_: u32_,
pub thread_id: u32, pub thread_id: u32_,
pub unknown: [u32; 2usize], pub unknown: [u32_; 2usize],
pub _bindgen_data_1_: [u64; 3usize], pub _bindgen_data_1_: [u64; 3usize],
} }
impl DebugEventInfo { impl DebugEventInfo {
@ -300,21 +296,21 @@ impl ::core::default::Default for DebugEventInfo {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
pub struct CodeSetInfo { pub struct CodeSetInfo {
pub name: [u8; 8usize], pub name: [u8_; 8usize],
pub unk1: u16, pub unk1: u16_,
pub unk2: u16, pub unk2: u16_,
pub unk3: u32, pub unk3: u32_,
pub text_addr: u32, pub text_addr: u32_,
pub text_size: u32, pub text_size: u32_,
pub ro_addr: u32, pub ro_addr: u32_,
pub ro_size: u32, pub ro_size: u32_,
pub rw_addr: u32, pub rw_addr: u32_,
pub rw_size: u32, pub rw_size: u32_,
pub text_size_total: u32, pub text_size_total: u32_,
pub ro_size_total: u32, pub ro_size_total: u32_,
pub rw_size_total: u32, pub rw_size_total: u32_,
pub unk4: u32, pub unk4: u32_,
pub program_id: u64, pub program_id: u64_,
} }
impl ::core::default::Default for CodeSetInfo { impl ::core::default::Default for CodeSetInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@ -324,62 +320,62 @@ impl ::core::default::Default for CodeSetInfo {
#[derive(Debug)] #[derive(Debug)]
pub struct StartupInfo { pub struct StartupInfo {
pub priority: ::libc::c_int, pub priority: ::libc::c_int,
pub stack_size: u32, pub stack_size: u32_,
pub argc: ::libc::c_int, pub argc: ::libc::c_int,
pub argv: *mut u16, pub argv: *mut u16_,
pub envp: *mut u16, pub envp: *mut u16_,
} }
impl ::core::default::Default for StartupInfo { impl ::core::default::Default for StartupInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
} }
extern "C" { extern "C" {
pub fn svcControlMemory(addr_out: *mut u32, addr0: u32, addr1: u32, pub fn svcControlMemory(addr_out: *mut u32_, addr0: u32_, addr1: u32_,
size: u32, op: MemOp, perm: MemPerm) -> Result; size: u32_, op: MemOp, perm: MemPerm) -> Result;
pub fn svcControlProcessMemory(process: Handle, addr0: u32, addr1: u32, pub fn svcControlProcessMemory(process: Handle, addr0: u32_, addr1: u32_,
size: u32, type_: u32, perm: u32) size: u32_, type_: u32_, perm: u32_)
-> Result; -> Result;
pub fn svcCreateMemoryBlock(memblock: *mut Handle, addr: u32, size: u32, pub fn svcCreateMemoryBlock(memblock: *mut Handle, addr: u32_, size: u32_,
my_perm: MemPerm, other_perm: MemPerm) my_perm: MemPerm, other_perm: MemPerm)
-> Result; -> Result;
pub fn svcMapMemoryBlock(memblock: Handle, addr: u32, my_perm: MemPerm, pub fn svcMapMemoryBlock(memblock: Handle, addr: u32_, my_perm: MemPerm,
other_perm: MemPerm) -> Result; other_perm: MemPerm) -> Result;
pub fn svcMapProcessMemory(process: Handle, startAddr: u32, pub fn svcMapProcessMemory(process: Handle, startAddr: u32_,
endAddr: u32) -> Result; endAddr: u32_) -> Result;
pub fn svcUnmapProcessMemory(process: Handle, startAddr: u32, pub fn svcUnmapProcessMemory(process: Handle, startAddr: u32_,
endAddr: u32) -> Result; endAddr: u32_) -> Result;
pub fn svcUnmapMemoryBlock(memblock: Handle, addr: u32) -> Result; pub fn svcUnmapMemoryBlock(memblock: Handle, addr: u32_) -> Result;
pub fn svcStartInterProcessDma(dma: *mut Handle, dstProcess: Handle, pub fn svcStartInterProcessDma(dma: *mut Handle, dstProcess: Handle,
dst: *mut ::libc::c_void, dst: *mut ::libc::c_void,
srcProcess: Handle, srcProcess: Handle,
src: *const ::libc::c_void, size: u32, src: *const ::libc::c_void, size: u32_,
dmaConfig: *mut ::libc::c_void) -> Result; dmaConfig: *mut ::libc::c_void) -> Result;
pub fn svcStopDma(dma: Handle) -> Result; pub fn svcStopDma(dma: Handle) -> Result;
pub fn svcGetDmaState(dmaState: *mut ::libc::c_void, dma: Handle) pub fn svcGetDmaState(dmaState: *mut ::libc::c_void, dma: Handle)
-> Result; -> Result;
pub fn svcQueryMemory(info: *mut MemInfo, out: *mut PageInfo, addr: u32) pub fn svcQueryMemory(info: *mut MemInfo, out: *mut PageInfo, addr: u32_)
-> Result; -> Result;
pub fn svcQueryProcessMemory(info: *mut MemInfo, out: *mut PageInfo, pub fn svcQueryProcessMemory(info: *mut MemInfo, out: *mut PageInfo,
process: Handle, addr: u32) -> Result; process: Handle, addr: u32_) -> Result;
pub fn svcInvalidateProcessDataCache(process: Handle, pub fn svcInvalidateProcessDataCache(process: Handle,
addr: *mut ::libc::c_void, addr: *mut ::libc::c_void,
size: u32) -> Result; size: u32_) -> Result;
pub fn svcFlushProcessDataCache(process: Handle, pub fn svcFlushProcessDataCache(process: Handle,
addr: *const ::libc::c_void, size: u32) addr: *const ::libc::c_void, size: u32_)
-> Result; -> Result;
pub fn svcReadProcessMemory(buffer: *mut ::libc::c_void, debug: Handle, pub fn svcReadProcessMemory(buffer: *mut ::libc::c_void, debug: Handle,
addr: u32, size: u32) -> Result; addr: u32_, size: u32_) -> Result;
pub fn svcWriteProcessMemory(debug: Handle, buffer: *const ::libc::c_void, pub fn svcWriteProcessMemory(debug: Handle, buffer: *const ::libc::c_void,
addr: u32, size: u32) -> Result; addr: u32_, size: u32_) -> Result;
pub fn svcOpenProcess(process: *mut Handle, processId: u32) -> Result; pub fn svcOpenProcess(process: *mut Handle, processId: u32_) -> Result;
pub fn svcExitProcess(); pub fn svcExitProcess();
pub fn svcTerminateProcess(process: Handle) -> Result; pub fn svcTerminateProcess(process: Handle) -> Result;
pub fn svcGetProcessInfo(out: *mut i64, process: Handle, type_: u32) pub fn svcGetProcessInfo(out: *mut s64, process: Handle, type_: u32_)
-> Result; -> Result;
pub fn svcGetProcessId(out: *mut u32, handle: Handle) -> Result; pub fn svcGetProcessId(out: *mut u32_, handle: Handle) -> Result;
pub fn svcGetProcessList(processCount: *mut i32, processIds: *mut u32, pub fn svcGetProcessList(processCount: *mut s32, processIds: *mut u32_,
processIdMaxCount: i32) -> Result; processIdMaxCount: s32) -> Result;
pub fn svcCreatePort(portServer: *mut Handle, portClient: *mut Handle, pub fn svcCreatePort(portServer: *mut Handle, portClient: *mut Handle,
name: *const ::libc::c_char, maxSessions: i32) name: *const ::libc::c_char, maxSessions: s32)
-> Result; -> Result;
pub fn svcConnectToPort(out: *mut Handle, portName: *const ::libc::c_char) pub fn svcConnectToPort(out: *mut Handle, portName: *const ::libc::c_char)
-> Result; -> Result;
@ -388,94 +384,96 @@ extern "C" {
ro_ptr: *mut ::libc::c_void, ro_ptr: *mut ::libc::c_void,
data_ptr: *mut ::libc::c_void) -> Result; data_ptr: *mut ::libc::c_void) -> Result;
pub fn svcCreateProcess(out: *mut Handle, codeset: Handle, pub fn svcCreateProcess(out: *mut Handle, codeset: Handle,
arm11kernelcaps: *const u32, arm11kernelcaps: *const u32_,
arm11kernelcaps_num: u32) -> Result; arm11kernelcaps_num: u32_) -> Result;
pub fn svcSetProcessAffinityMask(process: Handle, pub fn svcSetProcessAffinityMask(process: Handle,
affinitymask: *const u8, affinitymask: *const u8_,
processorcount: i32) -> Result; processorcount: s32) -> Result;
pub fn svcSetProcessIdealProcessor(process: Handle, processorid: i32) pub fn svcSetProcessIdealProcessor(process: Handle, processorid: s32)
-> Result; -> Result;
pub fn svcRun(process: Handle, info: *const StartupInfo) -> Result; pub fn svcRun(process: Handle, info: *const StartupInfo) -> Result;
pub fn svcCreateThread(thread: *mut Handle, entrypoint: ThreadFunc, pub fn svcCreateThread(thread: *mut Handle, entrypoint: ThreadFunc,
arg: u32, stack_top: *mut u32, arg: u32_, stack_top: *mut u32_,
thread_priority: i32, processor_id: i32) -> Result; thread_priority: s32, processor_id: s32) -> Result;
pub fn svcOpenThread(thread: *mut Handle, process: Handle, threadId: u32) pub fn svcOpenThread(thread: *mut Handle, process: Handle, threadId: u32_)
-> Result; -> Result;
pub fn svcExitThread(); pub fn svcExitThread();
pub fn svcSleepThread(ns: i64); pub fn svcSleepThread(ns: s64);
pub fn svcGetThreadPriority(out: *mut i32, handle: Handle) -> Result; pub fn svcGetThreadPriority(out: *mut s32, handle: Handle) -> Result;
pub fn svcSetThreadPriority(thread: Handle, prio: i32) -> Result; pub fn svcSetThreadPriority(thread: Handle, prio: s32) -> Result;
pub fn svcGetThreadAffinityMask(affinitymask: *mut u8, thread: Handle, pub fn svcGetThreadAffinityMask(affinitymask: *mut u8_, thread: Handle,
processorcount: i32) -> Result; processorcount: s32) -> Result;
pub fn svcSetThreadAffinityMask(thread: Handle, affinitymask: *const u8, pub fn svcSetThreadAffinityMask(thread: Handle, affinitymask: *const u8_,
processorcount: i32) -> Result; processorcount: s32) -> Result;
pub fn svcGetThreadIdealProcessor(processorid: *mut i32, thread: Handle) pub fn svcGetThreadIdealProcessor(processorid: *mut s32, thread: Handle)
-> Result; -> Result;
pub fn svcSetThreadIdealProcessor(thread: Handle, processorid: i32) pub fn svcSetThreadIdealProcessor(thread: Handle, processorid: s32)
-> Result; -> Result;
pub fn svcGetProcessorID() -> i32; pub fn svcGetProcessorID() -> s32;
pub fn svcGetThreadId(out: *mut u32, handle: Handle) -> Result; pub fn svcGetThreadId(out: *mut u32_, handle: Handle) -> Result;
pub fn svcGetResourceLimit(resourceLimit: *mut Handle, process: Handle) pub fn svcGetResourceLimit(resourceLimit: *mut Handle, process: Handle)
-> Result; -> Result;
pub fn svcGetResourceLimitLimitValues(values: *mut i64, pub fn svcGetResourceLimitLimitValues(values: *mut s64,
resourceLimit: Handle, resourceLimit: Handle,
names: *mut u32, nameCount: i32) names: *mut u32_, nameCount: s32)
-> Result; -> Result;
pub fn svcGetResourceLimitCurrentValues(values: *mut i64, pub fn svcGetResourceLimitCurrentValues(values: *mut s64,
resourceLimit: Handle, resourceLimit: Handle,
names: *mut u32, nameCount: i32) names: *mut u32_, nameCount: s32)
-> Result; -> Result;
pub fn svcGetProcessIdOfThread(out: *mut u32, handle: Handle) -> Result; pub fn svcGetProcessIdOfThread(out: *mut u32_, handle: Handle) -> Result;
pub fn svcGetThreadInfo(out: *mut i64, thread: Handle, pub fn svcGetThreadInfo(out: *mut s64, thread: Handle,
type_: ThreadInfoType) -> Result; type_: ThreadInfoType) -> Result;
pub fn svcCreateMutex(mutex: *mut Handle, initially_locked: u8) -> Result; pub fn svcCreateMutex(mutex: *mut Handle, initially_locked: u8) -> Result;
pub fn svcReleaseMutex(handle: Handle) -> Result; pub fn svcReleaseMutex(handle: Handle) -> Result;
pub fn svcCreateSemaphore(semaphore: *mut Handle, initial_count: i32, pub fn svcCreateSemaphore(semaphore: *mut Handle, initial_count: s32,
max_count: i32) -> Result; max_count: s32) -> Result;
pub fn svcReleaseSemaphore(count: *mut i32, semaphore: Handle, pub fn svcReleaseSemaphore(count: *mut s32, semaphore: Handle,
release_count: i32) -> Result; release_count: s32) -> Result;
pub fn svcCreateEvent(event: *mut Handle, reset_type: ResetType) pub fn svcCreateEvent(event: *mut Handle, reset_type: ResetType)
-> Result; -> Result;
pub fn svcSignalEvent(handle: Handle) -> Result; pub fn svcSignalEvent(handle: Handle) -> Result;
pub fn svcClearEvent(handle: Handle) -> Result; pub fn svcClearEvent(handle: Handle) -> Result;
pub fn svcWaitSynchronization(handle: Handle, nanoseconds: i64) -> Result; pub fn svcWaitSynchronization(handle: Handle, nanoseconds: s64) -> Result;
pub fn svcWaitSynchronizationN(out: *mut i32, handles: *mut Handle, pub fn svcWaitSynchronizationN(out: *mut s32, handles: *mut Handle,
handles_num: i32, wait_all: u8, handles_num: s32, wait_all: u8,
nanoseconds: i64) -> Result; nanoseconds: s64) -> Result;
pub fn svcCreateAddressArbiter(arbiter: *mut Handle) -> Result; pub fn svcCreateAddressArbiter(arbiter: *mut Handle) -> Result;
pub fn svcArbitrateAddress(arbiter: Handle, addr: u32, pub fn svcArbitrateAddress(arbiter: Handle, addr: u32_,
type_: ArbitrationType, value: i32, type_: ArbitrationType, value: s32,
nanoseconds: i64) -> Result; nanoseconds: s64) -> Result;
pub fn svcSendSyncRequest(session: Handle) -> Result; pub fn svcSendSyncRequest(session: Handle) -> Result;
pub fn svcAcceptSession(session: *mut Handle, port: Handle) -> Result; pub fn svcAcceptSession(session: *mut Handle, port: Handle) -> Result;
pub fn svcReplyAndReceive(index: *mut i32, handles: *mut Handle, pub fn svcReplyAndReceive(index: *mut s32, handles: *mut Handle,
handleCount: i32, replyTarget: Handle) handleCount: s32, replyTarget: Handle)
-> Result; -> Result;
pub fn svcBindInterrupt(interruptId: u32, event: Handle, priority: i32, pub fn svcBindInterrupt(interruptId: u32_, event: Handle, priority: s32,
isManualClear: u8) -> Result; isManualClear: u8) -> Result;
pub fn svcUnbindInterrupt(interruptId: u32, event: Handle) -> Result; pub fn svcUnbindInterrupt(interruptId: u32_, event: Handle) -> Result;
pub fn svcCreateTimer(timer: *mut Handle, reset_type: ResetType) pub fn svcCreateTimer(timer: *mut Handle, reset_type: ResetType)
-> Result; -> Result;
pub fn svcSetTimer(timer: Handle, initial: i64, interval: i64) -> Result; pub fn svcSetTimer(timer: Handle, initial: s64, interval: s64) -> Result;
pub fn svcCancelTimer(timer: Handle) -> Result; pub fn svcCancelTimer(timer: Handle) -> Result;
pub fn svcClearTimer(timer: Handle) -> Result; pub fn svcClearTimer(timer: Handle) -> Result;
pub fn svcGetSystemTick() -> u64; pub fn svcGetSystemTick() -> u64_;
pub fn svcCloseHandle(handle: Handle) -> Result; pub fn svcCloseHandle(handle: Handle) -> Result;
pub fn svcDuplicateHandle(out: *mut Handle, original: Handle) -> Result; pub fn svcDuplicateHandle(out: *mut Handle, original: Handle) -> Result;
pub fn svcGetSystemInfo(out: *mut i64, type_: u32, param: i32) -> Result; pub fn svcGetSystemInfo(out: *mut s64, type_: u32_, param: s32) -> Result;
pub fn svcKernelSetState(type_: u32, param0: u32, param1: u32, pub fn svcKernelSetState(type_: u32_, param0: u32_, param1: u32_,
param2: u32) -> Result; param2: u32_) -> Result;
pub fn svcBreak(breakReason: UserBreakType); pub fn svcBreak(breakReason: UserBreakType);
pub fn svcOutputDebugString(str: *const ::libc::c_char, pub fn svcOutputDebugString(str: *const ::libc::c_char,
length: ::libc::c_int) -> Result; length: ::libc::c_int) -> Result;
pub fn svcDebugActiveProcess(debug: *mut Handle, processId: u32) pub fn svcDebugActiveProcess(debug: *mut Handle, processId: u32_)
-> Result; -> Result;
pub fn svcBreakDebugProcess(debug: Handle) -> Result; pub fn svcBreakDebugProcess(debug: Handle) -> Result;
pub fn svcTerminateDebugProcess(debug: Handle) -> Result; pub fn svcTerminateDebugProcess(debug: Handle) -> Result;
pub fn svcGetProcessDebugEvent(info: *mut DebugEventInfo, debug: Handle) pub fn svcGetProcessDebugEvent(info: *mut DebugEventInfo, debug: Handle)
-> Result; -> Result;
pub fn svcContinueDebugEvent(debug: Handle, flags: u32) -> Result; pub fn svcContinueDebugEvent(debug: Handle, flags: u32_) -> Result;
pub fn svcBackdoor(callback: pub fn svcBackdoor(callback:
::core::option::Option<extern "C" fn() -> i32>) ::core::option::Option<extern "C" fn() -> s32>)
-> Result; -> Result;
} }
use ::types::*;

6
ctru-sys/src/sys/inaddr.rs

@ -5,11 +5,10 @@
non_upper_case_globals, non_upper_case_globals,
non_snake_case)] non_snake_case)]
use ::types::*;
use super::socket::*; use super::socket::*;
pub type in_port_t = uint16_t; pub type in_port_t = ::libc::uint16_t;
pub type in_addr_t = uint32_t; pub type in_addr_t = ::libc::uint32_t;
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
@ -41,4 +40,3 @@ pub struct ip_mreq {
impl ::core::default::Default for ip_mreq { impl ::core::default::Default for ip_mreq {
fn default() -> Self { unsafe { ::core::mem::zeroed() } } fn default() -> Self { unsafe { ::core::mem::zeroed() } }
} }

6
ctru-sys/src/sys/libc.rs

@ -85,8 +85,8 @@ pub type fsblkcnt_t = c_uint;
pub type fsfilcnt_t = c_uint; pub type fsfilcnt_t = c_uint;
extern "C" { extern "C" {
pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memchr(cx: *const c_void, c: c_int, n: ::libc::size_t) -> *mut c_void;
pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memrchr(cx: *const c_void, c: c_int, n: ::libc::size_t) -> *mut c_void;
pub fn strlen(cs: *const c_char) -> size_t; pub fn strlen(cs: *const c_char) -> size_t;
pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; pub fn write(fd: c_int, buf: *const c_void, count: ::libc::size_t) -> ::libc::ssize_t;
} }

3
ctru-sys/src/sys/mod.rs

@ -1,4 +1,3 @@
pub mod libc;
pub mod lock; pub mod lock;
pub mod socket;
pub mod inaddr; pub mod inaddr;
pub mod socket;

20
ctru-sys/src/sys/socket.rs

@ -4,8 +4,8 @@
non_camel_case_types, non_camel_case_types,
non_upper_case_globals, non_upper_case_globals,
non_snake_case)] non_snake_case)]
pub type socklen_t = uint32_t; pub type socklen_t = ::libc::uint32_t;
pub type sa_family_t = uint16_t; pub type sa_family_t = ::libc::uint16_t;
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[derive(Debug)] #[derive(Debug)]
@ -53,17 +53,17 @@ extern "C" {
optlen: *mut socklen_t) -> ::libc::c_int; optlen: *mut socklen_t) -> ::libc::c_int;
pub fn listen(sockfd: ::libc::c_int, backlog: ::libc::c_int) pub fn listen(sockfd: ::libc::c_int, backlog: ::libc::c_int)
-> ::libc::c_int; -> ::libc::c_int;
pub fn recv(sockfd: ::libc::c_int, buf: *mut ::libc::c_void, len: size_t, pub fn recv(sockfd: ::libc::c_int, buf: *mut ::libc::c_void, len: ::libc::size_t,
flags: ::libc::c_int) -> ssize_t; flags: ::libc::c_int) -> ::libc::ssize_t;
pub fn recvfrom(sockfd: ::libc::c_int, buf: *mut ::libc::c_void, pub fn recvfrom(sockfd: ::libc::c_int, buf: *mut ::libc::c_void,
len: size_t, flags: ::libc::c_int, len: ::libc::size_t, flags: ::libc::c_int,
src_addr: *mut sockaddr, addrlen: *mut socklen_t) src_addr: *mut sockaddr, addrlen: *mut socklen_t)
-> ssize_t; -> ::libc::ssize_t;
pub fn send(sockfd: ::libc::c_int, buf: *const ::libc::c_void, pub fn send(sockfd: ::libc::c_int, buf: *const ::libc::c_void,
len: size_t, flags: ::libc::c_int) -> ssize_t; len: ::libc::size_t, flags: ::libc::c_int) -> ::libc::ssize_t;
pub fn sendto(sockfd: ::libc::c_int, buf: *const ::libc::c_void, pub fn sendto(sockfd: ::libc::c_int, buf: *const ::libc::c_void,
len: size_t, flags: ::libc::c_int, len: ::libc::size_t, flags: ::libc::c_int,
dest_addr: *const sockaddr, addrlen: socklen_t) -> ssize_t; dest_addr: *const sockaddr, addrlen: socklen_t) -> ::libc::ssize_t;
pub fn setsockopt(sockfd: ::libc::c_int, level: ::libc::c_int, pub fn setsockopt(sockfd: ::libc::c_int, level: ::libc::c_int,
optname: ::libc::c_int, optval: *const ::libc::c_void, optname: ::libc::c_int, optval: *const ::libc::c_void,
optlen: socklen_t) -> ::libc::c_int; optlen: socklen_t) -> ::libc::c_int;
@ -73,5 +73,3 @@ extern "C" {
protocol: ::libc::c_int) -> ::libc::c_int; protocol: ::libc::c_int) -> ::libc::c_int;
pub fn sockatmark(sockfd: ::libc::c_int) -> ::libc::c_int; pub fn sockatmark(sockfd: ::libc::c_int) -> ::libc::c_int;
} }
use ::types::*;

4
ctru-sys/src/types.rs

@ -22,10 +22,6 @@ pub type vs32 = s32;
pub type vs64 = s64; pub type vs64 = s64;
pub type Handle = u32_; pub type Handle = u32_;
pub type Result = s32; pub type Result = s32;
pub type size_t = usize;
pub type ssize_t = isize;
pub type uint32_t = u32;
pub type uint16_t = u16;
pub type ThreadFunc = pub type ThreadFunc =
::core::option::Option<unsafe extern "C" fn(arg1: *mut ::libc::c_void)>; ::core::option::Option<unsafe extern "C" fn(arg1: *mut ::libc::c_void)>;
pub type voidfn = ::core::option::Option<extern "C" fn()>; pub type voidfn = ::core::option::Option<extern "C" fn()>;

1
src/lib.rs

@ -3,6 +3,7 @@
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate widestring;
extern crate ctru_sys as libctru; extern crate ctru_sys as libctru;

15
src/services/fs.rs

@ -8,11 +8,13 @@ use std::marker::PhantomData;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use std::mem; use std::mem;
use std::arc::Arc; use std::sync::Arc;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::ffi::OsString; use std::ffi::OsString;
use widestring::{WideCString, WideCStr};
use libctru::services::fs::*; use libctru::services::fs::*;
bitflags! { bitflags! {
@ -616,8 +618,11 @@ impl<'a> DirEntry<'a> {
/// Returns the bare file name of this directory entry without any other leading path /// Returns the bare file name of this directory entry without any other leading path
/// component. /// component.
pub fn file_name(&self) -> OsString { pub fn file_name(&self) -> OsString {
let filename = truncate_utf16_at_nul(&self.entry.name); unsafe {
OsString::from_wide(filename) let filename = truncate_utf16_at_nul(&self.entry.name);
let filename = WideCStr::from_ptr_str(filename.as_ptr());
filename.to_os_string()
}
} }
} }
@ -797,8 +802,8 @@ pub fn rename<P, Q>(arch: &Archive, from: P, to: Q) -> Result<(), i32>
} }
// TODO: Determine if we should check UTF-16 paths for interior NULs // TODO: Determine if we should check UTF-16 paths for interior NULs
fn to_utf16(path: &Path) -> Vec<u16> { fn to_utf16(path: &Path) -> WideCString {
path.as_os_str().encode_wide().collect::<Vec<_>>() WideCString::from_str(path).unwrap()
} }
// Adapted from sys/windows/fs.rs in libstd // Adapted from sys/windows/fs.rs in libstd

15
std/Cargo.toml

@ -1,15 +0,0 @@
[package]
name = "std"
version = "0.0.0"
[lib]
crate-type = ["rlib"]
[dependencies.alloc_system3ds]
git = "https://github.com/rust3ds/alloc_system3ds"
[dependencies.ctru-sys]
path = "../ctru-sys"
[dependencies.spin]
version = "0.4"

5
std/src/ffi/mod.rs

@ -1,5 +0,0 @@
pub use self::c_str::{CString, CStr};
pub use self::os_str::{OsString, OsStr};
mod c_str;
mod os_str;

100
std/src/lib.rs

@ -1,100 +0,0 @@
#![feature(alloc)]
#![feature(allow_internal_unstable)]
#![feature(collections)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(char_escape_debug)]
#![feature(float_extras)]
#![feature(int_error_internals)]
#![feature(lang_items)]
#![feature(macro_reexport)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(raw)]
#![feature(slice_concat_ext)]
#![feature(slice_patterns)]
#![feature(str_internals)]
#![feature(try_from)]
#![feature(unicode)]
#![feature(zero_one)]
#![allow(non_camel_case_types)]
#![no_std]
#[prelude_import]
#[allow(unused)]
use prelude::v1::*;
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
unreachable, unimplemented, write, writeln)]
extern crate core as __core;
#[macro_use]
#[macro_reexport(vec, format)]
extern crate collections as core_collections;
extern crate alloc;
extern crate std_unicode;
extern crate alloc_system;
extern crate ctru_sys as libctru;
extern crate spin;
pub use core::any;
pub use core::cell;
pub use core::clone;
pub use core::cmp;
pub use core::convert;
pub use core::default;
pub use core::hash;
pub use core::intrinsics;
pub use core::iter;
pub use core::marker;
pub use core::mem;
pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::result;
pub use core::option;
pub use alloc::arc;
pub use alloc::boxed;
pub use alloc::rc;
pub use core_collections::borrow;
pub use core_collections::fmt;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
pub use core_collections::vec;
pub use std_unicode::char;
#[macro_use]
pub mod macros;
pub mod prelude;
pub use core::isize;
pub use core::i8;
pub use core::i16;
pub use core::i32;
pub use core::i64;
pub use core::usize;
pub use core::u8;
pub use core::u16;
pub use core::u32;
pub use core::u64;
#[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64;
pub mod ascii;
pub mod error;
pub mod ffi;
pub mod io;
pub mod num;
pub mod path;
pub mod rt;
pub mod sync;
mod memchr;
mod panicking;
mod sys;

105
std/src/macros.rs

@ -1,105 +0,0 @@
// Copyright 2014 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.
/// The entry point for panic of Rust threads.
///
/// This macro is used to inject panic into a Rust thread, causing the thread to
/// panic entirely. Each thread's panic can be reaped as the `Box<Any>` type,
/// and the single-argument form of the `panic!` macro will be the value which
/// is transmitted.
///
/// The multi-argument form of this macro panics with a string and has the
/// `format!` syntax for building a string.
///
/// # Examples
///
/// ```should_panic
/// # #![allow(unreachable_code)]
/// panic!();
/// panic!("this is a terrible mistake!");
/// panic!(4); // panic with the value of 4 to be collected elsewhere
/// panic!("this is a {} {message}", "fancy", message = "message");
/// ```
#[macro_export]
macro_rules! panic {
() => ({
panic!("explicit panic")
});
($msg:expr) => ({
$crate::rt::begin_panic($msg, {
// static requires less code at runtime, more constant data
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
&_FILE_LINE
})
});
($fmt:expr, $($arg:tt)+) => ({
$crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+), {
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
// insufficient, since the user may have
// `#[forbid(dead_code)]` and which cannot be overridden.
static _FILE_LINE: (&'static str, u32) = (file!(), line!());
&_FILE_LINE
})
});
}
/// Helper macro for unwrapping `Result` values while returning early with an
/// error if the value of the expression is `Err`. Can only be used in
/// functions that return `Result` because of the early return of `Err` that
/// it provides.
///
/// # Examples
///
/// ```
/// use std::io;
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// fn write_to_file_using_try() -> Result<(), io::Error> {
/// let mut file = try!(File::create("my_best_friends.txt"));
/// try!(file.write_all(b"This is a list of my best friends."));
/// println!("I wrote to the file");
/// Ok(())
/// }
/// // This is equivalent to:
/// fn write_to_file_using_match() -> Result<(), io::Error> {
/// let mut file = try!(File::create("my_best_friends.txt"));
/// match file.write_all(b"This is a list of my best friends.") {
/// Ok(v) => v,
/// Err(e) => return Err(e),
/// }
/// println!("I wrote to the file");
/// Ok(())
/// }
/// ```
#[macro_export]
macro_rules! try {
($expr:expr) => (match $expr {
$crate::result::Result::Ok(val) => val,
$crate::result::Result::Err(err) => {
return $crate::result::Result::Err($crate::convert::From::from(err))
}
})
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => (
$crate::io::_print(format_args!($($arg)*));
);
}
#[macro_export]
macro_rules! println {
() => (print!("\n"));
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

397
std/src/memchr.rs

@ -1,397 +0,0 @@
// Copyright 2015 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.
//
// Original implementation taken from rust-memchr
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
/// A safe interface to `memchr`.
///
/// Returns the index corresponding to the first occurrence of `needle` in
/// `haystack`, or `None` if one is not found.
///
/// memchr reduces to super-optimized machine code at around an order of
/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
/// (See benchmarks.)
///
/// # Example
///
/// This shows how to find the first position of a byte in a byte string.
///
/// ```rust,ignore
/// use memchr::memchr;
///
/// let haystack = b"the quick brown fox";
/// assert_eq!(memchr(b'k', haystack), Some(8));
/// ```
pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
fn memchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
use libctru::libc;
let p = unsafe {
libc::memchr(haystack.as_ptr() as *const libc::c_void,
needle as libc::c_int,
haystack.len() as libc::size_t)
};
if p.is_null() {
None
} else {
Some(p as usize - (haystack.as_ptr() as usize))
}
}
memchr_specific(needle, haystack)
}
/// A safe interface to `memrchr`.
///
/// Returns the index corresponding to the last occurrence of `needle` in
/// `haystack`, or `None` if one is not found.
///
/// # Example
///
/// This shows how to find the last position of a byte in a byte string.
///
/// ```rust,ignore
/// use memchr::memrchr;
///
/// let haystack = b"the quick brown fox";
/// assert_eq!(memrchr(b'o', haystack), Some(17));
/// ```
pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
use libctru::libc;
// GNU's memrchr() will - unlike memchr() - error if haystack is empty.
if haystack.is_empty() {
return None;
}
let p = unsafe {
libc::memrchr(haystack.as_ptr() as *const libc::c_void,
needle as libc::c_int,
haystack.len() as libc::size_t)
};
if p.is_null() {
None
} else {
Some(p as usize - (haystack.as_ptr() as usize))
}
}
memrchr_specific(needle, haystack)
}
#[allow(dead_code)]
mod fallback {
use core::cmp;
use core::mem;
const LO_U64: u64 = 0x0101010101010101;
const HI_U64: u64 = 0x8080808080808080;
// use truncation
const LO_USIZE: usize = LO_U64 as usize;
const HI_USIZE: usize = HI_U64 as usize;
/// Return `true` if `x` contains any zero byte.
///
/// From *Matters Computational*, J. Arndt
///
/// "The idea is to subtract one from each of the bytes and then look for
/// bytes where the borrow propagated all the way to the most significant
/// bit."
#[inline]
fn contains_zero_byte(x: usize) -> bool {
x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
}
#[cfg(target_pointer_width = "32")]
#[inline]
fn repeat_byte(b: u8) -> usize {
let mut rep = (b as usize) << 8 | b as usize;
rep = rep << 16 | rep;
rep
}
#[cfg(target_pointer_width = "64")]
#[inline]
fn repeat_byte(b: u8) -> usize {
let mut rep = (b as usize) << 8 | b as usize;
rep = rep << 16 | rep;
rep = rep << 32 | rep;
rep
}
/// Return the first index matching the byte `a` in `text`.
pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
// Scan for a single byte value by reading two `usize` words at a time.
//
// Split `text` in three parts
// - unaligned initial part, before the first word aligned address in text
// - body, scan by 2 words at a time
// - the last remaining part, < 2 word size
let len = text.len();
let ptr = text.as_ptr();
let usize_bytes = mem::size_of::<usize>();
// search up to an aligned boundary
let align = (ptr as usize) & (usize_bytes - 1);
let mut offset;
if align > 0 {
offset = cmp::min(usize_bytes - align, len);
if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
return Some(index);
}
} else {
offset = 0;
}
// search the body of the text
let repeated_x = repeat_byte(x);
if len >= 2 * usize_bytes {
while offset <= len - 2 * usize_bytes {
unsafe {
let u = *(ptr.offset(offset as isize) as *const usize);
let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize);
// break if there is a matching byte
let zu = contains_zero_byte(u ^ repeated_x);
let zv = contains_zero_byte(v ^ repeated_x);
if zu || zv {
break;
}
}
offset += usize_bytes * 2;
}
}
// find the byte after the point the body loop stopped
text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i)
}
/// Return the last index matching the byte `a` in `text`.
pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
// Scan for a single byte value by reading two `usize` words at a time.
//
// Split `text` in three parts
// - unaligned tail, after the last word aligned address in text
// - body, scan by 2 words at a time
// - the first remaining bytes, < 2 word size
let len = text.len();
let ptr = text.as_ptr();
let usize_bytes = mem::size_of::<usize>();
// search to an aligned boundary
let end_align = (ptr as usize + len) & (usize_bytes - 1);
let mut offset;
if end_align > 0 {
offset = if end_align >= len {
0
} else {
len - end_align
};
if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
return Some(offset + index);
}
} else {
offset = len;
}
// search the body of the text
let repeated_x = repeat_byte(x);
while offset >= 2 * usize_bytes {
unsafe {
let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
// break if there is a matching byte
let zu = contains_zero_byte(u ^ repeated_x);
let zv = contains_zero_byte(v ^ repeated_x);
if zu || zv {
break;
}
}
offset -= 2 * usize_bytes;
}
// find the byte before the point the body loop stopped
text[..offset].iter().rposition(|elt| *elt == x)
}
// test fallback implementations on all platforms
#[test]
fn matches_one() {
assert_eq!(Some(0), memchr(b'a', b"a"));
}
#[test]
fn matches_begin() {
assert_eq!(Some(0), memchr(b'a', b"aaaa"));
}
#[test]
fn matches_end() {
assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
}
#[test]
fn matches_nul() {
assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
}
#[test]
fn matches_past_nul() {
assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
}
#[test]
fn no_match_empty() {
assert_eq!(None, memchr(b'a', b""));
}
#[test]
fn no_match() {
assert_eq!(None, memchr(b'a', b"xyz"));
}
#[test]
fn matches_one_reversed() {
assert_eq!(Some(0), memrchr(b'a', b"a"));
}
#[test]
fn matches_begin_reversed() {
assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
}
#[test]
fn matches_end_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
}
#[test]
fn matches_nul_reversed() {
assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
}
#[test]
fn matches_past_nul_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
}
#[test]
fn no_match_empty_reversed() {
assert_eq!(None, memrchr(b'a', b""));
}
#[test]
fn no_match_reversed() {
assert_eq!(None, memrchr(b'a', b"xyz"));
}
#[test]
fn each_alignment_reversed() {
let mut data = [1u8; 64];
let needle = 2;
let pos = 40;
data[pos] = needle;
for start in 0..16 {
assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
}
}
}
#[cfg(test)]
mod tests {
// test the implementations for the current plattform
use super::{memchr, memrchr};
#[test]
fn matches_one() {
assert_eq!(Some(0), memchr(b'a', b"a"));
}
#[test]
fn matches_begin() {
assert_eq!(Some(0), memchr(b'a', b"aaaa"));
}
#[test]
fn matches_end() {
assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
}
#[test]
fn matches_nul() {
assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
}
#[test]
fn matches_past_nul() {
assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
}
#[test]
fn no_match_empty() {
assert_eq!(None, memchr(b'a', b""));
}
#[test]
fn no_match() {
assert_eq!(None, memchr(b'a', b"xyz"));
}
#[test]
fn matches_one_reversed() {
assert_eq!(Some(0), memrchr(b'a', b"a"));
}
#[test]
fn matches_begin_reversed() {
assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
}
#[test]
fn matches_end_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
}
#[test]
fn matches_nul_reversed() {
assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
}
#[test]
fn matches_past_nul_reversed() {
assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
}
#[test]
fn no_match_empty_reversed() {
assert_eq!(None, memrchr(b'a', b""));
}
#[test]
fn no_match_reversed() {
assert_eq!(None, memrchr(b'a', b"xyz"));
}
#[test]
fn each_alignment() {
let mut data = [1u8; 64];
let needle = 2;
let pos = 40;
data[pos] = needle;
for start in 0..16 {
assert_eq!(Some(pos - start), memchr(needle, &data[start..]));
}
}
}

1
std/src/prelude/mod.rs

@ -1 +0,0 @@
pub mod v1;

49
std/src/prelude/v1.rs

@ -1,49 +0,0 @@
// Copyright 2013 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.
//! The first version of the prelude of The Rust Standard Library.
// Reexported core operators
#[doc(no_inline)]
pub use marker::{Copy, Send, Sized, Sync};
#[doc(no_inline)]
pub use ops::{Drop, Fn, FnMut, FnOnce};
// Reexported functions
#[doc(no_inline)]
pub use mem::drop;
// Reexported types and traits
#[doc(no_inline)]
pub use boxed::Box;
#[doc(no_inline)]
pub use borrow::ToOwned;
#[doc(no_inline)]
pub use clone::Clone;
#[doc(no_inline)]
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)]
pub use convert::{AsRef, AsMut, Into, From};
#[doc(no_inline)]
pub use default::Default;
#[doc(no_inline)]
pub use iter::{Iterator, Extend, IntoIterator};
#[doc(no_inline)]
pub use iter::{DoubleEndedIterator, ExactSizeIterator};
#[doc(no_inline)]
pub use option::Option::{self, Some, None};
#[doc(no_inline)]
pub use result::Result::{self, Ok, Err};
#[doc(no_inline)]
pub use slice::SliceConcatExt;
#[doc(no_inline)]
pub use string::{String, ToString};
#[doc(no_inline)]
pub use vec::Vec;

5
std/src/sync/mod.rs

@ -1,5 +0,0 @@
mod mutex;
pub use self::mutex::{Mutex, MutexGuard};
pub type LockResult<T> = Result<T, ()>;

92
std/src/sync/mutex.rs

@ -1,92 +0,0 @@
use cell::UnsafeCell;
use borrow::{Borrow, BorrowMut};
use ops::{Deref, DerefMut};
use super::LockResult;
use libctru::synchronization::*;
/// A mutex based on libctru's LightLock primitive
pub struct Mutex<T: ?Sized> {
mutex: Box<LightLock>,
data: UnsafeCell<T>,
}
/// Mutex guard
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
inner: &'a Mutex<T>,
}
// NOTE: This is used when implementing condvar, which hasn't been done yet
#[allow(dead_code)]
pub fn guard_lock<'a, T: ?Sized + 'a>(guard: &'a MutexGuard<'a, T>) -> &'a LightLock {
&guard.inner.mutex
}
impl<T> Mutex<T> {
pub fn new(t: T) -> Mutex<T> {
unsafe {
let mut mutex = Box::new(0);
LightLock_Init(mutex.borrow_mut());
Mutex {
mutex: mutex,
data: UnsafeCell::new(t),
}
}
}
pub fn into_inner(self) -> T {
unsafe { self.data.into_inner() }
}
}
impl<T: ?Sized> Mutex<T> {
pub fn lock(&self) -> MutexGuard<T> {
unsafe {
LightLock_Lock(self.mutex.borrow());
MutexGuard { inner: self }
}
}
pub fn try_lock(&self) -> LockResult<MutexGuard<T>> {
unsafe {
let locked = LightLock_TryLock(self.mutex.borrow());
if locked == 0 {
Ok(MutexGuard { inner: self })
} else {
Err(())
}
}
}
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.data.get() }
}
}
unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
unsafe { LightLock_Unlock(self.inner.mutex.borrow());
}
}
}
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.inner.data.get() }
}
}
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.inner.data.get() }
}
}
impl<'a, T: ?Sized> !Send for MutexGuard<'a, T> {}

25
std/src/sys/mod.rs

@ -1,25 +0,0 @@
/// A trait for viewing representations from std types
#[doc(hidden)]
pub trait AsInner<Inner: ?Sized> {
fn as_inner(&self) -> &Inner;
}
/// A trait for viewing representations from std types
#[doc(hidden)]
pub trait AsInnerMut<Inner: ?Sized> {
fn as_inner_mut(&mut self) -> &mut Inner;
}
/// A trait for extracting representations from std types
#[doc(hidden)]
pub trait IntoInner<Inner> {
fn into_inner(self) -> Inner;
}
/// A trait for creating std types from internal representations
#[doc(hidden)]
pub trait FromInner<Inner> {
fn from_inner(inner: Inner) -> Self;
}
pub mod wtf8;

1204
std/src/sys/wtf8.rs

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save