aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFenrir <[email protected]>2017-01-19 01:30:05 -0700
committerFenrir <[email protected]>2017-01-21 17:44:58 -0700
commit08b71a18cd917724ee3d270d49a78e508a176e36 (patch)
treeb5eb42603929957f4bc826942e29b154c863003a
parentUpdate Cargo.toml (diff)
downloadctru-rs-08b71a18cd917724ee3d270d49a78e508a176e36.tar.xz
ctru-rs-08b71a18cd917724ee3d270d49a78e508a176e36.zip
We stdlib now
-rw-r--r--3ds.json5
-rw-r--r--Cargo.toml5
-rw-r--r--Xargo.toml12
-rw-r--r--build.rs4
-rw-r--r--ctr-libc/Cargo.toml14
-rw-r--r--ctr-libc/README.md1
-rw-r--r--ctr-libc/src/constants.rs122
-rw-r--r--ctr-libc/src/functions.rs39
-rw-r--r--ctr-libc/src/lib.rs190
-rw-r--r--ctr-std/3ds.json31
-rw-r--r--ctr-std/Cargo.toml13
-rw-r--r--ctr-std/README.md1
-rw-r--r--ctr-std/Xargo.toml6
-rw-r--r--ctr-std/src/ascii.rs (renamed from std/src/ascii.rs)30
-rw-r--r--ctr-std/src/error.rs (renamed from std/src/error.rs)53
-rw-r--r--ctr-std/src/f32.rs (renamed from std/src/num/f32.rs)181
-rw-r--r--ctr-std/src/f64.rs (renamed from std/src/num/f64.rs)216
-rw-r--r--ctr-std/src/ffi/c_str.rs (renamed from std/src/ffi/c_str.rs)74
-rw-r--r--ctr-std/src/ffi/mod.rs24
-rw-r--r--ctr-std/src/ffi/os_str.rs (renamed from std/src/ffi/os_str.rs)166
-rw-r--r--ctr-std/src/io/buffered.rs (renamed from std/src/io/buffered.rs)72
-rw-r--r--ctr-std/src/io/cursor.rs (renamed from std/src/io/cursor.rs)70
-rw-r--r--ctr-std/src/io/error.rs (renamed from std/src/io/error.rs)315
-rw-r--r--ctr-std/src/io/impls.rs (renamed from std/src/io/impls.rs)25
-rw-r--r--ctr-std/src/io/mod.rs (renamed from std/src/io/mod.rs)297
-rw-r--r--ctr-std/src/io/prelude.rs (renamed from std/src/io/prelude.rs)2
-rw-r--r--ctr-std/src/io/print.rs (renamed from std/src/io/print.rs)3
-rw-r--r--ctr-std/src/io/util.rs (renamed from std/src/io/util.rs)11
-rw-r--r--ctr-std/src/lib.rs174
-rw-r--r--ctr-std/src/macros.rs481
-rw-r--r--ctr-std/src/memchr.rs143
-rw-r--r--ctr-std/src/num.rs (renamed from std/src/num/mod.rs)44
-rw-r--r--ctr-std/src/os/mod.rs17
-rw-r--r--ctr-std/src/panicking.rs (renamed from std/src/panicking.rs)11
-rw-r--r--ctr-std/src/path.rs (renamed from std/src/path.rs)510
-rw-r--r--ctr-std/src/prelude/mod.rs146
-rw-r--r--ctr-std/src/prelude/v1.rs53
-rw-r--r--ctr-std/src/rt.rs (renamed from std/src/rt.rs)6
-rw-r--r--ctr-std/src/sync/mod.rs29
-rw-r--r--ctr-std/src/sys/mod.rs37
-rw-r--r--ctr-std/src/sys/unix/ext/ffi.rs61
-rw-r--r--ctr-std/src/sys/unix/ext/mod.rs41
-rw-r--r--ctr-std/src/sys/unix/memchr.rs51
-rw-r--r--ctr-std/src/sys/unix/mod.rs50
-rw-r--r--ctr-std/src/sys/unix/os.rs123
-rw-r--r--ctr-std/src/sys/unix/os_str.rs119
-rw-r--r--ctr-std/src/sys/unix/path.rs29
-rw-r--r--ctr-std/src/sys_common/io.rs179
-rw-r--r--ctr-std/src/sys_common/mod.rs76
-rw-r--r--ctru-sys/Cargo.toml5
-rw-r--r--ctru-sys/src/applets/mod.rs1
-rw-r--r--ctru-sys/src/applets/swkbd.rs258
-rw-r--r--ctru-sys/src/lib.rs7
-rw-r--r--ctru-sys/src/ndsp/channel.rs82
-rw-r--r--ctru-sys/src/ndsp/mod.rs2
-rw-r--r--ctru-sys/src/ndsp/ndsp.rs112
-rw-r--r--ctru-sys/src/os.rs62
-rw-r--r--ctru-sys/src/romfs.rs64
-rw-r--r--ctru-sys/src/sdmc.rs24
-rw-r--r--ctru-sys/src/services/apt.rs28
-rw-r--r--ctru-sys/src/services/mod.rs1
-rw-r--r--ctru-sys/src/services/nfc.rs6
-rw-r--r--ctru-sys/src/services/ps.rs2
-rw-r--r--ctru-sys/src/services/soc.rs2
-rw-r--r--ctru-sys/src/services/sslc.rs4
-rw-r--r--ctru-sys/src/svc.rs244
-rw-r--r--ctru-sys/src/sys/inaddr.rs6
-rw-r--r--ctru-sys/src/sys/libc.rs6
-rw-r--r--ctru-sys/src/sys/mod.rs3
-rw-r--r--ctru-sys/src/sys/socket.rs20
-rw-r--r--ctru-sys/src/types.rs4
-rw-r--r--src/lib.rs1
-rw-r--r--src/services/fs.rs15
-rw-r--r--std/Cargo.toml15
-rw-r--r--std/src/ffi/mod.rs5
-rw-r--r--std/src/lib.rs100
-rw-r--r--std/src/macros.rs105
-rw-r--r--std/src/memchr.rs397
-rw-r--r--std/src/prelude/mod.rs1
-rw-r--r--std/src/prelude/v1.rs49
-rw-r--r--std/src/sync/mod.rs5
-rw-r--r--std/src/sync/mutex.rs92
-rw-r--r--std/src/sys/mod.rs25
-rw-r--r--std/src/sys/wtf8.rs1204
84 files changed, 4569 insertions, 2750 deletions
diff --git a/3ds.json b/3ds.json
index fbdf65d..1f2484b 100644
--- a/3ds.json
+++ b/3ds.json
@@ -5,15 +5,16 @@
"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",
- "disable-redzone": true,
"executables": true,
- "no-compiler-rt": true,
"exe-suffix": ".elf",
+ "panic-strategy": "abort",
"pre-link-args": [
"-specs=3dsx.specs",
"-march=armv6k",
diff --git a/Cargo.toml b/Cargo.toml
index 81239fa..56c2a78 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,10 @@ crate-type = ["rlib"]
name = "ctru"
[dependencies.ctru-sys]
-path = "ctru-sys"
+path = "../ctru-sys"
[dependencies.bitflags]
version = "0.7.0"
+
+[dependencies.widestring]
+widestring = "0.2.2"
diff --git a/Xargo.toml b/Xargo.toml
index afe92d8..05f1470 100644
--- a/Xargo.toml
+++ b/Xargo.toml
@@ -1,2 +1,10 @@
-[target.3ds.dependencies]
-collections = {}
+[dependencies.collections]
+
+[dependencies.ctr-libc]
+path = "ctr-libc"
+default-features = false
+stage = 0
+
+[dependencies.std]
+path = "ctr-std"
+stage = 1
diff --git a/build.rs b/build.rs
index 6b07e4e..57ff190 100644
--- a/build.rs
+++ b/build.rs
@@ -4,12 +4,12 @@ use std::fs;
use std::option::Option::{self, Some, None};
-const ENV_DKP: &'static str = "CTRULIB";
+const ENV_DKP: &'static str = "DEVKITPRO";
fn find_libctru() -> Option<PathBuf> {
if let Ok(value) = env::var(ENV_DKP) {
let mut path = PathBuf::from(value);
- path.push("lib");
+ path.push("libctru/lib");
// metadata returns Err if the dir does not exist
if let Ok(metadata) = fs::metadata(path.as_path()) {
if metadata.is_dir() {
diff --git a/ctr-libc/Cargo.toml b/ctr-libc/Cargo.toml
new file mode 100644
index 0000000..5bc4c6b
--- /dev/null
+++ b/ctr-libc/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "ctr-libc"
+version = "0.1.0"
+authors = ["Fenrir <[email protected]>", "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 = []
diff --git a/ctr-libc/README.md b/ctr-libc/README.md
new file mode 100644
index 0000000..ce5eb41
--- /dev/null
+++ b/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.
diff --git a/ctr-libc/src/constants.rs b/ctr-libc/src/constants.rs
new file mode 100644
index 0000000..d007e53
--- /dev/null
+++ b/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;
diff --git a/ctr-libc/src/functions.rs b/ctr-libc/src/functions.rs
new file mode 100644
index 0000000..a0d21ac
--- /dev/null
+++ b/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;
+}
diff --git a/ctr-libc/src/lib.rs b/ctr-libc/src/lib.rs
new file mode 100644
index 0000000..729a38d
--- /dev/null
+++ b/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 }
+}
diff --git a/ctr-std/3ds.json b/ctr-std/3ds.json
new file mode 100644
index 0000000..bdd5caa
--- /dev/null
+++ b/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"
+ ]
+}
diff --git a/ctr-std/Cargo.toml b/ctr-std/Cargo.toml
new file mode 100644
index 0000000..dfd5037
--- /dev/null
+++ b/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"
diff --git a/ctr-std/README.md b/ctr-std/README.md
new file mode 100644
index 0000000..604a43c
--- /dev/null
+++ b/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.
diff --git a/ctr-std/Xargo.toml b/ctr-std/Xargo.toml
new file mode 100644
index 0000000..3bc68c1
--- /dev/null
+++ b/ctr-std/Xargo.toml
@@ -0,0 +1,6 @@
+[dependencies.collections]
+
+[dependencies.ctr-libc]
+path = "../ctr-libc"
+default-features = false
+stage = 1
diff --git a/std/src/ascii.rs b/ctr-std/src/ascii.rs
index 5424921..a063b85 100644
--- a/std/src/ascii.rs
+++ b/ctr-std/src/ascii.rs
@@ -10,8 +10,11 @@
//! Operations on ASCII strings and characters.
+#![stable(feature = "rust1", since = "1.0.0")]
+
use mem;
use ops::Range;
+use iter::FusedIterator;
/// 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}"`.
///
/// [combining character]: https://en.wikipedia.org/wiki/Combining_character
+#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsciiExt {
/// Container type for copied ASCII characters.
+ #[stable(feature = "rust1", since = "1.0.0")]
type Owned;
/// Checks if the value is within the ASCII range.
@@ -52,6 +57,7 @@ pub trait AsciiExt {
/// assert!(ascii.is_ascii());
/// assert!(!utf8.is_ascii());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn is_ascii(&self) -> bool;
/// 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!('❤', utf8.to_ascii_uppercase());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn to_ascii_uppercase(&self) -> Self::Owned;
/// 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!('❤', utf8.to_ascii_lowercase());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn to_ascii_lowercase(&self) -> Self::Owned;
/// 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(&ascii4));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
/// Converts this type to its ASCII upper case equivalent in-place.
@@ -126,6 +135,7 @@ pub trait AsciiExt {
///
/// assert_eq!('A', ascii);
/// ```
+ #[stable(feature = "ascii", since = "1.9.0")]
fn make_ascii_uppercase(&mut self);
/// Converts this type to its ASCII lower case equivalent in-place.
@@ -143,9 +153,11 @@ pub trait AsciiExt {
///
/// assert_eq!('a', ascii);
/// ```
+ #[stable(feature = "ascii", since = "1.9.0")]
fn make_ascii_lowercase(&mut self);
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for str {
type Owned = String;
@@ -186,6 +198,7 @@ impl AsciiExt for str {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for [u8] {
type Owned = Vec<u8>;
#[inline]
@@ -228,6 +241,7 @@ impl AsciiExt for [u8] {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for u8 {
type Owned = u8;
#[inline]
@@ -246,6 +260,7 @@ impl AsciiExt for u8 {
fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for char {
type Owned = char;
#[inline]
@@ -284,6 +299,7 @@ impl AsciiExt for char {
/// An iterator over the escaped version of a byte, constructed via
/// `std::ascii::escape_default`.
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct EscapeDefault {
range: Range<usize>,
data: [u8; 4],
@@ -314,6 +330,7 @@ pub struct EscapeDefault {
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b't', escaped.next().unwrap());
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn escape_default(c: u8) -> EscapeDefault {
let (data, len) = match c {
b'\t' => ([b'\\', b't', 0, 0], 2),
@@ -336,17 +353,23 @@ pub fn escape_default(c: u8) -> EscapeDefault {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for EscapeDefault {
type Item = u8;
fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
fn next_back(&mut self) -> Option<u8> {
self.range.next_back().map(|i| self.data[i])
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {}
+#[unstable(feature = "fused", issue = "35602")]
+impl FusedIterator for EscapeDefault {}
+
static ASCII_LOWERCASE_MAP: [u8; 256] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -430,8 +453,7 @@ static ASCII_UPPERCASE_MAP: [u8; 256] = [
#[cfg(test)]
mod tests {
use super::*;
- use std_unicode::char::from_u32;
- use collections::string::ToString;
+ use char::from_u32;
#[test]
fn test_is_ascii() {
@@ -446,9 +468,7 @@ mod tests {
assert!("banana\0\u{7F}".is_ascii());
assert!("banana\0\u{7F}".chars().all(|c| c.is_ascii()));
assert!(!"ประเทศไทย中华Việt Nam".chars().all(|c| c.is_ascii()));
-
- // NOTE: This test fails for some reason.
- assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
+ assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
}
#[test]
diff --git a/std/src/error.rs b/ctr-std/src/error.rs
index 5beae2f..454fa47 100644
--- a/std/src/error.rs
+++ b/ctr-std/src/error.rs
@@ -38,6 +38,8 @@
//! [`Display`]: ../fmt/trait.Display.html
//! [`cause`]: trait.Error.html#method.cause
+#![stable(feature = "rust1", since = "1.0.0")]
+
// A note about crates and the facade:
//
// Originally, the `Error` trait was defined in libcore, and the impls
@@ -59,12 +61,17 @@ use str;
use string;
/// Base functionality for all errors in Rust.
+#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display {
/// A short description of the error.
///
- /// The description should not contain newlines or sentence-ending
- /// punctuation, to facilitate embedding in larger user-facing
- /// strings.
+ /// The description should only be used for a simple message.
+ /// It should not contain newlines or sentence-ending punctuation,
+ /// to facilitate embedding in larger user-facing strings.
+ /// For showing formatted error messages with more information see
+ /// [`Display`].
+ ///
+ /// [`Display`]: ../fmt/trait.Display.html
///
/// # Examples
///
@@ -78,6 +85,7 @@ pub trait Error: Debug + Display {
/// _ => println!("No error"),
/// }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn description(&self) -> &str;
/// 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 }
/// Get the `TypeId` of `self`
#[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 {
TypeId::of::<Self>()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
fn from(err: E) -> Box<Error + 'a> {
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> {
fn from(err: E) -> Box<Error + Send + Sync + 'a> {
Box::new(err)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for Box<Error + Send + Sync> {
fn from(err: String) -> Box<Error + Send + Sync> {
#[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> {
fn from(str_err: String) -> Box<Error> {
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> {
fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
From::from(String::from(err))
}
}
+#[stable(feature = "string_box_error", since = "1.7.0")]
impl<'a> From<&'a str> for Box<Error> {
fn from(err: &'a str) -> Box<Error> {
From::from(String::from(err))
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for str::ParseBoolError {
fn description(&self) -> &str { "failed to parse bool" }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for str::Utf8Error {
fn description(&self) -> &str {
"invalid utf-8: corrupt contents"
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for num::ParseIntError {
fn description(&self) -> &str {
self.__description()
}
}
+#[unstable(feature = "try_from", issue = "33417")]
impl Error for num::TryFromIntError {
fn description(&self) -> &str {
self.__description()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for num::ParseFloatError {
fn description(&self) -> &str {
self.__description()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for string::FromUtf8Error {
fn description(&self) -> &str {
"invalid utf-8"
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for string::FromUtf16Error {
fn description(&self) -> &str {
"invalid utf-16"
}
}
+#[stable(feature = "str_parse_error2", since = "1.8.0")]
impl Error for string::ParseError {
fn description(&self) -> &str {
match *self {}
}
}
+#[stable(feature = "decode_utf16", since = "1.9.0")]
impl Error for char::DecodeUtf16Error {
fn description(&self) -> &str {
"unpaired surrogate found"
}
}
+#[stable(feature = "box_error", since = "1.7.0")]
impl<T: Error> Error for Box<T> {
fn description(&self) -> &str {
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 {
fn description(&self) -> &str {
"an error occurred when formatting an argument"
}
}
+#[stable(feature = "try_borrow", since = "1.13.0")]
impl Error for cell::BorrowError {
fn description(&self) -> &str {
"already mutably borrowed"
}
}
+#[stable(feature = "try_borrow", since = "1.13.0")]
impl Error for cell::BorrowMutError {
fn description(&self) -> &str {
"already borrowed"
}
}
+#[unstable(feature = "try_from", issue = "33417")]
impl Error for char::CharTryFromError {
fn description(&self) -> &str {
"converted integer out of range for `char`"
@@ -287,6 +319,7 @@ impl Error for char::CharTryFromError {
// copied from any.rs
impl Error + 'static {
/// Returns true if the boxed type is the same as `T`
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn is<T: Error + 'static>(&self) -> bool {
// 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
/// `None` if it isn't.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&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
/// `None` if it isn't.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
@@ -328,18 +363,21 @@ impl Error + 'static {
impl Error + 'static + Send {
/// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn is<T: Error + 'static>(&self) -> bool {
<Error + 'static>::is::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
<Error + 'static>::downcast_ref::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
<Error + 'static>::downcast_mut::<T>(self)
@@ -348,18 +386,21 @@ impl Error + 'static + Send {
impl Error + 'static + Send + Sync {
/// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn is<T: Error + 'static>(&self) -> bool {
<Error + 'static>::is::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
<Error + 'static>::downcast_ref::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
<Error + 'static>::downcast_mut::<T>(self)
@@ -368,6 +409,7 @@ impl Error + 'static + Send + Sync {
impl Error {
#[inline]
+ #[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> {
if self.is::<T>() {
@@ -383,6 +425,7 @@ impl Error {
impl Error + Send {
#[inline]
+ #[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>)
-> Result<Box<T>, Box<Error + Send>> {
@@ -396,6 +439,7 @@ impl Error + Send {
impl Error + Send + Sync {
#[inline]
+ #[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>)
-> Result<Box<T>, Box<Self>> {
@@ -410,8 +454,7 @@ impl Error + Send + Sync {
#[cfg(test)]
mod tests {
use super::Error;
- use core::fmt;
- use alloc::boxed::Box;
+ use fmt;
#[derive(Debug, PartialEq)]
struct A;
diff --git a/std/src/num/f32.rs b/ctr-std/src/f32.rs
index f1cfe5a..7a676c0 100644
--- a/std/src/num/f32.rs
+++ b/ctr-std/src/f32.rs
@@ -12,6 +12,7 @@
//!
//! *[See also the `f32` primitive type](../primitive.f32.html).*
+#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
#[cfg(not(test))]
@@ -19,22 +20,27 @@ use core::num;
#[cfg(not(test))]
use intrinsics;
#[cfg(not(test))]
-use libctru::libc::c_int;
+use libc::c_int;
#[cfg(not(test))]
use num::FpCategory;
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::{MIN, MIN_POSITIVE, MAX};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f32::consts;
#[allow(dead_code)]
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 erff(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
// here.
#[cfg(not(target_env = "msvc"))]
- extern "C" {
+ extern {
pub fn acosf(n: c_float) -> c_float;
pub fn asinf(n: 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::*;
#[cfg(target_env = "msvc")]
mod shims {
- use libctru::libc::{c_float, c_int};
+ use libc::{c_float, c_int};
#[inline]
pub unsafe fn acosf(n: c_float) -> c_float {
@@ -148,10 +154,9 @@ impl f32 {
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_nan(self) -> bool {
- num::Float::is_nan(self)
- }
+ pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
@@ -170,10 +175,9 @@ impl f32 {
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_infinite(self) -> bool {
- num::Float::is_infinite(self)
- }
+ pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
/// Returns `true` if this number is neither infinite nor `NaN`.
///
@@ -191,10 +195,9 @@ impl f32 {
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_finite(self) -> bool {
- num::Float::is_finite(self)
- }
+ pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
@@ -217,10 +220,9 @@ impl f32 {
/// assert!(!lower_than_min.is_normal());
/// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_normal(self) -> bool {
- num::Float::is_normal(self)
- }
+ pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
/// 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
@@ -236,10 +238,9 @@ impl f32 {
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn classify(self) -> FpCategory {
- num::Float::classify(self)
- }
+ pub fn classify(self) -> FpCategory { num::Float::classify(self) }
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
@@ -264,6 +265,11 @@ impl f32 {
/// assert!(abs_difference <= f32::EPSILON);
/// ```
/// [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]
#[allow(deprecated)]
pub fn integer_decode(self) -> (u64, i16, i8) {
@@ -279,6 +285,7 @@ impl f32 {
/// assert_eq!(f.floor(), 3.0);
/// assert_eq!(g.floor(), 3.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn floor(self) -> f32 {
// 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!(g.ceil(), 4.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ceil(self) -> f32 {
// see notes above in `floor`
@@ -328,6 +336,7 @@ impl f32 {
/// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn round(self) -> f32 {
unsafe { intrinsics::roundf32(self) }
@@ -342,6 +351,7 @@ impl f32 {
/// assert_eq!(f.trunc(), 3.0);
/// assert_eq!(g.trunc(), -3.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn trunc(self) -> f32 {
unsafe { intrinsics::truncf32(self) }
@@ -360,10 +370,9 @@ impl f32 {
/// assert!(abs_difference_x <= f32::EPSILON);
/// assert!(abs_difference_y <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn fract(self) -> f32 {
- self - self.trunc()
- }
+ pub fn fract(self) -> f32 { self - self.trunc() }
/// Computes the absolute value of `self`. Returns `NAN` if the
/// number is `NAN`.
@@ -382,10 +391,9 @@ impl f32 {
///
/// assert!(f32::NAN.abs().is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn abs(self) -> f32 {
- num::Float::abs(self)
- }
+ pub fn abs(self) -> f32 { num::Float::abs(self) }
/// Returns a number that represents the sign of `self`.
///
@@ -403,10 +411,9 @@ impl f32 {
///
/// assert!(f32::NAN.signum().is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn signum(self) -> f32 {
- num::Float::signum(self)
- }
+ pub fn signum(self) -> f32 { num::Float::signum(self) }
/// Returns `true` if `self`'s sign bit is positive, including
/// `+0.0` and `INFINITY`.
@@ -423,10 +430,9 @@ impl f32 {
/// // Requires both tests to determine if is `NaN`
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_sign_positive(self) -> bool {
- num::Float::is_sign_positive(self)
- }
+ pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
/// Returns `true` if `self`'s sign is negative, including `-0.0`
/// and `NEG_INFINITY`.
@@ -443,10 +449,9 @@ impl f32 {
/// // Requires both tests to determine if is `NaN`.
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_sign_negative(self) -> bool {
- num::Float::is_sign_negative(self)
- }
+ pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
@@ -464,6 +469,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn mul_add(self, a: f32, b: f32) -> f32 {
unsafe { intrinsics::fmaf32(self, a, b) }
@@ -479,10 +485,9 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn recip(self) -> f32 {
- num::Float::recip(self)
- }
+ pub fn recip(self) -> f32 { num::Float::recip(self) }
/// Raises a number to an integer power.
///
@@ -496,10 +501,9 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn powi(self, n: i32) -> f32 {
- num::Float::powi(self, n)
- }
+ pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
/// Raises a number to a floating point power.
///
@@ -511,6 +515,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn powf(self, n: f32) -> f32 {
// see notes above in `floor`
@@ -535,6 +540,7 @@ impl f32 {
/// assert!(abs_difference <= f32::EPSILON);
/// assert!(negative.sqrt().is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sqrt(self) -> f32 {
if self < 0.0 {
@@ -558,6 +564,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp(self) -> f32 {
// see notes above in `floor`
@@ -579,6 +586,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp2(self) -> f32 {
unsafe { intrinsics::exp2f32(self) }
@@ -598,6 +606,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln(self) -> f32 {
// see notes above in `floor`
@@ -624,10 +633,9 @@ impl f32 {
/// assert!(abs_difference_10 <= f32::EPSILON);
/// assert!(abs_difference_2 <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn log(self, base: f32) -> f32 {
- self.ln() / base.ln()
- }
+ pub fn log(self, base: f32) -> f32 { self.ln() / base.ln() }
/// Returns the base 2 logarithm of the number.
///
@@ -641,6 +649,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log2(self) -> f32 {
#[cfg(target_os = "android")]
@@ -661,6 +670,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log10(self) -> f32 {
// see notes above in `floor`
@@ -681,10 +691,9 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
- pub fn to_degrees(self) -> f32 {
- num::Float::to_degrees(self)
- }
+ pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
/// Converts degrees to radians.
///
@@ -697,10 +706,9 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
#[inline]
- pub fn to_radians(self) -> f32 {
- num::Float::to_radians(self)
- }
+ pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
/// Constructs a floating point number of `x*2^exp`.
///
@@ -713,6 +721,12 @@ impl f32 {
///
/// 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]
pub fn ldexp(x: f32, exp: isize) -> f32 {
unsafe { cmath::ldexpf(x, exp as c_int) }
@@ -739,6 +753,12 @@ impl f32 {
/// assert!(abs_difference_0 <= 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]
pub fn frexp(self) -> (f32, isize) {
unsafe {
@@ -762,6 +782,12 @@ impl f32 {
///
/// 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]
pub fn next_after(self, other: f32) -> f32 {
unsafe { cmath::nextafterf(self, other) }
@@ -777,6 +803,7 @@ impl f32 {
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f32) -> f32 {
unsafe { cmath::fmaxf(self, other) }
@@ -792,6 +819,7 @@ impl f32 {
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f32) -> f32 {
unsafe { cmath::fminf(self, other) }
@@ -814,6 +842,15 @@ impl f32 {
/// assert!(abs_difference_x <= 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 {
unsafe { cmath::fdimf(self, other) }
}
@@ -830,6 +867,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cbrt(self) -> f32 {
unsafe { cmath::cbrtf(self) }
@@ -849,6 +887,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn hypot(self, other: f32) -> f32 {
unsafe { cmath::hypotf(self, other) }
@@ -865,6 +904,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sin(self) -> f32 {
// see notes in `core::f32::Float::floor`
@@ -885,6 +925,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cos(self) -> f32 {
// see notes in `core::f32::Float::floor`
@@ -904,6 +945,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tan(self) -> f32 {
unsafe { cmath::tanf(self) }
@@ -923,6 +965,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asin(self) -> f32 {
unsafe { cmath::asinf(self) }
@@ -942,6 +985,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acos(self) -> f32 {
unsafe { cmath::acosf(self) }
@@ -960,6 +1004,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan(self) -> f32 {
unsafe { cmath::atanf(self) }
@@ -991,6 +1036,7 @@ impl f32 {
/// assert!(abs_difference_1 <= f32::EPSILON);
/// assert!(abs_difference_2 <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan2(self, other: f32) -> f32 {
unsafe { cmath::atan2f(self, other) }
@@ -1011,6 +1057,7 @@ impl f32 {
/// assert!(abs_difference_0 <= f32::EPSILON);
/// assert!(abs_difference_1 <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sin_cos(self) -> (f32, f32) {
(self.sin(), self.cos())
@@ -1029,6 +1076,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp_m1(self) -> f32 {
unsafe { cmath::expm1f(self) }
@@ -1047,6 +1095,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln_1p(self) -> f32 {
unsafe { cmath::log1pf(self) }
@@ -1067,6 +1116,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sinh(self) -> f32 {
unsafe { cmath::sinhf(self) }
@@ -1087,6 +1137,7 @@ impl f32 {
/// // Same result
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cosh(self) -> f32 {
unsafe { cmath::coshf(self) }
@@ -1107,6 +1158,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tanh(self) -> f32 {
unsafe { cmath::tanhf(self) }
@@ -1124,6 +1176,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asinh(self) -> f32 {
if self == NEG_INFINITY {
@@ -1145,6 +1198,7 @@ impl f32 {
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acosh(self) -> f32 {
match self {
@@ -1165,6 +1219,7 @@ impl f32 {
///
/// assert!(abs_difference <= 1e-5);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atanh(self) -> f32 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
@@ -1438,7 +1493,7 @@ mod tests {
assert_eq!((-0f32).abs(), 0f32);
assert_eq!((-1f32).abs(), 1f32);
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());
}
@@ -1450,7 +1505,7 @@ mod tests {
assert_eq!((-0f32).signum(), -1f32);
assert_eq!((-1f32).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());
}
@@ -1462,7 +1517,7 @@ mod tests {
assert!(!(-0f32).is_sign_positive());
assert!(!(-1f32).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());
}
@@ -1474,7 +1529,7 @@ mod tests {
assert!((-0f32).is_sign_negative());
assert!((-1f32).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());
}
@@ -1712,25 +1767,15 @@ mod tests {
assert_eq!((-0f32).frexp(), (-0f32, 0));
}
- #[test]
- #[cfg_attr(windows, ignore)]
- // FIXME #8755
+ #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
#[allow(deprecated)]
fn test_frexp_nowin() {
let inf: f32 = f32::INFINITY;
let neg_inf: f32 = f32::NEG_INFINITY;
let nan: f32 = f32::NAN;
- assert_eq!(match inf.frexp() {
- (x, _) => x,
- },
- inf);
- assert_eq!(match neg_inf.frexp() {
- (x, _) => x,
- },
- neg_inf);
- assert!(match nan.frexp() {
- (x, _) => x.is_nan(),
- })
+ assert_eq!(match inf.frexp() { (x, _) => x }, inf);
+ assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
+ assert!(match nan.frexp() { (x, _) => x.is_nan() })
}
#[test]
diff --git a/std/src/num/f64.rs b/ctr-std/src/f64.rs
index 2f23dbe..67a1c30 100644
--- a/std/src/num/f64.rs
+++ b/ctr-std/src/f64.rs
@@ -2,8 +2,9 @@
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
-// Licensed under the Apache License, Version 2.0 or the MIT license
-// , at your
+// 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.
@@ -11,29 +12,35 @@
//!
//! *[See also the `f64` primitive type](../primitive.f64.html).*
+#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
#[cfg(not(test))]
use core::num;
#[cfg(not(test))]
-use core::intrinsics;
+use intrinsics;
#[cfg(not(test))]
-use libctru::libc::c_int;
+use libc::c_int;
#[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};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::{MIN, MIN_POSITIVE, MAX};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::f64::consts;
#[allow(dead_code)]
mod cmath {
- use libctru::libc::{c_double, c_int};
+ use libc::{c_double, c_int};
#[link_name = "m"]
- extern "C" {
+ extern {
pub fn acos(n: c_double) -> c_double;
pub fn asin(n: c_double) -> c_double;
pub fn atan(n: c_double) -> c_double;
@@ -91,10 +98,9 @@ impl f64 {
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_nan(self) -> bool {
- num::Float::is_nan(self)
- }
+ pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
@@ -113,10 +119,9 @@ impl f64 {
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_infinite(self) -> bool {
- num::Float::is_infinite(self)
- }
+ pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
/// Returns `true` if this number is neither infinite nor `NaN`.
///
@@ -134,10 +139,9 @@ impl f64 {
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_finite(self) -> bool {
- num::Float::is_finite(self)
- }
+ pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
@@ -160,10 +164,9 @@ impl f64 {
/// assert!(!lower_than_min.is_normal());
/// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_normal(self) -> bool {
- num::Float::is_normal(self)
- }
+ pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
/// 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
@@ -179,10 +182,9 @@ impl f64 {
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn classify(self) -> FpCategory {
- num::Float::classify(self)
- }
+ pub fn classify(self) -> FpCategory { num::Float::classify(self) }
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
@@ -205,11 +207,14 @@ impl f64 {
/// assert!(abs_difference < 1e-10);
/// ```
/// [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]
#[allow(deprecated)]
- pub fn integer_decode(self) -> (u64, i16, i8) {
- num::Float::integer_decode(self)
- }
+ pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
/// 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!(g.floor(), 3.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn floor(self) -> f64 {
unsafe { intrinsics::floorf64(self) }
@@ -234,6 +240,7 @@ impl f64 {
/// assert_eq!(f.ceil(), 4.0);
/// assert_eq!(g.ceil(), 4.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ceil(self) -> f64 {
unsafe { intrinsics::ceilf64(self) }
@@ -249,6 +256,7 @@ impl f64 {
/// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn round(self) -> f64 {
unsafe { intrinsics::roundf64(self) }
@@ -263,6 +271,7 @@ impl f64 {
/// assert_eq!(f.trunc(), 3.0);
/// assert_eq!(g.trunc(), -3.0);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn trunc(self) -> f64 {
unsafe { intrinsics::truncf64(self) }
@@ -279,10 +288,9 @@ impl f64 {
/// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn fract(self) -> f64 {
- self - self.trunc()
- }
+ pub fn fract(self) -> f64 { self - self.trunc() }
/// Computes the absolute value of `self`. Returns `NAN` if the
/// number is `NAN`.
@@ -301,10 +309,9 @@ impl f64 {
///
/// assert!(f64::NAN.abs().is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn abs(self) -> f64 {
- num::Float::abs(self)
- }
+ pub fn abs(self) -> f64 { num::Float::abs(self) }
/// Returns a number that represents the sign of `self`.
///
@@ -322,10 +329,9 @@ impl f64 {
///
/// assert!(f64::NAN.signum().is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn signum(self) -> f64 {
- num::Float::signum(self)
- }
+ pub fn signum(self) -> f64 { num::Float::signum(self) }
/// Returns `true` if `self`'s sign bit is positive, including
/// `+0.0` and `INFINITY`.
@@ -343,15 +349,14 @@ impl f64 {
/// // Requires both tests to determine if is `NaN`
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_sign_positive(self) -> bool {
- num::Float::is_sign_positive(self)
- }
+ pub fn is_sign_positive(self) -> bool { 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]
- pub fn is_positive(self) -> bool {
- num::Float::is_sign_positive(self)
- }
+ pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
/// Returns `true` if `self`'s sign is negative, including `-0.0`
/// and `NEG_INFINITY`.
@@ -369,15 +374,14 @@ impl f64 {
/// // Requires both tests to determine if is `NaN`.
/// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn is_sign_negative(self) -> bool {
- num::Float::is_sign_negative(self)
- }
+ pub fn is_sign_negative(self) -> bool { 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]
- pub fn is_negative(self) -> bool {
- num::Float::is_sign_negative(self)
- }
+ pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) }
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
@@ -393,6 +397,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn mul_add(self, a: f64, b: f64) -> f64 {
unsafe { intrinsics::fmaf64(self, a, b) }
@@ -406,10 +411,9 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn recip(self) -> f64 {
- num::Float::recip(self)
- }
+ pub fn recip(self) -> f64 { num::Float::recip(self) }
/// Raises a number to an integer power.
///
@@ -421,10 +425,9 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn powi(self, n: i32) -> f64 {
- num::Float::powi(self, n)
- }
+ pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
/// Raises a number to a floating point power.
///
@@ -434,6 +437,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn powf(self, n: f64) -> f64 {
unsafe { intrinsics::powf64(self, n) }
@@ -452,6 +456,7 @@ impl f64 {
/// assert!(abs_difference < 1e-10);
/// assert!(negative.sqrt().is_nan());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sqrt(self) -> f64 {
if self < 0.0 {
@@ -473,6 +478,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp(self) -> f64 {
unsafe { intrinsics::expf64(self) }
@@ -488,6 +494,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp2(self) -> f64 {
unsafe { intrinsics::exp2f64(self) }
@@ -505,6 +512,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln(self) -> f64 {
self.log_wrapper(|n| { unsafe { intrinsics::logf64(n) } })
@@ -525,10 +533,9 @@ impl f64 {
/// assert!(abs_difference_10 < 1e-10);
/// assert!(abs_difference_2 < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn log(self, base: f64) -> f64 {
- self.ln() / base.ln()
- }
+ pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() }
/// Returns the base 2 logarithm of the number.
///
@@ -540,9 +547,13 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log2(self) -> f64 {
self.log_wrapper(|n| {
+ #[cfg(target_os = "android")]
+ return ::sys::android::log2f64(n);
+ #[cfg(not(target_os = "android"))]
return unsafe { intrinsics::log2f64(n) };
})
}
@@ -557,6 +568,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log10(self) -> f64 {
self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
@@ -573,10 +585,9 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn to_degrees(self) -> f64 {
- num::Float::to_degrees(self)
- }
+ pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
/// Converts degrees to radians.
///
@@ -589,10 +600,9 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn to_radians(self) -> f64 {
- num::Float::to_radians(self)
- }
+ pub fn to_radians(self) -> f64 { num::Float::to_radians(self) }
/// Constructs a floating point number of `x*2^exp`.
///
@@ -604,6 +614,12 @@ impl f64 {
///
/// 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]
pub fn ldexp(x: f64, exp: isize) -> f64 {
unsafe { cmath::ldexp(x, exp as c_int) }
@@ -628,6 +644,12 @@ impl f64 {
/// assert!(abs_difference_0 < 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]
pub fn frexp(self) -> (f64, isize) {
unsafe {
@@ -649,6 +671,12 @@ impl f64 {
///
/// 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]
pub fn next_after(self, other: f64) -> f64 {
unsafe { cmath::nextafter(self, other) }
@@ -664,6 +692,7 @@ impl f64 {
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f64) -> f64 {
unsafe { cmath::fmax(self, other) }
@@ -679,6 +708,7 @@ impl f64 {
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f64) -> f64 {
unsafe { cmath::fmin(self, other) }
@@ -699,10 +729,18 @@ impl f64 {
/// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
- pub fn abs_sub(self, other: f64) -> f64 {
- unsafe { cmath::fdim(self, other) }
- }
+ #[rustc_deprecated(since = "1.10.0",
+ 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.
///
@@ -714,6 +752,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cbrt(self) -> f64 {
unsafe { cmath::cbrt(self) }
@@ -731,6 +770,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn hypot(self, other: f64) -> f64 {
unsafe { cmath::hypot(self, other) }
@@ -747,6 +787,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sin(self) -> f64 {
unsafe { intrinsics::sinf64(self) }
@@ -763,6 +804,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cos(self) -> f64 {
unsafe { intrinsics::cosf64(self) }
@@ -778,6 +820,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-14);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tan(self) -> f64 {
unsafe { cmath::tan(self) }
@@ -797,6 +840,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asin(self) -> f64 {
unsafe { cmath::asin(self) }
@@ -816,6 +860,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acos(self) -> f64 {
unsafe { cmath::acos(self) }
@@ -832,6 +877,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan(self) -> f64 {
unsafe { cmath::atan(self) }
@@ -863,6 +909,7 @@ impl f64 {
/// assert!(abs_difference_1 < 1e-10);
/// assert!(abs_difference_2 < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atan2(self, other: f64) -> f64 {
unsafe { cmath::atan2(self, other) }
@@ -883,6 +930,7 @@ impl f64 {
/// assert!(abs_difference_0 < 1e-10);
/// assert!(abs_difference_1 < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sin_cos(self) -> (f64, f64) {
(self.sin(), self.cos())
@@ -899,6 +947,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn exp_m1(self) -> f64 {
unsafe { cmath::expm1(self) }
@@ -917,6 +966,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln_1p(self) -> f64 {
unsafe { cmath::log1p(self) }
@@ -937,6 +987,7 @@ impl f64 {
///
/// assert!(abs_difference < 1e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn sinh(self) -> f64 {
unsafe { cmath::sinh(self) }
@@ -957,6 +1008,7 @@ impl f64 {
/// // Same result
/// assert!(abs_difference < 1.0e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn cosh(self) -> f64 {
unsafe { cmath::cosh(self) }
@@ -977,6 +1029,7 @@ impl f64 {
///
/// assert!(abs_difference < 1.0e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn tanh(self) -> f64 {
unsafe { cmath::tanh(self) }
@@ -992,6 +1045,7 @@ impl f64 {
///
/// assert!(abs_difference < 1.0e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn asinh(self) -> f64 {
if self == NEG_INFINITY {
@@ -1011,6 +1065,7 @@ impl f64 {
///
/// assert!(abs_difference < 1.0e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn acosh(self) -> f64 {
match self {
@@ -1031,6 +1086,7 @@ impl f64 {
///
/// assert!(abs_difference < 1.0e-10);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn atanh(self) -> f64 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
@@ -1236,10 +1292,8 @@ mod tests {
#[test]
#[allow(deprecated)]
fn test_integer_decode() {
- assert_eq!(3.14159265359f64.integer_decode(),
- (7074237752028906, -51, 1));
- assert_eq!((-8573.5918555f64).integer_decode(),
- (4713381968463931, -39, -1));
+ assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1));
+ assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -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));
@@ -1330,7 +1384,7 @@ mod tests {
assert_eq!((-0f64).abs(), 0f64);
assert_eq!((-1f64).abs(), 1f64);
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());
}
@@ -1342,7 +1396,7 @@ mod tests {
assert_eq!((-0f64).signum(), -1f64);
assert_eq!((-1f64).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());
}
@@ -1354,7 +1408,7 @@ mod tests {
assert!(!(-0f64).is_sign_positive());
assert!(!(-1f64).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());
}
@@ -1366,7 +1420,7 @@ mod tests {
assert!((-0f64).is_sign_negative());
assert!((-1f64).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());
}
@@ -1604,25 +1658,15 @@ mod tests {
assert_eq!((-0f64).frexp(), (-0f64, 0));
}
- #[test]
- #[cfg_attr(windows, ignore)]
- // FIXME #8755
+ #[test] #[cfg_attr(windows, ignore)] // FIXME #8755
#[allow(deprecated)]
fn test_frexp_nowin() {
let inf: f64 = INFINITY;
let neg_inf: f64 = NEG_INFINITY;
let nan: f64 = NAN;
- assert_eq!(match inf.frexp() {
- (x, _) => x,
- },
- inf);
- assert_eq!(match neg_inf.frexp() {
- (x, _) => x,
- },
- neg_inf);
- assert!(match nan.frexp() {
- (x, _) => x.is_nan(),
- })
+ assert_eq!(match inf.frexp() { (x, _) => x }, inf);
+ assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
+ assert!(match nan.frexp() { (x, _) => x.is_nan() })
}
#[test]
diff --git a/std/src/ffi/c_str.rs b/ctr-std/src/ffi/c_str.rs
index 159c683..ad40660 100644
--- a/std/src/ffi/c_str.rs
+++ b/ctr-std/src/ffi/c_str.rs
@@ -14,7 +14,7 @@ use cmp::Ordering;
use error::Error;
use fmt::{self, Write};
use io;
-use libctru::libc::{self, c_char};
+use libc::{self, c_char};
use mem;
use memchr;
use ops;
@@ -66,6 +66,7 @@ use str::{self, Utf8Error};
/// and other memory errors.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
// 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.
@@ -133,6 +134,7 @@ pub struct CString {
/// println!("string: {}", my_string_safe());
/// ```
#[derive(Hash)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct CStr {
// 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
@@ -144,16 +146,19 @@ pub struct CStr {
/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Eq, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);
/// 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.
#[derive(Clone, PartialEq, Eq, Debug)]
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub struct FromBytesWithNulError { _a: () }
/// An error returned from `CString::into_string` to indicate that a UTF-8 error
/// was encountered during the conversion.
#[derive(Clone, PartialEq, Eq, Debug)]
+#[stable(feature = "cstring_into", since = "1.7.0")]
pub struct IntoStringError {
inner: CString,
error: Utf8Error,
@@ -184,6 +189,7 @@ impl CString {
/// 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
/// 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> {
Self::_new(t.into())
}
@@ -212,6 +218,7 @@ impl CString {
/// 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 {
v.reserve_exact(1);
v.push(0);
@@ -228,6 +235,7 @@ impl CString {
/// 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
/// to undefined behavior or allocator corruption.
+ #[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = libc::strlen(ptr) + 1; // Including the NUL byte
let slice = slice::from_raw_parts(ptr, len as usize);
@@ -242,6 +250,7 @@ impl CString {
/// this string.
///
/// 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 {
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.
///
/// 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> {
String::from_utf8(self.into_bytes())
.map_err(|e| IntoStringError {
@@ -261,6 +271,7 @@ impl CString {
///
/// The returned buffer does **not** contain the trailing nul separator and
/// 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> {
let mut vec = self.into_inner().into_vec();
let _nul = vec.pop();
@@ -270,6 +281,7 @@ impl CString {
/// Equivalent to the `into_bytes` function except that the returned vector
/// includes the trailing nul byte.
+ #[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_bytes_with_nul(self) -> Vec<u8> {
self.into_inner().into_vec()
}
@@ -278,12 +290,14 @@ impl CString {
///
/// The returned slice does **not** contain the trailing nul separator and
/// it is guaranteed to not have any interior nul bytes.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes(&self) -> &[u8] {
&self.inner[..self.inner.len() - 1]
}
/// Equivalent to the `as_bytes` function except that the returned slice
/// includes the trailing nul byte.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes_with_nul(&self) -> &[u8] {
&self.inner
}
@@ -301,6 +315,7 @@ impl CString {
// Turns this `CString` into an empty string to prevent
// memory unsafe code from working by accident. Inline
// to prevent LLVM from optimizing it away in debug builds.
+#[stable(feature = "cstring_drop", since = "1.13.0")]
impl Drop for CString {
#[inline]
fn drop(&mut self) {
@@ -308,6 +323,7 @@ impl Drop for CString {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for CString {
type Target = CStr;
@@ -316,18 +332,21 @@ impl ops::Deref for CString {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for CString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
+#[stable(feature = "cstring_into", since = "1.7.0")]
impl From<CString> for Vec<u8> {
fn from(s: CString) -> Vec<u8> {
s.into_bytes()
}
}
+#[stable(feature = "cstr_debug", since = "1.3.0")]
impl fmt::Debug for CStr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 {
fn default() -> &'a CStr {
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 {
/// Creates an empty `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 {
fn borrow(&self) -> &CStr { self }
}
@@ -372,6 +394,7 @@ impl NulError {
/// let nul_error = CString::new("foo bar\0").unwrap_err();
/// assert_eq!(nul_error.nul_position(), 7);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn nul_position(&self) -> usize { self.0 }
/// 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();
/// 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 }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Error for NulError {
fn description(&self) -> &str { "nul byte found in data" }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for NulError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 {
fn from(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput,
@@ -408,16 +435,19 @@ impl From<NulError> for io::Error {
impl IntoStringError {
/// Consumes this error, returning original `CString` which generated the
/// error.
+ #[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_cstring(self) -> CString {
self.inner
}
/// 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 {
self.error
}
}
+#[stable(feature = "cstring_into", since = "1.7.0")]
impl Error for IntoStringError {
fn description(&self) -> &str {
"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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 {
let len = libc::strlen(ptr);
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");
/// assert!(cstr.is_ok());
/// ```
+ #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub fn from_bytes_with_nul(bytes: &[u8])
-> Result<&CStr, FromBytesWithNulError> {
if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) {
@@ -513,6 +546,7 @@ impl CStr {
/// assert_eq!(cstr, &*cstring);
/// }
/// ```
+ #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
mem::transmute(bytes)
}
@@ -554,6 +588,7 @@ impl CStr {
/// *ptr;
/// }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_ptr(&self) -> *const c_char {
self.inner.as_ptr()
}
@@ -570,6 +605,7 @@ impl CStr {
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes(&self) -> &[u8] {
let bytes = self.to_bytes_with_nul();
&bytes[..bytes.len() - 1]
@@ -583,6 +619,7 @@ impl CStr {
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
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
/// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called.
+ #[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
// 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
@@ -615,28 +653,34 @@ impl CStr {
/// > after a 0-cost cast, but it is planned to alter its definition in the
/// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called.
+ #[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.to_bytes())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for CStr {
fn eq(&self, other: &CStr) -> bool {
self.to_bytes().eq(other.to_bytes())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for CStr {}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for CStr {
fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
self.to_bytes().partial_cmp(&other.to_bytes())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for CStr {
fn cmp(&self, other: &CStr) -> Ordering {
self.to_bytes().cmp(&other.to_bytes())
}
}
+#[stable(feature = "cstr_borrow", since = "1.3.0")]
impl ToOwned for CStr {
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 {
fn from(s: &'a CStr) -> CString {
s.to_owned()
}
}
+#[stable(feature = "cstring_asref", since = "1.7.0")]
impl ops::Index<ops::RangeFull> for CString {
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 {
fn as_ref(&self) -> &CStr {
self
}
}
+#[stable(feature = "cstring_asref", since = "1.7.0")]
impl AsRef<CStr> for CString {
fn as_ref(&self) -> &CStr {
self
@@ -675,10 +723,10 @@ impl AsRef<CStr> for CString {
#[cfg(test)]
mod tests {
use super::*;
- use libc::c_char;
- use collections::borrow::Cow::{Borrowed, Owned};
- use collections::borrow::ToOwned;
- use core::hash::{Hash, Hasher};
+ use os::raw::c_char;
+ use borrow::Cow::{Borrowed, Owned};
+ use hash::{Hash, Hasher};
+ use collections::hash_map::DefaultHasher;
#[test]
fn c_to_rust() {
@@ -755,6 +803,22 @@ mod tests {
}
#[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]
fn from_bytes_with_nul() {
let data = b"123\0";
let cstr = CStr::from_bytes_with_nul(data);
diff --git a/ctr-std/src/ffi/mod.rs b/ctr-std/src/ffi/mod.rs
new file mode 100644
index 0000000..ca1ff18
--- /dev/null
+++ b/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;
diff --git a/std/src/ffi/os_str.rs b/ctr-std/src/ffi/os_str.rs
index 651eaf3..84b50f0 100644
--- a/std/src/ffi/os_str.rs
+++ b/ctr-std/src/ffi/os_str.rs
@@ -15,9 +15,8 @@ use ops;
use cmp;
use hash::{Hash, Hasher};
-use sys::wtf8::{Wtf8, Wtf8Buf};
-use sys::{AsInner, IntoInner, FromInner};
-pub use sys::wtf8::EncodeWide;
+use sys::os_str::{Buf, Slice};
+use sys_common::{AsInner, IntoInner, FromInner};
/// A type that can represent owned, mutable platform-native strings, but is
/// 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
/// to be converted into an "OS" string with no cost.
#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsString {
- inner: Wtf8Buf
+ inner: Buf
}
/// Slices into OS strings (see `OsString`).
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsStr {
- inner: Wtf8
+ inner: Slice
}
impl OsString {
/// Constructs a new empty `OsString`.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> OsString {
- OsString { inner: Wtf8Buf::from_string(String::new()) }
- }
-
- fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
- String::from_utf8(vec).ok().map(OsString::from)
+ OsString { inner: Buf::from_string(String::new()) }
}
/// Converts to an `OsStr` slice.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_os_str(&self) -> &OsStr {
self
}
@@ -63,13 +62,15 @@ impl OsString {
/// Converts the `OsString` into a `String` if it contains valid Unicode data.
///
/// On failure, ownership of the original `OsString` is returned.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_string(self) -> Result<String, OsString> {
self.inner.into_string().map_err(|buf| OsString { inner: buf} )
}
/// 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) {
- self.inner.push_wtf8(&s.as_ref().inner)
+ self.inner.push_slice(&s.as_ref().inner)
}
/// Creates a new `OsString` with the given capacity.
@@ -79,13 +80,15 @@ impl OsString {
/// allocate.
///
/// See main `OsString` documentation information about encoding.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn with_capacity(capacity: usize) -> OsString {
OsString {
- inner: Wtf8Buf::with_capacity(capacity)
+ inner: Buf::with_capacity(capacity)
}
}
/// Truncates the `OsString` to zero length.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn clear(&mut self) {
self.inner.clear()
}
@@ -93,6 +96,7 @@ impl OsString {
/// Returns the capacity this `OsString` can hold without reallocating.
///
/// See `OsString` introduction for information about encoding.
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
@@ -101,6 +105,7 @@ impl OsString {
/// in the given `OsString`.
///
/// 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) {
self.inner.reserve(additional)
}
@@ -112,34 +117,27 @@ impl OsString {
/// Note that the allocator may give the collection more space than it
/// requests. Therefore capacity can not be relied upon to be precisely
/// 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) {
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 {
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 {
fn from(s: &'a T) -> OsString {
s.as_ref().to_os_string()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Index<ops::RangeFull> for OsString {
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 {
type Target = OsStr;
@@ -158,39 +157,47 @@ impl ops::Deref for OsString {
}
}
+#[stable(feature = "osstring_default", since = "1.9.0")]
impl Default for OsString {
+ /// Constructs an empty `OsString`.
#[inline]
fn default() -> OsString {
OsString::new()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for OsString {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fmt::Debug::fmt(&**self, formatter)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for OsString {
fn eq(&self, other: &OsString) -> bool {
&**self == &**other
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<str> for OsString {
fn eq(&self, other: &str) -> bool {
&**self == other
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<OsString> for str {
fn eq(&self, other: &OsString) -> bool {
&**other == self
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for OsString {}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for OsString {
#[inline]
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 }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd<str> for OsString {
#[inline]
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 {
#[inline]
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 {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
@@ -229,38 +239,61 @@ impl Hash for OsString {
impl OsStr {
/// 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 {
s.as_ref()
}
- fn from_inner(inner: &Wtf8) -> &OsStr {
+ fn from_inner(inner: &Slice) -> &OsStr {
unsafe { mem::transmute(inner) }
}
/// Yields a `&str` slice if the `OsStr` is valid Unicode.
///
/// 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> {
- self.inner.as_str()
+ self.inner.to_str()
}
/// Converts an `OsStr` to a `Cow<str>`.
///
/// 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> {
self.inner.to_string_lossy()
}
/// Copies the slice into an owned `OsString`.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn to_os_string(&self) -> OsString {
- let mut buf = Wtf8Buf::with_capacity(self.inner.len());
- buf.push_wtf8(&self.inner);
- OsString { inner: buf }
+ OsString { inner: self.inner.to_owned() }
}
/// 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 {
- self.inner.is_empty()
+ self.inner.inner.is_empty()
}
/// Returns the length of this `OsStr`.
@@ -271,8 +304,21 @@ impl OsStr {
/// other methods like `OsString::with_capacity` to avoid reallocations.
///
/// 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 {
- self.inner.len()
+ self.inner.inner.len()
}
/// Gets the underlying byte representation.
@@ -282,46 +328,42 @@ impl OsStr {
fn bytes(&self) -> &[u8] {
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 {
+ /// Creates an empty `OsStr`.
#[inline]
fn default() -> &'a OsStr {
OsStr::new("")
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for OsStr {
fn eq(&self, other: &OsStr) -> bool {
self.bytes().eq(other.bytes())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<str> for OsStr {
fn eq(&self, other: &str) -> bool {
*self == *OsStr::new(other)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<OsStr> for str {
fn eq(&self, other: &OsStr) -> bool {
*other == *OsStr::new(self)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for OsStr {}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd for OsStr {
#[inline]
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()) }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl PartialOrd<str> for OsStr {
#[inline]
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
// have more flexible coherence rules.
+#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for OsStr {
#[inline]
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
@@ -354,16 +398,19 @@ impl Ord for OsStr {
macro_rules! impl_cmp {
($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline]
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 {
#[inline]
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 {
#[inline]
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 {
#[inline]
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>, OsString);
+#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for OsStr {
#[inline]
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 {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.inner.fmt(formatter)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<OsStr> for OsString {
fn borrow(&self) -> &OsStr { &self[..] }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for OsStr {
type Owned = OsString;
fn to_owned(&self) -> OsString { self.to_os_string() }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for OsStr {
fn as_ref(&self) -> &OsStr {
self
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for OsString {
fn as_ref(&self) -> &OsStr {
self
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for str {
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 {
fn as_ref(&self) -> &OsStr {
(&**self).as_ref()
}
}
-impl FromInner<Wtf8Buf> for OsString {
- fn from_inner(buf: Wtf8Buf) -> OsString {
+impl FromInner<Buf> for OsString {
+ fn from_inner(buf: Buf) -> OsString {
OsString { inner: buf }
}
}
-impl IntoInner<Wtf8Buf> for OsString {
- fn into_inner(self) -> Wtf8Buf {
+impl IntoInner<Buf> for OsString {
+ fn into_inner(self) -> Buf {
self.inner
}
}
-impl AsInner<Wtf8> for OsStr {
- fn as_inner(&self) -> &Wtf8 {
+impl AsInner<Slice> for OsStr {
+ fn as_inner(&self) -> &Slice {
&self.inner
}
}
@@ -453,29 +509,29 @@ impl AsInner<Wtf8> for OsStr {
#[cfg(test)]
mod tests {
use super::*;
- use sys::{AsInner, IntoInner};
+ use sys_common::{AsInner, IntoInner};
#[test]
fn test_os_string_with_capacity() {
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);
- assert_eq!(10, os_string.inner.capacity());
+ assert_eq!(10, os_string.inner.into_inner().capacity());
let mut os_string = OsString::with_capacity(0);
os_string.push("abc");
- assert!(os_string.inner.capacity() >= 3);
+ assert!(os_string.inner.into_inner().capacity() >= 3);
}
#[test]
fn test_os_string_clear() {
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();
assert_eq!(&os_string, "");
- assert_eq!(0, os_string.inner.len());
+ assert_eq!(0, os_string.inner.as_inner().len());
}
#[test]
diff --git a/std/src/io/buffered.rs b/ctr-std/src/io/buffered.rs
index 39733f2..44dd4e9 100644
--- a/std/src/io/buffered.rs
+++ b/ctr-std/src/io/buffered.rs
@@ -20,11 +20,15 @@ use memchr;
/// The `BufReader` struct adds buffering to any reader.
///
-/// 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.
-/// A `BufReader` performs large, infrequent reads on the underlying `Read`
+/// 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.
+/// A `BufReader` performs large, infrequent reads on the underlying [`Read`]
/// 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
///
/// ```
@@ -42,6 +46,7 @@ use memchr;
/// # Ok(())
/// # }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufReader<R> {
inner: R,
buf: Box<[u8]>,
@@ -64,6 +69,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
}
@@ -84,6 +90,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
BufReader {
inner: inner,
@@ -111,6 +118,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &R { &self.inner }
/// Gets a mutable reference to the underlying reader.
@@ -131,6 +139,7 @@ impl<R: Read> BufReader<R> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
/// Unwraps this `BufReader`, returning the underlying reader.
@@ -151,9 +160,11 @@ impl<R: Read> BufReader<R> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> R { self.inner }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Read for BufReader<R> {
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
@@ -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> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
// 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 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
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> {
/// 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
/// would otherwise fall within it. This guarantees that calling
- /// `.unwrap()` immediately after a seek yields the underlying reader at
- /// the same position.
+ /// `.into_inner()` immediately after a seek yields the underlying reader
+ /// at the same position.
///
/// See `std::io::Seek` for more details.
///
@@ -220,7 +234,7 @@ impl<R: Seek> Seek for BufReader<R> {
if let SeekFrom::Current(n) = pos {
let remainder = (self.cap - self.pos) as i64;
// 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
// support seeking by i64::min_value() so we need to handle underflow when subtracting
// remainder.
@@ -244,7 +258,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// Wraps a writer and buffers its output.
///
/// 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
/// and writes it to an underlying writer in large, infrequent batches.
///
@@ -252,7 +266,7 @@ impl<R: Seek> Seek for BufReader<R> {
///
/// # 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
/// 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
/// together by the buffer, and will all be written out in one system call when
/// 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> {
inner: Option<W>,
buf: Vec<u8>,
@@ -318,6 +337,7 @@ pub struct BufWriter<W: Write> {
/// };
/// ```
#[derive(Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoInnerError<W>(W, Error);
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());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> BufWriter<W> {
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 mut buffer = BufWriter::with_capacity(100, stream);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> {
BufWriter {
inner: Some(inner),
@@ -396,6 +418,7 @@ impl<W: Write> BufWriter<W> {
/// // we can use reference just like buffer
/// let reference = buffer.get_ref();
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() }
/// Gets a mutable reference to the underlying writer.
@@ -413,6 +436,7 @@ impl<W: Write> BufWriter<W> {
/// // we can use reference just like buffer
/// 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() }
/// Unwraps this `BufWriter`, returning the underlying writer.
@@ -430,6 +454,7 @@ impl<W: Write> BufWriter<W> {
/// // unwrap the TcpStream and flush the buffer
/// let stream = buffer.into_inner().unwrap();
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
match self.flush_buf() {
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> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.buf.len() + buf.len() > self.buf.capacity() {
@@ -449,8 +475,7 @@ impl<W: Write> Write for BufWriter<W> {
self.panicked = false;
r
} else {
- let amt = cmp::min(buf.len(), self.buf.capacity());
- Write::write(&mut self.buf, &buf[..amt])
+ Write::write(&mut self.buf, buf)
}
}
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 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
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> {
/// 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> {
fn drop(&mut self) {
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 }
/// 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 }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<W> From<IntoInnerError<W>> for Error {
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> {
fn description(&self) -> &str {
error::Error::description(self.error())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<W> fmt::Display for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.error().fmt(f)
@@ -613,6 +646,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// # Ok(())
/// # }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct LineWriter<W: Write> {
inner: BufWriter<W>,
}
@@ -632,6 +666,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> LineWriter<W> {
// Lines typically aren't that long, don't use a giant buffer
LineWriter::with_capacity(1024, inner)
@@ -652,6 +687,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
LineWriter { inner: BufWriter::with_capacity(cap, inner) }
}
@@ -672,6 +708,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W { self.inner.get_ref() }
/// Gets a mutable reference to the underlying writer.
@@ -694,6 +731,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() }
/// Unwraps this `LineWriter`, returning the underlying writer.
@@ -715,6 +753,7 @@ impl<W: Write> LineWriter<W> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
self.inner.into_inner().map_err(|IntoInnerError(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> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
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() }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("LineWriter")
@@ -754,13 +795,10 @@ impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
mod tests {
use io::prelude::*;
use io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
- //use sync::atomic::{AtomicUsize, Ordering};
- //use thread;
+ use sync::atomic::{AtomicUsize, Ordering};
+ use thread;
use test;
- use collections::{Vec, String};
- use collections::string::ToString;
-
/// A dummy reader intended at testing short-reads propagation.
pub struct ShortReader {
lengths: Vec<usize>,
@@ -1075,9 +1113,8 @@ mod tests {
panic!();
}
- // NOTE: These tests are for threading stuff that is not yet implemented
- /*
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn panic_in_write_doesnt_flush_in_drop() {
static WRITES: AtomicUsize = AtomicUsize::new(0);
@@ -1113,5 +1150,4 @@ mod tests {
BufWriter::new(io::sink())
});
}
- */
}
diff --git a/std/src/io/cursor.rs b/ctr-std/src/io/cursor.rs
index befbf14..1b50233 100644
--- a/std/src/io/cursor.rs
+++ b/ctr-std/src/io/cursor.rs
@@ -10,26 +10,33 @@
use io::prelude::*;
+use core::convert::TryInto;
use cmp;
use io::{self, SeekFrom, Error, ErrorKind};
/// 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
-/// implement `Read` and/or `Write`, allowing these buffers to be used
+/// `Cursor`s are typically used with in-memory buffers to allow them to
+/// implement [`Read`] and/or [`Write`], allowing these buffers to be used
/// 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
-/// 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
///
-/// 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
/// `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
/// 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]);
/// }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone, Debug)]
pub struct Cursor<T> {
inner: T,
@@ -90,6 +98,7 @@ impl<T> Cursor<T> {
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
/// # force_inference(&buff);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: T) -> Cursor<T> {
Cursor { pos: 0, inner: inner }
}
@@ -107,6 +116,7 @@ impl<T> Cursor<T> {
///
/// let vec = buff.into_inner();
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> T { self.inner }
/// Gets a reference to the underlying value in this cursor.
@@ -122,6 +132,7 @@ impl<T> Cursor<T> {
///
/// let reference = buff.get_ref();
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &T { &self.inner }
/// Gets a mutable reference to the underlying value in this cursor.
@@ -140,6 +151,7 @@ impl<T> Cursor<T> {
///
/// let reference = buff.get_mut();
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut T { &mut self.inner }
/// Returns the current position of this cursor.
@@ -161,6 +173,7 @@ impl<T> Cursor<T> {
/// buff.seek(SeekFrom::Current(-1)).unwrap();
/// assert_eq!(buff.position(), 1);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn position(&self) -> u64 { self.pos }
/// Sets the position of this cursor.
@@ -180,9 +193,11 @@ impl<T> Cursor<T> {
/// buff.set_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; }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
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]> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
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]> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
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; }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> {
#[inline]
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(()) }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Cursor<Vec<u8>> {
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
// 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();
- 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
// there (left), and what will be appended on the end (right)
{
- let pos = pos as usize;
let space = self.inner.len() - pos;
let (left, right) = buf.split_at(cmp::min(space, buf.len()));
self.inner[pos..pos + left.len()].copy_from_slice(left);
@@ -249,12 +270,13 @@ impl Write for Cursor<Vec<u8>> {
}
// Bump us forward
- self.set_position(pos + buf.len() as u64);
+ self.set_position((pos + buf.len()) as u64);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
+#[stable(feature = "cursor_box_slice", since = "1.5.0")]
impl Write for Cursor<Box<[u8]>> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -271,8 +293,6 @@ mod tests {
use io::prelude::*;
use io::{Cursor, SeekFrom};
- use collections::Vec;
-
#[test]
fn test_vec_writer() {
let mut writer = Vec::new();
@@ -372,7 +392,7 @@ mod tests {
#[test]
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 = [];
assert_eq!(reader.read(&mut buf).unwrap(), 0);
assert_eq!(reader.position(), 0);
@@ -394,7 +414,7 @@ mod tests {
#[test]
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 = [];
assert_eq!(reader.read(&mut buf).unwrap(), 0);
assert_eq!(reader.position(), 0);
@@ -416,7 +436,7 @@ mod tests {
#[test]
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();
reader.read_to_end(&mut v).unwrap();
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.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.read(&mut [0]).unwrap(), 0);
@@ -512,14 +532,14 @@ mod tests {
let mut r = Cursor::new(&buf[..]);
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());
let mut buf = [0];
let mut r = Cursor::new(&mut buf[..]);
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());
}
@@ -569,4 +589,12 @@ mod tests {
let mut r = Cursor::new(Vec::new());
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());
+ }
}
diff --git a/std/src/io/error.rs b/ctr-std/src/io/error.rs
index bc05469..795c89c 100644
--- a/std/src/io/error.rs
+++ b/ctr-std/src/io/error.rs
@@ -8,10 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use error;
use fmt;
use result;
+use sys;
+use convert::From;
/// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations.
@@ -43,6 +44,7 @@ use result;
/// Ok(buffer)
/// }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = result::Result<T, Error>;
/// 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
/// `Error` can be created with crafted error messages and a particular value of
-/// `ErrorKind`.
+/// [`ErrorKind`].
+///
+/// [`ErrorKind`]: enum.ErrorKind.html
#[derive(Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error {
repr: Repr,
}
enum Repr {
Os(i32),
+ Simple(ErrorKind),
Custom(Box<Custom>),
}
@@ -71,59 +77,86 @@ struct Custom {
///
/// This list is intended to grow over time and it is not recommended to
/// 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)]
pub enum ErrorKind {
/// An entity was not found, often a file.
+ #[stable(feature = "rust1", since = "1.0.0")]
NotFound,
/// The operation lacked the necessary privileges to complete.
+ #[stable(feature = "rust1", since = "1.0.0")]
PermissionDenied,
/// The connection was refused by the remote server.
+ #[stable(feature = "rust1", since = "1.0.0")]
ConnectionRefused,
/// The connection was reset by the remote server.
+ #[stable(feature = "rust1", since = "1.0.0")]
ConnectionReset,
/// The connection was aborted (terminated) by the remote server.
+ #[stable(feature = "rust1", since = "1.0.0")]
ConnectionAborted,
/// The network operation failed because it was not connected yet.
+ #[stable(feature = "rust1", since = "1.0.0")]
NotConnected,
/// A socket address could not be bound because the address is already in
/// use elsewhere.
+ #[stable(feature = "rust1", since = "1.0.0")]
AddrInUse,
/// A nonexistent interface was requested or the requested address was not
/// local.
+ #[stable(feature = "rust1", since = "1.0.0")]
AddrNotAvailable,
/// The operation failed because a pipe was closed.
+ #[stable(feature = "rust1", since = "1.0.0")]
BrokenPipe,
/// An entity already exists, often a file.
+ #[stable(feature = "rust1", since = "1.0.0")]
AlreadyExists,
/// The operation needs to block to complete, but the blocking operation was
/// requested to not occur.
+ #[stable(feature = "rust1", since = "1.0.0")]
WouldBlock,
/// A parameter was incorrect.
+ #[stable(feature = "rust1", since = "1.0.0")]
InvalidInput,
/// 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
/// input data.
///
/// 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.
+ ///
+ /// [`InvalidInput`]: #variant.InvalidInput
+ #[stable(feature = "io_invalid_data", since = "1.2.0")]
InvalidData,
/// The I/O operation's timeout expired, causing it to be canceled.
+ #[stable(feature = "rust1", since = "1.0.0")]
TimedOut,
/// 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
/// particular number of bytes but only a smaller number of bytes could be
/// written.
+ ///
+ /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write
+ /// [`Ok(0)`]: ../../std/io/type.Result.html
+ #[stable(feature = "rust1", since = "1.0.0")]
WriteZero,
/// This operation was interrupted.
///
/// Interrupted operations can typically be retried.
+ #[stable(feature = "rust1", since = "1.0.0")]
Interrupted,
/// Any I/O error not part of this list.
+ #[stable(feature = "rust1", since = "1.0.0")]
Other,
/// 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
/// particular number of bytes but only a smaller number of bytes could be
/// read.
+ #[stable(feature = "read_exact", since = "1.6.0")]
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)]
__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 {
/// Creates a new I/O error from a known kind of error as well as an
/// arbitrary error payload.
@@ -158,6 +234,7 @@ impl Error {
/// // errors can also be created from other errors
/// 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
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.
+ ///
+ /// # 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 {
Error { repr: Repr::Os(code) }
}
@@ -183,10 +303,33 @@ impl Error {
/// If this `Error` was constructed via `last_os_error` or
/// `from_raw_os_error`, then this function will return `Some`, otherwise
/// 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> {
match self.repr {
Repr::Os(i) => Some(i),
Repr::Custom(..) => None,
+ Repr::Simple(..) => None,
}
}
@@ -194,9 +337,32 @@ impl Error {
///
/// If this `Error` was constructed via `new` then this function will
/// 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)> {
match self.repr {
Repr::Os(..) => None,
+ Repr::Simple(..) => None,
Repr::Custom(ref c) => Some(&*c.error),
}
}
@@ -206,9 +372,68 @@ impl Error {
///
/// If this `Error` was constructed via `new` then this function will
/// 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)> {
match self.repr {
Repr::Os(..) => None,
+ Repr::Simple(..) => None,
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
/// 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>> {
match self.repr {
Repr::Os(..) => None,
+ Repr::Simple(..) => None,
Repr::Custom(c) => Some(c.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 {
match self.repr {
- Repr::Os(_code) => ErrorKind::Other,
+ Repr::Os(code) => sys::decode_error_kind(code),
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 {
match *self {
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::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.repr {
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::Simple(kind) => write!(fmt, "{}", kind.as_str()),
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl error::Error for Error {
fn description(&self) -> &str {
match self.repr {
- Repr::Os(..) => match self.kind() {
- 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::Os(..) | Repr::Simple(..) => self.kind().as_str(),
Repr::Custom(ref c) => c.error.description(),
}
}
@@ -285,6 +538,7 @@ impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> {
match self.repr {
Repr::Os(..) => None,
+ Repr::Simple(..) => None,
Repr::Custom(ref c) => c.error.cause(),
}
}
@@ -297,7 +551,6 @@ fn _assert_error_is_sync_send() {
#[cfg(test)]
mod test {
- use prelude::v1::*;
use super::{Error, ErrorKind};
use error;
use fmt;
diff --git a/std/src/io/impls.rs b/ctr-std/src/io/impls.rs
index 360e734..6b26c01 100644
--- a/std/src/io/impls.rs
+++ b/ctr-std/src/io/impls.rs
@@ -16,6 +16,7 @@ use mem;
// =============================================================================
// Forwarding implementations
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, R: Read + ?Sized> Read for &'a mut R {
#[inline]
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)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, W: Write + ?Sized> Write for &'a mut W {
#[inline]
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)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
#[inline]
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 {
#[inline]
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> {
#[inline]
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)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + ?Sized> Write for Box<W> {
#[inline]
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)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<S: Seek + ?Sized> Seek for Box<S> {
#[inline]
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> {
#[inline]
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
+/// 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] {
#[inline]
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] {
#[inline]
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..]; }
}
+/// 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] {
#[inline]
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(()) }
}
+/// 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> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -215,8 +238,6 @@ mod tests {
use io::prelude::*;
use test;
- use collections::Vec;
-
#[bench]
fn bench_read_slice(b: &mut test::Bencher) {
let buf = [5; 1024];
diff --git a/std/src/io/mod.rs b/ctr-std/src/io/mod.rs
index f66aa60..1653790 100644
--- a/std/src/io/mod.rs
+++ b/ctr-std/src/io/mod.rs
@@ -12,18 +12,15 @@
//!
//! 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
-//! 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.
//!
-//! [read]: trait.Read.html
-//! [write]: trait.Write.html
-//!
//! # 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,
//! 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:
//!
//! ```
@@ -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
-//! of 'a type that implements the `Read` trait'. Much easier!
+//! of 'a type that implements the [`Read`] trait'. Much easier!
//!
//! ## Seek and BufRead
//!
-//! Beyond that, there are two important traits that are provided: [`Seek`][seek]
-//! and [`BufRead`][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
+//! Beyond that, there are two important traits that are provided: [`Seek`]
+//! 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
//! coming from:
//!
//! ```
@@ -75,21 +72,18 @@
//! # }
//! ```
//!
-//! [seek]: trait.Seek.html
-//! [bufread]: trait.BufRead.html
-//!
-//! `BufRead` uses an internal buffer to provide a number of other ways to read, but
+//! [`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!
//!
//! ## BufReader and BufWriter
//!
//! 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,
-//! `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
//! 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:
//!
//! ```
@@ -111,8 +105,8 @@
//! # }
//! ```
//!
-//! `BufWriter` doesn't add any new ways of writing; it just buffers every call
-//! to [`write()`][write()]:
+//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
+//! to [`write()`]:
//!
//! ```
//! use std::io;
@@ -134,8 +128,6 @@
//! # }
//! ```
//!
-//! [write()]: trait.Write.html#tymethod.write
-//!
//! ## Standard input and output
//!
//! 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
-//! `println!`.
+//! Of course, using [`io::stdout()`] directly is less common than something like
+//! [`println!`].
//!
//! ## Iterator types
//!
//! 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:
//!
//! ```
@@ -211,10 +203,10 @@
//!
//! ## 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
//! 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;
@@ -230,14 +222,11 @@
//! }
//! ```
//!
-//! The return type of `read_input()`, `io::Result<()>`, is a very common type
-//! for functions which don't have a 'real' return value, but do want to return
-//! errors if they happen. In this case, the only purpose of this function is
+//! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very
+//! common type for functions which don't have a 'real' return value, but do want to
+//! 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 `()`.
//!
-//! [result]: type.Result.html
-//! [try]: ../macro.try.html
-//!
//! ## Platform-specific behavior
//!
//! 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
//! contract. The implementation of many of these functions are subject to change over
//! 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 std_unicode::str as core_str;
@@ -255,17 +262,19 @@ use result;
use str;
use memchr;
+#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::{BufReader, BufWriter, LineWriter};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use self::buffered::IntoInnerError;
+#[stable(feature = "rust1", since = "1.0.0")]
pub use self::cursor::Cursor;
+#[stable(feature = "rust1", since = "1.0.0")]
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};
+#[stable(feature = "rust1", since = "1.0.0")]
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;
mod buffered;
@@ -275,10 +284,7 @@ mod impls;
mod util;
mod print;
-//mod lazy;
-//mod stdio;
-
-const DEFAULT_BUF_SIZE: usize = 8 * 1024;
+const DEFAULT_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
// 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
@@ -411,6 +417,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
/// # Ok(())
/// # }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub trait Read {
/// Pull some bytes from this source into the specified buffer, returning
/// how many bytes were read.
@@ -460,6 +467,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
/// Read all bytes until EOF in this source, placing them into `buf`.
@@ -501,6 +509,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
read_to_end(self, buf)
}
@@ -538,6 +547,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
// Note that we do *not* call `.read_to_end()` here. We are passing
// `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end`
@@ -598,6 +608,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "read_exact", since = "1.6.0")]
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
while !buf.is_empty() {
match self.read(buf) {
@@ -649,6 +660,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
/// Transforms this `Read` instance to an `Iterator` over its bytes.
@@ -678,6 +690,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn bytes(self) -> Bytes<Self> where Self: Sized {
Bytes { inner: self }
}
@@ -714,6 +727,10 @@ pub trait Read {
/// # 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 {
Chars { inner: self }
}
@@ -748,6 +765,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
Chain { first: self, second: next, done_first: false }
}
@@ -781,6 +799,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn take(self, limit: u64) -> Take<Self> where Self: Sized {
Take { inner: self, limit: limit }
}
@@ -816,6 +835,7 @@ pub trait Read {
/// # Ok(())
/// # }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub trait Write {
/// Write a buffer into this object, returning how many bytes were written.
///
@@ -855,6 +875,7 @@ pub trait Write {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, buf: &[u8]) -> Result<usize>;
/// Flush this output stream, ensuring that all intermediately buffered
@@ -880,6 +901,7 @@ pub trait Write {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn flush(&mut self) -> Result<()>;
/// Attempts to write an entire buffer into this write.
@@ -906,6 +928,7 @@ pub trait Write {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
while !buf.is_empty() {
match self.write(buf) {
@@ -957,6 +980,7 @@ pub trait Write {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
// Create a shim which translates a Write to a fmt::Write and saves
// off I/O errors. instead of discarding them
@@ -1012,6 +1036,7 @@ pub trait Write {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
}
@@ -1041,6 +1066,7 @@ pub trait Write {
/// # Ok(())
/// # }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub trait Seek {
/// 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.
///
/// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
+ #[stable(feature = "rust1", since = "1.0.0")]
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
}
@@ -1065,23 +1092,27 @@ pub trait Seek {
///
/// [`Seek`]: trait.Seek.html
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub enum SeekFrom {
/// 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
/// bytes.
///
/// It is possible to seek beyond the end of an object, but it's an error to
/// 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
/// bytes.
///
/// It is possible to seek beyond the end of an object, but it's an error to
/// 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>)
@@ -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
/// 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.
-///
-/// [readline]: #method.read_line
-/// [lines]: #method.lines
+/// [`read_line()`] method as well as a [`lines()`] iterator.
///
/// # 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`
-/// type][bufreader] to turn it into a `BufRead`.
+/// If you have something that implements [`Read`], you can use the [`BufReader`
+/// type][`BufReader`] to turn it into a `BufRead`.
///
-/// For example, [`File`][file] implements `Read`, but not `BufRead`.
-/// `BufReader` to the rescue!
+/// For example, [`File`] implements [`Read`], but not `BufRead`.
+/// [`BufReader`] to the rescue!
///
-/// [bufreader]: struct.BufReader.html
-/// [file]: ../fs/struct.File.html
+/// [`BufReader`]: struct.BufReader.html
+/// [`File`]: ../fs/struct.File.html
+/// [`read_line()`]: #method.read_line
+/// [`lines()`]: #method.lines
+/// [`Read`]: trait.Read.html
///
/// ```
/// 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 {
/// 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
- /// [`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
- /// calling `read` may return the same contents. As such, `consume` must be
- /// called with the number of bytes that are consumed from this buffer to
+ /// calling `read` may return the same contents. As such, [`consume()`] must
+ /// be called with the number of bytes that are consumed from this buffer to
/// 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.
///
@@ -1207,43 +1239,43 @@ pub trait BufRead: Read {
/// // ensure the bytes we worked with aren't returned again later
/// stdin.consume(length);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn fill_buf(&mut self) -> Result<&[u8]>;
/// Tells this buffer that `amt` bytes have been consumed from the buffer,
/// 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
- /// [`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
- /// its buffer, returned from `fill_buf`, has been consumed and should no
- /// longer be returned. As such, this function may do odd things if
- /// `fill_buf` isn't called before calling it.
- ///
- /// [fillbuf]: #tymethod.fill_buf
+ /// its buffer, returned from [`fill_buf()`], has been consumed and should
+ /// no longer be returned. As such, this function may do odd things if
+ /// [`fill_buf()`] isn't called before calling it.
///
/// The `amt` must be `<=` the number of bytes in the buffer returned by
- /// `fill_buf`.
+ /// [`fill_buf()`].
///
/// # 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()`.
+ ///
+ /// [`fill_buf()`]: #tymethod.fill_buf
+ #[stable(feature = "rust1", since = "1.0.0")]
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
/// delimiter or EOF is found. Once found, all bytes up to, and including,
/// the delimiter (if found) will be appended to `buf`.
///
- /// If this reader is currently at EOF then this function will not modify
- /// `buf` and will return `Ok(n)` where `n` is the number of bytes which
- /// were read.
+ /// If successful, this function will return the total number of bytes read.
///
/// # Errors
///
- /// This function will ignore all instances of `ErrorKind::Interrupted` and
- /// will otherwise return any errors returned by `fill_buf`.
+ /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
+ /// will otherwise return any errors returned by [`fill_buf()`].
///
/// 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.
@@ -1253,6 +1285,9 @@ pub trait BufRead: Read {
/// A locked standard input implements `BufRead`. In this example, we'll
/// 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::prelude::*;
@@ -1268,6 +1303,7 @@ pub trait BufRead: Read {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
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
/// `buf`.
///
- /// If this reader is currently at EOF then this function will not modify
- /// `buf` and will return `Ok(n)` where `n` is the number of bytes which
- /// were read.
+ /// If successful, this function will return the total number of bytes read.
///
/// # Errors
///
- /// This function has the same error semantics as `read_until` and will also
- /// return an error if the read bytes are not valid UTF-8. If an I/O error
- /// is encountered then `buf` may contain some bytes already read in the
- /// event that all data read so far was valid UTF-8.
+ /// This function has the same error semantics as [`read_until()`] and will
+ /// also return an error if the read bytes are not valid UTF-8. If an I/O
+ /// error is encountered then `buf` may contain some bytes already read in
+ /// the event that all data read so far was valid UTF-8.
///
/// # Examples
///
/// 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
- /// an actual project, the [`lines()`][lines] method would be easier, of
+ /// an actual project, the [`lines()`] method would be easier, of
/// course.
///
- /// [lines]: #method.lines
+ /// [`lines()`]: #method.lines
+ /// [`read_until()`]: #method.read_until
///
/// ```
/// use std::io;
@@ -1315,6 +1350,7 @@ pub trait BufRead: Read {
/// buffer.clear();
/// }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn read_line(&mut self, buf: &mut String) -> Result<usize> {
// Note that we are not calling the `.read_until` method here, but
// rather our hardcoded implementation. For more details as to why, see
@@ -1326,17 +1362,21 @@ pub trait BufRead: Read {
/// `byte`.
///
/// The iterator returned from this function will return instances of
- /// `io::Result<Vec<u8>>`. Each vector returned will *not* have the
- /// delimiter byte at the end.
+ /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
+ /// the delimiter byte at the end.
///
- /// This function will yield errors whenever `read_until` would have also
- /// yielded an error.
+ /// This function will yield errors whenever [`read_until()`] would have
+ /// also yielded an error.
///
/// # Examples
///
/// A locked standard input implements `BufRead`. In this example, we'll
/// 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::prelude::*;
@@ -1347,6 +1387,7 @@ pub trait BufRead: Read {
/// println!("{:?}", content.unwrap());
/// }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn split(self, byte: u8) -> Split<Self> where Self: Sized {
Split { buf: self, delim: byte }
}
@@ -1354,9 +1395,12 @@ pub trait BufRead: Read {
/// Returns an iterator over the lines of this reader.
///
/// 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.
///
+ /// [`io::Result`]: type.Result.html
+ /// [`String`]: ../string/struct.String.html
+ ///
/// # Examples
///
/// A locked standard input implements `BufRead`:
@@ -1371,6 +1415,7 @@ pub trait BufRead: Read {
/// println!("{}", line.unwrap());
/// }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
fn lines(self) -> Lines<Self> where Self: Sized {
Lines { buf: self }
}
@@ -1378,21 +1423,23 @@ pub trait BufRead: Read {
/// Adaptor to chain together two readers.
///
-/// This struct is generally created by calling [`chain()`][chain] on a reader.
-/// Please see the documentation of `chain()` for more details.
+/// This struct is generally created by calling [`chain()`] on a reader.
+/// 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> {
first: T,
second: U,
done_first: bool,
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Read, U: Read> Read for Chain<T, U> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if !self.done_first {
match self.first.read(buf)? {
- 0 => { self.done_first = true; }
+ 0 if buf.len() != 0 => { self.done_first = true; }
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> {
fn fill_buf(&mut self) -> Result<&[u8]> {
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.
///
/// [take]: trait.Read.html#method.take
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Take<T> {
inner: T,
limit: u64,
@@ -1457,9 +1506,38 @@ impl<T> Take<T> {
/// # Ok(())
/// # }
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
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> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
// 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> {
fn fill_buf(&mut self) -> Result<&[u8]> {
// 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.
///
-/// This struct is generally created by calling [`bytes()`][bytes] on a reader.
-/// Please see the documentation of `bytes()` for more details.
+/// This struct is generally created by calling [`bytes()`] on a reader.
+/// 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> {
inner: R,
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Iterator for Bytes<R> {
type Item = Result<u8>;
@@ -1530,6 +1611,8 @@ impl<R: Read> Iterator for Bytes<R> {
/// Please see the documentation of `chars()` for more details.
///
/// [chars]: trait.Read.html#method.chars
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
+ issue = "27802")]
pub struct Chars<R> {
inner: R,
}
@@ -1537,6 +1620,8 @@ pub struct Chars<R> {
/// An enumeration of possible errors that can be generated from the `Chars`
/// adapter.
#[derive(Debug)]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
+ issue = "27802")]
pub enum CharsError {
/// Variant representing that the underlying stream was read successfully
/// but it did not contain valid utf8 data.
@@ -1546,6 +1631,8 @@ pub enum CharsError {
Other(Error),
}
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
+ issue = "27802")]
impl<R: Read> Iterator for Chars<R> {
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 {
fn description(&self) -> &str {
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@@ -1610,11 +1701,13 @@ impl fmt::Display for CharsError {
/// `BufRead`. Please see the documentation of `split()` for more details.
///
/// [split]: trait.BufRead.html#method.split
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Split<B> {
buf: B,
delim: u8,
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead> Iterator for Split<B> {
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.
///
/// [lines]: trait.BufRead.html#method.lines
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Lines<B> {
buf: B,
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead> Iterator for Lines<B> {
type Item = Result<String>;
@@ -1669,13 +1764,11 @@ mod tests {
use io::prelude::*;
use io;
use super::Cursor;
- use super::repeat;
use test;
-
- use collections::{Vec, String};
- use collections::string::ToString;
+ use super::repeat;
#[test]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn read_until() {
let mut buf = Cursor::new(&b"12"[..]);
let mut v = Vec::new();
@@ -1874,7 +1967,19 @@ mod tests {
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]
+ #[cfg_attr(target_os = "emscripten", ignore)]
fn bench_read_to_end(b: &mut test::Bencher) {
b.iter(|| {
let mut lr = repeat(1).take(10000000);
diff --git a/std/src/io/prelude.rs b/ctr-std/src/io/prelude.rs
index 8f209e5..8772d0f 100644
--- a/std/src/io/prelude.rs
+++ b/ctr-std/src/io/prelude.rs
@@ -18,5 +18,7 @@
//! 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};
diff --git a/std/src/io/print.rs b/ctr-std/src/io/print.rs
index 2940f35..8a5851b 100644
--- a/std/src/io/print.rs
+++ b/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
// implement mutexes with ctrulib functions
use spin::Mutex;
-use libctru::libc;
+use libc;
pub static STDOUT: Mutex<StdoutRaw> = Mutex::new(StdoutRaw(()));
pub struct StdoutRaw(());
+#[stable(feature = "3ds", since = "1.0.0")]
impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
unsafe {
diff --git a/std/src/io/util.rs b/ctr-std/src/io/util.rs
index 1bcc5a6..2c68802 100644
--- a/std/src/io/util.rs
+++ b/ctr-std/src/io/util.rs
@@ -42,6 +42,7 @@ use io::{self, Read, Write, ErrorKind, BufRead};
/// # Ok(())
/// # }
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
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.
///
/// [empty]: fn.empty.html
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }
/// Constructs a new handle to an empty reader.
@@ -82,11 +84,14 @@ pub struct Empty { _priv: () }
/// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty());
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }
+#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
fn consume(&mut self, _n: usize) {}
@@ -98,6 +103,7 @@ impl BufRead for Empty {
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }
/// 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();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }
+#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
for slot in &mut *buf {
@@ -131,6 +139,7 @@ impl Read for Repeat {
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }
/// 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();
/// assert_eq!(num_bytes, 5);
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }
+#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
fn flush(&mut self) -> io::Result<()> { Ok(()) }
diff --git a/ctr-std/src/lib.rs b/ctr-std/src/lib.rs
new file mode 100644
index 0000000..b43e108
--- /dev/null
+++ b/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()
+}
diff --git a/ctr-std/src/macros.rs b/ctr-std/src/macros.rs
new file mode 100644
index 0000000..0ce6b0a
--- /dev/null
+++ b/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 */ }) }
+}
diff --git a/ctr-std/src/memchr.rs b/ctr-std/src/memchr.rs
new file mode 100644
index 0000000..7c8c97a
--- /dev/null
+++ b/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..]));
+ }
+ }
+}
diff --git a/std/src/num/mod.rs b/ctr-std/src/num.rs
index 1aa23b8..d1c2fc3 100644
--- a/std/src/num/mod.rs
+++ b/ctr-std/src/num.rs
@@ -13,17 +13,19 @@
//! This module provides some extra types that are useful when doing numerical
//! work. See the individual documentation for each piece for more information.
+#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
+#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use core::num::{Zero, One};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::Wrapping;
-#[cfg(test)]
-use fmt;
-#[cfg(test)]
-use ops::{Add, Sub, Mul, Div, Rem};
+#[cfg(test)] use fmt;
+#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
/// Helper function for testing numeric operations
#[cfg(test)]
@@ -34,11 +36,11 @@ pub fn test_num<T>(ten: T, two: T) where
+ Rem<Output=T> + fmt::Debug
+ Copy
{
- assert_eq!(ten.add(two), ten + two);
- assert_eq!(ten.sub(two), ten - two);
- assert_eq!(ten.mul(two), ten * two);
- assert_eq!(ten.div(two), ten / two);
- assert_eq!(ten.rem(two), ten % two);
+ assert_eq!(ten.add(two), ten + two);
+ assert_eq!(ten.sub(two), ten - two);
+ assert_eq!(ten.mul(two), ten * two);
+ assert_eq!(ten.div(two), ten / two);
+ assert_eq!(ten.rem(two), ten % two);
}
#[cfg(test)]
@@ -54,9 +56,9 @@ mod tests {
fn test_saturating_add_uint() {
use usize::MAX;
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 - 2).saturating_add(1), MAX - 1);
+ assert_eq!((MAX-2).saturating_add(1), MAX-1);
}
#[test]
@@ -65,16 +67,16 @@ mod tests {
assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
assert_eq!(3_usize.saturating_sub(5_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]
fn test_saturating_add_int() {
- use isize::{MIN, MAX};
+ use isize::{MIN,MAX};
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 - 2).saturating_add(1), MAX - 1);
+ assert_eq!((MAX-2).saturating_add(1), MAX-1);
assert_eq!(3i32.saturating_add(-5), -2);
assert_eq!(MIN.saturating_add(-1), MIN);
assert_eq!((-2isize).saturating_add(-MAX), MIN);
@@ -82,14 +84,14 @@ mod tests {
#[test]
fn test_saturating_sub_int() {
- use isize::{MIN, MAX};
+ use isize::{MIN,MAX};
assert_eq!(3i32.saturating_sub(5), -2);
assert_eq!(MIN.saturating_sub(1), MIN);
assert_eq!((-2isize).saturating_sub(MAX), MIN);
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 - 2).saturating_sub(-1), MAX - 1);
+ assert_eq!((MAX-2).saturating_sub(-1), MAX-1);
}
#[test]
@@ -193,7 +195,7 @@ mod tests {
#[test]
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)
}
macro_rules! assert_pow {
@@ -286,8 +288,6 @@ mod bench {
#[bench]
fn bench_pow_function(b: &mut Bencher) {
let v = (0..1024).collect::<Vec<u32>>();
- b.iter(|| {
- v.iter().fold(0u32, |old, new| old.pow(*new as u32));
- });
+ b.iter(|| {v.iter().fold(0u32, |old, new| old.pow(*new as u32));});
}
}
diff --git a/ctr-std/src/os/mod.rs b/ctr-std/src/os/mod.rs
new file mode 100644
index 0000000..bd05ac3
--- /dev/null
+++ b/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;
diff --git a/std/src/panicking.rs b/ctr-std/src/panicking.rs
index b02dd4f..2b5a178 100644
--- a/std/src/panicking.rs
+++ b/ctr-std/src/panicking.rs
@@ -11,8 +11,9 @@
//! Implementation of various bits and pieces of the `panic!` macro and
//! associated runtime pieces.
-use fmt::{self, Display};
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.
#[lang = "eh_personality"]
@@ -20,7 +21,7 @@ extern fn eh_personality() {}
/// Entry point of panic from the libcore crate.
#[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))
}
@@ -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
/// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place.
-#[inline(never)]
-#[cold]
+#[unstable(feature = "libstd_sys_internals",
+ reason = "used by the panic! macro",
+ issue = "0")]
+#[inline(never)] #[cold]
pub fn begin_panic_fmt(msg: &fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
use fmt::Write;
diff --git a/std/src/path.rs b/ctr-std/src/path.rs
index 428296f..92c561f 100644
--- a/std/src/path.rs
+++ b/ctr-std/src/path.rs
@@ -97,21 +97,23 @@
//! normalization is possible to build on top of the components APIs,
//! and will be included in this library in the near future.
+#![stable(feature = "rust1", since = "1.0.0")]
+
use ascii::*;
-use borrow::{Borrow, ToOwned, Cow};
+use borrow::{Borrow, Cow};
use cmp;
-//use error::Error;
+use error::Error;
use fmt;
//use fs;
use hash::{Hash, Hasher};
//use io;
+use iter::{self, FusedIterator};
use mem;
use ops::{self, Deref};
-use iter;
use ffi::{OsStr, OsString};
-use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
+use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
////////////////////////////////////////////////////////////////////////////////
// GENERAL NOTES
@@ -124,35 +126,6 @@ use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
// available.
////////////////////////////////////////////////////////////////////////////////
-// Platform-specific definitions
-////////////////////////////////////////////////////////////////////////////////
-
-// The following modules give the most basic tools for parsing paths on various
-// platforms. The bulk of the code is devoted to parsing prefixes on Windows.
-
-mod platform {
- use super::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 = '/';
-}
-
-////////////////////////////////////////////////////////////////////////////////
// Windows Prefixes
////////////////////////////////////////////////////////////////////////////////
@@ -164,29 +137,37 @@ mod platform {
/// `/` is *not* treated as a separator and essentially no normalization is
/// performed.
#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub enum Prefix<'a> {
/// Prefix `\\?\`, together with the given component immediately following it.
- Verbatim(&'a OsStr),
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
+
/// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
+ #[stable(feature = "rust1", since = "1.0.0")]
VerbatimUNC(
- &'a OsStr,
- &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
),
/// Prefix like `\\?\C:\`, for the given drive letter
- VerbatimDisk(u8),
+ #[stable(feature = "rust1", since = "1.0.0")]
+ VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
/// Prefix `\\.\`, together with the given component immediately following it.
- DeviceNS(&'a OsStr),
+ #[stable(feature = "rust1", since = "1.0.0")]
+ DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
/// Prefix `\\server\share`, with the given "server" and "share" components.
+ #[stable(feature = "rust1", since = "1.0.0")]
UNC(
- &'a OsStr,
- &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
+ #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
),
/// Prefix `C:` for the given disk drive.
- Disk(u8),
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),
}
impl<'a> Prefix<'a> {
@@ -223,10 +204,11 @@ impl<'a> Prefix<'a> {
/// Determines if the prefix is verbatim, i.e. begins with `\\?\`.
#[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn is_verbatim(&self) -> bool {
use self::Prefix::*;
match *self {
- Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(_, _) => true,
+ Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true,
_ => false,
}
}
@@ -260,12 +242,14 @@ impl<'a> Prefix<'a> {
/// assert!(path::is_separator('/'));
/// assert!(!path::is_separator('❤'));
/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_separator(c: char) -> bool {
c.is_ascii() && is_sep_byte(c as u8)
}
/// The primary separator for the current platform
-pub const MAIN_SEPARATOR: char = platform::MAIN_SEP;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub const MAIN_SEPARATOR: char = ::sys::path::MAIN_SEP;
////////////////////////////////////////////////////////////////////////////////
// Misc helpers
@@ -359,6 +343,7 @@ enum State {
/// A Windows path prefix, e.g. `C:` or `\\server\share`.
///
/// Does not occur on Unix.
+#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Copy, Clone, Eq, Debug)]
pub struct PrefixComponent<'a> {
/// The prefix as an unparsed `OsStr` slice.
@@ -370,34 +355,40 @@ pub struct PrefixComponent<'a> {
impl<'a> PrefixComponent<'a> {
/// The parsed prefix data.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn kind(&self) -> Prefix<'a> {
self.parsed
}
/// The raw `OsStr` slice for this prefix.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_os_str(&self) -> &'a OsStr {
self.raw
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialEq for PrefixComponent<'a> {
fn eq(&self, other: &PrefixComponent<'a>) -> bool {
cmp::PartialEq::eq(&self.parsed, &other.parsed)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialOrd for PrefixComponent<'a> {
fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {
cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::Ord for PrefixComponent<'a> {
fn cmp(&self, other: &PrefixComponent<'a>) -> cmp::Ordering {
cmp::Ord::cmp(&self.parsed, &other.parsed)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Hash for PrefixComponent<'a> {
fn hash<H: Hasher>(&self, h: &mut H) {
self.parsed.hash(h);
@@ -429,29 +420,36 @@ impl<'a> Hash for PrefixComponent<'a> {
///
/// [`path::Components`]: struct.Components.html
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub enum Component<'a> {
/// A Windows path prefix, e.g. `C:` or `\\server\share`.
///
/// Does not occur on Unix.
+ #[stable(feature = "rust1", since = "1.0.0")]
Prefix(
- PrefixComponent<'a>
+ #[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>
),
/// The root directory component, appears after any prefix and before anything else
+ #[stable(feature = "rust1", since = "1.0.0")]
RootDir,
/// A reference to the current directory, i.e. `.`
+ #[stable(feature = "rust1", since = "1.0.0")]
CurDir,
/// A reference to the parent directory, i.e. `..`
+ #[stable(feature = "rust1", since = "1.0.0")]
ParentDir,
/// A normal component, i.e. `a` and `b` in `a/b`
- Normal(&'a OsStr),
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
}
impl<'a> Component<'a> {
/// Extracts the underlying `OsStr` slice
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_os_str(self) -> &'a OsStr {
match self {
Component::Prefix(p) => p.as_os_str(),
@@ -463,6 +461,7 @@ impl<'a> Component<'a> {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRef<OsStr> for Component<'a> {
fn as_ref(&self) -> &OsStr {
self.as_os_str()
@@ -490,6 +489,7 @@ impl<'a> AsRef<OsStr> for Component<'a> {
///
/// [`path::Path::components`]: struct.Path.html#method.components
#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Components<'a> {
// The path left to parse components from
path: &'a [u8],
@@ -510,10 +510,30 @@ pub struct Components<'a> {
/// An iterator over the components of a path, as `OsStr` slices.
#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a> {
inner: Components<'a>,
}
+#[stable(feature = "path_components_debug", since = "1.13.0")]
+impl<'a> fmt::Debug for Components<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ struct DebugHelper<'a>(&'a Path);
+
+ impl<'a> fmt::Debug for DebugHelper<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list()
+ .entries(self.0.components())
+ .finish()
+ }
+ }
+
+ f.debug_tuple("Components")
+ .field(&DebugHelper(self.as_path()))
+ .finish()
+ }
+}
+
impl<'a> Components<'a> {
// how long is the prefix, if any?
#[inline]
@@ -580,6 +600,7 @@ impl<'a> Components<'a> {
///
/// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_path(&self) -> &'a Path {
let mut comps = self.clone();
if comps.front == State::Body {
@@ -678,37 +699,62 @@ impl<'a> Components<'a> {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRef<Path> for Components<'a> {
fn as_ref(&self) -> &Path {
self.as_path()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRef<OsStr> for Components<'a> {
fn as_ref(&self) -> &OsStr {
self.as_path().as_os_str()
}
}
+#[stable(feature = "path_iter_debug", since = "1.13.0")]
+impl<'a> fmt::Debug for Iter<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ struct DebugHelper<'a>(&'a Path);
+
+ impl<'a> fmt::Debug for DebugHelper<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list()
+ .entries(self.0.iter())
+ .finish()
+ }
+ }
+
+ f.debug_tuple("Iter")
+ .field(&DebugHelper(self.as_path()))
+ .finish()
+ }
+}
+
impl<'a> Iter<'a> {
/// Extracts a slice corresponding to the portion of the path remaining for iteration.
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_path(&self) -> &'a Path {
self.inner.as_path()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRef<Path> for Iter<'a> {
fn as_ref(&self) -> &Path {
self.as_path()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRef<OsStr> for Iter<'a> {
fn as_ref(&self) -> &OsStr {
self.as_path().as_os_str()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Iterator for Iter<'a> {
type Item = &'a OsStr;
@@ -717,12 +763,17 @@ impl<'a> Iterator for Iter<'a> {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> DoubleEndedIterator for Iter<'a> {
fn next_back(&mut self) -> Option<&'a OsStr> {
self.inner.next_back().map(Component::as_os_str)
}
}
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a> FusedIterator for Iter<'a> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Iterator for Components<'a> {
type Item = Component<'a>;
@@ -775,6 +826,7 @@ impl<'a> Iterator for Components<'a> {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> DoubleEndedIterator for Components<'a> {
fn next_back(&mut self) -> Option<Component<'a>> {
while !self.finished() {
@@ -821,20 +873,27 @@ impl<'a> DoubleEndedIterator for Components<'a> {
}
}
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a> FusedIterator for Components<'a> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialEq for Components<'a> {
fn eq(&self, other: &Components<'a>) -> bool {
Iterator::eq(self.clone(), other.clone())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::Eq for Components<'a> {}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialOrd for Components<'a> {
fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
Iterator::partial_cmp(self.clone(), other.clone())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::Ord for Components<'a> {
fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
Iterator::cmp(self.clone(), other.clone())
@@ -845,11 +904,17 @@ impl<'a> cmp::Ord for Components<'a> {
// Basic types and traits
////////////////////////////////////////////////////////////////////////////////
-/// An owned, mutable path (akin to `String`).
+/// An owned, mutable path (akin to [`String`]).
+///
+/// This type provides methods like [`push`] and [`set_extension`] that mutate
+/// the path in place. It also implements [`Deref`] to [`Path`], meaning that
+/// all methods on [`Path`] slices are available on `PathBuf` values as well.
///
-/// This type provides methods like `push` and `set_extension` that mutate the
-/// path in place. It also implements `Deref` to `Path`, meaning that all
-/// methods on `Path` slices are available on `PathBuf` values as well.
+/// [`String`]: ../string/struct.String.html
+/// [`Path`]: struct.Path.html
+/// [`push`]: struct.PathBuf.html#method.push
+/// [`set_extension`]: struct.PathBuf.html#method.set_extension
+/// [`Deref`]: ../ops/trait.Deref.html
///
/// More details about the overall approach can be found in
/// the module documentation.
@@ -865,6 +930,7 @@ impl<'a> cmp::Ord for Components<'a> {
/// path.set_extension("dll");
/// ```
#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct PathBuf {
inner: OsString,
}
@@ -875,11 +941,32 @@ impl PathBuf {
}
/// Allocates an empty `PathBuf`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::path::PathBuf;
+ ///
+ /// let path = PathBuf::new();
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> PathBuf {
PathBuf { inner: OsString::new() }
}
- /// Coerces to a `Path` slice.
+ /// Coerces to a [`Path`] slice.
+ ///
+ /// [`Path`]: struct.Path.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::path::{Path, PathBuf};
+ ///
+ /// let p = PathBuf::from("/test");
+ /// assert_eq!(Path::new("/test"), p.as_path());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_path(&self) -> &Path {
self
}
@@ -908,6 +995,7 @@ impl PathBuf {
/// path.push("/etc/passwd");
/// assert_eq!(path, PathBuf::from("/etc/passwd"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn push<P: AsRef<Path>>(&mut self, path: P) {
self._push(path.as_ref())
}
@@ -942,10 +1030,27 @@ impl PathBuf {
self.inner.push(path);
}
- /// Truncate `self` to `self.parent()`.
+ /// Truncate `self` to [`self.parent()`].
///
- /// Returns false and does nothing if `self.file_name()` is `None`.
+ /// Returns false and does nothing if [`self.file_name()`] is `None`.
/// Otherwise, returns `true`.
+ ///
+ /// [`self.parent()`]: struct.PathBuf.html#method.parent
+ /// [`self.file_name()`]: struct.PathBuf.html#method.file_name
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::path::{Path, PathBuf};
+ ///
+ /// let mut p = PathBuf::from("/test/test.rs");
+ ///
+ /// p.pop();
+ /// assert_eq!(Path::new("/test"), p);
+ /// p.pop();
+ /// assert_eq!(Path::new("/"), p);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn pop(&mut self) -> bool {
match self.parent().map(|p| p.as_u8_slice().len()) {
Some(len) => {
@@ -956,11 +1061,13 @@ impl PathBuf {
}
}
- /// Updates `self.file_name()` to `file_name`.
+ /// Updates [`self.file_name()`] to `file_name`.
///
- /// If `self.file_name()` was `None`, this is equivalent to pushing
+ /// If [`self.file_name()`] was `None`, this is equivalent to pushing
/// `file_name`.
///
+ /// [`self.file_name()`]: struct.PathBuf.html#method.file_name
+ ///
/// # Examples
///
/// ```
@@ -974,6 +1081,7 @@ impl PathBuf {
/// buf.set_file_name("baz.txt");
/// assert!(buf == PathBuf::from("/baz.txt"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
self._set_file_name(file_name.as_ref())
}
@@ -986,12 +1094,30 @@ impl PathBuf {
self.push(file_name);
}
- /// Updates `self.extension()` to `extension`.
+ /// Updates [`self.extension()`] to `extension`.
+ ///
+ /// If [`self.file_name()`] is `None`, does nothing and returns `false`.
+ ///
+ /// Otherwise, returns `true`; if [`self.extension()`] is `None`, the
+ /// extension is added; otherwise it is replaced.
+ ///
+ /// [`self.file_name()`]: struct.PathBuf.html#method.file_name
+ /// [`self.extension()`]: struct.PathBuf.html#method.extension
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::path::{Path, PathBuf};
///
- /// If `self.file_name()` is `None`, does nothing and returns `false`.
+ /// let mut p = PathBuf::from("/feel/the");
///
- /// Otherwise, returns `true`; if `self.extension()` is `None`, the extension
- /// is added; otherwise it is replaced.
+ /// p.set_extension("force");
+ /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
+ ///
+ /// p.set_extension("dark_side");
+ /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
self._set_extension(extension.as_ref())
}
@@ -1015,30 +1141,53 @@ impl PathBuf {
true
}
- /// Consumes the `PathBuf`, yielding its internal `OsString` storage.
+ /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.
+ ///
+ /// [`OsString`]: ../ffi/struct.OsString.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::path::PathBuf;
+ ///
+ /// let p = PathBuf::from("/the/head");
+ /// let os_str = p.into_os_string();
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn into_os_string(self) -> OsString {
self.inner
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
fn from(s: &'a T) -> PathBuf {
PathBuf::from(s.as_ref().to_os_string())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl From<OsString> for PathBuf {
fn from(s: OsString) -> PathBuf {
PathBuf { inner: s }
}
}
+#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
+impl From<PathBuf> for OsString {
+ fn from(path_buf : PathBuf) -> OsString {
+ path_buf.inner
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for PathBuf {
fn from(s: String) -> PathBuf {
PathBuf::from(OsString::from(s))
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
let mut buf = PathBuf::new();
@@ -1047,6 +1196,7 @@ impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
for p in iter {
@@ -1055,12 +1205,14 @@ impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for PathBuf {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fmt::Debug::fmt(&**self, formatter)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for PathBuf {
type Target = Path;
@@ -1069,12 +1221,14 @@ impl ops::Deref for PathBuf {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<Path> for PathBuf {
fn borrow(&self) -> &Path {
self.deref()
}
}
+#[stable(feature = "cow_from_path", since = "1.6.0")]
impl<'a> From<&'a Path> for Cow<'a, Path> {
#[inline]
fn from(s: &'a Path) -> Cow<'a, Path> {
@@ -1082,6 +1236,7 @@ impl<'a> From<&'a Path> for Cow<'a, Path> {
}
}
+#[stable(feature = "cow_from_path", since = "1.6.0")]
impl<'a> From<PathBuf> for Cow<'a, Path> {
#[inline]
fn from(s: PathBuf) -> Cow<'a, Path> {
@@ -1089,6 +1244,7 @@ impl<'a> From<PathBuf> for Cow<'a, Path> {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for Path {
type Owned = PathBuf;
fn to_owned(&self) -> PathBuf {
@@ -1096,54 +1252,61 @@ impl ToOwned for Path {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialEq for PathBuf {
fn eq(&self, other: &PathBuf) -> bool {
self.components() == other.components()
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for PathBuf {
fn hash<H: Hasher>(&self, h: &mut H) {
self.as_path().hash(h)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Eq for PathBuf {}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialOrd for PathBuf {
fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
self.components().partial_cmp(other.components())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Ord for PathBuf {
fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
self.components().cmp(other.components())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for PathBuf {
fn as_ref(&self) -> &OsStr {
&self.inner[..]
}
}
-impl Into<OsString> for PathBuf {
- fn into(self) -> OsString {
- self.inner
- }
-}
-
-/// A slice of a path (akin to `str`).
+/// A slice of a path (akin to [`str`]).
///
/// This type supports a number of operations for inspecting a path, including
/// breaking the path into its components (separated by `/` or `\`, depending on
/// the platform), extracting the file name, determining whether the path is
-/// absolute, and so on. More details about the overall approach can be found in
-/// the module documentation.
+/// absolute, and so on.
///
/// This is an *unsized* type, meaning that it must always be used behind a
-/// pointer like `&` or `Box`.
+/// pointer like `&` or [`Box`]. For an owned version of this type,
+/// see [`PathBuf`].
+///
+/// [`str`]: ../primitive.str.html
+/// [`Box`]: ../boxed/struct.Box.html
+/// [`PathBuf`]: struct.PathBuf.html
+///
+/// More details about the overall approach can be found in
+/// the module documentation.
///
/// # Examples
///
@@ -1156,6 +1319,7 @@ impl Into<OsString> for PathBuf {
/// let parent_dir = path.parent();
/// ```
///
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Path {
inner: OsStr,
}
@@ -1163,6 +1327,7 @@ pub struct Path {
/// An error returned from the `Path::strip_prefix` method indicating that the
/// prefix was not found in `self`.
#[derive(Debug, Clone, PartialEq, Eq)]
+#[stable(since = "1.7.0", feature = "strip_prefix")]
pub struct StripPrefixError(());
impl Path {
@@ -1198,11 +1363,14 @@ impl Path {
/// let from_path = Path::new(&from_string);
/// assert_eq!(from_string, from_path);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
unsafe { mem::transmute(s.as_ref()) }
}
- /// Yields the underlying `OsStr` slice.
+ /// Yields the underlying [`OsStr`] slice.
+ ///
+ /// [`OsStr`]: ../ffi/struct.OsStr.html
///
/// # Examples
///
@@ -1212,14 +1380,17 @@ impl Path {
/// let os_str = Path::new("foo.txt").as_os_str();
/// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn as_os_str(&self) -> &OsStr {
&self.inner
}
- /// Yields a `&str` slice if the `Path` is valid unicode.
+ /// Yields a [`&str`] slice if the `Path` is valid unicode.
///
/// This conversion may entail doing a check for UTF-8 validity.
///
+ /// [`&str`]: ../primitive.str.html
+ ///
/// # Examples
///
/// ```
@@ -1228,14 +1399,17 @@ impl Path {
/// let path_str = Path::new("foo.txt").to_str();
/// assert_eq!(path_str, Some("foo.txt"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn to_str(&self) -> Option<&str> {
self.inner.to_str()
}
- /// Converts a `Path` to a `Cow<str>`.
+ /// Converts a `Path` to a [`Cow<str>`].
///
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
///
+ /// [`Cow<str>`]: ../borrow/enum.Cow.html
+ ///
/// # Examples
///
/// ```
@@ -1244,11 +1418,14 @@ impl Path {
/// let path_str = Path::new("foo.txt").to_string_lossy();
/// assert_eq!(path_str, "foo.txt");
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn to_string_lossy(&self) -> Cow<str> {
self.inner.to_string_lossy()
}
- /// Converts a `Path` to an owned `PathBuf`.
+ /// Converts a `Path` to an owned [`PathBuf`].
+ ///
+ /// [`PathBuf`]: struct.PathBuf.html
///
/// # Examples
///
@@ -1258,6 +1435,7 @@ impl Path {
/// let path_buf = Path::new("foo.txt").to_path_buf();
/// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn to_path_buf(&self) -> PathBuf {
PathBuf::from(self.inner.to_os_string())
}
@@ -1277,6 +1455,7 @@ impl Path {
///
/// assert!(!Path::new("foo.txt").is_absolute());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub fn is_absolute(&self) -> bool {
self.has_root() && (cfg!(unix) || self.prefix().is_some())
@@ -1291,6 +1470,7 @@ impl Path {
///
/// assert!(Path::new("foo.txt").is_relative());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn is_relative(&self) -> bool {
!self.is_absolute()
}
@@ -1315,6 +1495,7 @@ impl Path {
///
/// assert!(Path::new("/etc/passwd").has_root());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn has_root(&self) -> bool {
self.components().has_root()
}
@@ -1336,6 +1517,7 @@ impl Path {
/// assert_eq!(grand_parent, Path::new("/"));
/// assert_eq!(grand_parent.parent(), None);
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn parent(&self) -> Option<&Path> {
let mut comps = self.components();
let comp = comps.next_back();
@@ -1375,6 +1557,7 @@ impl Path {
/// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
/// assert_eq!(None, Path::new("foo.txt/..").file_name());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn file_name(&self) -> Option<&OsStr> {
self.components().next_back().and_then(|p| {
match p {
@@ -1390,6 +1573,19 @@ impl Path {
///
/// If `base` is not a prefix of `self` (i.e. `starts_with`
/// returns `false`), returns `Err`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::path::Path;
+ ///
+ /// let path = Path::new("/test/haha/foo.txt");
+ ///
+ /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
+ /// assert_eq!(path.strip_prefix("test").is_ok(), false);
+ /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
+ /// ```
+ #[stable(since = "1.7.0", feature = "path_strip_prefix")]
pub fn strip_prefix<'a, P: ?Sized>(&'a self, base: &'a P)
-> Result<&'a Path, StripPrefixError>
where P: AsRef<Path>
@@ -1419,6 +1615,7 @@ impl Path {
///
/// assert!(!path.starts_with("/e"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
self._starts_with(base.as_ref())
}
@@ -1440,6 +1637,7 @@ impl Path {
///
/// assert!(path.ends_with("passwd"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
self._ends_with(child.as_ref())
}
@@ -1448,7 +1646,9 @@ impl Path {
iter_after(self.components().rev(), child.components().rev()).is_some()
}
- /// Extracts the stem (non-extension) portion of `self.file_name()`.
+ /// Extracts the stem (non-extension) portion of [`self.file_name()`].
+ ///
+ /// [`self.file_name()`]: struct.Path.html#method.file_name
///
/// The stem is:
///
@@ -1466,11 +1666,14 @@ impl Path {
///
/// assert_eq!("foo", path.file_stem().unwrap());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn file_stem(&self) -> Option<&OsStr> {
self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
}
- /// Extracts the extension of `self.file_name()`, if possible.
+ /// Extracts the extension of [`self.file_name()`], if possible.
+ ///
+ /// [`self.file_name()`]: struct.Path.html#method.file_name
///
/// The extension is:
///
@@ -1488,13 +1691,17 @@ impl Path {
///
/// assert_eq!("rs", path.extension().unwrap());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn extension(&self) -> Option<&OsStr> {
self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
}
- /// Creates an owned `PathBuf` with `path` adjoined to `self`.
+ /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
+ ///
+ /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
///
- /// See `PathBuf::push` for more details on what it means to adjoin a path.
+ /// [`PathBuf`]: struct.PathBuf.html
+ /// [`PathBuf::push`]: struct.PathBuf.html#method.push
///
/// # Examples
///
@@ -1503,6 +1710,7 @@ impl Path {
///
/// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
self._join(path.as_ref())
}
@@ -1513,9 +1721,12 @@ impl Path {
buf
}
- /// Creates an owned `PathBuf` like `self` but with the given file name.
+ /// Creates an owned [`PathBuf`] like `self` but with the given file name.
+ ///
+ /// See [`PathBuf::set_file_name`] for more details.
///
- /// See `PathBuf::set_file_name` for more details.
+ /// [`PathBuf`]: struct.PathBuf.html
+ /// [`PathBuf::set_file_name`]: struct.PathBuf.html#method.set_file_name
///
/// # Examples
///
@@ -1525,6 +1736,7 @@ impl Path {
/// let path = Path::new("/tmp/foo.txt");
/// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
self._with_file_name(file_name.as_ref())
}
@@ -1535,9 +1747,12 @@ impl Path {
buf
}
- /// Creates an owned `PathBuf` like `self` but with the given extension.
+ /// Creates an owned [`PathBuf`] like `self` but with the given extension.
///
- /// See `PathBuf::set_extension` for more details.
+ /// See [`PathBuf::set_extension`] for more details.
+ ///
+ /// [`PathBuf`]: struct.PathBuf.html
+ /// [`PathBuf::set_extension`]: struct.PathBuf.html#method.set_extension
///
/// # Examples
///
@@ -1547,6 +1762,7 @@ impl Path {
/// let path = Path::new("foo.rs");
/// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
self._with_extension(extension.as_ref())
}
@@ -1572,6 +1788,7 @@ impl Path {
/// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
/// assert_eq!(components.next(), None)
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn components(&self) -> Components {
let prefix = parse_prefix(self.as_os_str());
Components {
@@ -1583,7 +1800,9 @@ impl Path {
}
}
- /// Produce an iterator over the path's components viewed as `OsStr` slices.
+ /// Produce an iterator over the path's components viewed as [`OsStr`] slices.
+ ///
+ /// [`OsStr`]: ../ffi/struct.OsStr.html
///
/// # Examples
///
@@ -1597,13 +1816,16 @@ impl Path {
/// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
/// assert_eq!(it.next(), None)
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn iter(&self) -> Iter {
Iter { inner: self.components() }
}
- /// Returns an object that implements `Display` for safely printing paths
+ /// Returns an object that implements [`Display`] for safely printing paths
/// that may contain non-Unicode data.
///
+ /// [`Display`]: ../fmt/trait.Display.html
+ ///
/// # Examples
///
/// ```
@@ -1613,16 +1835,12 @@ impl Path {
///
/// println!("{}", path.display());
/// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn display(&self) -> Display {
Display { path: self }
}
- //NOTE: The following functions rely on filesystem functionality that
- //probably have to be implemented in ctru-rs instead of this library,
- //and thus are commented out
-
- /*
/// Query the file system to get information about a file, directory, etc.
///
/// This function will traverse symbolic links to query information about the
@@ -1631,6 +1849,7 @@ impl Path {
/// This is an alias to [`fs::metadata`].
///
/// [`fs::metadata`]: ../fs/fn.metadata.html
+ #[cfg(feature = "fs_not_implemented")]
pub fn metadata(&self) -> io::Result<fs::Metadata> {
fs::metadata(self)
}
@@ -1640,49 +1859,47 @@ impl Path {
/// This is an alias to [`fs::symlink_metadata`].
///
/// [`fs::symlink_metadata`]: ../fs/fn.symlink_metadata.html
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
fs::symlink_metadata(self)
}
-
/// Returns the canonical form of the path with all intermediate components
/// normalized and symbolic links resolved.
///
/// This is an alias to [`fs::canonicalize`].
///
/// [`fs::canonicalize`]: ../fs/fn.canonicalize.html
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn canonicalize(&self) -> io::Result<PathBuf> {
fs::canonicalize(self)
}
-
/// Reads a symbolic link, returning the file that the link points to.
///
/// This is an alias to [`fs::read_link`].
///
/// [`fs::read_link`]: ../fs/fn.read_link.html
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn read_link(&self) -> io::Result<PathBuf> {
fs::read_link(self)
}
-
/// Returns an iterator over the entries within a directory.
///
- /// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
- /// be encountered after an iterator is initially constructed.
+ /// The iterator will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. New
+ /// errors may be encountered after an iterator is initially constructed.
///
/// This is an alias to [`fs::read_dir`].
///
+ /// [`io::Result`]: ../io/type.Result.html
+ /// [`DirEntry`]: ../fs/struct.DirEntry.html
/// [`fs::read_dir`]: ../fs/fn.read_dir.html
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
fs::read_dir(self)
}
-
/// Returns whether the path points at an existing entity.
///
/// This function will traverse symbolic links to query information about the
@@ -1694,12 +1911,11 @@ impl Path {
/// use std::path::Path;
/// assert_eq!(Path::new("does_not_exist.txt").exists(), false);
/// ```
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn exists(&self) -> bool {
fs::metadata(self).is_ok()
}
-
/// Returns whether the path is pointing at a regular file.
///
/// This function will traverse symbolic links to query information about the
@@ -1712,12 +1928,11 @@ impl Path {
/// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
/// assert_eq!(Path::new("a_file.txt").is_file(), true);
/// ```
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn is_file(&self) -> bool {
fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
}
-
/// Returns whether the path is pointing at a directory.
///
/// This function will traverse symbolic links to query information about the
@@ -1730,19 +1945,20 @@ impl Path {
/// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
/// assert_eq!(Path::new("a_file.txt").is_dir(), false);
/// ```
-
+ #[cfg(feature = "fs_not_implemented")]
pub fn is_dir(&self) -> bool {
fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
}
- */
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for Path {
fn as_ref(&self) -> &OsStr {
&self.inner
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Path {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.inner.fmt(formatter)
@@ -1750,28 +1966,33 @@ impl fmt::Debug for Path {
}
/// Helper struct for safely printing paths with `format!()` and `{}`
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct Display<'a> {
path: &'a Path,
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> fmt::Debug for Display<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.path.to_string_lossy(), f)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> fmt::Display for Display<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.path.to_string_lossy(), f)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialEq for Path {
fn eq(&self, other: &Path) -> bool {
self.components().eq(other.components())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for Path {
fn hash<H: Hasher>(&self, h: &mut H) {
for component in self.components() {
@@ -1780,68 +2001,80 @@ impl Hash for Path {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Eq for Path {}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialOrd for Path {
fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
self.components().partial_cmp(other.components())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Ord for Path {
fn cmp(&self, other: &Path) -> cmp::Ordering {
self.components().cmp(other.components())
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for Path {
fn as_ref(&self) -> &Path {
self
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for OsStr {
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
+#[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
impl<'a> AsRef<Path> for Cow<'a, OsStr> {
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for OsString {
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for str {
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for String {
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for PathBuf {
fn as_ref(&self) -> &Path {
self
}
}
+#[stable(feature = "path_into_iter", since = "1.6.0")]
impl<'a> IntoIterator for &'a PathBuf {
type Item = &'a OsStr;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a> { self.iter() }
}
+#[stable(feature = "path_into_iter", since = "1.6.0")]
impl<'a> IntoIterator for &'a Path {
type Item = &'a OsStr;
type IntoIter = Iter<'a>;
@@ -1850,16 +2083,19 @@ impl<'a> IntoIterator for &'a Path {
macro_rules! impl_cmp {
($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "partialeq_path", since = "1.6.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other) }
}
+ #[stable(feature = "partialeq_path", since = "1.6.0")]
impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) }
}
+ #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
@@ -1867,6 +2103,7 @@ macro_rules! impl_cmp {
}
}
+ #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
@@ -1884,16 +2121,19 @@ impl_cmp!(Cow<'a, Path>, PathBuf);
macro_rules! impl_cmp_os_str {
($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other.as_ref()) }
}
+ #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self.as_ref(), other) }
}
+ #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
@@ -1901,6 +2141,7 @@ macro_rules! impl_cmp_os_str {
}
}
+ #[stable(feature = "cmp_path", since = "1.8.0")]
impl<'a, 'b> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
@@ -1925,26 +2166,21 @@ impl_cmp_os_str!(Cow<'a, Path>, OsStr);
impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
impl_cmp_os_str!(Cow<'a, Path>, OsString);
-/*
+#[stable(since = "1.7.0", feature = "strip_prefix")]
impl fmt::Display for StripPrefixError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
-*/
-/*
+#[stable(since = "1.7.0", feature = "strip_prefix")]
impl Error for StripPrefixError {
fn description(&self) -> &str { "prefix not found" }
}
-*/
#[cfg(test)]
mod tests {
use super::*;
- use collections::string::{ToString, String};
- use collections::borrow;
- use collections::Vec;
macro_rules! t(
($path:expr, iter: $iter:expr) => (
@@ -2031,7 +2267,7 @@ mod tests {
#[test]
fn into() {
- use collections::borrow::Cow;
+ use borrow::Cow;
let static_path = Path::new("/home/foo");
let static_cow_path: Cow<'static, Path> = static_path.into();
@@ -3131,7 +3367,7 @@ mod tests {
#[test]
fn test_eq_recievers() {
- use collections::borrow::Cow;
+ use borrow::Cow;
let borrowed: &Path = Path::new("foo/bar");
let mut owned: PathBuf = PathBuf::new();
@@ -3156,10 +3392,11 @@ mod tests {
#[test]
pub fn test_compare() {
- use core::hash::{Hash, Hasher, SipHasher};
+ use hash::{Hash, Hasher};
+ use collections::hash_map::DefaultHasher;
fn hash<T: Hash>(t: T) -> u64 {
- let mut s = SipHasher::new_with_keys(0, 0);
+ let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
@@ -3278,4 +3515,47 @@ mod tests {
);
}
}
+
+ #[test]
+ fn test_components_debug() {
+ let path = Path::new("/tmp");
+
+ let mut components = path.components();
+
+ let expected = "Components([RootDir, Normal(\"tmp\")])";
+ let actual = format!("{:?}", components);
+ assert_eq!(expected, actual);
+
+ let _ = components.next().unwrap();
+ let expected = "Components([Normal(\"tmp\")])";
+ let actual = format!("{:?}", components);
+ assert_eq!(expected, actual);
+
+ let _ = components.next().unwrap();
+ let expected = "Components([])";
+ let actual = format!("{:?}", components);
+ assert_eq!(expected, actual);
+ }
+
+ #[cfg(unix)]
+ #[test]
+ fn test_iter_debug() {
+ let path = Path::new("/tmp");
+
+ let mut iter = path.iter();
+
+ let expected = "Iter([\"/\", \"tmp\"])";
+ let actual = format!("{:?}", iter);
+ assert_eq!(expected, actual);
+
+ let _ = iter.next().unwrap();
+ let expected = "Iter([\"tmp\"])";
+ let actual = format!("{:?}", iter);
+ assert_eq!(expected, actual);
+
+ let _ = iter.next().unwrap();
+ let expected = "Iter([])";
+ let actual = format!("{:?}", iter);
+ assert_eq!(expected, actual);
+ }
}
diff --git a/ctr-std/src/prelude/mod.rs b/ctr-std/src/prelude/mod.rs
new file mode 100644
index 0000000..f4cd319
--- /dev/null
+++ b/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;
diff --git a/ctr-std/src/prelude/v1.rs b/ctr-std/src/prelude/v1.rs
new file mode 100644
index 0000000..9ca5b44
--- /dev/null
+++ b/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;
diff --git a/std/src/rt.rs b/ctr-std/src/rt.rs
index 72f276b..178b5a0 100644
--- a/std/src/rt.rs
+++ b/ctr-std/src/rt.rs
@@ -16,6 +16,12 @@
//! and should be considered as private implementation details for the
//! time being.
+#![unstable(feature = "rt",
+ reason = "this public module should not exist and is highly likely \
+ to disappear",
+ issue = "0")]
+#![doc(hidden)]
+
use mem;
// Reexport some of our utilities which are expected by other crates.
diff --git a/ctr-std/src/sync/mod.rs b/ctr-std/src/sync/mod.rs
new file mode 100644
index 0000000..487c4c9
--- /dev/null
+++ b/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};
diff --git a/ctr-std/src/sys/mod.rs b/ctr-std/src/sys/mod.rs
new file mode 100644
index 0000000..175e227
--- /dev/null
+++ b/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;
diff --git a/ctr-std/src/sys/unix/ext/ffi.rs b/ctr-std/src/sys/unix/ext/ffi.rs
new file mode 100644
index 0000000..d59b4fc
--- /dev/null
+++ b/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
+ }
+}
diff --git a/ctr-std/src/sys/unix/ext/mod.rs b/ctr-std/src/sys/unix/ext/mod.rs
new file mode 100644
index 0000000..04ea563
--- /dev/null
+++ b/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};
+}
diff --git a/ctr-std/src/sys/unix/memchr.rs b/ctr-std/src/sys/unix/memchr.rs
new file mode 100644
index 0000000..d7e9c2b
--- /dev/null
+++ b/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)
+}
diff --git a/ctr-std/src/sys/unix/mod.rs b/ctr-std/src/sys/unix/mod.rs
new file mode 100644
index 0000000..698e31a
--- /dev/null
+++ b/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()
+}
diff --git a/ctr-std/src/sys/unix/os.rs b/ctr-std/src/sys/unix/os.rs
new file mode 100644
index 0000000..de087d9
--- /dev/null
+++ b/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) }
+}
diff --git a/ctr-std/src/sys/unix/os_str.rs b/ctr-std/src/sys/unix/os_str.rs
new file mode 100644
index 0000000..5a733c0
--- /dev/null
+++ b/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() }
+ }
+}
diff --git a/ctr-std/src/sys/unix/path.rs b/ctr-std/src/sys/unix/path.rs
new file mode 100644
index 0000000..bf9af7a
--- /dev/null
+++ b/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 = '/';
diff --git a/ctr-std/src/sys_common/io.rs b/ctr-std/src/sys_common/io.rs
new file mode 100644
index 0000000..23daeeb
--- /dev/null
+++ b/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) }
+ });
+ }
+}
diff --git a/ctr-std/src/sys_common/mod.rs b/ctr-std/src/sys_common/mod.rs
new file mode 100644
index 0000000..38057b8
--- /dev/null
+++ b/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);
+}
diff --git a/ctru-sys/Cargo.toml b/ctru-sys/Cargo.toml
index 578ee82..fa204ee 100644
--- a/ctru-sys/Cargo.toml
+++ b/ctru-sys/Cargo.toml
@@ -1,5 +1,8 @@
[package]
name = "ctru-sys"
-version = "0.2.0"
+version = "0.3.0"
authors = ["Ronald Kinard <[email protected]>"]
license = "https://en.wikipedia.org/wiki/Zlib_License"
+
+[dependencies]
+ctr-libc = { path = "../ctr-libc", default-features = false }
diff --git a/ctru-sys/src/applets/mod.rs b/ctru-sys/src/applets/mod.rs
new file mode 100644
index 0000000..73469a3
--- /dev/null
+++ b/ctru-sys/src/applets/mod.rs
@@ -0,0 +1 @@
+pub mod swkbd;
diff --git a/ctru-sys/src/applets/swkbd.rs b/ctru-sys/src/applets/swkbd.rs
new file mode 100644
index 0000000..3fba279
--- /dev/null
+++ b/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;
+}
diff --git a/ctru-sys/src/lib.rs b/ctru-sys/src/lib.rs
index fdfae33..5bbc54d 100644
--- a/ctru-sys/src/lib.rs
+++ b/ctru-sys/src/lib.rs
@@ -2,18 +2,23 @@
* 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 --sysroot=$DEVKITARM/arm-none-eabi -I$CTRULIB/include $CTRULIB/include/3ds.h
*/
#![no_std]
#![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 env;
pub mod gfx;
pub mod gpu;
pub mod ipc;
+pub mod ndsp;
pub mod os;
+pub mod romfs;
pub mod sdmc;
pub mod services;
pub mod svc;
diff --git a/ctru-sys/src/ndsp/channel.rs b/ctru-sys/src/ndsp/channel.rs
new file mode 100644
index 0000000..be5b91e
--- /dev/null
+++ b/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;
+}
diff --git a/ctru-sys/src/ndsp/mod.rs b/ctru-sys/src/ndsp/mod.rs
new file mode 100644
index 0000000..bfebfe6
--- /dev/null
+++ b/ctru-sys/src/ndsp/mod.rs
@@ -0,0 +1,2 @@
+pub mod channel;
+pub mod ndsp;
diff --git a/ctru-sys/src/ndsp/ndsp.rs b/ctru-sys/src/ndsp/ndsp.rs
new file mode 100644
index 0000000..6139f26
--- /dev/null
+++ b/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::*;
diff --git a/ctru-sys/src/os.rs b/ctru-sys/src/os.rs
index 768ece0..c3dff74 100644
--- a/ctru-sys/src/os.rs
+++ b/ctru-sys/src/os.rs
@@ -1,53 +1,47 @@
-//TODO: Fix Bindgen's issues again.
+/* automatically generated by rust-bindgen */
-use libc::c_void;
-use types::*;
-
-#[inline]
-pub fn SYSTEM_VERSION(major: i32, minor: i32, revision: i32) {
- (((major)<<24)|((minor)<<16)|((revision)<<8));
-}
-
-#[derive(Clone, Copy)]
-#[repr(C)]
-pub enum Enum_Unnamed1 {
+#![allow(dead_code,
+ non_camel_case_types,
+ non_upper_case_globals,
+ non_snake_case)]
+#[derive(Copy, Clone)]
+#[repr(u32)]
+#[derive(Debug)]
+pub enum MemRegion {
MEMREGION_ALL = 0,
MEMREGION_APPLICATION = 1,
MEMREGION_SYSTEM = 2,
MEMREGION_BASE = 3,
}
-pub type MemRegion = Enum_Unnamed1;
#[repr(C)]
-#[derive(Copy)]
-pub struct Struct_Unnamed2 {
- pub build: u8,
- pub minor: u8,
- pub mainver: u8,
- pub reserved_x3: u8,
- pub region: u8,
- pub reserved_x5: [u8; 3usize],
-}
-impl ::core::clone::Clone for Struct_Unnamed2 {
- fn clone(&self) -> Self { *self }
+#[derive(Copy, Clone)]
+#[derive(Debug)]
+pub struct OS_VersionBin {
+ pub build: u8_,
+ pub minor: u8_,
+ pub mainver: u8_,
+ pub reserved_x3: u8_,
+ pub region: ::libc::c_char,
+ pub reserved_x5: [u8_; 3usize],
}
-impl ::core::default::Default for Struct_Unnamed2 {
+impl ::core::default::Default for OS_VersionBin {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
-pub type OS_VersionBin = Struct_Unnamed2;
extern "C" {
- pub fn osConvertVirtToPhys(vaddr: *const c_void) -> u32;
- pub fn osConvertOldLINEARMemToNew(vaddr: *const c_void)
- -> *mut c_void;
- pub fn osStrError(error: u32) -> *const u8;
+ pub fn osConvertVirtToPhys(vaddr: *const ::libc::c_void) -> u32_;
+ pub fn osConvertOldLINEARMemToNew(vaddr: *const ::libc::c_void)
+ -> *mut ::libc::c_void;
+ pub fn osStrError(error: u32_) -> *const ::libc::c_char;
pub fn osGetMemRegionUsed(region: MemRegion) -> s64;
- pub fn osGetTime() -> u64;
+ pub fn osGetTime() -> u64_;
pub fn osSetSpeedupEnable(enable: u8);
pub fn osGetSystemVersionData(nver_versionbin: *mut OS_VersionBin,
cver_versionbin: *mut OS_VersionBin)
-> Result;
pub fn osGetSystemVersionDataString(nver_versionbin: *mut OS_VersionBin,
cver_versionbin: *mut OS_VersionBin,
- sysverstr:
- *mut u8,
- sysverstr_maxsize: u32) -> Result;
+ sysverstr: *mut ::libc::c_char,
+ sysverstr_maxsize: u32_) -> Result;
}
+
+use ::types::*;
diff --git a/ctru-sys/src/romfs.rs b/ctru-sys/src/romfs.rs
new file mode 100644
index 0000000..dc25e39
--- /dev/null
+++ b/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::*;
diff --git a/ctru-sys/src/sdmc.rs b/ctru-sys/src/sdmc.rs
index ee70839..9cf1209 100644
--- a/ctru-sys/src/sdmc.rs
+++ b/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" {
pub fn sdmcInit() -> Result;
+ pub fn sdmcWriteSafe(enable: u8);
pub fn sdmcExit() -> Result;
+ pub fn sdmc_getmtime(name: *const ::libc::c_char, mtime: *mut u64_)
+ -> Result;
}
diff --git a/ctru-sys/src/services/apt.rs b/ctru-sys/src/services/apt.rs
index 22acd27..d713102 100644
--- a/ctru-sys/src/services/apt.rs
+++ b/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,
sender: NS_APPID,
msg: *mut ::libc::c_void,
- msgsize: size_t)>;
+ msgsize: ::libc::size_t)>;
extern "C" {
pub fn aptInit() -> Result;
pub fn aptExit();
@@ -157,7 +157,7 @@ extern "C" {
pub fn aptSetMessageCallback(callback: aptMessageCb,
user: *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_Initialize(appId: NS_APPID, attr: APT_AppletAttr,
signalEvent: *mut Handle, resumeEvent: *mut Handle)
@@ -178,31 +178,31 @@ extern "C" {
titleversion: *mut u16_) -> Result;
pub fn APT_GetProgramID(pProgramID: *mut u64_) -> 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;
pub fn APT_PrepareToJumpToApplication(exiting: u8) -> Result;
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_InquireNotification(appID: u32_, signalType: *mut APT_Signal)
-> Result;
pub fn APT_NotifyToWait(appID: NS_APPID) -> Result;
pub fn APT_AppletUtility(id: ::libc::c_int, out: *mut ::libc::c_void,
- outSize: size_t, in_: *const ::libc::c_void,
- inSize: size_t) -> Result;
+ outSize: ::libc::size_t, in_: *const ::libc::c_void,
+ inSize: ::libc::size_t) -> Result;
pub fn APT_SleepIfShellClosed() -> Result;
pub fn APT_TryLockTransition(transition: u32_, succeeded: *mut u8)
-> Result;
pub fn APT_UnlockTransition(transition: u32_) -> Result;
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,
- actualSize: *mut size_t,
+ actualSize: *mut ::libc::size_t,
parameter: *mut Handle) -> Result;
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,
- actualSize: *mut size_t,
+ actualSize: *mut ::libc::size_t,
parameter: *mut Handle) -> Result;
pub fn APT_SendParameter(source: NS_APPID, dest: NS_APPID,
command: APT_Command,
@@ -217,24 +217,24 @@ extern "C" {
pub fn APT_ReplySleepNotificationComplete(appID: NS_APPID) -> Result;
pub fn APT_PrepareToCloseApplication(cancelPreload: u8) -> Result;
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_GetAppCpuTimeLimit(percent: *mut u32_) -> Result;
pub fn APT_CheckNew3DS(out: *mut u8) -> Result;
pub fn APT_PrepareToDoApplicationJump(flags: u8_, programID: u64_,
mediatype: u8_) -> Result;
pub fn APT_DoApplicationJump(param: *const ::libc::c_void,
- paramSize: size_t,
+ paramSize: ::libc::size_t,
hmac: *const ::libc::c_void) -> Result;
pub fn APT_PrepareToStartLibraryApplet(appID: NS_APPID) -> Result;
pub fn APT_StartLibraryApplet(appID: NS_APPID,
param: *const ::libc::c_void,
- paramSize: size_t, handle: Handle)
+ paramSize: ::libc::size_t, handle: Handle)
-> Result;
pub fn APT_PrepareToStartSystemApplet(appID: NS_APPID) -> Result;
pub fn APT_StartSystemApplet(appID: NS_APPID,
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_)
-> Result;
}
diff --git a/ctru-sys/src/services/mod.rs b/ctru-sys/src/services/mod.rs
index 30d0f68..880b32d 100644
--- a/ctru-sys/src/services/mod.rs
+++ b/ctru-sys/src/services/mod.rs
@@ -25,7 +25,6 @@ pub mod ptmsysm;
pub mod ptmu;
pub mod pxidev;
pub mod qtm;
-pub mod soc;
pub mod srvpm;
pub mod sslc;
pub mod uds;
diff --git a/ctru-sys/src/services/nfc.rs b/ctru-sys/src/services/nfc.rs
index 09a6a63..c6ac09e 100644
--- a/ctru-sys/src/services/nfc.rs
+++ b/ctru-sys/src/services/nfc.rs
@@ -116,10 +116,10 @@ extern "C" {
pub fn nfcGetTagInfo(out: *mut NFC_TagInfo) -> Result;
pub fn nfcOpenAppData(amiibo_appid: u32_) -> Result;
pub fn nfcInitializeWriteAppData(amiibo_appid: u32_,
- buf: *const ::libc::c_void, size: size_t)
+ buf: *const ::libc::c_void, size: ::libc::size_t)
-> Result;
- pub fn nfcReadAppData(buf: *mut ::libc::c_void, size: size_t) -> Result;
- pub fn nfcWriteAppData(buf: *const ::libc::c_void, size: size_t,
+ pub fn nfcReadAppData(buf: *mut ::libc::c_void, size: ::libc::size_t) -> Result;
+ pub fn nfcWriteAppData(buf: *const ::libc::c_void, size: ::libc::size_t,
taginfo: *mut NFC_TagInfo) -> Result;
pub fn nfcGetAmiiboSettings(out: *mut NFC_AmiiboSettings) -> Result;
pub fn nfcGetAmiiboConfig(out: *mut NFC_AmiiboConfig) -> Result;
diff --git a/ctru-sys/src/services/ps.rs b/ctru-sys/src/services/ps.rs
index 8198dbb..3a1e16c 100644
--- a/ctru-sys/src/services/ps.rs
+++ b/ctru-sys/src/services/ps.rs
@@ -47,7 +47,7 @@ extern "C" {
nonce: *mut u8_) -> Result;
pub fn PS_GetLocalFriendCodeSeed(seed: *mut u64_) -> 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;
}
use ::types::*;
diff --git a/ctru-sys/src/services/soc.rs b/ctru-sys/src/services/soc.rs
index 8fa7a3d..94ac632 100644
--- a/ctru-sys/src/services/soc.rs
+++ b/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 socExit() -> Result;
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;
pub fn SOCU_ShutdownSockets() -> ::libc::c_int;
pub fn SOCU_CloseSockets() -> ::libc::c_int;
diff --git a/ctru-sys/src/services/sslc.rs b/ctru-sys/src/services/sslc.rs
index 5a18e59..f310269 100644
--- a/ctru-sys/src/services/sslc.rs
+++ b/ctru-sys/src/services/sslc.rs
@@ -89,9 +89,9 @@ extern "C" {
internal_retval: *mut ::libc::c_int,
out: *mut u32_) -> Result;
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,
- len: size_t) -> Result;
+ len: ::libc::size_t) -> Result;
pub fn sslcContextSetRootCertChain(context: *mut sslcContext,
handle: u32_) -> Result;
pub fn sslcContextSetClientCert(context: *mut sslcContext, handle: u32_)
diff --git a/ctru-sys/src/svc.rs b/ctru-sys/src/svc.rs
index 88a6992..fb41bc0 100644
--- a/ctru-sys/src/svc.rs
+++ b/ctru-sys/src/svc.rs
@@ -4,10 +4,6 @@
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
-
-use ::{Handle, Result};
-use ::ThreadFunc;
-
#[derive(Copy, Clone)]
#[repr(u32)]
#[derive(Debug)]
@@ -56,10 +52,10 @@ pub enum MemPerm {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct MemInfo {
- pub base_addr: u32,
- pub size: u32,
- pub perm: u32,
- pub state: u32,
+ pub base_addr: u32_,
+ pub size: u32_,
+ pub perm: u32_,
+ pub state: u32_,
}
impl ::core::default::Default for MemInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -68,7 +64,7 @@ impl ::core::default::Default for MemInfo {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct PageInfo {
- pub flags: u32,
+ pub flags: u32_,
}
impl ::core::default::Default for PageInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -99,10 +95,10 @@ pub enum ProcessEventReason { REASON_CREATE = 1, REASON_ATTACH = 2, }
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct ProcessEvent {
- pub program_id: u64,
- pub process_name: [u8; 8usize],
- pub process_id: u32,
- pub reason: u32,
+ pub program_id: u64_,
+ pub process_name: [u8_; 8usize],
+ pub process_id: u32_,
+ pub reason: u32_,
}
impl ::core::default::Default for ProcessEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -119,7 +115,7 @@ pub enum ExitProcessEventReason {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct ExitProcessEvent {
- pub reason: u32,
+ pub reason: u32_,
}
impl ::core::default::Default for ExitProcessEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -128,9 +124,9 @@ impl ::core::default::Default for ExitProcessEvent {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct CreateThreadEvent {
- pub creator_thread_id: u32,
- pub base_addr: u32,
- pub entry_point: u32,
+ pub creator_thread_id: u32_,
+ pub base_addr: u32_,
+ pub entry_point: u32_,
}
impl ::core::default::Default for CreateThreadEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -148,7 +144,7 @@ pub enum ExitThreadEventReason {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct ExitThreadEvent {
- pub reason: u32,
+ pub reason: u32_,
}
impl ::core::default::Default for ExitThreadEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -179,9 +175,9 @@ pub enum ExceptionEventType {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct ExceptionEvent {
- pub type_: u32,
- pub address: u32,
- pub argument: u32,
+ pub type_: u32_,
+ pub address: u32_,
+ pub argument: u32_,
}
impl ::core::default::Default for ExceptionEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -190,7 +186,7 @@ impl ::core::default::Default for ExceptionEvent {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct SchedulerInOutEvent {
- pub clock_tick: u64,
+ pub clock_tick: u64_,
}
impl ::core::default::Default for SchedulerInOutEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -199,8 +195,8 @@ impl ::core::default::Default for SchedulerInOutEvent {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct SyscallInOutEvent {
- pub clock_tick: u64,
- pub syscall: u32,
+ pub clock_tick: u64_,
+ pub syscall: u32_,
_bindgen_padding_0_: [u8; 4usize],
}
impl ::core::default::Default for SyscallInOutEvent {
@@ -210,8 +206,8 @@ impl ::core::default::Default for SyscallInOutEvent {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct OutputStringEvent {
- pub string_addr: u32,
- pub string_size: u32,
+ pub string_addr: u32_,
+ pub string_size: u32_,
}
impl ::core::default::Default for OutputStringEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -220,10 +216,10 @@ impl ::core::default::Default for OutputStringEvent {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct MapEvent {
- pub mapped_addr: u32,
- pub mapped_size: u32,
- pub memperm: u32,
- pub memstate: u32,
+ pub mapped_addr: u32_,
+ pub mapped_size: u32_,
+ pub memperm: u32_,
+ pub memstate: u32_,
}
impl ::core::default::Default for MapEvent {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -250,9 +246,9 @@ pub enum DebugEventType {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct DebugEventInfo {
- pub type_: u32,
- pub thread_id: u32,
- pub unknown: [u32; 2usize],
+ pub type_: u32_,
+ pub thread_id: u32_,
+ pub unknown: [u32_; 2usize],
pub _bindgen_data_1_: [u64; 3usize],
}
impl DebugEventInfo {
@@ -300,21 +296,21 @@ impl ::core::default::Default for DebugEventInfo {
#[derive(Copy, Clone)]
#[derive(Debug)]
pub struct CodeSetInfo {
- pub name: [u8; 8usize],
- pub unk1: u16,
- pub unk2: u16,
- pub unk3: u32,
- pub text_addr: u32,
- pub text_size: u32,
- pub ro_addr: u32,
- pub ro_size: u32,
- pub rw_addr: u32,
- pub rw_size: u32,
- pub text_size_total: u32,
- pub ro_size_total: u32,
- pub rw_size_total: u32,
- pub unk4: u32,
- pub program_id: u64,
+ pub name: [u8_; 8usize],
+ pub unk1: u16_,
+ pub unk2: u16_,
+ pub unk3: u32_,
+ pub text_addr: u32_,
+ pub text_size: u32_,
+ pub ro_addr: u32_,
+ pub ro_size: u32_,
+ pub rw_addr: u32_,
+ pub rw_size: u32_,
+ pub text_size_total: u32_,
+ pub ro_size_total: u32_,
+ pub rw_size_total: u32_,
+ pub unk4: u32_,
+ pub program_id: u64_,
}
impl ::core::default::Default for CodeSetInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
@@ -324,62 +320,62 @@ impl ::core::default::Default for CodeSetInfo {
#[derive(Debug)]
pub struct StartupInfo {
pub priority: ::libc::c_int,
- pub stack_size: u32,
+ pub stack_size: u32_,
pub argc: ::libc::c_int,
- pub argv: *mut u16,
- pub envp: *mut u16,
+ pub argv: *mut u16_,
+ pub envp: *mut u16_,
}
impl ::core::default::Default for StartupInfo {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
extern "C" {
- pub fn svcControlMemory(addr_out: *mut u32, addr0: u32, addr1: u32,
- size: u32, op: MemOp, perm: MemPerm) -> Result;
- pub fn svcControlProcessMemory(process: Handle, addr0: u32, addr1: u32,
- size: u32, type_: u32, perm: u32)
+ pub fn svcControlMemory(addr_out: *mut u32_, addr0: u32_, addr1: u32_,
+ size: u32_, op: MemOp, perm: MemPerm) -> Result;
+ pub fn svcControlProcessMemory(process: Handle, addr0: u32_, addr1: u32_,
+ size: u32_, type_: u32_, perm: u32_)
-> 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)
-> 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;
- pub fn svcMapProcessMemory(process: Handle, startAddr: u32,
- endAddr: u32) -> Result;
- pub fn svcUnmapProcessMemory(process: Handle, startAddr: u32,
- endAddr: u32) -> Result;
- pub fn svcUnmapMemoryBlock(memblock: Handle, addr: u32) -> Result;
+ pub fn svcMapProcessMemory(process: Handle, startAddr: u32_,
+ endAddr: u32_) -> Result;
+ pub fn svcUnmapProcessMemory(process: Handle, startAddr: u32_,
+ endAddr: u32_) -> Result;
+ pub fn svcUnmapMemoryBlock(memblock: Handle, addr: u32_) -> Result;
pub fn svcStartInterProcessDma(dma: *mut Handle, dstProcess: Handle,
dst: *mut ::libc::c_void,
srcProcess: Handle,
- src: *const ::libc::c_void, size: u32,
+ src: *const ::libc::c_void, size: u32_,
dmaConfig: *mut ::libc::c_void) -> Result;
pub fn svcStopDma(dma: Handle) -> Result;
pub fn svcGetDmaState(dmaState: *mut ::libc::c_void, dma: Handle)
-> Result;
- pub fn svcQueryMemory(info: *mut MemInfo, out: *mut PageInfo, addr: u32)
+ pub fn svcQueryMemory(info: *mut MemInfo, out: *mut PageInfo, addr: u32_)
-> Result;
pub fn svcQueryProcessMemory(info: *mut MemInfo, out: *mut PageInfo,
- process: Handle, addr: u32) -> Result;
+ process: Handle, addr: u32_) -> Result;
pub fn svcInvalidateProcessDataCache(process: Handle,
addr: *mut ::libc::c_void,
- size: u32) -> Result;
+ size: u32_) -> Result;
pub fn svcFlushProcessDataCache(process: Handle,
- addr: *const ::libc::c_void, size: u32)
+ addr: *const ::libc::c_void, size: u32_)
-> Result;
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,
- addr: u32, size: u32) -> Result;
- pub fn svcOpenProcess(process: *mut Handle, processId: u32) -> Result;
+ addr: u32_, size: u32_) -> Result;
+ pub fn svcOpenProcess(process: *mut Handle, processId: u32_) -> Result;
pub fn svcExitProcess();
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;
- pub fn svcGetProcessId(out: *mut u32, handle: Handle) -> Result;
- pub fn svcGetProcessList(processCount: *mut i32, processIds: *mut u32,
- processIdMaxCount: i32) -> Result;
+ pub fn svcGetProcessId(out: *mut u32_, handle: Handle) -> Result;
+ pub fn svcGetProcessList(processCount: *mut s32, processIds: *mut u32_,
+ processIdMaxCount: s32) -> Result;
pub fn svcCreatePort(portServer: *mut Handle, portClient: *mut Handle,
- name: *const ::libc::c_char, maxSessions: i32)
+ name: *const ::libc::c_char, maxSessions: s32)
-> Result;
pub fn svcConnectToPort(out: *mut Handle, portName: *const ::libc::c_char)
-> Result;
@@ -388,94 +384,96 @@ extern "C" {
ro_ptr: *mut ::libc::c_void,
data_ptr: *mut ::libc::c_void) -> Result;
pub fn svcCreateProcess(out: *mut Handle, codeset: Handle,
- arm11kernelcaps: *const u32,
- arm11kernelcaps_num: u32) -> Result;
+ arm11kernelcaps: *const u32_,
+ arm11kernelcaps_num: u32_) -> Result;
pub fn svcSetProcessAffinityMask(process: Handle,
- affinitymask: *const u8,
- processorcount: i32) -> Result;
- pub fn svcSetProcessIdealProcessor(process: Handle, processorid: i32)
+ affinitymask: *const u8_,
+ processorcount: s32) -> Result;
+ pub fn svcSetProcessIdealProcessor(process: Handle, processorid: s32)
-> Result;
pub fn svcRun(process: Handle, info: *const StartupInfo) -> Result;
pub fn svcCreateThread(thread: *mut Handle, entrypoint: ThreadFunc,
- arg: u32, stack_top: *mut u32,
- thread_priority: i32, processor_id: i32) -> Result;
- pub fn svcOpenThread(thread: *mut Handle, process: Handle, threadId: u32)
+ arg: u32_, stack_top: *mut u32_,
+ thread_priority: s32, processor_id: s32) -> Result;
+ pub fn svcOpenThread(thread: *mut Handle, process: Handle, threadId: u32_)
-> Result;
pub fn svcExitThread();
- pub fn svcSleepThread(ns: i64);
- pub fn svcGetThreadPriority(out: *mut i32, handle: Handle) -> Result;
- pub fn svcSetThreadPriority(thread: Handle, prio: i32) -> Result;
- pub fn svcGetThreadAffinityMask(affinitymask: *mut u8, thread: Handle,
- processorcount: i32) -> Result;
- pub fn svcSetThreadAffinityMask(thread: Handle, affinitymask: *const u8,
- processorcount: i32) -> Result;
- pub fn svcGetThreadIdealProcessor(processorid: *mut i32, thread: Handle)
+ pub fn svcSleepThread(ns: s64);
+ pub fn svcGetThreadPriority(out: *mut s32, handle: Handle) -> Result;
+ pub fn svcSetThreadPriority(thread: Handle, prio: s32) -> Result;
+ pub fn svcGetThreadAffinityMask(affinitymask: *mut u8_, thread: Handle,
+ processorcount: s32) -> Result;
+ pub fn svcSetThreadAffinityMask(thread: Handle, affinitymask: *const u8_,
+ processorcount: s32) -> Result;
+ pub fn svcGetThreadIdealProcessor(processorid: *mut s32, thread: Handle)
-> Result;
- pub fn svcSetThreadIdealProcessor(thread: Handle, processorid: i32)
+ pub fn svcSetThreadIdealProcessor(thread: Handle, processorid: s32)
-> Result;
- pub fn svcGetProcessorID() -> i32;
- pub fn svcGetThreadId(out: *mut u32, handle: Handle) -> Result;
+ pub fn svcGetProcessorID() -> s32;
+ pub fn svcGetThreadId(out: *mut u32_, handle: Handle) -> Result;
pub fn svcGetResourceLimit(resourceLimit: *mut Handle, process: Handle)
-> Result;
- pub fn svcGetResourceLimitLimitValues(values: *mut i64,
+ pub fn svcGetResourceLimitLimitValues(values: *mut s64,
resourceLimit: Handle,
- names: *mut u32, nameCount: i32)
+ names: *mut u32_, nameCount: s32)
-> Result;
- pub fn svcGetResourceLimitCurrentValues(values: *mut i64,
+ pub fn svcGetResourceLimitCurrentValues(values: *mut s64,
resourceLimit: Handle,
- names: *mut u32, nameCount: i32)
+ names: *mut u32_, nameCount: s32)
-> Result;
- pub fn svcGetProcessIdOfThread(out: *mut u32, handle: Handle) -> Result;
- pub fn svcGetThreadInfo(out: *mut i64, thread: Handle,
+ pub fn svcGetProcessIdOfThread(out: *mut u32_, handle: Handle) -> Result;
+ pub fn svcGetThreadInfo(out: *mut s64, thread: Handle,
type_: ThreadInfoType) -> Result;
pub fn svcCreateMutex(mutex: *mut Handle, initially_locked: u8) -> Result;
pub fn svcReleaseMutex(handle: Handle) -> Result;
- pub fn svcCreateSemaphore(semaphore: *mut Handle, initial_count: i32,
- max_count: i32) -> Result;
- pub fn svcReleaseSemaphore(count: *mut i32, semaphore: Handle,
- release_count: i32) -> Result;
+ pub fn svcCreateSemaphore(semaphore: *mut Handle, initial_count: s32,
+ max_count: s32) -> Result;
+ pub fn svcReleaseSemaphore(count: *mut s32, semaphore: Handle,
+ release_count: s32) -> Result;
pub fn svcCreateEvent(event: *mut Handle, reset_type: ResetType)
-> Result;
pub fn svcSignalEvent(handle: Handle) -> Result;
pub fn svcClearEvent(handle: Handle) -> Result;
- pub fn svcWaitSynchronization(handle: Handle, nanoseconds: i64) -> Result;
- pub fn svcWaitSynchronizationN(out: *mut i32, handles: *mut Handle,
- handles_num: i32, wait_all: u8,
- nanoseconds: i64) -> Result;
+ pub fn svcWaitSynchronization(handle: Handle, nanoseconds: s64) -> Result;
+ pub fn svcWaitSynchronizationN(out: *mut s32, handles: *mut Handle,
+ handles_num: s32, wait_all: u8,
+ nanoseconds: s64) -> Result;
pub fn svcCreateAddressArbiter(arbiter: *mut Handle) -> Result;
- pub fn svcArbitrateAddress(arbiter: Handle, addr: u32,
- type_: ArbitrationType, value: i32,
- nanoseconds: i64) -> Result;
+ pub fn svcArbitrateAddress(arbiter: Handle, addr: u32_,
+ type_: ArbitrationType, value: s32,
+ nanoseconds: s64) -> Result;
pub fn svcSendSyncRequest(session: Handle) -> Result;
pub fn svcAcceptSession(session: *mut Handle, port: Handle) -> Result;
- pub fn svcReplyAndReceive(index: *mut i32, handles: *mut Handle,
- handleCount: i32, replyTarget: Handle)
+ pub fn svcReplyAndReceive(index: *mut s32, handles: *mut Handle,
+ handleCount: s32, replyTarget: Handle)
-> Result;
- pub fn svcBindInterrupt(interruptId: u32, event: Handle, priority: i32,
+ pub fn svcBindInterrupt(interruptId: u32_, event: Handle, priority: s32,
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)
-> 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 svcClearTimer(timer: Handle) -> Result;
- pub fn svcGetSystemTick() -> u64;
+ pub fn svcGetSystemTick() -> u64_;
pub fn svcCloseHandle(handle: Handle) -> Result;
pub fn svcDuplicateHandle(out: *mut Handle, original: Handle) -> Result;
- pub fn svcGetSystemInfo(out: *mut i64, type_: u32, param: i32) -> Result;
- pub fn svcKernelSetState(type_: u32, param0: u32, param1: u32,
- param2: u32) -> Result;
+ pub fn svcGetSystemInfo(out: *mut s64, type_: u32_, param: s32) -> Result;
+ pub fn svcKernelSetState(type_: u32_, param0: u32_, param1: u32_,
+ param2: u32_) -> Result;
pub fn svcBreak(breakReason: UserBreakType);
pub fn svcOutputDebugString(str: *const ::libc::c_char,
length: ::libc::c_int) -> Result;
- pub fn svcDebugActiveProcess(debug: *mut Handle, processId: u32)
+ pub fn svcDebugActiveProcess(debug: *mut Handle, processId: u32_)
-> Result;
pub fn svcBreakDebugProcess(debug: Handle) -> Result;
pub fn svcTerminateDebugProcess(debug: Handle) -> Result;
pub fn svcGetProcessDebugEvent(info: *mut DebugEventInfo, debug: Handle)
-> Result;
- pub fn svcContinueDebugEvent(debug: Handle, flags: u32) -> Result;
+ pub fn svcContinueDebugEvent(debug: Handle, flags: u32_) -> Result;
pub fn svcBackdoor(callback:
- ::core::option::Option<extern "C" fn() -> i32>)
+ ::core::option::Option<extern "C" fn() -> s32>)
-> Result;
}
+
+use ::types::*;
diff --git a/ctru-sys/src/sys/inaddr.rs b/ctru-sys/src/sys/inaddr.rs
index f16e233..d188f2c 100644
--- a/ctru-sys/src/sys/inaddr.rs
+++ b/ctru-sys/src/sys/inaddr.rs
@@ -5,11 +5,10 @@
non_upper_case_globals,
non_snake_case)]
-use ::types::*;
use super::socket::*;
-pub type in_port_t = uint16_t;
-pub type in_addr_t = uint32_t;
+pub type in_port_t = ::libc::uint16_t;
+pub type in_addr_t = ::libc::uint32_t;
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
@@ -41,4 +40,3 @@ pub struct ip_mreq {
impl ::core::default::Default for ip_mreq {
fn default() -> Self { unsafe { ::core::mem::zeroed() } }
}
-
diff --git a/ctru-sys/src/sys/libc.rs b/ctru-sys/src/sys/libc.rs
index ab8eb7c..3ae6456 100644
--- a/ctru-sys/src/sys/libc.rs
+++ b/ctru-sys/src/sys/libc.rs
@@ -85,8 +85,8 @@ pub type fsblkcnt_t = c_uint;
pub type fsfilcnt_t = c_uint;
extern "C" {
- 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 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: ::libc::size_t) -> *mut c_void;
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;
}
diff --git a/ctru-sys/src/sys/mod.rs b/ctru-sys/src/sys/mod.rs
index af15a1c..d2d4cbe 100644
--- a/ctru-sys/src/sys/mod.rs
+++ b/ctru-sys/src/sys/mod.rs
@@ -1,4 +1,3 @@
-pub mod libc;
pub mod lock;
-pub mod socket;
pub mod inaddr;
+pub mod socket;
diff --git a/ctru-sys/src/sys/socket.rs b/ctru-sys/src/sys/socket.rs
index ec544dc..19d1cb1 100644
--- a/ctru-sys/src/sys/socket.rs
+++ b/ctru-sys/src/sys/socket.rs
@@ -4,8 +4,8 @@
non_camel_case_types,
non_upper_case_globals,
non_snake_case)]
-pub type socklen_t = uint32_t;
-pub type sa_family_t = uint16_t;
+pub type socklen_t = ::libc::uint32_t;
+pub type sa_family_t = ::libc::uint16_t;
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Debug)]
@@ -53,17 +53,17 @@ extern "C" {
optlen: *mut socklen_t) -> ::libc::c_int;
pub fn listen(sockfd: ::libc::c_int, backlog: ::libc::c_int)
-> ::libc::c_int;
- pub fn recv(sockfd: ::libc::c_int, buf: *mut ::libc::c_void, len: size_t,
- flags: ::libc::c_int) -> ssize_t;
+ pub fn recv(sockfd: ::libc::c_int, buf: *mut ::libc::c_void, len: ::libc::size_t,
+ flags: ::libc::c_int) -> ::libc::ssize_t;
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)
- -> ssize_t;
+ -> ::libc::ssize_t;
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,
- len: size_t, flags: ::libc::c_int,
- dest_addr: *const sockaddr, addrlen: socklen_t) -> ssize_t;
+ len: ::libc::size_t, flags: ::libc::c_int,
+ dest_addr: *const sockaddr, addrlen: socklen_t) -> ::libc::ssize_t;
pub fn setsockopt(sockfd: ::libc::c_int, level: ::libc::c_int,
optname: ::libc::c_int, optval: *const ::libc::c_void,
optlen: socklen_t) -> ::libc::c_int;
@@ -73,5 +73,3 @@ extern "C" {
protocol: ::libc::c_int) -> ::libc::c_int;
pub fn sockatmark(sockfd: ::libc::c_int) -> ::libc::c_int;
}
-
-use ::types::*;
diff --git a/ctru-sys/src/types.rs b/ctru-sys/src/types.rs
index 92534b7..d5baa88 100644
--- a/ctru-sys/src/types.rs
+++ b/ctru-sys/src/types.rs
@@ -22,10 +22,6 @@ pub type vs32 = s32;
pub type vs64 = s64;
pub type Handle = u32_;
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 =
::core::option::Option<unsafe extern "C" fn(arg1: *mut ::libc::c_void)>;
pub type voidfn = ::core::option::Option<extern "C" fn()>;
diff --git a/src/lib.rs b/src/lib.rs
index a4252a1..bfdb614 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,6 +3,7 @@
#[macro_use]
extern crate bitflags;
+extern crate widestring;
extern crate ctru_sys as libctru;
diff --git a/src/services/fs.rs b/src/services/fs.rs
index 7e80607..cf1a443 100644
--- a/src/services/fs.rs
+++ b/src/services/fs.rs
@@ -8,11 +8,13 @@ use std::marker::PhantomData;
use std::ptr;
use std::slice;
use std::mem;
-use std::arc::Arc;
+use std::sync::Arc;
use std::path::{Path, PathBuf};
use std::ffi::OsString;
+use widestring::{WideCString, WideCStr};
+
use libctru::services::fs::*;
bitflags! {
@@ -616,8 +618,11 @@ impl<'a> DirEntry<'a> {
/// Returns the bare file name of this directory entry without any other leading path
/// component.
pub fn file_name(&self) -> OsString {
- let filename = truncate_utf16_at_nul(&self.entry.name);
- OsString::from_wide(filename)
+ unsafe {
+ 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
-fn to_utf16(path: &Path) -> Vec<u16> {
- path.as_os_str().encode_wide().collect::<Vec<_>>()
+fn to_utf16(path: &Path) -> WideCString {
+ WideCString::from_str(path).unwrap()
}
// Adapted from sys/windows/fs.rs in libstd
diff --git a/std/Cargo.toml b/std/Cargo.toml
deleted file mode 100644
index f23c3c2..0000000
--- a/std/Cargo.toml
+++ /dev/null
@@ -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"
diff --git a/std/src/ffi/mod.rs b/std/src/ffi/mod.rs
deleted file mode 100644
index d4ed3a7..0000000
--- a/std/src/ffi/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-pub use self::c_str::{CString, CStr};
-pub use self::os_str::{OsString, OsStr};
-
-mod c_str;
-mod os_str;
diff --git a/std/src/lib.rs b/std/src/lib.rs
deleted file mode 100644
index 48d0e1d..0000000
--- a/std/src/lib.rs
+++ /dev/null
@@ -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;
diff --git a/std/src/macros.rs b/std/src/macros.rs
deleted file mode 100644
index f1a5b75..0000000
--- a/std/src/macros.rs
+++ /dev/null
@@ -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)*));
-}
diff --git a/std/src/memchr.rs b/std/src/memchr.rs
deleted file mode 100644
index 210ba80..0000000
--- a/std/src/memchr.rs
+++ /dev/null
@@ -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..]));
- }
- }
-}
diff --git a/std/src/prelude/mod.rs b/std/src/prelude/mod.rs
deleted file mode 100644
index a3a6d96..0000000
--- a/std/src/prelude/mod.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod v1;
diff --git a/std/src/prelude/v1.rs b/std/src/prelude/v1.rs
deleted file mode 100644
index e17d2ec..0000000
--- a/std/src/prelude/v1.rs
+++ /dev/null
@@ -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;
diff --git a/std/src/sync/mod.rs b/std/src/sync/mod.rs
deleted file mode 100644
index 62152ed..0000000
--- a/std/src/sync/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-mod mutex;
-
-pub use self::mutex::{Mutex, MutexGuard};
-
-pub type LockResult<T> = Result<T, ()>;
diff --git a/std/src/sync/mutex.rs b/std/src/sync/mutex.rs
deleted file mode 100644
index 03ea729..0000000
--- a/std/src/sync/mutex.rs
+++ /dev/null
@@ -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> {}
diff --git a/std/src/sys/mod.rs b/std/src/sys/mod.rs
deleted file mode 100644
index 86f49e5..0000000
--- a/std/src/sys/mod.rs
+++ /dev/null
@@ -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;
diff --git a/std/src/sys/wtf8.rs b/std/src/sys/wtf8.rs
deleted file mode 100644
index 8f0662c..0000000
--- a/std/src/sys/wtf8.rs
+++ /dev/null
@@ -1,1204 +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.
-
-//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/).
-//!
-//! This library uses Rust’s type system to maintain
-//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed),
-//! like the `String` and `&str` types do for UTF-8.
-//!
-//! Since [WTF-8 must not be used
-//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience),
-//! this library deliberately does not provide access to the underlying bytes
-//! of WTF-8 strings,
-//! nor can it decode WTF-8 from arbitrary bytes.
-//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points.
-
-// this module is imported from @SimonSapin's repo and has tons of dead code on
-// unix (it's mostly used on windows), so don't worry about dead code here.
-#![allow(dead_code)]
-
-use core::str::next_code_point;
-
-use ascii::*;
-use borrow::Cow;
-use std_unicode::char;
-use fmt;
-use hash::{Hash, Hasher};
-use iter::FromIterator;
-use mem;
-use ops;
-use slice;
-use str;
-use super::AsInner;
-
-const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD";
-
-/// A Unicode code point: from U+0000 to U+10FFFF.
-///
-/// Compare with the `char` type,
-/// which represents a Unicode scalar value:
-/// a code point that is not a surrogate (U+D800 to U+DFFF).
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
-pub struct CodePoint {
- value: u32,
-}
-
-/// Format the code point as `U+` followed by four to six hexadecimal digits.
-/// Example: `U+1F4A9`
-impl fmt::Debug for CodePoint {
- #[inline]
- fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(formatter, "U+{:04X}", self.value)
- }
-}
-
-impl CodePoint {
- /// Unsafely creates a new `CodePoint` without checking the value.
- ///
- /// Only use when `value` is known to be less than or equal to 0x10FFFF.
- #[inline]
- pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
- CodePoint { value: value }
- }
-
- /// Creates a new `CodePoint` if the value is a valid code point.
- ///
- /// Returns `None` if `value` is above 0x10FFFF.
- #[inline]
- pub fn from_u32(value: u32) -> Option<CodePoint> {
- match value {
- 0...0x10FFFF => Some(CodePoint { value: value }),
- _ => None,
- }
- }
-
- /// Creates a new `CodePoint` from a `char`.
- ///
- /// Since all Unicode scalar values are code points, this always succeeds.
- #[inline]
- pub fn from_char(value: char) -> CodePoint {
- CodePoint { value: value as u32 }
- }
-
- /// Returns the numeric value of the code point.
- #[inline]
- pub fn to_u32(&self) -> u32 {
- self.value
- }
-
- /// Optionally returns a Unicode scalar value for the code point.
- ///
- /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF).
- #[inline]
- pub fn to_char(&self) -> Option<char> {
- match self.value {
- 0xD800...0xDFFF => None,
- _ => Some(unsafe { char::from_u32_unchecked(self.value) }),
- }
- }
-
- /// Returns a Unicode scalar value for the code point.
- ///
- /// Returns `'\u{FFFD}'` (the replacement character “�”)
- /// if the code point is a surrogate (from U+D800 to U+DFFF).
- #[inline]
- pub fn to_char_lossy(&self) -> char {
- self.to_char().unwrap_or('\u{FFFD}')
- }
-}
-
-/// An owned, growable string of well-formed WTF-8 data.
-///
-/// Similar to `String`, but can additionally contain surrogate code points
-/// if they’re not in a surrogate pair.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
-pub struct Wtf8Buf {
- bytes: Vec<u8>,
-}
-
-impl ops::Deref for Wtf8Buf {
- type Target = Wtf8;
-
- fn deref(&self) -> &Wtf8 {
- self.as_slice()
- }
-}
-
-/// Format the string with double quotes,
-/// and surrogates as `\u` followed by four hexadecimal digits.
-/// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
-impl fmt::Debug for Wtf8Buf {
- #[inline]
- fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- fmt::Debug::fmt(&**self, formatter)
- }
-}
-
-impl Wtf8Buf {
- /// Creates a new, empty WTF-8 string.
- #[inline]
- pub fn new() -> Wtf8Buf {
- Wtf8Buf { bytes: Vec::new() }
- }
-
- /// Creates a new, empty WTF-8 string with pre-allocated capacity for `n` bytes.
- #[inline]
- pub fn with_capacity(n: usize) -> Wtf8Buf {
- Wtf8Buf { bytes: Vec::with_capacity(n) }
- }
-
- /// Creates a WTF-8 string from a UTF-8 `String`.
- ///
- /// This takes ownership of the `String` and does not copy.
- ///
- /// Since WTF-8 is a superset of UTF-8, this always succeeds.
- #[inline]
- pub fn from_string(string: String) -> Wtf8Buf {
- Wtf8Buf { bytes: string.into_bytes() }
- }
-
- /// Creates a WTF-8 string from a UTF-8 `&str` slice.
- ///
- /// This copies the content of the slice.
- ///
- /// Since WTF-8 is a superset of UTF-8, this always succeeds.
- #[inline]
- pub fn from_str(str: &str) -> Wtf8Buf {
- Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) }
- }
-
- pub fn clear(&mut self) {
- self.bytes.clear()
- }
-
- /// Creates a WTF-8 string 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.
- pub fn from_wide(v: &[u16]) -> Wtf8Buf {
- let mut string = Wtf8Buf::with_capacity(v.len());
- for item in char::decode_utf16(v.iter().cloned()) {
- match item {
- Ok(ch) => string.push_char(ch),
- Err(surrogate) => {
- let surrogate = surrogate.unpaired_surrogate();
- // Surrogates are known to be in the code point range.
- let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) };
- // Skip the WTF-8 concatenation check,
- // surrogate pairs are already decoded by decode_utf16
- string.push_code_point_unchecked(code_point)
- }
- }
- }
- string
- }
-
- /// Copied from String::push
- /// This does **not** include the WTF-8 concatenation check.
- fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
- let c = unsafe {
- char::from_u32_unchecked(code_point.value)
- };
- let mut bytes = [0; 4];
- let bytes = c.encode_utf8(&mut bytes).as_bytes();
- self.bytes.extend_from_slice(bytes)
- }
-
- #[inline]
- pub fn as_slice(&self) -> &Wtf8 {
- unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
- }
-
- /// Reserves capacity for at least `additional` more bytes to be inserted
- /// in the given `Wtf8Buf`.
- /// The collection may reserve more space to avoid frequent reallocations.
- ///
- /// # Panics
- ///
- /// Panics if the new capacity overflows `usize`.
- #[inline]
- pub fn reserve(&mut self, additional: usize) {
- self.bytes.reserve(additional)
- }
-
- #[inline]
- pub fn reserve_exact(&mut self, additional: usize) {
- self.bytes.reserve_exact(additional)
- }
-
- /// Returns the number of bytes that this string buffer can hold without reallocating.
- #[inline]
- pub fn capacity(&self) -> usize {
- self.bytes.capacity()
- }
-
- /// Append a UTF-8 slice at the end of the string.
- #[inline]
- pub fn push_str(&mut self, other: &str) {
- self.bytes.extend_from_slice(other.as_bytes())
- }
-
- /// Append a WTF-8 slice at the end of the string.
- ///
- /// This replaces newly paired surrogates at the boundary
- /// with a supplementary code point,
- /// like concatenating ill-formed UTF-16 strings effectively would.
- #[inline]
- pub fn push_wtf8(&mut self, other: &Wtf8) {
- match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) {
- // Replace newly paired surrogates by a supplementary code point.
- (Some(lead), Some(trail)) => {
- let len_without_lead_surrogate = self.len() - 3;
- self.bytes.truncate(len_without_lead_surrogate);
- let other_without_trail_surrogate = &other.bytes[3..];
- // 4 bytes for the supplementary code point
- self.bytes.reserve(4 + other_without_trail_surrogate.len());
- self.push_char(decode_surrogate_pair(lead, trail));
- self.bytes.extend_from_slice(other_without_trail_surrogate);
- }
- _ => self.bytes.extend_from_slice(&other.bytes),
- }
- }
-
- /// Append a Unicode scalar value at the end of the string.
- #[inline]
- pub fn push_char(&mut self, c: char) {
- self.push_code_point_unchecked(CodePoint::from_char(c))
- }
-
- /// Append a code point at the end of the string.
- ///
- /// This replaces newly paired surrogates at the boundary
- /// with a supplementary code point,
- /// like concatenating ill-formed UTF-16 strings effectively would.
- #[inline]
- pub fn push(&mut self, code_point: CodePoint) {
- if let trail @ 0xDC00...0xDFFF = code_point.to_u32() {
- if let Some(lead) = (&*self).final_lead_surrogate() {
- let len_without_lead_surrogate = self.len() - 3;
- self.bytes.truncate(len_without_lead_surrogate);
- self.push_char(decode_surrogate_pair(lead, trail as u16));
- return;
- }
- }
-
- // No newly paired surrogates at the boundary.
- self.push_code_point_unchecked(code_point)
- }
-
- /// Shortens a string to the specified length.
- ///
- /// # Panics
- ///
- /// Panics if `new_len` > current length,
- /// or if `new_len` is not a code point boundary.
- #[inline]
- pub fn truncate(&mut self, new_len: usize) {
- assert!(is_code_point_boundary(self, new_len));
- self.bytes.truncate(new_len)
- }
-
- /// Consumes the WTF-8 string and tries to convert it to UTF-8.
- ///
- /// This does not copy the data.
- ///
- /// If the contents are not well-formed UTF-8
- /// (that is, if the string contains surrogates),
- /// the original WTF-8 string is returned instead.
- pub fn into_string(self) -> Result<String, Wtf8Buf> {
- match self.next_surrogate(0) {
- None => Ok(unsafe { String::from_utf8_unchecked(self.bytes) }),
- Some(_) => Err(self),
- }
- }
-
- /// Consumes the WTF-8 string and converts it lossily to UTF-8.
- ///
- /// This does not copy the data (but may overwrite parts of it in place).
- ///
- /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
- pub fn into_string_lossy(mut self) -> String {
- let mut pos = 0;
- loop {
- match self.next_surrogate(pos) {
- Some((surrogate_pos, _)) => {
- pos = surrogate_pos + 3;
- self.bytes[surrogate_pos..pos].copy_from_slice(UTF8_REPLACEMENT_CHARACTER);
- }
- None => return unsafe { String::from_utf8_unchecked(self.bytes) },
- }
- }
- }
-}
-
-/// Create a new WTF-8 string from an iterator of code points.
-///
-/// This replaces surrogate code point pairs with supplementary code points,
-/// like concatenating ill-formed UTF-16 strings effectively would.
-impl FromIterator<CodePoint> for Wtf8Buf {
- fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf {
- let mut string = Wtf8Buf::new();
- string.extend(iter);
- string
- }
-}
-
-/// Append code points from an iterator to the string.
-///
-/// This replaces surrogate code point pairs with supplementary code points,
-/// like concatenating ill-formed UTF-16 strings effectively would.
-impl Extend<CodePoint> for Wtf8Buf {
- fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) {
- let iterator = iter.into_iter();
- let (low, _high) = iterator.size_hint();
- // Lower bound of one byte per code point (ASCII only)
- self.bytes.reserve(low);
- for code_point in iterator {
- self.push(code_point);
- }
- }
-}
-
-/// A borrowed slice of well-formed WTF-8 data.
-///
-/// Similar to `&str`, but can additionally contain surrogate code points
-/// if they’re not in a surrogate pair.
-#[derive(Eq, Ord, PartialEq, PartialOrd)]
-pub struct Wtf8 {
- bytes: [u8],
-}
-
-impl AsInner<[u8]> for Wtf8 {
- fn as_inner(&self) -> &[u8] {
- &self.bytes
- }
-}
-
-/// Format the slice with double quotes,
-/// and surrogates as `\u` followed by four hexadecimal digits.
-/// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800]
-impl fmt::Debug for Wtf8 {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- fn write_str_escaped(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
- use core::fmt::Write;
- for c in s.chars().flat_map(|c| c.escape_debug()) {
- f.write_char(c)?
- }
- Ok(())
- }
-
- formatter.write_str("\"")?;
- let mut pos = 0;
- loop {
- match self.next_surrogate(pos) {
- None => break,
- Some((surrogate_pos, surrogate)) => {
- write_str_escaped(formatter, unsafe {
- str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos])
- })
- ?;
- write!(formatter, "\\u{{{:x}}}", surrogate)?;
- pos = surrogate_pos + 3;
- }
- }
- }
- write_str_escaped(formatter,
- unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })
- ?;
- formatter.write_str("\"")
- }
-}
-
-impl Wtf8 {
- /// Creates a WTF-8 slice from a UTF-8 `&str` slice.
- ///
- /// Since WTF-8 is a superset of UTF-8, this always succeeds.
- #[inline]
- pub fn from_str(value: &str) -> &Wtf8 {
- unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
- }
-
- /// Creates a WTF-8 slice from a WTF-8 byte slice.
- ///
- /// Since the byte slice is not checked for valid WTF-8, this functions is
- /// marked unsafe.
- #[inline]
- unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
- mem::transmute(value)
- }
-
- /// Returns the length, in WTF-8 bytes.
- #[inline]
- pub fn len(&self) -> usize {
- self.bytes.len()
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.bytes.is_empty()
- }
-
- /// Returns the code point at `position` if it is in the ASCII range,
- /// or `b'\xFF' otherwise.
- ///
- /// # Panics
- ///
- /// Panics if `position` is beyond the end of the string.
- #[inline]
- pub fn ascii_byte_at(&self, position: usize) -> u8 {
- match self.bytes[position] {
- ascii_byte @ 0x00...0x7F => ascii_byte,
- _ => 0xFF,
- }
- }
-
- /// Returns an iterator for the string’s code points.
- #[inline]
- pub fn code_points(&self) -> Wtf8CodePoints {
- Wtf8CodePoints { bytes: self.bytes.iter() }
- }
-
- /// Tries to convert the string to UTF-8 and return a `&str` slice.
- ///
- /// Returns `None` if the string contains surrogates.
- ///
- /// This does not copy the data.
- #[inline]
- pub fn as_str(&self) -> Option<&str> {
- // Well-formed WTF-8 is also well-formed UTF-8
- // if and only if it contains no surrogate.
- match self.next_surrogate(0) {
- None => Some(unsafe { str::from_utf8_unchecked(&self.bytes) }),
- Some(_) => None,
- }
- }
-
- /// Lossily converts the string to UTF-8.
- /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8.
- ///
- /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
- ///
- /// This only copies the data if necessary (if it contains any surrogate).
- pub fn to_string_lossy(&self) -> Cow<str> {
- let surrogate_pos = match self.next_surrogate(0) {
- None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }),
- Some((pos, _)) => pos,
- };
- let wtf8_bytes = &self.bytes;
- let mut utf8_bytes = Vec::with_capacity(self.len());
- utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]);
- utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER);
- let mut pos = surrogate_pos + 3;
- loop {
- match self.next_surrogate(pos) {
- Some((surrogate_pos, _)) => {
- utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]);
- utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER);
- pos = surrogate_pos + 3;
- }
- None => {
- utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
- return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) });
- }
- }
- }
- }
-
- /// Converts the WTF-8 string to potentially ill-formed UTF-16
- /// and return an iterator of 16-bit code units.
- ///
- /// This is lossless:
- /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
- /// would always return the original WTF-8 string.
- #[inline]
- pub fn encode_wide(&self) -> EncodeWide {
- EncodeWide {
- code_points: self.code_points(),
- extra: 0,
- }
- }
-
- #[inline]
- fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
- let mut iter = self.bytes[pos..].iter();
- loop {
- let b = match iter.next() {
- None => return None,
- Some(&b) => b,
- };
- if b < 0x80 {
- pos += 1;
- } else if b < 0xE0 {
- iter.next();
- pos += 2;
- } else if b == 0xED {
- match (iter.next(), iter.next()) {
- (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
- return Some((pos, decode_surrogate(b2, b3)))
- }
- _ => pos += 3,
- }
- } else if b < 0xF0 {
- iter.next();
- iter.next();
- pos += 3;
- } else {
- iter.next();
- iter.next();
- iter.next();
- pos += 4;
- }
- }
- }
-
- #[inline]
- fn final_lead_surrogate(&self) -> Option<u16> {
- let len = self.len();
- if len < 3 {
- return None;
- }
- match &self.bytes[(len - 3)..] {
- &[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)),
- _ => None,
- }
- }
-
- #[inline]
- fn initial_trail_surrogate(&self) -> Option<u16> {
- let len = self.len();
- if len < 3 {
- return None;
- }
- match &self.bytes[..3] {
- &[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)),
- _ => None,
- }
- }
-}
-
-
-/// Return a slice of the given string for the byte range [`begin`..`end`).
-///
-/// # Panics
-///
-/// Panics when `begin` and `end` do not point to code point boundaries,
-/// or point beyond the end of the string.
-impl ops::Index<ops::Range<usize>> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
- // is_code_point_boundary checks that the index is in [0, .len()]
- if range.start <= range.end && is_code_point_boundary(self, range.start) &&
- is_code_point_boundary(self, range.end) {
- unsafe { slice_unchecked(self, range.start, range.end) }
- } else {
- slice_error_fail(self, range.start, range.end)
- }
- }
-}
-
-/// Return a slice of the given string from byte `begin` to its end.
-///
-/// # Panics
-///
-/// Panics when `begin` is not at a code point boundary,
-/// or is beyond the end of the string.
-impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
- // is_code_point_boundary checks that the index is in [0, .len()]
- if is_code_point_boundary(self, range.start) {
- unsafe { slice_unchecked(self, range.start, self.len()) }
- } else {
- slice_error_fail(self, range.start, self.len())
- }
- }
-}
-
-/// Return a slice of the given string from its beginning to byte `end`.
-///
-/// # Panics
-///
-/// Panics when `end` is not at a code point boundary,
-/// or is beyond the end of the string.
-impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
- // is_code_point_boundary checks that the index is in [0, .len()]
- if is_code_point_boundary(self, range.end) {
- unsafe { slice_unchecked(self, 0, range.end) }
- } else {
- slice_error_fail(self, 0, range.end)
- }
- }
-}
-
-impl ops::Index<ops::RangeFull> for Wtf8 {
- type Output = Wtf8;
-
- #[inline]
- fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
- self
- }
-}
-
-#[inline]
-fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
- // The first byte is assumed to be 0xED
- 0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F
-}
-
-#[inline]
-fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
- let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
- unsafe { char::from_u32_unchecked(code_point) }
-}
-
-/// Copied from core::str::StrPrelude::is_char_boundary
-#[inline]
-pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
- if index == slice.len() {
- return true;
- }
- match slice.bytes.get(index) {
- None => false,
- Some(&b) => b < 128 || b >= 192,
- }
-}
-
-/// Copied from core::str::raw::slice_unchecked
-#[inline]
-pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
- // memory layout of an &[u8] and &Wtf8 are the same
- Wtf8::from_bytes_unchecked(slice::from_raw_parts(s.bytes.as_ptr().offset(begin as isize),
- end - begin))
-}
-
-/// Copied from core::str::raw::slice_error_fail
-#[inline(never)]
-pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
- assert!(begin <= end);
- panic!("index {} and/or {} in `{:?}` do not lie on character boundary",
- begin,
- end,
- s);
-}
-
-/// Iterator for the code points of a WTF-8 string.
-///
-/// Created with the method `.code_points()`.
-#[derive(Clone)]
-pub struct Wtf8CodePoints<'a> {
- bytes: slice::Iter<'a, u8>,
-}
-
-impl<'a> Iterator for Wtf8CodePoints<'a> {
- type Item = CodePoint;
-
- #[inline]
- fn next(&mut self) -> Option<CodePoint> {
- next_code_point(&mut self.bytes).map(|c| CodePoint { value: c })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.bytes.len();
- (len.saturating_add(3) / 4, Some(len))
- }
-}
-
-#[derive(Clone)]
-pub struct EncodeWide<'a> {
- code_points: Wtf8CodePoints<'a>,
- extra: u16,
-}
-
-// Copied from libunicode/u_str.rs
-impl<'a> Iterator for EncodeWide<'a> {
- type Item = u16;
-
- #[inline]
- fn next(&mut self) -> Option<u16> {
- if self.extra != 0 {
- let tmp = self.extra;
- self.extra = 0;
- return Some(tmp);
- }
-
- let mut buf = [0; 2];
- self.code_points.next().map(|code_point| {
- let c = unsafe {
- char::from_u32_unchecked(code_point.value)
- };
- let n = c.encode_utf16(&mut buf).len();
- if n == 2 {
- self.extra = buf[1];
- }
- buf[0]
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let (low, high) = self.code_points.size_hint();
- // every code point gets either one u16 or two u16,
- // so this iterator is between 1 or 2 times as
- // long as the underlying iterator.
- (low, high.and_then(|n| n.checked_mul(2)))
- }
-}
-
-impl Hash for CodePoint {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.value.hash(state)
- }
-}
-
-impl Hash for Wtf8Buf {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- state.write(&self.bytes);
- 0xfeu8.hash(state)
- }
-}
-
-impl Hash for Wtf8 {
- #[inline]
- fn hash<H: Hasher>(&self, state: &mut H) {
- state.write(&self.bytes);
- 0xfeu8.hash(state)
- }
-}
-
-impl AsciiExt for Wtf8 {
- type Owned = Wtf8Buf;
-
- fn is_ascii(&self) -> bool {
- self.bytes.is_ascii()
- }
- fn to_ascii_uppercase(&self) -> Wtf8Buf {
- Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
- }
- fn to_ascii_lowercase(&self) -> Wtf8Buf {
- Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
- }
- fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
- self.bytes.eq_ignore_ascii_case(&other.bytes)
- }
-
- fn make_ascii_uppercase(&mut self) {
- self.bytes.make_ascii_uppercase()
- }
- fn make_ascii_lowercase(&mut self) {
- self.bytes.make_ascii_lowercase()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use collections::borrow::Cow;
- use collections::{String, Vec};
- use super::*;
-
- #[test]
- fn code_point_from_u32() {
- assert!(CodePoint::from_u32(0).is_some());
- assert!(CodePoint::from_u32(0xD800).is_some());
- assert!(CodePoint::from_u32(0x10FFFF).is_some());
- assert!(CodePoint::from_u32(0x110000).is_none());
- }
-
- #[test]
- fn code_point_to_u32() {
- fn c(value: u32) -> CodePoint {
- CodePoint::from_u32(value).unwrap()
- }
- assert_eq!(c(0).to_u32(), 0);
- assert_eq!(c(0xD800).to_u32(), 0xD800);
- assert_eq!(c(0x10FFFF).to_u32(), 0x10FFFF);
- }
-
- #[test]
- fn code_point_from_char() {
- assert_eq!(CodePoint::from_char('a').to_u32(), 0x61);
- assert_eq!(CodePoint::from_char('💩').to_u32(), 0x1F4A9);
- }
-
- #[test]
- fn code_point_to_string() {
- assert_eq!(format!("{:?}", CodePoint::from_char('a')), "U+0061");
- assert_eq!(format!("{:?}", CodePoint::from_char('💩')), "U+1F4A9");
- }
-
- #[test]
- fn code_point_to_char() {
- fn c(value: u32) -> CodePoint {
- CodePoint::from_u32(value).unwrap()
- }
- assert_eq!(c(0x61).to_char(), Some('a'));
- assert_eq!(c(0x1F4A9).to_char(), Some('💩'));
- assert_eq!(c(0xD800).to_char(), None);
- }
-
- #[test]
- fn code_point_to_char_lossy() {
- fn c(value: u32) -> CodePoint {
- CodePoint::from_u32(value).unwrap()
- }
- assert_eq!(c(0x61).to_char_lossy(), 'a');
- assert_eq!(c(0x1F4A9).to_char_lossy(), '💩');
- assert_eq!(c(0xD800).to_char_lossy(), '\u{FFFD}');
- }
-
- #[test]
- fn wtf8buf_new() {
- assert_eq!(Wtf8Buf::new().bytes, b"");
- }
-
- #[test]
- fn wtf8buf_from_str() {
- assert_eq!(Wtf8Buf::from_str("").bytes, b"");
- assert_eq!(Wtf8Buf::from_str("aé 💩").bytes,
- b"a\xC3\xA9 \xF0\x9F\x92\xA9");
- }
-
- #[test]
- fn wtf8buf_from_string() {
- assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b"");
- assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes,
- b"a\xC3\xA9 \xF0\x9F\x92\xA9");
- }
-
- #[test]
- fn wtf8buf_from_wide() {
- assert_eq!(Wtf8Buf::from_wide(&[]).bytes, b"");
- assert_eq!(Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]).bytes,
- b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9");
- }
-
- #[test]
- fn wtf8buf_push_str() {
- let mut string = Wtf8Buf::new();
- assert_eq!(string.bytes, b"");
- string.push_str("aé 💩");
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
- }
-
- #[test]
- fn wtf8buf_push_char() {
- let mut string = Wtf8Buf::from_str("aé ");
- assert_eq!(string.bytes, b"a\xC3\xA9 ");
- string.push_char('💩');
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
- }
-
- #[test]
- fn wtf8buf_push() {
- let mut string = Wtf8Buf::from_str("aé ");
- assert_eq!(string.bytes, b"a\xC3\xA9 ");
- string.push(CodePoint::from_char('💩'));
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
-
- fn c(value: u32) -> CodePoint {
- CodePoint::from_u32(value).unwrap()
- }
-
- let mut string = Wtf8Buf::new();
- string.push(c(0xD83D)); // lead
- string.push(c(0xDCA9)); // trail
- assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic!
-
- let mut string = Wtf8Buf::new();
- string.push(c(0xD83D)); // lead
- string.push(c(0x20)); // not surrogate
- string.push(c(0xDCA9)); // trail
- assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
-
- let mut string = Wtf8Buf::new();
- string.push(c(0xD800)); // lead
- string.push(c(0xDBFF)); // lead
- assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
-
- let mut string = Wtf8Buf::new();
- string.push(c(0xD800)); // lead
- string.push(c(0xE000)); // not surrogate
- assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
-
- let mut string = Wtf8Buf::new();
- string.push(c(0xD7FF)); // not surrogate
- string.push(c(0xDC00)); // trail
- assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
-
- let mut string = Wtf8Buf::new();
- string.push(c(0x61)); // not surrogate, < 3 bytes
- string.push(c(0xDC00)); // trail
- assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
-
- let mut string = Wtf8Buf::new();
- string.push(c(0xDC00)); // trail
- assert_eq!(string.bytes, b"\xED\xB0\x80");
- }
-
- #[test]
- fn wtf8buf_push_wtf8() {
- let mut string = Wtf8Buf::from_str("aé");
- assert_eq!(string.bytes, b"a\xC3\xA9");
- string.push_wtf8(Wtf8::from_str(" 💩"));
- assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
-
- fn w(v: &[u8]) -> &Wtf8 {
- unsafe { Wtf8::from_bytes_unchecked(v) }
- }
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
- string.push_wtf8(w(b"\xED\xB2\xA9")); // trail
- assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic!
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
- string.push_wtf8(w(b" ")); // not surrogate
- string.push_wtf8(w(b"\xED\xB2\xA9")); // trail
- assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"\xED\xA0\x80")); // lead
- string.push_wtf8(w(b"\xED\xAF\xBF")); // lead
- assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"\xED\xA0\x80")); // lead
- string.push_wtf8(w(b"\xEE\x80\x80")); // not surrogate
- assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"\xED\x9F\xBF")); // not surrogate
- string.push_wtf8(w(b"\xED\xB0\x80")); // trail
- assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"a")); // not surrogate, < 3 bytes
- string.push_wtf8(w(b"\xED\xB0\x80")); // trail
- assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
-
- let mut string = Wtf8Buf::new();
- string.push_wtf8(w(b"\xED\xB0\x80")); // trail
- assert_eq!(string.bytes, b"\xED\xB0\x80");
- }
-
- #[test]
- fn wtf8buf_truncate() {
- let mut string = Wtf8Buf::from_str("aé");
- string.truncate(1);
- assert_eq!(string.bytes, b"a");
- }
-
- #[test]
- #[should_panic]
- fn wtf8buf_truncate_fail_code_point_boundary() {
- let mut string = Wtf8Buf::from_str("aé");
- string.truncate(2);
- }
-
- #[test]
- #[should_panic]
- fn wtf8buf_truncate_fail_longer() {
- let mut string = Wtf8Buf::from_str("aé");
- string.truncate(4);
- }
-
- #[test]
- fn wtf8buf_into_string() {
- let mut string = Wtf8Buf::from_str("aé 💩");
- assert_eq!(string.clone().into_string(), Ok(String::from("aé 💩")));
- string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!(string.clone().into_string(), Err(string));
- }
-
- #[test]
- fn wtf8buf_into_string_lossy() {
- let mut string = Wtf8Buf::from_str("aé 💩");
- assert_eq!(string.clone().into_string_lossy(), String::from("aé 💩"));
- string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!(string.clone().into_string_lossy(),
- String::from("aé 💩�"));
- }
-
- #[test]
- fn wtf8buf_from_iterator() {
- fn f(values: &[u32]) -> Wtf8Buf {
- values.iter().map(|&c| CodePoint::from_u32(c).unwrap()).collect::<Wtf8Buf>()
- }
- assert_eq!(f(&[0x61, 0xE9, 0x20, 0x1F4A9]).bytes,
- b"a\xC3\xA9 \xF0\x9F\x92\xA9");
-
- assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
- assert_eq!(f(&[0xD83D, 0x20, 0xDCA9]).bytes,
- b"\xED\xA0\xBD \xED\xB2\xA9");
- assert_eq!(f(&[0xD800, 0xDBFF]).bytes, b"\xED\xA0\x80\xED\xAF\xBF");
- assert_eq!(f(&[0xD800, 0xE000]).bytes, b"\xED\xA0\x80\xEE\x80\x80");
- assert_eq!(f(&[0xD7FF, 0xDC00]).bytes, b"\xED\x9F\xBF\xED\xB0\x80");
- assert_eq!(f(&[0x61, 0xDC00]).bytes, b"\x61\xED\xB0\x80");
- assert_eq!(f(&[0xDC00]).bytes, b"\xED\xB0\x80");
- }
-
- #[test]
- fn wtf8buf_extend() {
- fn e(initial: &[u32], extended: &[u32]) -> Wtf8Buf {
- fn c(value: &u32) -> CodePoint {
- CodePoint::from_u32(*value).unwrap()
- }
- let mut string = initial.iter().map(c).collect::<Wtf8Buf>();
- string.extend(extended.iter().map(c));
- string
- }
-
- assert_eq!(e(&[0x61, 0xE9], &[0x20, 0x1F4A9]).bytes,
- b"a\xC3\xA9 \xF0\x9F\x92\xA9");
-
- assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
- assert_eq!(e(&[0xD83D, 0x20], &[0xDCA9]).bytes,
- b"\xED\xA0\xBD \xED\xB2\xA9");
- assert_eq!(e(&[0xD800], &[0xDBFF]).bytes, b"\xED\xA0\x80\xED\xAF\xBF");
- assert_eq!(e(&[0xD800], &[0xE000]).bytes, b"\xED\xA0\x80\xEE\x80\x80");
- assert_eq!(e(&[0xD7FF], &[0xDC00]).bytes, b"\xED\x9F\xBF\xED\xB0\x80");
- assert_eq!(e(&[0x61], &[0xDC00]).bytes, b"\x61\xED\xB0\x80");
- assert_eq!(e(&[], &[0xDC00]).bytes, b"\xED\xB0\x80");
- }
-
- #[test]
- fn wtf8buf_show() {
- let mut string = Wtf8Buf::from_str("a\té \u{7f}💩\r");
- string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!(format!("{:?}", string),
- "\"a\\té \\u{7f}\u{1f4a9}\\r\\u{d800}\"");
- }
-
- #[test]
- fn wtf8buf_as_slice() {
- assert_eq!(Wtf8Buf::from_str("aé").as_slice(), Wtf8::from_str("aé"));
- }
-
- #[test]
- fn wtf8buf_show_str() {
- let text = "a\té 💩\r";
- let string = Wtf8Buf::from_str(text);
- assert_eq!(format!("{:?}", text), format!("{:?}", string));
- }
-
- #[test]
- fn wtf8_from_str() {
- assert_eq!(&Wtf8::from_str("").bytes, b"");
- assert_eq!(&Wtf8::from_str("aé 💩").bytes,
- b"a\xC3\xA9 \xF0\x9F\x92\xA9");
- }
-
- #[test]
- fn wtf8_len() {
- assert_eq!(Wtf8::from_str("").len(), 0);
- assert_eq!(Wtf8::from_str("aé 💩").len(), 8);
- }
-
- #[test]
- fn wtf8_slice() {
- assert_eq!(&Wtf8::from_str("aé 💩")[1..4].bytes, b"\xC3\xA9 ");
- }
-
- #[test]
- #[should_panic]
- fn wtf8_slice_not_code_point_boundary() {
- &Wtf8::from_str("aé 💩")[2..4];
- }
-
- #[test]
- fn wtf8_slice_from() {
- assert_eq!(&Wtf8::from_str("aé 💩")[1..].bytes,
- b"\xC3\xA9 \xF0\x9F\x92\xA9");
- }
-
- #[test]
- #[should_panic]
- fn wtf8_slice_from_not_code_point_boundary() {
- &Wtf8::from_str("aé 💩")[2..];
- }
-
- #[test]
- fn wtf8_slice_to() {
- assert_eq!(&Wtf8::from_str("aé 💩")[..4].bytes, b"a\xC3\xA9 ");
- }
-
- #[test]
- #[should_panic]
- fn wtf8_slice_to_not_code_point_boundary() {
- &Wtf8::from_str("aé 💩")[5..];
- }
-
- #[test]
- fn wtf8_ascii_byte_at() {
- let slice = Wtf8::from_str("aé 💩");
- assert_eq!(slice.ascii_byte_at(0), b'a');
- assert_eq!(slice.ascii_byte_at(1), b'\xFF');
- assert_eq!(slice.ascii_byte_at(2), b'\xFF');
- assert_eq!(slice.ascii_byte_at(3), b' ');
- assert_eq!(slice.ascii_byte_at(4), b'\xFF');
- }
-
- #[test]
- fn wtf8_code_points() {
- fn c(value: u32) -> CodePoint {
- CodePoint::from_u32(value).unwrap()
- }
- fn cp(string: &Wtf8Buf) -> Vec<Option<char>> {
- string.code_points().map(|c| c.to_char()).collect::<Vec<_>>()
- }
- let mut string = Wtf8Buf::from_str("é ");
- assert_eq!(cp(&string), [Some('é'), Some(' ')]);
- string.push(c(0xD83D));
- assert_eq!(cp(&string), [Some('é'), Some(' '), None]);
- string.push(c(0xDCA9));
- assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]);
- }
-
- #[test]
- fn wtf8_as_str() {
- assert_eq!(Wtf8::from_str("").as_str(), Some(""));
- assert_eq!(Wtf8::from_str("aé 💩").as_str(), Some("aé 💩"));
- let mut string = Wtf8Buf::new();
- string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!(string.as_str(), None);
- }
-
- #[test]
- fn wtf8_to_string_lossy() {
- assert_eq!(Wtf8::from_str("").to_string_lossy(), Cow::Borrowed(""));
- assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(),
- Cow::Borrowed("aé 💩"));
- let mut string = Wtf8Buf::from_str("aé 💩");
- string.push(CodePoint::from_u32(0xD800).unwrap());
- let expected: Cow<str> = Cow::Owned(String::from("aé 💩�"));
- assert_eq!(string.to_string_lossy(), expected);
- }
-
- #[test]
- fn wtf8_encode_wide() {
- let mut string = Wtf8Buf::from_str("aé ");
- string.push(CodePoint::from_u32(0xD83D).unwrap());
- string.push_char('💩');
- assert_eq!(string.encode_wide().collect::<Vec<_>>(),
- vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]);
- }
-}