Ronald Kinard
8 years ago
committed by
GitHub
126 changed files with 16417 additions and 3415 deletions
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
use std::env; |
||||
use std::path::PathBuf; |
||||
use std::fs; |
||||
|
||||
use std::option::Option::{self, Some, None}; |
||||
|
||||
const ENV_DKP: &'static str = "CTRULIB"; |
||||
|
||||
fn find_libctru() -> Option<PathBuf> { |
||||
if let Ok(value) = env::var(ENV_DKP) { |
||||
let mut path = PathBuf::from(value); |
||||
path.push("lib"); |
||||
// metadata returns Err if the dir does not exist
|
||||
if let Ok(metadata) = fs::metadata(path.as_path()) { |
||||
if metadata.is_dir() { |
||||
return Some(path); |
||||
} |
||||
} |
||||
} |
||||
return None; |
||||
} |
||||
|
||||
fn main() { |
||||
if let Some(path) = find_libctru() { |
||||
if let Some(s) = path.to_str() { |
||||
println!("cargo:rustc-link-lib=static=ctru"); |
||||
println!("cargo:rustc-link-search=native={}", s); |
||||
} else { |
||||
println!("path is not a valid string"); |
||||
std::process::exit(1); |
||||
} |
||||
} else { |
||||
println!("could not find libctru"); |
||||
std::process::exit(1); |
||||
} |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
[package] |
||||
name = "ctr-libc" |
||||
version = "0.1.0" |
||||
authors = ["Fenrir <fenrirwolf@gmail.com>", "The Rust Project Developers"] |
||||
license = "MIT/Apache 2.0" |
||||
|
||||
description = """ |
||||
A library for types and bindings to native C functions found in newlib |
||||
for devkitARM |
||||
""" |
||||
|
||||
[features] |
||||
default = ["use_std"] |
||||
use_std = [] |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
Extended libc bindings for use with ctr-std. This library is experimental. Use of some functions might result in undefined symbols. |
@ -0,0 +1,122 @@
@@ -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; |
@ -0,0 +1,39 @@
@@ -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; |
||||
} |
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
// 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)] |
||||
|
||||
#![no_std] |
||||
|
||||
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 } |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
[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.ctr-libc] |
||||
path = "../ctr-libc" |
||||
|
||||
[dependencies.alloc_system] |
||||
version = "0.1.1" |
||||
|
||||
[dependencies.spin] |
||||
version = "0.4" |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
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. |
||||
|
||||
## Structure |
||||
|
||||
This library aims to mimick the Rust standard library's public interface as closely as possible, exposing functionality that is common between the 3DS and other platforms. System-specific functionality such as control input, save file management, GPU features, and so forth are implemented in `ctru-rs`. |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
[dependencies.collections] |
||||
|
||||
[dependencies.ctr-libc] |
||||
path = "../ctr-libc" |
||||
stage = 1 |
@ -0,0 +1,497 @@
@@ -0,0 +1,497 @@
|
||||
// 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.
|
||||
|
||||
//! Traits for working with Errors.
|
||||
//!
|
||||
//! # The `Error` trait
|
||||
//!
|
||||
//! `Error` is a trait representing the basic expectations for error values,
|
||||
//! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide
|
||||
//! a description, but they may optionally provide additional detail (via
|
||||
//! [`Display`]) and cause chain information:
|
||||
//!
|
||||
//! ```
|
||||
//! use std::fmt::Display;
|
||||
//!
|
||||
//! trait Error: Display {
|
||||
//! fn description(&self) -> &str;
|
||||
//!
|
||||
//! fn cause(&self) -> Option<&Error> { None }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The [`cause`] method is generally used when errors cross "abstraction
|
||||
//! boundaries", i.e. when a one module must report an error that is "caused"
|
||||
//! by an error from a lower-level module. This setup makes it possible for the
|
||||
//! high-level module to provide its own errors that do not commit to any
|
||||
//! particular implementation, but also reveal some of its implementation for
|
||||
//! debugging via [`cause`] chains.
|
||||
//!
|
||||
//! [`Result<T, E>`]: ../result/enum.Result.html
|
||||
//! [`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
|
||||
// were scattered about. However, coherence objected to this
|
||||
// arrangement, because to create the blanket impls for `Box` required
|
||||
// knowing that `&str: !Error`, and we have no means to deal with that
|
||||
// sort of conflict just now. Therefore, for the time being, we have
|
||||
// moved the `Error` trait into libstd. As we evolve a sol'n to the
|
||||
// coherence challenge (e.g., specialization, neg impls, etc) we can
|
||||
// reconsider what crate these items belong in.
|
||||
|
||||
use any::TypeId; |
||||
use cell; |
||||
use char; |
||||
use fmt::{self, Debug, Display}; |
||||
use mem::transmute; |
||||
use num; |
||||
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 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
|
||||
///
|
||||
/// ```
|
||||
/// use std::error::Error;
|
||||
///
|
||||
/// match "xc".parse::<u32>() {
|
||||
/// Err(e) => {
|
||||
/// println!("Error: {}", e.description());
|
||||
/// }
|
||||
/// _ => println!("No error"),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")] |
||||
fn description(&self) -> &str; |
||||
|
||||
/// The lower-level cause of this error, if any.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::error::Error;
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct SuperError {
|
||||
/// side: SuperErrorSideKick,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Display for SuperError {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// write!(f, "SuperError is here!")
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Error for SuperError {
|
||||
/// fn description(&self) -> &str {
|
||||
/// "I'm the superhero of errors!"
|
||||
/// }
|
||||
///
|
||||
/// fn cause(&self) -> Option<&Error> {
|
||||
/// Some(&self.side)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
/// struct SuperErrorSideKick;
|
||||
///
|
||||
/// impl fmt::Display for SuperErrorSideKick {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// write!(f, "SuperErrorSideKick is here!")
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Error for SuperErrorSideKick {
|
||||
/// fn description(&self) -> &str {
|
||||
/// "I'm SuperError side kick!"
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn get_super_error() -> Result<(), SuperError> {
|
||||
/// Err(SuperError { side: SuperErrorSideKick })
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// match get_super_error() {
|
||||
/// Err(e) => {
|
||||
/// println!("Error: {}", e.description());
|
||||
/// println!("Caused by: {}", e.cause().unwrap());
|
||||
/// }
|
||||
/// _ => println!("No error"),
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[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)] |
||||
struct StringError(String); |
||||
|
||||
impl Error for StringError { |
||||
fn description(&self) -> &str { &self.0 } |
||||
} |
||||
|
||||
impl Display for StringError { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
Display::fmt(&self.0, f) |
||||
} |
||||
} |
||||
|
||||
Box::new(StringError(err)) |
||||
} |
||||
} |
||||
|
||||
#[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); |
||||
let err2: Box<Error> = err1; |
||||
err2 |
||||
} |
||||
} |
||||
|
||||
#[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) |
||||
} |
||||
|
||||
fn cause(&self) -> Option<&Error> { |
||||
Error::cause(&**self) |
||||
} |
||||
} |
||||
|
||||
#[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`" |
||||
} |
||||
} |
||||
|
||||
// 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
|
||||
let t = TypeId::of::<T>(); |
||||
|
||||
// Get TypeId of the type in the trait object
|
||||
let boxed = self.type_id(); |
||||
|
||||
// Compare both TypeIds on equality
|
||||
t == boxed |
||||
} |
||||
|
||||
/// 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>() { |
||||
unsafe { |
||||
Some(&*(self as *const Error as *const T)) |
||||
} |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
|
||||
/// 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>() { |
||||
unsafe { |
||||
Some(&mut *(self as *mut Error as *mut T)) |
||||
} |
||||
} else { |
||||
None |
||||
} |
||||
} |
||||
} |
||||
|
||||
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) |
||||
} |
||||
} |
||||
|
||||
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) |
||||
} |
||||
} |
||||
|
||||
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>() { |
||||
unsafe { |
||||
let raw: *mut Error = Box::into_raw(self); |
||||
Ok(Box::from_raw(raw as *mut T)) |
||||
} |
||||
} else { |
||||
Err(self) |
||||
} |
||||
} |
||||
} |
||||
|
||||
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>> { |
||||
let err: Box<Error> = self; |
||||
<Error>::downcast(err).map_err(|s| unsafe { |
||||
// reapply the Send marker
|
||||
transmute::<Box<Error>, Box<Error + Send>>(s) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
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>> { |
||||
let err: Box<Error> = self; |
||||
<Error>::downcast(err).map_err(|s| unsafe { |
||||
// reapply the Send+Sync marker
|
||||
transmute::<Box<Error>, Box<Error + Send + Sync>>(s) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use super::Error; |
||||
use fmt; |
||||
|
||||
#[derive(Debug, PartialEq)] |
||||
struct A; |
||||
#[derive(Debug, PartialEq)] |
||||
struct B; |
||||
|
||||
impl fmt::Display for A { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
write!(f, "A") |
||||
} |
||||
} |
||||
impl fmt::Display for B { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
write!(f, "B") |
||||
} |
||||
} |
||||
|
||||
impl Error for A { |
||||
fn description(&self) -> &str { "A-desc" } |
||||
} |
||||
impl Error for B { |
||||
fn description(&self) -> &str { "A-desc" } |
||||
} |
||||
|
||||
#[test] |
||||
fn downcasting() { |
||||
let mut a = A; |
||||
let mut a = &mut a as &mut (Error + 'static); |
||||
assert_eq!(a.downcast_ref::<A>(), Some(&A)); |
||||
assert_eq!(a.downcast_ref::<B>(), None); |
||||
assert_eq!(a.downcast_mut::<A>(), Some(&mut A)); |
||||
assert_eq!(a.downcast_mut::<B>(), None); |
||||
|
||||
let a: Box<Error> = Box::new(A); |
||||
match a.downcast::<B>() { |
||||
Ok(..) => panic!("expected error"), |
||||
Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A), |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,849 @@
@@ -0,0 +1,849 @@
|
||||
// Copyright 2012 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 ascii; |
||||
use borrow::{Cow, Borrow}; |
||||
use cmp::Ordering; |
||||
use error::Error; |
||||
use fmt::{self, Write}; |
||||
use io; |
||||
use libc::{self, c_char}; |
||||
use mem; |
||||
use memchr; |
||||
use ops; |
||||
use ptr; |
||||
use slice; |
||||
use str::{self, Utf8Error}; |
||||
|
||||
/// A type representing an owned C-compatible string
|
||||
///
|
||||
/// This type serves the primary purpose of being able to safely generate a
|
||||
/// C-compatible string from a Rust byte slice or vector. An instance of this
|
||||
/// type is a static guarantee that the underlying bytes contain no interior 0
|
||||
/// bytes and the final byte is 0.
|
||||
///
|
||||
/// A `CString` is created from either a byte slice or a byte vector. After
|
||||
/// being created, a `CString` predominately inherits all of its methods from
|
||||
/// the `Deref` implementation to `[c_char]`. Note that the underlying array
|
||||
/// is represented as an array of `c_char` as opposed to `u8`. A `u8` slice
|
||||
/// can be obtained with the `as_bytes` method. Slices produced from a `CString`
|
||||
/// do *not* contain the trailing nul terminator unless otherwise specified.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() {
|
||||
/// use std::ffi::CString;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// extern {
|
||||
/// fn my_printer(s: *const c_char);
|
||||
/// }
|
||||
///
|
||||
/// let c_to_print = CString::new("Hello, world!").unwrap();
|
||||
/// unsafe {
|
||||
/// my_printer(c_to_print.as_ptr());
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `CString` is intended for working with traditional C-style strings
|
||||
/// (a sequence of non-null bytes terminated by a single null byte); the
|
||||
/// primary use case for these kinds of strings is interoperating with C-like
|
||||
/// code. Often you will need to transfer ownership to/from that external
|
||||
/// code. It is strongly recommended that you thoroughly read through the
|
||||
/// documentation of `CString` before use, as improper ownership management
|
||||
/// of `CString` instances can lead to invalid memory accesses, memory leaks,
|
||||
/// 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.
|
||||
// Improper usage of unsafe function can break Invariant 2, but not Invariant 1.
|
||||
inner: Box<[u8]>, |
||||
} |
||||
|
||||
/// Representation of a borrowed C string.
|
||||
///
|
||||
/// This dynamically sized type is only safely constructed via a borrowed
|
||||
/// version of an instance of `CString`. This type can be constructed from a raw
|
||||
/// C string as well and represents a C string borrowed from another location.
|
||||
///
|
||||
/// Note that this structure is **not** `repr(C)` and is not recommended to be
|
||||
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
|
||||
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
|
||||
/// interface to other consumers.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Inspecting a foreign C string
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// extern { fn my_string() -> *const c_char; }
|
||||
///
|
||||
/// unsafe {
|
||||
/// let slice = CStr::from_ptr(my_string());
|
||||
/// println!("string length: {}", slice.to_bytes().len());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Passing a Rust-originating C string
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::{CString, CStr};
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// fn work(data: &CStr) {
|
||||
/// extern { fn work_with(data: *const c_char); }
|
||||
///
|
||||
/// unsafe { work_with(data.as_ptr()) }
|
||||
/// }
|
||||
///
|
||||
/// let s = CString::new("data data data data").unwrap();
|
||||
/// work(&s);
|
||||
/// ```
|
||||
///
|
||||
/// Converting a foreign C string into a Rust `String`
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// extern { fn my_string() -> *const c_char; }
|
||||
///
|
||||
/// fn my_string_safe() -> String {
|
||||
/// unsafe {
|
||||
/// CStr::from_ptr(my_string()).to_string_lossy().into_owned()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// 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
|
||||
// this an unsized type. Essentially `sizeof(&CStr)` should be the
|
||||
// same as `sizeof(&c_char)` but `CStr` should be an unsized type.
|
||||
inner: [c_char] |
||||
} |
||||
|
||||
/// 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, |
||||
} |
||||
|
||||
impl CString { |
||||
/// Creates a new C-compatible string from a container of bytes.
|
||||
///
|
||||
/// This method will consume the provided data and use the underlying bytes
|
||||
/// to construct a new string, ensuring that there is a trailing 0 byte.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::CString;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// extern { fn puts(s: *const c_char); }
|
||||
///
|
||||
/// let to_print = CString::new("Hello!").unwrap();
|
||||
/// unsafe {
|
||||
/// puts(to_print.as_ptr());
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// 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()) |
||||
} |
||||
|
||||
fn _new(bytes: Vec<u8>) -> Result<CString, NulError> { |
||||
match memchr::memchr(0, &bytes) { |
||||
Some(i) => Err(NulError(i, bytes)), |
||||
None => Ok(unsafe { CString::from_vec_unchecked(bytes) }), |
||||
} |
||||
} |
||||
|
||||
/// Creates a C-compatible string from a byte vector without checking for
|
||||
/// interior 0 bytes.
|
||||
///
|
||||
/// This method is equivalent to `new` except that no runtime assertion
|
||||
/// is made that `v` contains no 0 bytes, and it requires an actual
|
||||
/// byte vector, not anything that can be converted to one with Into.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::CString;
|
||||
///
|
||||
/// let raw = b"foo".to_vec();
|
||||
/// unsafe {
|
||||
/// 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); |
||||
CString { inner: v.into_boxed_slice() } |
||||
} |
||||
|
||||
/// Retakes ownership of a `CString` that was transferred to C.
|
||||
///
|
||||
/// Additionally, the length of the string will be recalculated from the pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This should only ever be called with a pointer that was earlier
|
||||
/// 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); |
||||
CString { inner: mem::transmute(slice) } |
||||
} |
||||
|
||||
/// Transfers ownership of the string to a C caller.
|
||||
///
|
||||
/// The pointer must be returned to Rust and reconstituted using
|
||||
/// `from_raw` to be properly deallocated. Specifically, one
|
||||
/// should *not* use the standard C `free` function to deallocate
|
||||
/// 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 |
||||
} |
||||
|
||||
/// 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 { |
||||
error: e.utf8_error(), |
||||
inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) }, |
||||
}) |
||||
} |
||||
|
||||
/// Returns the underlying byte buffer.
|
||||
///
|
||||
/// 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(); |
||||
debug_assert_eq!(_nul, Some(0u8)); |
||||
vec |
||||
} |
||||
|
||||
/// 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() |
||||
} |
||||
|
||||
/// Returns the contents of this `CString` as a slice of bytes.
|
||||
///
|
||||
/// 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 |
||||
} |
||||
|
||||
// Bypass "move out of struct which implements `Drop` trait" restriction.
|
||||
fn into_inner(self) -> Box<[u8]> { |
||||
unsafe { |
||||
let result = ptr::read(&self.inner); |
||||
mem::forget(self); |
||||
result |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 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) { |
||||
unsafe { *self.inner.get_unchecked_mut(0) = 0; } |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")] |
||||
impl ops::Deref for CString { |
||||
type Target = CStr; |
||||
|
||||
fn deref(&self) -> &CStr { |
||||
unsafe { mem::transmute(self.as_bytes_with_nul()) } |
||||
} |
||||
} |
||||
|
||||
#[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, "\"")?; |
||||
for byte in self.to_bytes().iter().flat_map(|&b| ascii::escape_default(b)) { |
||||
f.write_char(byte as char)?; |
||||
} |
||||
write!(f, "\"") |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "cstr_default", since = "1.10.0")] |
||||
impl<'a> Default for &'a CStr { |
||||
fn default() -> &'a CStr { |
||||
static SLICE: &'static [c_char] = &[0]; |
||||
unsafe { CStr::from_ptr(SLICE.as_ptr()) } |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "cstr_default", since = "1.10.0")] |
||||
impl Default for CString { |
||||
/// Creates an empty `CString`.
|
||||
fn default() -> CString { |
||||
let a: &CStr = Default::default(); |
||||
a.to_owned() |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "cstr_borrow", since = "1.3.0")] |
||||
impl Borrow<CStr> for CString { |
||||
fn borrow(&self) -> &CStr { self } |
||||
} |
||||
|
||||
impl NulError { |
||||
/// Returns the position of the nul byte in the slice that was provided to
|
||||
/// `CString::new`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::CString;
|
||||
///
|
||||
/// let nul_error = CString::new("foo\0bar").unwrap_err();
|
||||
/// assert_eq!(nul_error.nul_position(), 3);
|
||||
///
|
||||
/// 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
|
||||
/// generated the error in the first place.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::CString;
|
||||
///
|
||||
/// 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, |
||||
"data provided contains a nul byte") |
||||
} |
||||
} |
||||
|
||||
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" |
||||
} |
||||
|
||||
fn cause(&self) -> Option<&Error> { |
||||
Some(&self.error) |
||||
} |
||||
} |
||||
|
||||
#[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) |
||||
} |
||||
} |
||||
|
||||
impl CStr { |
||||
/// Casts a raw C string to a safe C string wrapper.
|
||||
///
|
||||
/// This function will cast the provided `ptr` to the `CStr` wrapper which
|
||||
/// allows inspection and interoperation of non-owned C strings. This method
|
||||
/// is unsafe for a number of reasons:
|
||||
///
|
||||
/// * There is no guarantee to the validity of `ptr`
|
||||
/// * The returned lifetime is not guaranteed to be the actual lifetime of
|
||||
/// `ptr`
|
||||
/// * There is no guarantee that the memory pointed to by `ptr` contains a
|
||||
/// valid nul terminator byte at the end of the string.
|
||||
///
|
||||
/// > **Note**: This operation is intended to be a 0-cost cast but it is
|
||||
/// > currently implemented with an up-front calculation of the length of
|
||||
/// > the string. This is not guaranteed to always be the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() {
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
/// extern {
|
||||
/// fn my_string() -> *const c_char;
|
||||
/// }
|
||||
///
|
||||
/// unsafe {
|
||||
/// let slice = CStr::from_ptr(my_string());
|
||||
/// println!("string returned: {}", slice.to_str().unwrap());
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[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)) |
||||
} |
||||
|
||||
/// Creates a C string wrapper from a byte slice.
|
||||
///
|
||||
/// This function will cast the provided `bytes` to a `CStr` wrapper after
|
||||
/// ensuring that it is null terminated and does not contain any interior
|
||||
/// nul bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::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) { |
||||
Err(FromBytesWithNulError { _a: () }) |
||||
} else { |
||||
Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) |
||||
} |
||||
} |
||||
|
||||
/// Unsafely creates a C string wrapper from a byte slice.
|
||||
///
|
||||
/// This function will cast the provided `bytes` to a `CStr` wrapper without
|
||||
/// performing any sanity checks. The provided slice must be null terminated
|
||||
/// and not contain any interior nul bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::{CStr, CString};
|
||||
///
|
||||
/// unsafe {
|
||||
/// let cstring = CString::new("hello").unwrap();
|
||||
/// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
|
||||
/// 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) |
||||
} |
||||
|
||||
/// Returns the inner pointer to this C string.
|
||||
///
|
||||
/// The returned pointer will be valid for as long as `self` is and points
|
||||
/// to a contiguous region of memory terminated with a 0 byte to represent
|
||||
/// the end of the string.
|
||||
///
|
||||
/// **WARNING**
|
||||
///
|
||||
/// It is your responsibility to make sure that the underlying memory is not
|
||||
/// freed too early. For example, the following code will cause undefined
|
||||
/// behaviour when `ptr` is used inside the `unsafe` block:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::{CString};
|
||||
///
|
||||
/// let ptr = CString::new("Hello").unwrap().as_ptr();
|
||||
/// unsafe {
|
||||
/// // `ptr` is dangling
|
||||
/// *ptr;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This happens because the pointer returned by `as_ptr` does not carry any
|
||||
/// lifetime information and the string is deallocated immediately after
|
||||
/// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated.
|
||||
/// To fix the problem, bind the string to a local variable:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::{CString};
|
||||
///
|
||||
/// let hello = CString::new("Hello").unwrap();
|
||||
/// let ptr = hello.as_ptr();
|
||||
/// unsafe {
|
||||
/// // `ptr` is valid because `hello` is in scope
|
||||
/// *ptr;
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")] |
||||
pub fn as_ptr(&self) -> *const c_char { |
||||
self.inner.as_ptr() |
||||
} |
||||
|
||||
/// Converts this C string to a byte slice.
|
||||
///
|
||||
/// This function will calculate the length of this string (which normally
|
||||
/// requires a linear amount of work to be done) and then return the
|
||||
/// resulting slice of `u8` elements.
|
||||
///
|
||||
/// The returned slice will **not** contain the trailing nul that this C
|
||||
/// string has.
|
||||
///
|
||||
/// > **Note**: This method is currently implemented as a 0-cost cast, but
|
||||
/// > it is planned to alter its definition in the future to perform the
|
||||
/// > length calculation whenever this method is called.
|
||||
#[stable(feature = "rust1", since = "1.0.0")] |
||||
pub fn to_bytes(&self) -> &[u8] { |
||||
let bytes = self.to_bytes_with_nul(); |
||||
&bytes[..bytes.len() - 1] |
||||
} |
||||
|
||||
/// Converts this C string to a byte slice containing the trailing 0 byte.
|
||||
///
|
||||
/// This function is the equivalent of `to_bytes` except that it will retain
|
||||
/// the trailing nul instead of chopping it off.
|
||||
///
|
||||
/// > **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) } |
||||
} |
||||
|
||||
/// Yields a `&str` slice if the `CStr` contains valid UTF-8.
|
||||
///
|
||||
/// This function will calculate the length of this string and check for
|
||||
/// UTF-8 validity, and then return the `&str` if it's valid.
|
||||
///
|
||||
/// > **Note**: This method is currently implemented to check for validity
|
||||
/// > after a 0-cost cast, but it is planned to alter its definition in the
|
||||
/// > future to perform the length calculation in addition to the UTF-8
|
||||
/// > check whenever this method is called.
|
||||
#[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
|
||||
// be rewritten to do the UTF-8 check inline with the length calculation
|
||||
// instead of doing it afterwards.
|
||||
str::from_utf8(self.to_bytes()) |
||||
} |
||||
|
||||
/// Converts a `CStr` into a `Cow<str>`.
|
||||
///
|
||||
/// This function will calculate the length of this string (which normally
|
||||
/// requires a linear amount of work to be done) and then return the
|
||||
/// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
|
||||
/// with `U+FFFD REPLACEMENT CHARACTER`.
|
||||
///
|
||||
/// > **Note**: This method is currently implemented to check for validity
|
||||
/// > after a 0-cost cast, but it is planned to alter its definition in the
|
||||
/// > future to perform the length calculation in addition to the UTF-8
|
||||
/// > check whenever this method is called.
|
||||
#[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; |
||||
|
||||
fn to_owned(&self) -> CString { |
||||
unsafe { CString::from_vec_unchecked(self.to_bytes().to_vec()) } |
||||
} |
||||
} |
||||
|
||||
#[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; |
||||
|
||||
#[inline] |
||||
fn index(&self, _index: ops::RangeFull) -> &CStr { |
||||
self |
||||
} |
||||
} |
||||
|
||||
#[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 |
||||
} |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use super::*; |
||||
use os::raw::c_char; |
||||
use borrow::Cow::{Borrowed, Owned}; |
||||
use hash::{Hash, Hasher}; |
||||
use collections::hash_map::DefaultHasher; |
||||
|
||||
#[test] |
||||
fn c_to_rust() { |
||||
let data = b"123\0"; |
||||
let ptr = data.as_ptr() as *const c_char; |
||||
unsafe { |
||||
assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123"); |
||||
assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0"); |
||||
} |
||||
} |
||||
|
||||
#[test] |
||||
fn simple() { |
||||
let s = CString::new("1234").unwrap(); |
||||
assert_eq!(s.as_bytes(), b"1234"); |
||||
assert_eq!(s.as_bytes_with_nul(), b"1234\0"); |
||||
} |
||||
|
||||
#[test] |
||||
fn build_with_zero1() { |
||||
assert!(CString::new(&b"\0"[..]).is_err()); |
||||
} |
||||
#[test] |
||||
fn build_with_zero2() { |
||||
assert!(CString::new(vec![0]).is_err()); |
||||
} |
||||
|
||||
#[test] |
||||
fn build_with_zero3() { |
||||
unsafe { |
||||
let s = CString::from_vec_unchecked(vec![0]); |
||||
assert_eq!(s.as_bytes(), b"\0"); |
||||
} |
||||
} |
||||
|
||||
#[test] |
||||
fn formatted() { |
||||
let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap(); |
||||
assert_eq!(format!("{:?}", s), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#); |
||||
} |
||||
|
||||
#[test] |
||||
fn borrowed() { |
||||
unsafe { |
||||
let s = CStr::from_ptr(b"12\0".as_ptr() as *const _); |
||||
assert_eq!(s.to_bytes(), b"12"); |
||||
assert_eq!(s.to_bytes_with_nul(), b"12\0"); |
||||
} |
||||
} |
||||
|
||||
#[test] |
||||
fn to_str() { |
||||
let data = b"123\xE2\x80\xA6\0"; |
||||
let ptr = data.as_ptr() as *const c_char; |
||||
unsafe { |
||||
assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…")); |
||||
assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…")); |
||||
} |
||||
let data = b"123\xE2\0"; |
||||
let ptr = data.as_ptr() as *const c_char; |
||||
unsafe { |
||||
assert!(CStr::from_ptr(ptr).to_str().is_err()); |
||||
assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::<str>(format!("123\u{FFFD}"))); |
||||
} |
||||
} |
||||
|
||||
#[test] |
||||
fn to_owned() { |
||||
let data = b"123\0"; |
||||
let ptr = data.as_ptr() as *const c_char; |
||||
|
||||
let owned = unsafe { CStr::from_ptr(ptr).to_owned() }; |
||||
assert_eq!(owned.as_bytes_with_nul(), data); |
||||
} |
||||
|
||||
#[test] |
||||
fn equal_hash() { |
||||
let data = b"123\xE2\xFA\xA6\0"; |
||||
let ptr = data.as_ptr() as *const c_char; |
||||
let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) }; |
||||
|
||||
let mut s = DefaultHasher::new(); |
||||
cstr.hash(&mut s); |
||||
let cstr_hash = s.finish(); |
||||
let mut s = DefaultHasher::new(); |
||||
CString::new(&data[..data.len() - 1]).unwrap().hash(&mut s); |
||||
let cstring_hash = s.finish(); |
||||
|
||||
assert_eq!(cstr_hash, cstring_hash); |
||||
} |
||||
|
||||
#[test] |
||||
fn from_bytes_with_nul() { |
||||
let data = b"123\0"; |
||||
let cstr = CStr::from_bytes_with_nul(data); |
||||
assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..])); |
||||
let cstr = CStr::from_bytes_with_nul(data); |
||||
assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..])); |
||||
|
||||
unsafe { |
||||
let cstr = CStr::from_bytes_with_nul(data); |
||||
let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data); |
||||
assert_eq!(cstr, Ok(cstr_unchecked)); |
||||
} |
||||
} |
||||
|
||||
#[test] |
||||
fn from_bytes_with_nul_unterminated() { |
||||
let data = b"123"; |
||||
let cstr = CStr::from_bytes_with_nul(data); |
||||
assert!(cstr.is_err()); |
||||
} |
||||
|
||||
#[test] |
||||
fn from_bytes_with_nul_interior() { |
||||
let data = b"1\023\0"; |
||||
let cstr = CStr::from_bytes_with_nul(data); |
||||
assert!(cstr.is_err()); |
||||
} |
||||
} |
@ -0,0 +1,24 @@
@@ -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; |
@ -0,0 +1,600 @@
@@ -0,0 +1,600 @@
|
||||
// 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::prelude::*; |
||||
|
||||
use core::convert::TryInto; |
||||
use cmp; |
||||
use io::{self, SeekFrom, Error, ErrorKind}; |
||||
|
||||
/// A `Cursor` wraps another type and provides it with a
|
||||
/// [`Seek`] implementation.
|
||||
///
|
||||
/// `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]`][bytes]`>`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// 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`:
|
||||
///
|
||||
/// [`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::*;
|
||||
/// use std::io::{self, SeekFrom};
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// // a library function we've written
|
||||
/// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> {
|
||||
/// try!(writer.seek(SeekFrom::End(-10)));
|
||||
///
|
||||
/// for i in 0..10 {
|
||||
/// try!(writer.write(&[i]));
|
||||
/// }
|
||||
///
|
||||
/// // all went well
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// # fn foo() -> io::Result<()> {
|
||||
/// // Here's some code that uses this library function.
|
||||
/// //
|
||||
/// // We might want to use a BufReader here for efficiency, but let's
|
||||
/// // keep this example focused.
|
||||
/// let mut file = try!(File::create("foo.txt"));
|
||||
///
|
||||
/// try!(write_ten_bytes_at_end(&mut file));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
///
|
||||
/// // now let's write a test
|
||||
/// #[test]
|
||||
/// fn test_writes_bytes() {
|
||||
/// // setting up a real File is much more slow than an in-memory buffer,
|
||||
/// // let's use a cursor instead
|
||||
/// use std::io::Cursor;
|
||||
/// let mut buff = Cursor::new(vec![0; 15]);
|
||||
///
|
||||
/// write_ten_bytes_at_end(&mut buff).unwrap();
|
||||
///
|
||||
/// 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, |
||||
pos: u64, |
||||
} |
||||
|
||||
impl<T> Cursor<T> { |
||||
/// Creates a new cursor wrapping the provided underlying I/O object.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let buff = Cursor::new(Vec::new());
|
||||
/// # 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 } |
||||
} |
||||
|
||||
/// Consumes this cursor, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// Care should be taken to avoid modifying the internal I/O state of the
|
||||
/// underlying value as it may corrupt this cursor's position.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Cursor;
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::io::SeekFrom;
|
||||
///
|
||||
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
|
||||
///
|
||||
/// assert_eq!(buff.position(), 0);
|
||||
///
|
||||
/// buff.seek(SeekFrom::Current(2)).unwrap();
|
||||
/// assert_eq!(buff.position(), 2);
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
|
||||
///
|
||||
/// assert_eq!(buff.position(), 0);
|
||||
///
|
||||
/// buff.set_position(2);
|
||||
/// assert_eq!(buff.position(), 2);
|
||||
///
|
||||
/// 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 { |
||||
SeekFrom::Start(n) => { self.pos = n; return Ok(n) } |
||||
SeekFrom::End(n) => self.inner.as_ref().len() as i64 + n, |
||||
SeekFrom::Current(n) => self.pos as i64 + n, |
||||
}; |
||||
|
||||
if pos < 0 { |
||||
Err(Error::new(ErrorKind::InvalidInput, |
||||
"invalid seek to a negative position")) |
||||
} else { |
||||
self.pos = pos as u64; |
||||
Ok(self.pos) |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[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)?; |
||||
self.pos += n as u64; |
||||
Ok(n) |
||||
} |
||||
} |
||||
|
||||
#[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); |
||||
Ok(&self.inner.as_ref()[(amt as usize)..]) |
||||
} |
||||
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> { |
||||
let pos = cmp::min(self.pos, self.inner.len() as u64); |
||||
let amt = (&mut self.inner[(pos as usize)..]).write(data)?; |
||||
self.pos += amt as u64; |
||||
Ok(amt) |
||||
} |
||||
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 len = self.inner.len(); |
||||
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 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); |
||||
self.inner.extend_from_slice(right); |
||||
} |
||||
|
||||
// Bump us forward
|
||||
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> { |
||||
let pos = cmp::min(self.pos, self.inner.len() as u64); |
||||
let amt = (&mut self.inner[(pos as usize)..]).write(buf)?; |
||||
self.pos += amt as u64; |
||||
Ok(amt) |
||||
} |
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) } |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use io::prelude::*; |
||||
use io::{Cursor, SeekFrom}; |
||||
|
||||
#[test] |
||||
fn test_vec_writer() { |
||||
let mut writer = Vec::new(); |
||||
assert_eq!(writer.write(&[0]).unwrap(), 1); |
||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); |
||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); |
||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; |
||||
assert_eq!(writer, b); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_mem_writer() { |
||||
let mut writer = Cursor::new(Vec::new()); |
||||
assert_eq!(writer.write(&[0]).unwrap(), 1); |
||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); |
||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); |
||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; |
||||
assert_eq!(&writer.get_ref()[..], b); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_box_slice_writer() { |
||||
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice()); |
||||
assert_eq!(writer.position(), 0); |
||||
assert_eq!(writer.write(&[0]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 1); |
||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); |
||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); |
||||
assert_eq!(writer.position(), 8); |
||||
assert_eq!(writer.write(&[]).unwrap(), 0); |
||||
assert_eq!(writer.position(), 8); |
||||
|
||||
assert_eq!(writer.write(&[8, 9]).unwrap(), 1); |
||||
assert_eq!(writer.write(&[10]).unwrap(), 0); |
||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; |
||||
assert_eq!(&**writer.get_ref(), b); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_buf_writer() { |
||||
let mut buf = [0 as u8; 9]; |
||||
{ |
||||
let mut writer = Cursor::new(&mut buf[..]); |
||||
assert_eq!(writer.position(), 0); |
||||
assert_eq!(writer.write(&[0]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 1); |
||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); |
||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); |
||||
assert_eq!(writer.position(), 8); |
||||
assert_eq!(writer.write(&[]).unwrap(), 0); |
||||
assert_eq!(writer.position(), 8); |
||||
|
||||
assert_eq!(writer.write(&[8, 9]).unwrap(), 1); |
||||
assert_eq!(writer.write(&[10]).unwrap(), 0); |
||||
} |
||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; |
||||
assert_eq!(buf, b); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_buf_writer_seek() { |
||||
let mut buf = [0 as u8; 8]; |
||||
{ |
||||
let mut writer = Cursor::new(&mut buf[..]); |
||||
assert_eq!(writer.position(), 0); |
||||
assert_eq!(writer.write(&[1]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 1); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2); |
||||
assert_eq!(writer.position(), 2); |
||||
assert_eq!(writer.write(&[2]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 3); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1); |
||||
assert_eq!(writer.position(), 1); |
||||
assert_eq!(writer.write(&[3]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 2); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); |
||||
assert_eq!(writer.position(), 7); |
||||
assert_eq!(writer.write(&[4]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 8); |
||||
|
||||
} |
||||
let b: &[_] = &[1, 3, 2, 0, 0, 0, 0, 4]; |
||||
assert_eq!(buf, b); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_buf_writer_error() { |
||||
let mut buf = [0 as u8; 2]; |
||||
let mut writer = Cursor::new(&mut buf[..]); |
||||
assert_eq!(writer.write(&[0]).unwrap(), 1); |
||||
assert_eq!(writer.write(&[0, 0]).unwrap(), 1); |
||||
assert_eq!(writer.write(&[0, 0]).unwrap(), 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_mem_reader() { |
||||
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); |
||||
let mut buf = [0]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 1); |
||||
assert_eq!(reader.position(), 1); |
||||
let b: &[_] = &[0]; |
||||
assert_eq!(buf, b); |
||||
let mut buf = [0; 4]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 4); |
||||
assert_eq!(reader.position(), 5); |
||||
let b: &[_] = &[1, 2, 3, 4]; |
||||
assert_eq!(buf, b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 3); |
||||
let b: &[_] = &[5, 6, 7]; |
||||
assert_eq!(&buf[..3], b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
} |
||||
|
||||
#[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 buf = []; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
assert_eq!(reader.position(), 0); |
||||
let mut buf = [0]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 1); |
||||
assert_eq!(reader.position(), 1); |
||||
let b: &[_] = &[0]; |
||||
assert_eq!(buf, b); |
||||
let mut buf = [0; 4]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 4); |
||||
assert_eq!(reader.position(), 5); |
||||
let b: &[_] = &[1, 2, 3, 4]; |
||||
assert_eq!(buf, b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 3); |
||||
let b: &[_] = &[5, 6, 7]; |
||||
assert_eq!(&buf[..3], b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn read_to_end() { |
||||
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]); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_slice_reader() { |
||||
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; |
||||
let mut reader = &mut &in_buf[..]; |
||||
let mut buf = []; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
let mut buf = [0]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 1); |
||||
assert_eq!(reader.len(), 7); |
||||
let b: &[_] = &[0]; |
||||
assert_eq!(&buf[..], b); |
||||
let mut buf = [0; 4]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 4); |
||||
assert_eq!(reader.len(), 3); |
||||
let b: &[_] = &[1, 2, 3, 4]; |
||||
assert_eq!(&buf[..], b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 3); |
||||
let b: &[_] = &[5, 6, 7]; |
||||
assert_eq!(&buf[..3], b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_buf_reader() { |
||||
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; |
||||
let mut reader = Cursor::new(&in_buf[..]); |
||||
let mut buf = []; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
assert_eq!(reader.position(), 0); |
||||
let mut buf = [0]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 1); |
||||
assert_eq!(reader.position(), 1); |
||||
let b: &[_] = &[0]; |
||||
assert_eq!(buf, b); |
||||
let mut buf = [0; 4]; |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 4); |
||||
assert_eq!(reader.position(), 5); |
||||
let b: &[_] = &[1, 2, 3, 4]; |
||||
assert_eq!(buf, b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 3); |
||||
let b: &[_] = &[5, 6, 7]; |
||||
assert_eq!(&buf[..3], b); |
||||
assert_eq!(reader.read(&mut buf).unwrap(), 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_read_char() { |
||||
let b = &b"Vi\xE1\xBB\x87t"[..]; |
||||
let mut c = Cursor::new(b).chars(); |
||||
assert_eq!(c.next().unwrap().unwrap(), 'V'); |
||||
assert_eq!(c.next().unwrap().unwrap(), 'i'); |
||||
assert_eq!(c.next().unwrap().unwrap(), 'ệ'); |
||||
assert_eq!(c.next().unwrap().unwrap(), 't'); |
||||
assert!(c.next().is_none()); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_read_bad_char() { |
||||
let b = &b"\x80"[..]; |
||||
let mut c = Cursor::new(b).chars(); |
||||
assert!(c.next().unwrap().is_err()); |
||||
} |
||||
|
||||
#[test] |
||||
fn seek_past_end() { |
||||
let buf = [0xff]; |
||||
let mut r = Cursor::new(&buf[..]); |
||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); |
||||
assert_eq!(r.read(&mut [0]).unwrap(), 0); |
||||
|
||||
let mut r = Cursor::new(vec![10]); |
||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); |
||||
assert_eq!(r.read(&mut [0]).unwrap(), 0); |
||||
|
||||
let mut buf = [0]; |
||||
let mut r = Cursor::new(&mut buf[..]); |
||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); |
||||
assert_eq!(r.write(&[3]).unwrap(), 0); |
||||
|
||||
let mut r = Cursor::new(vec![10].into_boxed_slice()); |
||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); |
||||
assert_eq!(r.write(&[3]).unwrap(), 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn seek_before_0() { |
||||
let buf = [0xff]; |
||||
let mut r = Cursor::new(&buf[..]); |
||||
assert!(r.seek(SeekFrom::End(-2)).is_err()); |
||||
|
||||
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()); |
||||
assert!(r.seek(SeekFrom::End(-2)).is_err()); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_seekable_mem_writer() { |
||||
let mut writer = Cursor::new(Vec::<u8>::new()); |
||||
assert_eq!(writer.position(), 0); |
||||
assert_eq!(writer.write(&[0]).unwrap(), 1); |
||||
assert_eq!(writer.position(), 1); |
||||
assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); |
||||
assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); |
||||
assert_eq!(writer.position(), 8); |
||||
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; |
||||
assert_eq!(&writer.get_ref()[..], b); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0); |
||||
assert_eq!(writer.position(), 0); |
||||
assert_eq!(writer.write(&[3, 4]).unwrap(), 2); |
||||
let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; |
||||
assert_eq!(&writer.get_ref()[..], b); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3); |
||||
assert_eq!(writer.write(&[0, 1]).unwrap(), 2); |
||||
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; |
||||
assert_eq!(&writer.get_ref()[..], b); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); |
||||
assert_eq!(writer.write(&[1, 2]).unwrap(), 2); |
||||
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; |
||||
assert_eq!(&writer.get_ref()[..], b); |
||||
|
||||
assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10); |
||||
assert_eq!(writer.write(&[1]).unwrap(), 1); |
||||
let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; |
||||
assert_eq!(&writer.get_ref()[..], b); |
||||
} |
||||
|
||||
#[test] |
||||
fn vec_seek_past_end() { |
||||
let mut r = Cursor::new(Vec::new()); |
||||
assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); |
||||
assert_eq!(r.write(&[3]).unwrap(), 1); |
||||
} |
||||
|
||||
#[test] |
||||
fn vec_seek_before_0() { |
||||
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()); |
||||
} |
||||
} |
@ -0,0 +1,594 @@
@@ -0,0 +1,594 @@
|
||||
// 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 error; |
||||
use fmt; |
||||
use result; |
||||
use sys; |
||||
use convert::From; |
||||
|
||||
/// A specialized [`Result`](../result/enum.Result.html) type for I/O
|
||||
/// operations.
|
||||
///
|
||||
/// This type is broadly used across `std::io` for any operation which may
|
||||
/// produce an error.
|
||||
///
|
||||
/// This typedef is generally used to avoid writing out `io::Error` directly and
|
||||
/// is otherwise a direct mapping to `Result`.
|
||||
///
|
||||
/// While usual Rust style is to import types directly, aliases of `Result`
|
||||
/// often are not, to make it easier to distinguish between them. `Result` is
|
||||
/// generally assumed to be `std::result::Result`, and so users of this alias
|
||||
/// will generally use `io::Result` instead of shadowing the prelude's import
|
||||
/// of `std::result::Result`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A convenience function that bubbles an `io::Result` to its caller:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io;
|
||||
///
|
||||
/// fn get_string() -> io::Result<String> {
|
||||
/// let mut buffer = String::new();
|
||||
///
|
||||
/// try!(io::stdin().read_line(&mut buffer));
|
||||
///
|
||||
/// 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
|
||||
/// associated traits.
|
||||
///
|
||||
/// 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`]: 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>), |
||||
} |
||||
|
||||
#[derive(Debug)] |
||||
struct Custom { |
||||
kind: ErrorKind, |
||||
error: Box<error::Error+Send+Sync>, |
||||
} |
||||
|
||||
/// A list specifying general categories of I/O error.
|
||||
///
|
||||
/// This list is intended to grow over time and it is not recommended to
|
||||
/// exhaustively match against it.
|
||||
///
|
||||
/// 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
|
||||
/// 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)`].
|
||||
///
|
||||
/// 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
|
||||
/// "end of file" was reached prematurely.
|
||||
///
|
||||
/// 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, |
||||
|
||||
/// 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.
|
||||
///
|
||||
/// This function is used to generically create I/O errors which do not
|
||||
/// originate from the OS itself. The `error` argument is an arbitrary
|
||||
/// payload which will be contained in this `Error`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{Error, ErrorKind};
|
||||
///
|
||||
/// // errors can be created from strings
|
||||
/// let custom_error = Error::new(ErrorKind::Other, "oh no!");
|
||||
///
|
||||
/// // 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>> |
||||
{ |
||||
Self::_new(kind, error.into()) |
||||
} |
||||
|
||||
fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error { |
||||
Error { |
||||
repr: Repr::Custom(Box::new(Custom { |
||||
kind: kind, |
||||
error: 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) } |
||||
} |
||||
|
||||
/// Returns the OS error that this error represents (if any).
|
||||
///
|
||||
/// 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, |
||||
} |
||||
} |
||||
|
||||
/// Returns a reference to the inner error wrapped by this error (if any).
|
||||
///
|
||||
/// 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), |
||||
} |
||||
} |
||||
|
||||
/// Returns a mutable reference to the inner error wrapped by this error
|
||||
/// (if any).
|
||||
///
|
||||
/// 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), |
||||
} |
||||
} |
||||
|
||||
/// Consumes the `Error`, returning its inner error (if any).
|
||||
///
|
||||
/// 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) => sys::decode_error_kind(code), |
||||
Repr::Custom(ref c) => c.kind, |
||||
Repr::Simple(kind) => kind, |
||||
} |
||||
} |
||||
} |
||||
|
||||
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) |
||||
.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) => { |
||||
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(..) | Repr::Simple(..) => self.kind().as_str(), |
||||
Repr::Custom(ref c) => c.error.description(), |
||||
} |
||||
} |
||||
|
||||
fn cause(&self) -> Option<&error::Error> { |
||||
match self.repr { |
||||
Repr::Os(..) => None, |
||||
Repr::Simple(..) => None, |
||||
Repr::Custom(ref c) => c.error.cause(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn _assert_error_is_sync_send() { |
||||
fn _is_sync_send<T: Sync+Send>() {} |
||||
_is_sync_send::<Error>(); |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod test { |
||||
use super::{Error, ErrorKind}; |
||||
use error; |
||||
use fmt; |
||||
use sys::os::error_string; |
||||
|
||||
#[test] |
||||
fn test_debug_error() { |
||||
let code = 6; |
||||
let msg = error_string(code); |
||||
let err = Error { repr: super::Repr::Os(code) }; |
||||
let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg); |
||||
assert_eq!(format!("{:?}", err), expected); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_downcasting() { |
||||
#[derive(Debug)] |
||||
struct TestError; |
||||
|
||||
impl fmt::Display for TestError { |
||||
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
impl error::Error for TestError { |
||||
fn description(&self) -> &str { |
||||
"asdf" |
||||
} |
||||
} |
||||
|
||||
// we have to call all of these UFCS style right now since method
|
||||
// resolution won't implicitly drop the Send+Sync bounds
|
||||
let mut err = Error::new(ErrorKind::Other, TestError); |
||||
assert!(err.get_ref().unwrap().is::<TestError>()); |
||||
assert_eq!("asdf", err.get_ref().unwrap().description()); |
||||
assert!(err.get_mut().unwrap().is::<TestError>()); |
||||
let extracted = err.into_inner().unwrap(); |
||||
extracted.downcast::<TestError>().unwrap(); |
||||
} |
||||
} |
@ -0,0 +1,296 @@
@@ -0,0 +1,296 @@
|
||||
// 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 cmp; |
||||
use io::{self, SeekFrom, Read, Write, Seek, BufRead, Error, ErrorKind}; |
||||
use fmt; |
||||
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> { |
||||
(**self).read(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
||||
(**self).read_to_end(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { |
||||
(**self).read_to_string(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { |
||||
(**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) } |
||||
|
||||
#[inline] |
||||
fn flush(&mut self) -> io::Result<()> { (**self).flush() } |
||||
|
||||
#[inline] |
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { |
||||
(**self).write_all(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { |
||||
(**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() } |
||||
|
||||
#[inline] |
||||
fn consume(&mut self, amt: usize) { (**self).consume(amt) } |
||||
|
||||
#[inline] |
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { |
||||
(**self).read_until(byte, buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { |
||||
(**self).read_line(buf) |
||||
} |
||||
} |
||||
|
||||
#[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> { |
||||
(**self).read(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { |
||||
(**self).read_to_end(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { |
||||
(**self).read_to_string(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { |
||||
(**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) } |
||||
|
||||
#[inline] |
||||
fn flush(&mut self) -> io::Result<()> { (**self).flush() } |
||||
|
||||
#[inline] |
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { |
||||
(**self).write_all(buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { |
||||
(**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() } |
||||
|
||||
#[inline] |
||||
fn consume(&mut self, amt: usize) { (**self).consume(amt) } |
||||
|
||||
#[inline] |
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { |
||||
(**self).read_until(byte, buf) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { |
||||
(**self).read_line(buf) |
||||
} |
||||
} |
||||
|
||||
// =============================================================================
|
||||
// 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> { |
||||
let amt = cmp::min(buf.len(), self.len()); |
||||
let (a, b) = self.split_at(amt); |
||||
buf[..amt].copy_from_slice(a); |
||||
*self = b; |
||||
Ok(amt) |
||||
} |
||||
|
||||
#[inline] |
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { |
||||
if buf.len() > self.len() { |
||||
return Err(Error::new(ErrorKind::UnexpectedEof, |
||||
"failed to fill whole buffer")); |
||||
} |
||||
let (a, b) = self.split_at(buf.len()); |
||||
buf.copy_from_slice(a); |
||||
*self = b; |
||||
Ok(()) |
||||
} |
||||
} |
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")] |
||||
impl<'a> BufRead for &'a [u8] { |
||||
#[inline] |
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } |
||||
|
||||
#[inline] |
||||
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> { |
||||
let amt = cmp::min(data.len(), self.len()); |
||||
let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); |
||||
a.copy_from_slice(&data[..amt]); |
||||
*self = b; |
||||
Ok(amt) |
||||
} |
||||
|
||||
#[inline] |
||||
fn write_all(&mut self, data: &[u8]) -> io::Result<()> { |
||||
if self.write(data)? == data.len() { |
||||
Ok(()) |
||||
} else { |
||||
Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) |
||||
} |
||||
} |
||||
|
||||
#[inline] |
||||
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> { |
||||
self.extend_from_slice(buf); |
||||
Ok(buf.len()) |
||||
} |
||||
|
||||
#[inline] |
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { |
||||
self.extend_from_slice(buf); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[inline] |
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) } |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use io::prelude::*; |
||||
use test; |
||||
|
||||
#[bench] |
||||
fn bench_read_slice(b: &mut test::Bencher) { |
||||
let buf = [5; 1024]; |
||||
let mut dst = [0; 128]; |
||||
|
||||
b.iter(|| { |
||||
let mut rd = &buf[..]; |
||||
for _ in 0..8 { |
||||
let _ = rd.read(&mut dst); |
||||
test::black_box(&dst); |
||||
} |
||||
}) |
||||
} |
||||
|
||||
#[bench] |
||||
fn bench_write_slice(b: &mut test::Bencher) { |
||||
let mut buf = [0; 1024]; |
||||
let src = [5; 128]; |
||||
|
||||
b.iter(|| { |
||||
let mut wr = &mut buf[..]; |
||||
for _ in 0..8 { |
||||
let _ = wr.write_all(&src); |
||||
test::black_box(&wr); |
||||
} |
||||
}) |
||||
} |
||||
|
||||
#[bench] |
||||
fn bench_read_vec(b: &mut test::Bencher) { |
||||
let buf = vec![5; 1024]; |
||||
let mut dst = [0; 128]; |
||||
|
||||
b.iter(|| { |
||||
let mut rd = &buf[..]; |
||||
for _ in 0..8 { |
||||
let _ = rd.read(&mut dst); |
||||
test::black_box(&dst); |
||||
} |
||||
}) |
||||
} |
||||
|
||||
#[bench] |
||||
fn bench_write_vec(b: &mut test::Bencher) { |
||||
let mut buf = Vec::with_capacity(1024); |
||||
let src = [5; 128]; |
||||
|
||||
b.iter(|| { |
||||
let mut wr = &mut buf[..]; |
||||
for _ in 0..8 { |
||||
let _ = wr.write_all(&src); |
||||
test::black_box(&wr); |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,24 @@
@@ -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.
|
||||
|
||||
//! The I/O Prelude
|
||||
//!
|
||||
//! The purpose of this module is to alleviate imports of many common I/O traits
|
||||
//! by adding a glob import to the top of I/O heavy modules:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![allow(unused_imports)]
|
||||
//! 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}; |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
use fmt; |
||||
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 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 { |
||||
// devkitPro's version of write(2) fails if zero bytes are written,
|
||||
// so let's just exit if the buffer size is zero
|
||||
if buf.is_empty() { |
||||
return Ok(buf.len()) |
||||
} |
||||
libc::write(libc::STDOUT_FILENO, buf.as_ptr() as *const _, buf.len()); |
||||
Ok(buf.len()) |
||||
} |
||||
} |
||||
|
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) } |
||||
} |
||||
|
||||
#[doc(hidden)] |
||||
pub fn _print(args: fmt::Arguments) { |
||||
STDOUT.lock().write_fmt(args).unwrap(); |
||||
} |
@ -0,0 +1,215 @@
@@ -0,0 +1,215 @@
|
||||
// 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_copy_implementations)] |
||||
|
||||
use io::{self, Read, Write, ErrorKind, BufRead}; |
||||
|
||||
/// Copies the entire contents of a reader into a writer.
|
||||
///
|
||||
/// This function will continuously read data from `reader` and then
|
||||
/// write it into `writer` in a streaming fashion until `reader`
|
||||
/// returns EOF.
|
||||
///
|
||||
/// On success, the total number of bytes that were copied from
|
||||
/// `reader` to `writer` is returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error immediately if any call to `read` or
|
||||
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
|
||||
/// handled by this function and the underlying operation is retried.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io;
|
||||
///
|
||||
/// # fn foo() -> io::Result<()> {
|
||||
/// let mut reader: &[u8] = b"hello";
|
||||
/// let mut writer: Vec<u8> = vec![];
|
||||
///
|
||||
/// try!(io::copy(&mut reader, &mut writer));
|
||||
///
|
||||
/// assert_eq!(reader, &writer[..]);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")] |
||||
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> |
||||
where R: Read, W: Write |
||||
{ |
||||
let mut buf = [0; super::DEFAULT_BUF_SIZE]; |
||||
let mut written = 0; |
||||
loop { |
||||
let len = match reader.read(&mut buf) { |
||||
Ok(0) => return Ok(written), |
||||
Ok(len) => len, |
||||
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, |
||||
Err(e) => return Err(e), |
||||
}; |
||||
writer.write_all(&buf[..len])?; |
||||
written += len as u64; |
||||
} |
||||
} |
||||
|
||||
/// A reader which is always at EOF.
|
||||
///
|
||||
/// This struct is generally created by calling [`empty()`][empty]. Please see
|
||||
/// 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.
|
||||
///
|
||||
/// All reads from the returned reader will return `Ok(0)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A slightly sad example of not reading anything into a buffer:
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{self, Read};
|
||||
///
|
||||
/// let mut buffer = String::new();
|
||||
/// 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) {} |
||||
} |
||||
|
||||
/// A reader which yields one byte over and over and over and over and over and...
|
||||
///
|
||||
/// This struct is generally created by calling [`repeat()`][repeat]. Please
|
||||
/// 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.
|
||||
///
|
||||
/// All reads from this reader will succeed by filling the specified buffer with
|
||||
/// the given byte.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{self, Read};
|
||||
///
|
||||
/// let mut buffer = [0; 3];
|
||||
/// 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 { |
||||
*slot = self.byte; |
||||
} |
||||
Ok(buf.len()) |
||||
} |
||||
} |
||||
|
||||
/// A writer which will move data into the void.
|
||||
///
|
||||
/// This struct is generally created by calling [`sink()`][sink]. Please
|
||||
/// 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.
|
||||
///
|
||||
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
|
||||
/// and the contents of the buffer will not be inspected.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::io::{self, Write};
|
||||
///
|
||||
/// let buffer = vec![1, 2, 3, 5, 8];
|
||||
/// 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(()) } |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use io::prelude::*; |
||||
use io::{copy, sink, empty, repeat}; |
||||
|
||||
#[test] |
||||
fn copy_copies() { |
||||
let mut r = repeat(0).take(4); |
||||
let mut w = sink(); |
||||
assert_eq!(copy(&mut r, &mut w).unwrap(), 4); |
||||
|
||||
let mut r = repeat(0).take(1 << 17); |
||||
assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17); |
||||
} |
||||
|
||||
#[test] |
||||
fn sink_sinks() { |
||||
let mut s = sink(); |
||||
assert_eq!(s.write(&[]).unwrap(), 0); |
||||
assert_eq!(s.write(&[0]).unwrap(), 1); |
||||
assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); |
||||
assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); |
||||
} |
||||
|
||||
#[test] |
||||
fn empty_reads() { |
||||
let mut e = empty(); |
||||
assert_eq!(e.read(&mut []).unwrap(), 0); |
||||
assert_eq!(e.read(&mut [0]).unwrap(), 0); |
||||
assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); |
||||
assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); |
||||
} |
||||
|
||||
#[test] |
||||
fn repeat_repeats() { |
||||
let mut r = repeat(4); |
||||
let mut b = [0; 1024]; |
||||
assert_eq!(r.read(&mut b).unwrap(), 1024); |
||||
assert!(b.iter().all(|b| *b == 4)); |
||||
} |
||||
|
||||
#[test] |
||||
fn take_some_bytes() { |
||||
assert_eq!(repeat(4).take(100).bytes().count(), 100); |
||||
assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); |
||||
assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); |
||||
} |
||||
} |
@ -0,0 +1,174 @@
@@ -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() |
||||
} |
@ -0,0 +1,481 @@
@@ -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 */ }) } |
||||
} |
@ -0,0 +1,143 @@
@@ -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..])); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,293 @@
@@ -0,0 +1,293 @@
|
||||
// Copyright 2012-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.
|
||||
|
||||
//! Additional functionality for numerics.
|
||||
//!
|
||||
//! 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}; |
||||
|
||||
/// Helper function for testing numeric operations
|
||||
#[cfg(test)] |
||||
pub fn test_num<T>(ten: T, two: T) where |
||||
T: PartialEq |
||||
+ Add<Output=T> + Sub<Output=T> |
||||
+ Mul<Output=T> + Div<Output=T> |
||||
+ 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); |
||||
} |
||||
|
||||
#[cfg(test)] |
||||
mod tests { |
||||
use u8; |
||||
use u16; |
||||
use u32; |
||||
use u64; |
||||
use usize; |
||||
use ops::Mul; |
||||
|
||||
#[test] |
||||
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!(MAX.saturating_add(MAX), MAX); |
||||
assert_eq!((MAX-2).saturating_add(1), MAX-1); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_saturating_sub_uint() { |
||||
use usize::MAX; |
||||
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); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_saturating_add_int() { |
||||
use isize::{MIN,MAX}; |
||||
assert_eq!(3i32.saturating_add(5), 8); |
||||
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!(3i32.saturating_add(-5), -2); |
||||
assert_eq!(MIN.saturating_add(-1), MIN); |
||||
assert_eq!((-2isize).saturating_add(-MAX), MIN); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_saturating_sub_int() { |
||||
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!(MAX.saturating_sub(-MAX), MAX); |
||||
assert_eq!((MAX-2).saturating_sub(-1), MAX-1); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_checked_add() { |
||||
let five_less = usize::MAX - 5; |
||||
assert_eq!(five_less.checked_add(0), Some(usize::MAX - 5)); |
||||
assert_eq!(five_less.checked_add(1), Some(usize::MAX - 4)); |
||||
assert_eq!(five_less.checked_add(2), Some(usize::MAX - 3)); |
||||
assert_eq!(five_less.checked_add(3), Some(usize::MAX - 2)); |
||||
assert_eq!(five_less.checked_add(4), Some(usize::MAX - 1)); |
||||
assert_eq!(five_less.checked_add(5), Some(usize::MAX)); |
||||
assert_eq!(five_less.checked_add(6), None); |
||||
assert_eq!(five_less.checked_add(7), None); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_checked_sub() { |
||||
assert_eq!(5_usize.checked_sub(0), Some(5)); |
||||
assert_eq!(5_usize.checked_sub(1), Some(4)); |
||||
assert_eq!(5_usize.checked_sub(2), Some(3)); |
||||
assert_eq!(5_usize.checked_sub(3), Some(2)); |
||||
assert_eq!(5_usize.checked_sub(4), Some(1)); |
||||
assert_eq!(5_usize.checked_sub(5), Some(0)); |
||||
assert_eq!(5_usize.checked_sub(6), None); |
||||
assert_eq!(5_usize.checked_sub(7), None); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_checked_mul() { |
||||
let third = usize::MAX / 3; |
||||
assert_eq!(third.checked_mul(0), Some(0)); |
||||
assert_eq!(third.checked_mul(1), Some(third)); |
||||
assert_eq!(third.checked_mul(2), Some(third * 2)); |
||||
assert_eq!(third.checked_mul(3), Some(third * 3)); |
||||
assert_eq!(third.checked_mul(4), None); |
||||
} |
||||
|
||||
macro_rules! test_is_power_of_two { |
||||
($test_name:ident, $T:ident) => ( |
||||
fn $test_name() { |
||||
#![test] |
||||
assert_eq!((0 as $T).is_power_of_two(), false); |
||||
assert_eq!((1 as $T).is_power_of_two(), true); |
||||
assert_eq!((2 as $T).is_power_of_two(), true); |
||||
assert_eq!((3 as $T).is_power_of_two(), false); |
||||
assert_eq!((4 as $T).is_power_of_two(), true); |
||||
assert_eq!((5 as $T).is_power_of_two(), false); |
||||
assert_eq!(($T::MAX / 2 + 1).is_power_of_two(), true); |
||||
} |
||||
) |
||||
} |
||||
|
||||
test_is_power_of_two!{ test_is_power_of_two_u8, u8 } |
||||
test_is_power_of_two!{ test_is_power_of_two_u16, u16 } |
||||
test_is_power_of_two!{ test_is_power_of_two_u32, u32 } |
||||
test_is_power_of_two!{ test_is_power_of_two_u64, u64 } |
||||
test_is_power_of_two!{ test_is_power_of_two_uint, usize } |
||||
|
||||
macro_rules! test_next_power_of_two { |
||||
($test_name:ident, $T:ident) => ( |
||||
fn $test_name() { |
||||
#![test] |
||||
assert_eq!((0 as $T).next_power_of_two(), 1); |
||||
let mut next_power = 1; |
||||
for i in 1 as $T..40 { |
||||
assert_eq!(i.next_power_of_two(), next_power); |
||||
if i == next_power { next_power *= 2 } |
||||
} |
||||
} |
||||
) |
||||
} |
||||
|
||||
test_next_power_of_two! { test_next_power_of_two_u8, u8 } |
||||
test_next_power_of_two! { test_next_power_of_two_u16, u16 } |
||||
test_next_power_of_two! { test_next_power_of_two_u32, u32 } |
||||
test_next_power_of_two! { test_next_power_of_two_u64, u64 } |
||||
test_next_power_of_two! { test_next_power_of_two_uint, usize } |
||||
|
||||
macro_rules! test_checked_next_power_of_two { |
||||
($test_name:ident, $T:ident) => ( |
||||
fn $test_name() { |
||||
#![test] |
||||
assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); |
||||
assert!(($T::MAX / 2).checked_next_power_of_two().is_some()); |
||||
assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None); |
||||
assert_eq!($T::MAX.checked_next_power_of_two(), None); |
||||
let mut next_power = 1; |
||||
for i in 1 as $T..40 { |
||||
assert_eq!(i.checked_next_power_of_two(), Some(next_power)); |
||||
if i == next_power { next_power *= 2 } |
||||
} |
||||
} |
||||
) |
||||
} |
||||
|
||||
test_checked_next_power_of_two! { test_checked_next_power_of_two_u8, u8 } |
||||
test_checked_next_power_of_two! { test_checked_next_power_of_two_u16, u16 } |
||||
test_checked_next_power_of_two! { test_checked_next_power_of_two_u32, u32 } |
||||
test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 } |
||||
test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize } |
||||
|
||||
#[test] |
||||
fn test_pow() { |
||||
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 { |
||||
(($num:expr, $exp:expr) => $expected:expr) => {{ |
||||
let result = $num.pow($exp); |
||||
assert_eq!(result, $expected); |
||||
assert_eq!(result, naive_pow(1, $num, $exp)); |
||||
}} |
||||
} |
||||
assert_pow!((3u32, 0 ) => 1); |
||||
assert_pow!((5u32, 1 ) => 5); |
||||
assert_pow!((-4i32, 2 ) => 16); |
||||
assert_pow!((8u32, 3 ) => 512); |
||||
assert_pow!((2u64, 50) => 1125899906842624); |
||||
} |
||||
|
||||
#[test] |
||||
fn test_uint_to_str_overflow() { |
||||
let mut u8_val: u8 = 255; |
||||
assert_eq!(u8_val.to_string(), "255"); |
||||
|
||||
u8_val = u8_val.wrapping_add(1); |
||||
assert_eq!(u8_val.to_string(), "0"); |
||||
|
||||
let mut u16_val: u16 = 65_535; |
||||
assert_eq!(u16_val.to_string(), "65535"); |
||||
|
||||
u16_val = u16_val.wrapping_add(1); |
||||
assert_eq!(u16_val.to_string(), "0"); |
||||
|
||||
let mut u32_val: u32 = 4_294_967_295; |
||||
assert_eq!(u32_val.to_string(), "4294967295"); |
||||
|
||||
u32_val = u32_val.wrapping_add(1); |
||||
assert_eq!(u32_val.to_string(), "0"); |
||||
|
||||
let mut u64_val: u64 = 18_446_744_073_709_551_615; |
||||
assert_eq!(u64_val.to_string(), "18446744073709551615"); |
||||
|
||||
u64_val = u64_val.wrapping_add(1); |
||||
assert_eq!(u64_val.to_string(), "0"); |
||||
} |
||||
|
||||
fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> { |
||||
::str::FromStr::from_str(t).ok() |
||||
} |
||||
|
||||
#[test] |
||||
fn test_uint_from_str_overflow() { |
||||
let mut u8_val: u8 = 255; |
||||
assert_eq!(from_str::<u8>("255"), Some(u8_val)); |
||||
assert_eq!(from_str::<u8>("256"), None); |
||||
|
||||
u8_val = u8_val.wrapping_add(1); |
||||
assert_eq!(from_str::<u8>("0"), Some(u8_val)); |
||||
assert_eq!(from_str::<u8>("-1"), None); |
||||
|
||||
let mut u16_val: u16 = 65_535; |
||||
assert_eq!(from_str::<u16>("65535"), Some(u16_val)); |
||||
assert_eq!(from_str::<u16>("65536"), None); |
||||
|
||||
u16_val = u16_val.wrapping_add(1); |
||||
assert_eq!(from_str::<u16>("0"), Some(u16_val)); |
||||
assert_eq!(from_str::<u16>("-1"), None); |
||||
|
||||
let mut u32_val: u32 = 4_294_967_295; |
||||
assert_eq!(from_str::<u32>("4294967295"), Some(u32_val)); |
||||
assert_eq!(from_str::<u32>("4294967296"), None); |
||||
|
||||
u32_val = u32_val.wrapping_add(1); |
||||
assert_eq!(from_str::<u32>("0"), Some(u32_val)); |
||||
assert_eq!(from_str::<u32>("-1"), None); |
||||
|
||||
let mut u64_val: u64 = 18_446_744_073_709_551_615; |
||||
assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val)); |
||||
assert_eq!(from_str::<u64>("18446744073709551616"), None); |
||||
|
||||
u64_val = u64_val.wrapping_add(1); |
||||
assert_eq!(from_str::<u64>("0"), Some(u64_val)); |
||||
assert_eq!(from_str::<u64>("-1"), None); |
||||
} |
||||
} |
||||
|
||||
|
||||
#[cfg(test)] |
||||
mod bench { |
||||
extern crate test; |
||||
use self::test::Bencher; |
||||
|
||||
#[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));}); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
@@ -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; |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,146 @@
@@ -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; |
@ -0,0 +1,53 @@
@@ -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; |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
//! Runtime services
|
||||
//!
|
||||
//! The `rt` module provides a narrow set of runtime services,
|
||||
//! including the global heap (exported in `heap`) and unwinding and
|
||||
//! backtrace support. The APIs in this module are highly unstable,
|
||||
//! 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.
|
||||
pub use panicking::{begin_panic, begin_panic_fmt}; |
||||
|
||||
//TODO: Handle argc/argv arguments
|
||||
#[lang = "start"] |
||||
#[allow(unused_variables)] |
||||
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { |
||||
unsafe { mem::transmute::<_, fn()>(main)(); } |
||||
0 |
||||
} |
@ -0,0 +1,29 @@
@@ -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}; |
@ -0,0 +1,37 @@
@@ -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; |
@ -0,0 +1,61 @@
@@ -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 |
||||
} |
||||
} |
@ -0,0 +1,41 @@
@@ -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}; |
||||
} |
@ -0,0 +1,51 @@
@@ -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) |
||||
} |
@ -0,0 +1,50 @@
@@ -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() |
||||
} |
@ -0,0 +1,123 @@
@@ -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) } |
||||
} |
@ -0,0 +1,119 @@
@@ -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() } |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -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 = '/'; |
@ -0,0 +1,179 @@
@@ -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) } |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,76 @@
@@ -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); |
||||
} |
@ -0,0 +1,31 @@
@@ -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" |
||||
] |
||||
} |
@ -1,18 +1,19 @@
@@ -1,18 +1,19 @@
|
||||
[package] |
||||
authors = ["Ronald Kinard <furyhunter600@gmail.com>"] |
||||
build = "build.rs" |
||||
description = "A safe wrapper around smealum's ctrulib." |
||||
license = "https://en.wikipedia.org/wiki/Zlib_License" |
||||
links = "ctru" |
||||
name = "ctru-rs" |
||||
version = "0.4.0" |
||||
|
||||
[dependencies.ctru-sys] |
||||
path = "ctru-sys" |
||||
|
||||
[dependencies.alloc_system3ds] |
||||
git = "https://github.com/rust3ds/alloc_system3ds" |
||||
version = "0.5.0" |
||||
|
||||
[lib] |
||||
crate-type = ["rlib"] |
||||
name = "ctru" |
||||
|
||||
[dependencies.ctru-sys] |
||||
path = "../ctru-sys" |
||||
|
||||
[dependencies.bitflags] |
||||
version = "0.7.0" |
||||
|
||||
[dependencies.widestring] |
||||
version = "0.2.2" |
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
# ctru-rs |
||||
|
||||
A Rust wrapper library for smealum's |
||||
[ctrulib](https://github.com/smealum/ctrulib). |
||||
|
||||
See the [3DS project template](https://github.com/rust3ds/rust3ds-template) for instructions on how to use this library. |
||||
|
||||
## Structure |
||||
|
||||
This library is meant to expose 3DS-specific functionality. Common functionality is implemented in `ctr-std` when possible. |
||||
|
||||
## Contributing |
||||
|
||||
PR's are welcome. Organization of rust specific features and wrapper functionality are still being decided on. |
||||
|
||||
## License |
||||
|
||||
Copyright (C) Rust 3DS Project authors, 2015-2016 |
||||
|
||||
See AUTHORS.md. |
||||
|
||||
As with the original ctrulib, this library is licensed under zlib. This |
||||
applies to every file in the tree, unless otherwise noted. |
||||
|
||||
This software is provided 'as-is', without any express or implied |
||||
warranty. In no event will the authors be held liable for any |
||||
damages arising from the use of this software. |
||||
|
||||
Permission is granted to anyone to use this software for any |
||||
purpose, including commercial applications, and to alter it and |
||||
redistribute it freely, subject to the following restrictions: |
||||
|
||||
1. The origin of this software must not be misrepresented; you |
||||
must not claim that you wrote the original software. If you use |
||||
this software in a product, an acknowledgment in the product |
||||
documentation would be appreciated but is not required. |
||||
2. Altered source versions must be plainly marked as such, and |
||||
must not be misrepresented as being the original software. |
||||
3. This notice may not be removed or altered from any source |
||||
distribution. |
||||
|
||||
Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses. |
||||
|
||||
See [LICENSE-APACHE](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE), [LICENSE-MIT](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT), and [COPYRIGHT](https://github.com/rust-lang/rust/blob/master/COPYRIGHT) for details. |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
[dependencies.collections] |
||||
|
||||
[dependencies.ctr-libc] |
||||
path = "../ctr-libc" |
||||
stage = 1 |
||||
|
||||
[dependencies.std] |
||||
path = "../ctr-std" |
||||
stage = 2 |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
use std::default::Default; |
||||
use std::ptr; |
||||
|
||||
use gfx::Screen; |
||||
|
||||
use libctru::console::*; |
||||
|
||||
pub struct Console { |
||||
context: PrintConsole, |
||||
} |
||||
|
||||
impl Console { |
||||
pub fn init(screen: Screen) -> Self { |
||||
unsafe { |
||||
let ret = *(consoleInit(screen.into(), ptr::null_mut())); |
||||
Console { context: ret } |
||||
} |
||||
} |
||||
|
||||
pub fn select(&mut self) { |
||||
unsafe { consoleSelect(&mut self.context); } |
||||
} |
||||
|
||||
pub fn set_window(&mut self, x: i32, y: i32, width: i32, height: i32) { |
||||
unsafe { consoleSetWindow(&mut self.context, x, y, width, height) } |
||||
}
|
||||
|
||||
pub fn clear(&mut self) { |
||||
unsafe { consoleClear() } |
||||
} |
||||
} |
||||
|
||||
impl Default for Console { |
||||
fn default() -> Self { |
||||
Console::init(Screen::Top) |
||||
} |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
use std::error; |
||||
use std::fmt; |
||||
|
||||
pub type Result<T> = ::std::result::Result<T, Error>; |
||||
|
||||
/// The error type returned by all libctru functions.
|
||||
pub enum Error { |
||||
Os(i32), |
||||
} |
||||
|
||||
impl From<i32> for Error { |
||||
fn from(err: i32) -> Self { |
||||
Error::Os(err) |
||||
} |
||||
} |
||||
|
||||
impl fmt::Debug for Error { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
match *self { |
||||
Error::Os(err) => write!(f, "libctru result code: {:08X}", err), |
||||
} |
||||
} |
||||
} |
||||
|
||||
// TODO: Expand libctru result code into human-readable error message
|
||||
impl fmt::Display for Error { |
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||
match *self { |
||||
Error::Os(err) => write!(f, "libctru result code: 0x{:08X}", err), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl error::Error for Error { |
||||
fn description(&self) -> &str { |
||||
"error originating from a libctru function" |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
#![crate_type = "rlib"] |
||||
#![crate_name = "ctru"] |
||||
|
||||
#[macro_use] |
||||
extern crate bitflags; |
||||
extern crate widestring; |
||||
|
||||
extern crate ctru_sys as libctru; |
||||
|
||||
pub mod console; |
||||
pub mod error; |
||||
pub mod srv; |
||||
pub mod gfx; |
||||
pub mod services; |
||||
pub mod sdmc; |
||||
|
||||
pub use error::{Result, Error}; |
||||
|
||||
pub use srv::Srv; |
||||
pub use gfx::Gfx; |
||||
pub use sdmc::Sdmc; |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
use std::marker::PhantomData; |
||||
|
||||
use libctru::services::apt; |
||||
|
||||
pub struct Apt { |
||||
pd: PhantomData<i32> |
||||
} |
||||
|
||||
impl Apt { |
||||
pub fn init() -> ::Result<Apt> { |
||||
unsafe { |
||||
let r = apt::aptInit(); |
||||
if r < 0 { |
||||
Err(::Error::from(r)) |
||||
} else { |
||||
Ok(Apt { pd: PhantomData }) |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub fn main_loop(&self) -> bool { |
||||
unsafe { |
||||
match apt::aptMainLoop() { |
||||
1 => true, |
||||
0 => false, |
||||
_ => unreachable!(), |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl Drop for Apt { |
||||
fn drop(&mut self) { |
||||
unsafe { apt::aptExit() }; |
||||
} |
||||
} |
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
||||
use libctru::services::gspgpu; |
||||
|
||||
use core::convert::From; |
||||
use std::convert::From; |
||||
|
||||
pub enum Event { |
||||
Psc0, |
@ -1,17 +1,17 @@
@@ -1,17 +1,17 @@
|
||||
use libctru::srv::*; |
||||
|
||||
use core::marker::PhantomData; |
||||
use std::marker::PhantomData; |
||||
|
||||
pub struct Srv { |
||||
pd: PhantomData<i32>, |
||||
} |
||||
|
||||
impl Srv { |
||||
pub fn init() -> Result<Srv, i32> { |
||||
pub fn init() -> ::Result<Srv> { |
||||
unsafe { |
||||
let r = srvInit(); |
||||
if r < 0 { |
||||
Err(r) |
||||
Err(::Error::from(r)) |
||||
} else { |
||||
Ok(Srv { pd: PhantomData }) |
||||
} |
@ -1,5 +1,8 @@
@@ -1,5 +1,8 @@
|
||||
[package] |
||||
name = "ctru-sys" |
||||
version = "0.2.0" |
||||
version = "0.3.0" |
||||
authors = ["Ronald Kinard <furyhunter600@gmail.com>"] |
||||
license = "https://en.wikipedia.org/wiki/Zlib_License" |
||||
|
||||
[dependencies] |
||||
ctr-libc = { path = "../ctr-libc" } |
||||
|
@ -0,0 +1,258 @@
@@ -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; |
||||
} |
@ -1,26 +1,27 @@
@@ -1,26 +1,27 @@
|
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#[inline] |
||||
pub fn GPUCMD_HEADER(incremental: u32, mask: u32, reg: u32) -> u32{ |
||||
(((incremental)<<31)|(((mask)&0xF)<<16)|((reg)&0x3FF)) |
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub static mut gpuCmdBuf: *mut u32_; |
||||
pub static mut gpuCmdBufSize: u32_; |
||||
pub static mut gpuCmdBufOffset: u32_; |
||||
} |
||||
|
||||
extern "C" { |
||||
pub static mut gpuCmdBuf: *mut u32; |
||||
pub static mut gpuCmdBufSize: u32; |
||||
pub static mut gpuCmdBufOffset: u32; |
||||
|
||||
pub fn GPUCMD_SetBuffer(adr: *mut u32, size: u32, offset: u32); |
||||
pub fn GPUCMD_SetBufferOffset(offset: u32); |
||||
pub fn GPUCMD_GetBuffer(adr: *mut *mut u32, size: *mut u32, |
||||
offset: *mut u32); |
||||
pub fn GPUCMD_AddRawCommands(cmd: *mut u32, size: u32); |
||||
pub fn GPUCMD_SetBuffer(adr: *mut u32_, size: u32_, offset: u32_); |
||||
pub fn GPUCMD_SetBufferOffset(offset: u32_); |
||||
pub fn GPUCMD_GetBuffer(adr: *mut *mut u32_, size: *mut u32_, |
||||
offset: *mut u32_); |
||||
pub fn GPUCMD_AddRawCommands(cmd: *const u32_, size: u32_); |
||||
pub fn GPUCMD_Run(); |
||||
pub fn GPUCMD_FlushAndRun(); |
||||
pub fn GPUCMD_Add(header: u32, param: *mut u32, paramlength: u32); |
||||
pub fn GPUCMD_Add(header: u32_, param: *const u32_, paramlength: u32_); |
||||
pub fn GPUCMD_Finalize(); |
||||
pub fn f32tof16(f: f32) -> u32; |
||||
pub fn f32tof20(f: f32) -> u32; |
||||
pub fn f32tof24(f: f32) -> u32; |
||||
pub fn f32tof31(f: f32) -> u32;
|
||||
pub fn f32tof16(f: f32) -> u32_; |
||||
pub fn f32tof20(f: f32) -> u32_; |
||||
pub fn f32tof24(f: f32) -> u32_; |
||||
pub fn f32tof31(f: f32) -> u32_; |
||||
} |
||||
use ::types::*; |
||||
|
@ -1,94 +1,55 @@
@@ -1,94 +1,55 @@
|
||||
use ::Result; |
||||
|
||||
#[inline] |
||||
pub fn GX_BUFFER_DIM(w: u32, h: u32) { |
||||
(((h)<<16)|((w)&0xFFFF)); |
||||
} |
||||
|
||||
#[repr(C)] |
||||
pub enum GX_TRANSFER_FORMAT |
||||
{ |
||||
GX_TRANSFER_FMT_RGBA8 = 0, |
||||
GX_TRANSFER_FMT_RGB8 = 1, |
||||
GX_TRANSFER_FMT_RGB565 = 2, |
||||
GX_TRANSFER_FMT_RGB5A1 = 3, |
||||
GX_TRANSFER_FMT_RGBA4 = 4, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
pub enum GX_TRANSFER_SCALE |
||||
{ |
||||
GX_TRANSFER_SCALE_NO = 0, |
||||
GX_TRANSFER_SCALE_X = 1, |
||||
GX_TRANSFER_SCALE_Y = 2, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
/* 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 GX_TRANSFER_FORMAT { |
||||
GX_TRANSFER_FMT_RGBA8 = 0, |
||||
GX_TRANSFER_FMT_RGB8 = 1, |
||||
GX_TRANSFER_FMT_RGB565 = 2, |
||||
GX_TRANSFER_FMT_RGB5A1 = 3, |
||||
GX_TRANSFER_FMT_RGBA4 = 4, |
||||
} |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum GX_TRANSFER_SCALE { |
||||
GX_TRANSFER_SCALE_NO = 0, |
||||
GX_TRANSFER_SCALE_X = 1, |
||||
GX_TRANSFER_SCALE_XY = 2, |
||||
} |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum GX_FILL_CONTROL { |
||||
GX_FILL_TRIGGER = 0x001, |
||||
GX_FILL_FINISHED = 0x002, |
||||
GX_FILL_16BIT_DEPTH = 0x000, |
||||
GX_FILL_24BIT_DEPTH = 0x100, |
||||
GX_FILL_32BIT_DEPTH = 0x200, |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_TRANSFER_FLIP_VERT(x: i32) { |
||||
((x)<<0); |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_TRANSFER_OUT_TILED(x: i32) { |
||||
((x)<<1); |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_TRANSFER_RAW_COPY(x: i32) { |
||||
((x)<<3); |
||||
GX_FILL_TRIGGER = 1, |
||||
GX_FILL_FINISHED = 2, |
||||
GX_FILL_16BIT_DEPTH = 0, |
||||
GX_FILL_24BIT_DEPTH = 256, |
||||
GX_FILL_32BIT_DEPTH = 512, |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_TRANSFER_IN_FORMAT(x: i32) { |
||||
((x)<<8); |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_TRANSFER_OUT_FORMAT(x: i32) { |
||||
((x)<<12); |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_TRANSFER_SCALING(x: i32) { |
||||
((x)<<24); |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_CMDLIST_BIT0() { |
||||
(1u32<<(0)); |
||||
} |
||||
|
||||
#[inline] |
||||
pub fn GX_CMNDLIST_FLUSH() { |
||||
(1u32<<(1)); |
||||
extern "C" { |
||||
pub static mut gxCmdBuf: *mut u32_; |
||||
} |
||||
|
||||
extern "C" { |
||||
pub static mut gxCmdBuf: *mut u32; |
||||
|
||||
pub fn GX_RequestDma(src: *mut u32, dst: *mut u32, length: u32) |
||||
pub fn GX_RequestDma(src: *mut u32_, dst: *mut u32_, length: u32_) |
||||
-> Result; |
||||
pub fn GX_ProcessCommandList(buf0a: *mut u32, buf0s: u32, flags: u8) |
||||
pub fn GX_ProcessCommandList(buf0a: *mut u32_, buf0s: u32_, flags: u8_) |
||||
-> Result; |
||||
pub fn GX_MemoryFill(buf0a: *mut u32, buf0v: u32, buf0e: *mut u32, |
||||
control0: u16, buf1a: *mut u32, buf1v: u32, |
||||
buf1e: *mut u32, control1: u16) -> Result; |
||||
pub fn GX_DisplayTransfer(inadr: *mut u32, indim: u32, |
||||
outadr: *mut u32, outdim: u32, flags: u32) |
||||
pub fn GX_MemoryFill(buf0a: *mut u32_, buf0v: u32_, buf0e: *mut u32_, |
||||
control0: u16_, buf1a: *mut u32_, buf1v: u32_, |
||||
buf1e: *mut u32_, control1: u16_) -> Result; |
||||
pub fn GX_DisplayTransfer(inadr: *mut u32_, indim: u32_, |
||||
outadr: *mut u32_, outdim: u32_, flags: u32_) |
||||
-> Result; |
||||
pub fn GX_TextureCopy(inadr: *mut u32, indim: u32, outadr: *mut u32, |
||||
outdim: u32, size: u32, flags: u32) -> Result; |
||||
pub fn GX_FlushCacheRegions(buf0a: *mut u32, buf0s: u32, |
||||
buf1a: *mut u32, buf1s: u32, |
||||
buf2a: *mut u32, buf2s: u32) -> Result; |
||||
pub fn GX_TextureCopy(inadr: *mut u32_, indim: u32_, outadr: *mut u32_, |
||||
outdim: u32_, size: u32_, flags: u32_) -> Result; |
||||
pub fn GX_FlushCacheRegions(buf0a: *mut u32_, buf0s: u32_, |
||||
buf1a: *mut u32_, buf1s: u32_, |
||||
buf2a: *mut u32_, buf2s: u32_) -> Result; |
||||
} |
||||
|
||||
use ::types::*; |
||||
|
@ -1,89 +1,68 @@
@@ -1,89 +1,68 @@
|
||||
use ::Result; |
||||
use ::types::*; |
||||
use gpu::shbin::*; |
||||
|
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct Struct_Unnamed1 { |
||||
pub id: u32, |
||||
pub data: [u32; 3usize], |
||||
} |
||||
impl ::core::clone::Clone for Struct_Unnamed1 { |
||||
fn clone(&self) -> Self { *self } |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct float24Uniform_s { |
||||
pub id: u32_, |
||||
pub data: [u32_; 3usize], |
||||
} |
||||
impl ::core::default::Default for Struct_Unnamed1 { |
||||
impl ::core::default::Default for float24Uniform_s { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
pub type float24Uniform_s = Struct_Unnamed1; |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct Struct_Unnamed2 { |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct shaderInstance_s { |
||||
pub dvle: *mut DVLE_s, |
||||
pub boolUniforms: u16, |
||||
pub boolUniformMask: u16, |
||||
pub intUniforms: [u32; 4usize], |
||||
pub boolUniforms: u16_, |
||||
pub boolUniformMask: u16_, |
||||
pub intUniforms: [u32_; 4usize], |
||||
pub float24Uniforms: *mut float24Uniform_s, |
||||
pub intUniformMask: u8, |
||||
pub numFloat24Uniforms: u8, |
||||
pub intUniformMask: u8_, |
||||
pub numFloat24Uniforms: u8_, |
||||
} |
||||
impl ::core::clone::Clone for Struct_Unnamed2 { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
impl ::core::default::Default for Struct_Unnamed2 { |
||||
impl ::core::default::Default for shaderInstance_s { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
pub type shaderInstance_s = Struct_Unnamed2; |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct Struct_Unnamed3 { |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct shaderProgram_s { |
||||
pub vertexShader: *mut shaderInstance_s, |
||||
pub geometryShader: *mut shaderInstance_s, |
||||
pub geoShaderInputPermutation: [u32; 2usize], |
||||
pub geoShaderInputStride: u8, |
||||
pub geoShaderMode: u8, |
||||
} |
||||
impl ::core::clone::Clone for Struct_Unnamed3 { |
||||
fn clone(&self) -> Self { *self } |
||||
pub geoShaderInputPermutation: [u32_; 2usize], |
||||
pub geoShaderInputStride: u8_, |
||||
} |
||||
impl ::core::default::Default for Struct_Unnamed3 { |
||||
impl ::core::default::Default for shaderProgram_s { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
pub type shaderProgram_s = Struct_Unnamed3; |
||||
#[derive(Clone, Copy)] |
||||
#[repr(u32)] |
||||
pub enum Enum_Unnamed4 { |
||||
GSH_NORMAL = 0, |
||||
GSH_PARTICLE = 1, |
||||
GSH_SUBDIVISION_LOOP = 2, |
||||
GSH_SUBDIVISION_CATMULL_CLARK = 3, |
||||
} |
||||
pub type geoShaderMode = Enum_Unnamed4; |
||||
extern "C" { |
||||
pub fn shaderInstanceInit(si: *mut shaderInstance_s, dvle: *mut DVLE_s) |
||||
-> Result; |
||||
pub fn shaderInstanceFree(si: *mut shaderInstance_s) -> Result; |
||||
pub fn shaderInstanceSetBool(si: *mut shaderInstance_s, |
||||
id: i32, value: u8) |
||||
-> Result; |
||||
pub fn shaderInstanceGetBool(si: *mut shaderInstance_s, |
||||
id: i32, value: *mut u8) |
||||
-> Result; |
||||
pub fn shaderInstanceSetBool(si: *mut shaderInstance_s, id: ::libc::c_int, |
||||
value: u8) -> Result; |
||||
pub fn shaderInstanceGetBool(si: *mut shaderInstance_s, id: ::libc::c_int, |
||||
value: *mut u8) -> Result; |
||||
pub fn shaderInstanceGetUniformLocation(si: *mut shaderInstance_s, |
||||
name: |
||||
*const u8) |
||||
name: *const ::libc::c_char) |
||||
-> s8; |
||||
pub fn shaderProgramInit(sp: *mut shaderProgram_s) -> Result; |
||||
pub fn shaderProgramFree(sp: *mut shaderProgram_s) -> Result; |
||||
pub fn shaderProgramSetVsh(sp: *mut shaderProgram_s, dvle: *mut DVLE_s) |
||||
-> Result; |
||||
pub fn shaderProgramSetGsh(sp: *mut shaderProgram_s, dvle: *mut DVLE_s, |
||||
stride: u8) -> Result; |
||||
stride: u8_) -> Result; |
||||
pub fn shaderProgramSetGshInputPermutation(sp: *mut shaderProgram_s, |
||||
permutation: u64) -> Result; |
||||
pub fn shaderProgramSetGshMode(sp: *mut shaderProgram_s, |
||||
mode: geoShaderMode) -> Result; |
||||
permutation: u64_) -> Result; |
||||
pub fn shaderProgramConfigure(sp: *mut shaderProgram_s, sendVshCode: u8, |
||||
sendGshCode: u8) -> Result; |
||||
pub fn shaderProgramUse(sp: *mut shaderProgram_s) -> Result; |
||||
} |
||||
use ::types::*; |
||||
use super::shbin::*; |
||||
|
@ -0,0 +1,82 @@
@@ -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; |
||||
} |
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
pub mod channel; |
||||
pub mod ndsp; |
@ -0,0 +1,112 @@
@@ -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::*; |
@ -1,54 +1,47 @@
@@ -1,54 +1,47 @@
|
||||
//TODO: Fix Bindgen's issues again.
|
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
use ::Result; |
||||
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::*; |
||||
|
@ -0,0 +1,64 @@
@@ -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::*; |
@ -1,7 +1,29 @@
@@ -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; |
||||
} |
||||
|
@ -1,8 +1,13 @@
@@ -1,8 +1,13 @@
|
||||
use ::Result; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub fn acInit() -> Result; |
||||
pub fn acExit(); |
||||
pub fn acWaitInternetConnection() -> Result; |
||||
pub fn ACU_GetWifiStatus(out: *mut u32) -> Result; |
||||
pub fn ACU_GetWifiStatus(out: *mut u32_) -> Result; |
||||
} |
||||
use ::types::*; |
||||
|
@ -1,49 +1,186 @@
@@ -1,49 +1,186 @@
|
||||
use ::{Handle, Result}; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct AM_TitleEntry { |
||||
pub titleID: u64, |
||||
pub size: u64, |
||||
pub version: u16, |
||||
pub unk: [u8; 6usize], |
||||
pub titleID: u64_, |
||||
pub size: u64_, |
||||
pub version: u16_, |
||||
pub unk: [u8_; 6usize], |
||||
} |
||||
|
||||
impl ::core::clone::Clone for AM_TitleEntry { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
|
||||
impl ::core::default::Default for AM_TitleEntry { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
|
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum Enum_Unnamed1 { |
||||
AM_STATUS_MASK_INSTALLING = 1, |
||||
AM_STATUS_MASK_AWAITING_FINALIZATION = 2, |
||||
} |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum AM_InstallStatus { |
||||
AM_STATUS_ABORTED = 2, |
||||
AM_STATUS_SAVED = 3, |
||||
AM_STATUS_INSTALL_IN_PROGRESS = 2050, |
||||
AM_STATUS_AWAITING_FINALIZATION = 2051, |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct AM_PendingTitleEntry { |
||||
pub titleId: u64_, |
||||
pub version: u16_, |
||||
pub status: u16_, |
||||
pub titleType: u32_, |
||||
pub unk: [u8_; 8usize], |
||||
} |
||||
impl ::core::default::Default for AM_PendingTitleEntry { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum Enum_Unnamed2 { |
||||
AM_DELETE_PENDING_NON_SYSTEM = 1, |
||||
AM_DELETE_PENDING_SYSTEM = 2, |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct AM_TWLPartitionInfo { |
||||
pub capacity: u64_, |
||||
pub freeSpace: u64_, |
||||
pub titlesCapacity: u64_, |
||||
pub titlesFreeSpace: u64_, |
||||
} |
||||
impl ::core::default::Default for AM_TWLPartitionInfo { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
extern "C" { |
||||
pub fn amInit() -> Result; |
||||
pub fn amAppInit() -> Result; |
||||
pub fn amExit(); |
||||
pub fn amGetSessionHandle() -> *mut Handle; |
||||
pub fn AM_GetTitleCount(mediatype: u8, count: *mut u32) -> Result; |
||||
pub fn AM_GetTitleIdList(mediatype: u8, count: u32, titleIDs: *mut u64) |
||||
pub fn AM_GetTitleCount(mediatype: FS_MediaType, count: *mut u32_) |
||||
-> Result; |
||||
pub fn AM_GetTitleList(titlesRead: *mut u32_, mediatype: FS_MediaType, |
||||
titleCount: u32_, titleIds: *mut u64_) -> Result; |
||||
pub fn AM_GetTitleInfo(mediatype: FS_MediaType, titleCount: u32_, |
||||
titleIds: *mut u64_, titleInfo: *mut AM_TitleEntry) |
||||
-> Result; |
||||
pub fn AM_GetDeviceId(deviceID: *mut u32) -> Result; |
||||
pub fn AM_ListTitles(mediatype: u8, titleCount: u32, |
||||
titleIdList: *mut u64, titleList: *mut AM_TitleEntry) |
||||
pub fn AM_GetTicketCount(count: *mut u32_) -> Result; |
||||
pub fn AM_GetTicketList(ticketsRead: *mut u32_, ticketCount: u32_, |
||||
skip: u32_, ticketIds: *mut u64_) -> Result; |
||||
pub fn AM_GetPendingTitleCount(count: *mut u32_, mediatype: FS_MediaType, |
||||
statusMask: u32_) -> Result; |
||||
pub fn AM_GetPendingTitleList(titlesRead: *mut u32_, titleCount: u32_, |
||||
mediatype: FS_MediaType, statusMask: u32_, |
||||
titleIds: *mut u64_) -> Result; |
||||
pub fn AM_GetPendingTitleInfo(titleCount: u32_, mediatype: FS_MediaType, |
||||
titleIds: *mut u64_, |
||||
titleInfo: *mut AM_PendingTitleEntry) |
||||
-> Result; |
||||
pub fn AM_StartCiaInstall(mediatype: u8, ciaHandle: *mut Handle) |
||||
pub fn AM_GetDeviceId(deviceID: *mut u32_) -> Result; |
||||
pub fn AM_ExportTwlBackup(titleID: u64_, operation: u8_, |
||||
workbuf: *mut ::libc::c_void, |
||||
workbuf_size: u32_, |
||||
filepath: *const ::libc::c_char) -> Result; |
||||
pub fn AM_ImportTwlBackup(filehandle: Handle, operation: u8_, |
||||
buffer: *mut ::libc::c_void, size: u32_) |
||||
-> Result; |
||||
pub fn AM_ReadTwlBackupInfo(filehandle: Handle, |
||||
outinfo: *mut ::libc::c_void, |
||||
outinfo_size: u32_, |
||||
workbuf: *mut ::libc::c_void, |
||||
workbuf_size: u32_, |
||||
banner: *mut ::libc::c_void, |
||||
banner_size: u32_) -> Result; |
||||
pub fn AM_GetTWLPartitionInfo(info: *mut AM_TWLPartitionInfo) -> Result; |
||||
pub fn AM_StartCiaInstall(mediatype: FS_MediaType, ciaHandle: *mut Handle) |
||||
-> Result; |
||||
pub fn AM_StartDlpChildCiaInstall(ciaHandle: *mut Handle) -> Result; |
||||
pub fn AM_CancelCIAInstall(ciaHandle: *mut Handle) -> Result; |
||||
pub fn AM_FinishCiaInstall(mediatype: u8, ciaHandle: *mut Handle) |
||||
pub fn AM_CancelCIAInstall(ciaHandle: Handle) -> Result; |
||||
pub fn AM_FinishCiaInstall(ciaHandle: Handle) -> Result; |
||||
pub fn AM_DeleteTitle(mediatype: FS_MediaType, titleID: u64_) -> Result; |
||||
pub fn AM_DeleteAppTitle(mediatype: FS_MediaType, titleID: u64_) |
||||
-> Result; |
||||
pub fn AM_DeleteTitle(mediatype: u8, titleID: u64) -> Result; |
||||
pub fn AM_DeleteAppTitle(mediatype: u8, titleID: u64) -> Result; |
||||
pub fn AM_InstallNativeFirm() -> Result; |
||||
pub fn AM_InstallFirm(titleID: u64) -> Result; |
||||
pub fn AM_GetTitleProductCode(mediatype: u8, titleID: u64,
|
||||
productCode: *mut u8) |
||||
pub fn AM_DeleteTicket(ticketId: u64_) -> Result; |
||||
pub fn AM_DeletePendingTitle(mediatype: FS_MediaType, titleId: u64_) |
||||
-> Result; |
||||
pub fn AM_GetCiaFileInfo(mediatype: u8, titleEntry: *mut AM_TitleEntry, |
||||
pub fn AM_DeletePendingTitles(mediatype: FS_MediaType, flags: u32_) |
||||
-> Result; |
||||
pub fn AM_DeleteAllPendingTitles(mediatype: FS_MediaType) -> Result; |
||||
pub fn AM_InstallNativeFirm() -> Result; |
||||
pub fn AM_InstallFirm(titleID: u64_) -> Result; |
||||
pub fn AM_GetTitleProductCode(mediatype: FS_MediaType, titleId: u64_, |
||||
productCode: *mut ::libc::c_char) -> Result; |
||||
pub fn AM_GetTitleExtDataId(extDataId: *mut u64_, mediatype: FS_MediaType, |
||||
titleId: u64_) -> Result; |
||||
pub fn AM_GetCiaFileInfo(mediatype: FS_MediaType, |
||||
titleEntry: *mut AM_TitleEntry, |
||||
fileHandle: Handle) -> Result; |
||||
pub fn AM_GetCiaIcon(icon: *mut ::libc::c_void, fileHandle: Handle) |
||||
-> Result; |
||||
pub fn AM_GetCiaDependencies(dependencies: *mut u64_, fileHandle: Handle) |
||||
-> Result; |
||||
pub fn AM_GetCiaMetaOffset(metaOffset: *mut u64_, fileHandle: Handle) |
||||
-> Result; |
||||
pub fn AM_GetCiaCoreVersion(coreVersion: *mut u32_, fileHandle: Handle) |
||||
-> Result; |
||||
pub fn AM_GetCiaRequiredSpace(requiredSpace: *mut u64_, |
||||
mediaType: FS_MediaType, fileHandle: Handle) |
||||
-> Result; |
||||
pub fn AM_GetCiaMetaSection(meta: *mut ::libc::c_void, size: u32_, |
||||
fileHandle: Handle) -> Result; |
||||
pub fn AM_InitializeExternalTitleDatabase(overwrite: u8) -> Result; |
||||
pub fn AM_QueryAvailableExternalTitleDatabase(available: *mut u8) |
||||
-> Result; |
||||
pub fn AM_InstallTicketBegin(ticketHandle: *mut Handle) -> Result; |
||||
pub fn AM_InstallTicketAbort(ticketHandle: Handle) -> Result; |
||||
pub fn AM_InstallTicketFinish(ticketHandle: Handle) -> Result; |
||||
pub fn AM_InstallTitleBegin(mediaType: FS_MediaType, titleId: u64_, |
||||
unk: u8) -> Result; |
||||
pub fn AM_InstallTitleStop() -> Result; |
||||
pub fn AM_InstallTitleResume(mediaType: FS_MediaType, titleId: u64_) |
||||
-> Result; |
||||
pub fn AM_InstallTitleAbort() -> Result; |
||||
pub fn AM_InstallTitleFinish() -> Result; |
||||
pub fn AM_CommitImportTitles(mediaType: FS_MediaType, titleCount: u32_, |
||||
temp: u8, titleIds: *mut u64_) -> Result; |
||||
pub fn AM_InstallTmdBegin(tmdHandle: *mut Handle) -> Result; |
||||
pub fn AM_InstallTmdAbort(tmdHandle: Handle) -> Result; |
||||
pub fn AM_InstallTmdFinish(tmdHandle: Handle, unk: u8) -> Result; |
||||
pub fn AM_CreateImportContentContexts(contentCount: u32_, |
||||
contentIndices: *mut u16_) |
||||
-> Result; |
||||
pub fn AM_InstallContentBegin(contentHandle: *mut Handle, index: u16_) |
||||
-> Result; |
||||
pub fn AM_InstallContentStop(contentHandle: Handle) -> Result; |
||||
pub fn AM_InstallContentResume(contentHandle: *mut Handle, |
||||
resumeOffset: *mut u64_, index: u16_) |
||||
-> Result; |
||||
pub fn AM_InstallContentCancel(contentHandle: Handle) -> Result; |
||||
pub fn AM_InstallContentFinish(contentHandle: Handle) -> Result; |
||||
pub fn AM_ImportCertificates(cert1Size: u32_, cert1: *mut ::libc::c_void, |
||||
cert2Size: u32_, cert2: *mut ::libc::c_void, |
||||
cert3Size: u32_, cert3: *mut ::libc::c_void, |
||||
cert4Size: u32_, cert4: *mut ::libc::c_void) |
||||
-> Result; |
||||
pub fn AM_ImportCertificate(certSize: u32_, cert: *mut ::libc::c_void) |
||||
-> Result; |
||||
pub fn AM_CommitImportTitlesAndUpdateFirmwareAuto(mediaType: FS_MediaType, |
||||
titleCount: u32_, |
||||
temp: u8, |
||||
titleIds: *mut u64_) |
||||
-> Result; |
||||
} |
||||
use ::types::*; |
||||
use super::fs::FS_MediaType; |
||||
|
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub fn ampxiInit(servhandle: Handle) -> Result; |
||||
pub fn ampxiExit(); |
||||
pub fn AMPXI_WriteTWLSavedata(titleid: u64_, buffer: *mut u8_, size: u32_, |
||||
image_filepos: u32_, section_type: u8_, |
||||
operation: u8_) -> Result; |
||||
pub fn AMPXI_InstallTitlesFinish(mediaType: FS_MediaType, db: u8_, |
||||
titlecount: u32_, tidlist: *mut u64_) |
||||
-> Result; |
||||
} |
||||
use ::types::*; |
||||
use super::fs::FS_MediaType; |
@ -1,14 +1,19 @@
@@ -1,14 +1,19 @@
|
||||
use ::Result; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub fn cfgnorInit(value: u8) -> Result; |
||||
pub fn cfgnorInit(value: u8_) -> Result; |
||||
pub fn cfgnorExit(); |
||||
pub fn cfgnorDumpFlash(buf: *mut u32, size: u32) -> Result; |
||||
pub fn cfgnorWriteFlash(buf: *mut u32, size: u32) -> Result; |
||||
pub fn CFGNOR_Initialize(value: u8) -> Result; |
||||
pub fn cfgnorDumpFlash(buf: *mut u32_, size: u32_) -> Result; |
||||
pub fn cfgnorWriteFlash(buf: *mut u32_, size: u32_) -> Result; |
||||
pub fn CFGNOR_Initialize(value: u8_) -> Result; |
||||
pub fn CFGNOR_Shutdown() -> Result; |
||||
pub fn CFGNOR_ReadData(offset: u32, buf: *mut u32, size: u32) |
||||
pub fn CFGNOR_ReadData(offset: u32_, buf: *mut u32_, size: u32_) |
||||
-> Result; |
||||
pub fn CFGNOR_WriteData(offset: u32, buf: *mut u32, size: u32) |
||||
pub fn CFGNOR_WriteData(offset: u32_, buf: *mut u32_, size: u32_) |
||||
-> Result; |
||||
} |
||||
use ::types::*; |
||||
|
@ -1,48 +1,45 @@
@@ -1,48 +1,45 @@
|
||||
use ::{Handle, Result}; |
||||
use ::libc::c_void; |
||||
|
||||
#[repr(C)] |
||||
#[derive(Clone, Copy)] |
||||
pub enum DSP_InterruptType { |
||||
DSP_INTERRUPT_PIPE = 2, |
||||
} |
||||
|
||||
#[repr(C)] |
||||
#[derive(Clone, Copy)] |
||||
pub enum DSP_PipeDirection { |
||||
DSP_PIPE_INPUT = 0, |
||||
DSP_PIPE_OUTPUT = 1, |
||||
} |
||||
/* 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 DSP_InterruptType { DSP_INTERRUPT_PIPE = 2, } |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum DSP_PipeDirection { DSP_PIPE_INPUT = 0, DSP_PIPE_OUTPUT = 1, } |
||||
extern "C" { |
||||
pub fn dspInit() -> Result; |
||||
pub fn dspExit(); |
||||
pub fn DSP_GetHeadphoneStatus(is_inserted: *mut u8) -> Result; |
||||
pub fn DSP_FlushDataCache(address: *const c_void, |
||||
size: u32) -> Result; |
||||
pub fn DSP_InvalidateDataCache(address: *const c_void, |
||||
size: u32) -> Result; |
||||
pub fn DSP_FlushDataCache(address: *const ::libc::c_void, size: u32_) |
||||
-> Result; |
||||
pub fn DSP_InvalidateDataCache(address: *const ::libc::c_void, size: u32_) |
||||
-> Result; |
||||
pub fn DSP_GetSemaphoreHandle(semaphore: *mut Handle) -> Result; |
||||
pub fn DSP_SetSemaphore(value: u16) -> Result; |
||||
pub fn DSP_SetSemaphoreMask(mask: u16) -> Result; |
||||
pub fn DSP_LoadComponent(component: *const c_void, |
||||
size: u32, prog_mask: u16, data_mask: u16, |
||||
pub fn DSP_SetSemaphore(value: u16_) -> Result; |
||||
pub fn DSP_SetSemaphoreMask(mask: u16_) -> Result; |
||||
pub fn DSP_LoadComponent(component: *const ::libc::c_void, size: u32_, |
||||
prog_mask: u16_, data_mask: u16_, |
||||
is_loaded: *mut u8) -> Result; |
||||
pub fn DSP_UnloadComponent() -> Result; |
||||
pub fn DSP_RegisterInterruptEvents(handle: Handle, interrupt: u32, |
||||
channel: u32) -> Result; |
||||
pub fn DSP_ReadPipeIfPossible(channel: u32, peer: u32, |
||||
buffer: *mut c_void, |
||||
length: u16, length_read: *mut u16) |
||||
-> Result; |
||||
pub fn DSP_WriteProcessPipe(channel: u32, |
||||
buffer: *const c_void, |
||||
length: u32) -> Result; |
||||
pub fn DSP_ConvertProcessAddressFromDspDram(dsp_address: u32, |
||||
arm_address: *mut u32) |
||||
pub fn DSP_RegisterInterruptEvents(handle: Handle, interrupt: u32_, |
||||
channel: u32_) -> Result; |
||||
pub fn DSP_ReadPipeIfPossible(channel: u32_, peer: u32_, |
||||
buffer: *mut ::libc::c_void, length: u16_, |
||||
length_read: *mut u16_) -> Result; |
||||
pub fn DSP_WriteProcessPipe(channel: u32_, buffer: *const ::libc::c_void, |
||||
length: u32_) -> Result; |
||||
pub fn DSP_ConvertProcessAddressFromDspDram(dsp_address: u32_, |
||||
arm_address: *mut u32_) |
||||
-> Result; |
||||
pub fn DSP_RecvData(regNo: u16, value: *mut u16) -> Result; |
||||
pub fn DSP_RecvDataIsReady(regNo: u16, is_ready: *mut u8) -> Result; |
||||
pub fn DSP_SendData(regNo: u16, value: u16) -> Result; |
||||
pub fn DSP_SendDataIsEmpty(regNo: u16, is_empty: *mut u8) -> Result; |
||||
pub fn DSP_RecvData(regNo: u16_, value: *mut u16_) -> Result; |
||||
pub fn DSP_RecvDataIsReady(regNo: u16_, is_ready: *mut u8) -> Result; |
||||
pub fn DSP_SendData(regNo: u16_, value: u16_) -> Result; |
||||
pub fn DSP_SendDataIsEmpty(regNo: u16_, is_empty: *mut u8) -> Result; |
||||
} |
||||
use ::types::*; |
||||
|
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
use ::Result; |
||||
use ::libc::c_void; |
||||
|
||||
|
||||
extern "C" { |
||||
pub fn hbInit() -> Result; |
||||
pub fn hbExit() -> (); |
||||
pub fn HB_FlushInvalidateCache() -> Result; |
||||
pub fn HB_GetBootloaderAddresses(load3dsx: *mut *mut c_void, setArgv: *mut *mut c_void)
|
||||
-> Result; |
||||
pub fn HB_ReprotectMemory(addr: *mut u32, pages: u32, mode: u32, reprotectedPages: *mut u32)
|
||||
-> Result; |
||||
} |
@ -1,79 +1,126 @@
@@ -1,79 +1,126 @@
|
||||
use ::{Handle, Result}; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct httpcContext { |
||||
pub servhandle: Handle, |
||||
pub httphandle: u32, |
||||
} |
||||
impl ::core::clone::Clone for httpcContext { |
||||
fn clone(&self) -> Self { *self } |
||||
pub httphandle: u32_, |
||||
} |
||||
impl ::core::default::Default for httpcContext { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
|
||||
#[derive(Clone, Copy)] |
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum HTTPC_RequestMethod { |
||||
HTTPC_METHOD_GET = 1, |
||||
HTTPC_METHOD_POST = 2, |
||||
HTTPC_METHOD_HEAD = 3, |
||||
HTTPC_METHOD_PUT = 4, |
||||
HTTPC_METHOD_DELETE = 5, |
||||
} |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum HTTPC_RequestStatus { |
||||
HTTPC_STATUS_REQUEST_IN_PROGRESS = 5, |
||||
HTTPC_STATUS_DOWNLOAD_READY = 7, |
||||
} |
||||
|
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum HTTPC_KeepAlive { |
||||
HTTPC_KEEPALIVE_DISABLED = 0, |
||||
HTTPC_KEEPALIVE_ENABLED = 1, |
||||
} |
||||
extern "C" { |
||||
pub fn httpcInit() -> Result; |
||||
pub fn httpcInit(sharedmem_size: u32_) -> Result; |
||||
pub fn httpcExit(); |
||||
pub fn httpcOpenContext(context: *mut httpcContext, |
||||
url: *mut u8, |
||||
use_defaultproxy: u32) -> Result; |
||||
method: HTTPC_RequestMethod, |
||||
url: *const ::libc::c_char, |
||||
use_defaultproxy: u32_) -> Result; |
||||
pub fn httpcCloseContext(context: *mut httpcContext) -> Result; |
||||
pub fn httpcCancelConnection(context: *mut httpcContext) -> Result; |
||||
pub fn httpcAddRequestHeaderField(context: *mut httpcContext, |
||||
name: *mut u8, |
||||
value: *mut u8) |
||||
-> Result; |
||||
name: *const ::libc::c_char, |
||||
value: *const ::libc::c_char) -> Result; |
||||
pub fn httpcAddPostDataAscii(context: *mut httpcContext, |
||||
name: *const ::libc::c_char, |
||||
value: *const ::libc::c_char) -> Result; |
||||
pub fn httpcAddPostDataRaw(context: *mut httpcContext, data: *const u32_, |
||||
len: u32_) -> Result; |
||||
pub fn httpcBeginRequest(context: *mut httpcContext) -> Result; |
||||
pub fn httpcReceiveData(context: *mut httpcContext, buffer: *mut u8, |
||||
size: u32) -> Result; |
||||
pub fn httpcReceiveData(context: *mut httpcContext, buffer: *mut u8_, |
||||
size: u32_) -> Result; |
||||
pub fn httpcReceiveDataTimeout(context: *mut httpcContext, |
||||
buffer: *mut u8_, size: u32_, |
||||
timeout: u64_) -> Result; |
||||
pub fn httpcGetRequestState(context: *mut httpcContext, |
||||
out: *mut HTTPC_RequestStatus) -> Result; |
||||
pub fn httpcGetDownloadSizeState(context: *mut httpcContext, |
||||
downloadedsize: *mut u32, |
||||
contentsize: *mut u32) -> Result; |
||||
downloadedsize: *mut u32_, |
||||
contentsize: *mut u32_) -> Result; |
||||
pub fn httpcGetResponseStatusCode(context: *mut httpcContext, |
||||
out: *mut u32, delay: u64) -> Result; |
||||
out: *mut u32_) -> Result; |
||||
pub fn httpcGetResponseStatusCodeTimeout(context: *mut httpcContext, |
||||
out: *mut u32_, timeout: u64_) |
||||
-> Result; |
||||
pub fn httpcGetResponseHeader(context: *mut httpcContext, |
||||
name: *mut u8, |
||||
value: *mut u8, |
||||
valuebuf_maxsize: u32) -> Result; |
||||
pub fn httpcDownloadData(context: *mut httpcContext, buffer: *mut u8, |
||||
size: u32, downloadedsize: *mut u32) -> Result; |
||||
pub fn HTTPC_Initialize(handle: Handle) -> Result; |
||||
pub fn HTTPC_InitializeConnectionSession(handle: Handle, |
||||
contextHandle: Handle) -> Result; |
||||
pub fn HTTPC_CreateContext(handle: Handle, |
||||
url: *mut u8, |
||||
contextHandle: *mut Handle) -> Result; |
||||
pub fn HTTPC_CloseContext(handle: Handle, contextHandle: Handle) |
||||
name: *const ::libc::c_char, |
||||
value: *mut ::libc::c_char, |
||||
valuebuf_maxsize: u32_) -> Result; |
||||
pub fn httpcAddTrustedRootCA(context: *mut httpcContext, cert: *const u8_, |
||||
certsize: u32_) -> Result; |
||||
pub fn httpcAddDefaultCert(context: *mut httpcContext, |
||||
certID: SSLC_DefaultRootCert) -> Result; |
||||
pub fn httpcSelectRootCertChain(context: *mut httpcContext, |
||||
RootCertChain_contexthandle: u32_) |
||||
-> Result; |
||||
pub fn httpcSetClientCert(context: *mut httpcContext, cert: *const u8_, |
||||
certsize: u32_, privk: *const u8_, |
||||
privk_size: u32_) -> Result; |
||||
pub fn httpcSetClientCertDefault(context: *mut httpcContext, |
||||
certID: SSLC_DefaultClientCert) |
||||
-> Result; |
||||
pub fn httpcSetClientCertContext(context: *mut httpcContext, |
||||
ClientCert_contexthandle: u32_) |
||||
-> Result; |
||||
pub fn httpcSetSSLOpt(context: *mut httpcContext, options: u32_) |
||||
-> Result; |
||||
pub fn httpcSetSSLClearOpt(context: *mut httpcContext, options: u32_) |
||||
-> Result; |
||||
pub fn httpcCreateRootCertChain(RootCertChain_contexthandle: *mut u32_) |
||||
-> Result; |
||||
pub fn httpcDestroyRootCertChain(RootCertChain_contexthandle: u32_) |
||||
-> Result; |
||||
pub fn HTTPC_SetProxyDefault(handle: Handle, contextHandle: Handle) |
||||
pub fn httpcRootCertChainAddCert(RootCertChain_contexthandle: u32_, |
||||
cert: *const u8_, certsize: u32_, |
||||
cert_contexthandle: *mut u32_) -> Result; |
||||
pub fn httpcRootCertChainAddDefaultCert(RootCertChain_contexthandle: u32_, |
||||
certID: SSLC_DefaultRootCert, |
||||
cert_contexthandle: *mut u32_) |
||||
-> Result; |
||||
pub fn HTTPC_AddRequestHeaderField(handle: Handle, contextHandle: Handle, |
||||
name: *mut u8, |
||||
value: *mut u8) |
||||
pub fn httpcRootCertChainRemoveCert(RootCertChain_contexthandle: u32_, |
||||
cert_contexthandle: u32_) -> Result; |
||||
pub fn httpcOpenClientCertContext(cert: *const u8_, certsize: u32_, |
||||
privk: *const u8_, privk_size: u32_, |
||||
ClientCert_contexthandle: *mut u32_) |
||||
-> Result; |
||||
pub fn HTTPC_BeginRequest(handle: Handle, contextHandle: Handle) |
||||
pub fn httpcOpenDefaultClientCertContext(certID: SSLC_DefaultClientCert, |
||||
ClientCert_contexthandle: |
||||
*mut u32_) -> Result; |
||||
pub fn httpcCloseClientCertContext(ClientCert_contexthandle: u32_) |
||||
-> Result; |
||||
pub fn HTTPC_ReceiveData(handle: Handle, contextHandle: Handle, |
||||
buffer: *mut u8, size: u32) -> Result; |
||||
pub fn HTTPC_GetRequestState(handle: Handle, contextHandle: Handle, |
||||
out: *mut HTTPC_RequestStatus) -> Result; |
||||
pub fn HTTPC_GetDownloadSizeState(handle: Handle, contextHandle: Handle, |
||||
downloadedsize: *mut u32, |
||||
contentsize: *mut u32) -> Result; |
||||
pub fn HTTPC_GetResponseHeader(handle: Handle, contextHandle: Handle, |
||||
name: *mut u8, |
||||
value: *mut u8, |
||||
valuebuf_maxsize: u32) -> Result; |
||||
pub fn HTTPC_GetResponseStatusCode(handle: Handle, contextHandle: Handle, |
||||
out: *mut u32) -> Result; |
||||
pub fn httpcDownloadData(context: *mut httpcContext, buffer: *mut u8_, |
||||
size: u32_, downloadedsize: *mut u32_) -> Result; |
||||
pub fn httpcSetKeepAlive(context: *mut httpcContext, |
||||
option: HTTPC_KeepAlive) -> Result; |
||||
} |
||||
use ::types::*; |
||||
use super::sslc::*; |
||||
|
@ -1,21 +1,25 @@
@@ -1,21 +1,25 @@
|
||||
use ::{Result, Handle}; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub fn iruInit(sharedmem_addr: *mut u32, sharedmem_size: u32) -> Result; |
||||
pub fn iruInit(sharedmem_addr: *mut u32_, sharedmem_size: u32_) -> Result; |
||||
pub fn iruExit(); |
||||
pub fn iruGetServHandle() -> Handle; |
||||
pub fn iruSendData(buf: *mut u8, size: u32, wait: u8) -> Result; |
||||
pub fn iruRecvData(buf: *mut u8, size: u32, flag: u8, |
||||
transfercount: *mut u32, wait: u8) -> Result; |
||||
pub fn iruSendData(buf: *mut u8_, size: u32_, wait: u8) -> Result; |
||||
pub fn iruRecvData(buf: *mut u8_, size: u32_, flag: u8_, |
||||
transfercount: *mut u32_, wait: u8) -> Result; |
||||
pub fn IRU_Initialize() -> Result; |
||||
pub fn IRU_Shutdown() -> Result; |
||||
pub fn IRU_StartSendTransfer(buf: *mut u8, size: u32) -> Result; |
||||
pub fn IRU_StartSendTransfer(buf: *mut u8_, size: u32_) -> Result; |
||||
pub fn IRU_WaitSendTransfer() -> Result; |
||||
pub fn IRU_StartRecvTransfer(size: u32, flag: u8) -> Result; |
||||
pub fn IRU_WaitRecvTransfer(transfercount: *mut u32) -> Result; |
||||
pub fn IRU_SetBitRate(value: u8) -> Result; |
||||
pub fn IRU_GetBitRate(out: *mut u8) -> Result; |
||||
pub fn IRU_SetIRLEDState(value: u32) -> Result; |
||||
pub fn IRU_GetIRLEDRecvState(out: *mut u32) -> Result; |
||||
pub fn IRU_StartRecvTransfer(size: u32_, flag: u8_) -> Result; |
||||
pub fn IRU_WaitRecvTransfer(transfercount: *mut u32_) -> Result; |
||||
pub fn IRU_SetBitRate(value: u8_) -> Result; |
||||
pub fn IRU_GetBitRate(out: *mut u8_) -> Result; |
||||
pub fn IRU_SetIRLEDState(value: u32_) -> Result; |
||||
pub fn IRU_GetIRLEDRecvState(out: *mut u32_) -> Result; |
||||
} |
||||
|
||||
use ::types::*; |
||||
|
@ -1,21 +1,24 @@
@@ -1,21 +1,24 @@
|
||||
use ::{Result, Handle}; |
||||
use ::types::*; |
||||
|
||||
use super::hid::circlePosition; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub static mut irrstMemHandle: Handle; |
||||
pub static mut irrstSharedMem: *mut vu32; |
||||
|
||||
} |
||||
extern "C" { |
||||
pub fn irrstInit() -> Result; |
||||
pub fn irrstExit(); |
||||
pub fn irrstScanInput(); |
||||
pub fn irrstKeysHeld() -> u32; |
||||
pub fn irrstKeysHeld() -> u32_; |
||||
pub fn irrstCstickRead(pos: *mut circlePosition); |
||||
pub fn irrstWaitForEvent(nextEvent: u8); |
||||
pub fn IRRST_GetHandles(outMemHandle: *mut Handle, |
||||
outEventHandle: *mut Handle) -> Result; |
||||
pub fn IRRST_Initialize(unk1: u32, unk2: u8) -> Result; |
||||
pub fn IRRST_Initialize(unk1: u32_, unk2: u8_) -> Result; |
||||
pub fn IRRST_Shutdown() -> Result; |
||||
|
||||
} |
||||
use ::types::*; |
||||
use super::hid::*; |
||||
|
@ -1,42 +1,47 @@
@@ -1,42 +1,47 @@
|
||||
use ::{Handle, Result}; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#[derive(Clone, Copy)] |
||||
#[repr(C)] |
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum MICU_Encoding { |
||||
MICU_ENCODING_PCM8 = 0, |
||||
MICU_ENCODING_PCM16 = 1, |
||||
MICU_ENCODING_PCM8_SIGNED = 2, |
||||
MICU_ENCODING_PCM16_SIGNED = 3, |
||||
} |
||||
|
||||
#[derive(Clone, Copy)] |
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum MICU_SampleRate { |
||||
MICU_SAMPLE_RATE_32730 = 0, |
||||
MICU_SAMPLE_RATE_16360 = 1, |
||||
MICU_SAMPLE_RATE_10910 = 2, |
||||
MICU_SAMPLE_RATE_8180 = 3, |
||||
} |
||||
|
||||
extern "C" { |
||||
pub fn micInit(buffer: *mut u8, bufferSize: u32) -> Result; |
||||
pub fn micInit(buffer: *mut u8_, bufferSize: u32_) -> Result; |
||||
pub fn micExit(); |
||||
pub fn micGetSampleDataSize() -> u32; |
||||
pub fn micGetLastSampleOffset() -> u32; |
||||
pub fn MICU_MapSharedMem(size: u32, handle: Handle) -> Result; |
||||
pub fn micGetSampleDataSize() -> u32_; |
||||
pub fn micGetLastSampleOffset() -> u32_; |
||||
pub fn MICU_MapSharedMem(size: u32_, handle: Handle) -> Result; |
||||
pub fn MICU_UnmapSharedMem() -> Result; |
||||
pub fn MICU_StartSampling(encoding: MICU_Encoding, |
||||
sampleRate: MICU_SampleRate, offset: u32, |
||||
size: u32, _loop: u8) -> Result; |
||||
sampleRate: MICU_SampleRate, offset: u32_, |
||||
size: u32_, loop_: u8) -> Result; |
||||
pub fn MICU_AdjustSampling(sampleRate: MICU_SampleRate) -> Result; |
||||
pub fn MICU_StopSampling() -> Result; |
||||
pub fn MICU_IsSampling(sampling: *mut u8) -> Result; |
||||
pub fn MICU_GetEventHandle(handle: *mut Handle) -> Result; |
||||
pub fn MICU_SetGain(gain: u8) -> Result; |
||||
pub fn MICU_GetGain(gain: *mut u8) -> Result; |
||||
pub fn MICU_SetGain(gain: u8_) -> Result; |
||||
pub fn MICU_GetGain(gain: *mut u8_) -> Result; |
||||
pub fn MICU_SetPower(power: u8) -> Result; |
||||
pub fn MICU_GetPower(power: *mut u8) -> Result; |
||||
pub fn MICU_SetClamp(clamp: u8) -> Result; |
||||
pub fn MICU_GetClamp(clamp: *mut u8) -> Result; |
||||
pub fn MICU_SetAllowShellClosed(allowShellClosed: u8) -> Result; |
||||
} |
||||
use ::types::*; |
||||
|
@ -1,67 +0,0 @@
@@ -1,67 +0,0 @@
|
||||
use ::Result; |
||||
|
||||
#[derive(Clone, Copy)] |
||||
#[repr(C)] |
||||
pub enum MVDSTD_Mode { |
||||
MVDMODE_COLORFORMATCONV = 0, |
||||
MVDMODE_VIDEOPROCESSING = 1, |
||||
} |
||||
|
||||
#[derive(Clone, Copy)] |
||||
#[repr(C)] |
||||
pub enum MVDSTD_InputFormat { |
||||
MVD_INPUT_YUYV422 = 65537, |
||||
MVD_INPUT_H264 = 131073, |
||||
} |
||||
|
||||
#[derive(Clone, Copy)] |
||||
#[repr(C)] |
||||
pub enum MVDSTD_OutputFormat { MVD_OUTPUT_RGB565 = 262146, } |
||||
|
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct MVDSTD_Config { |
||||
pub input_type: MVDSTD_InputFormat, |
||||
pub unk_x04: u32, |
||||
pub unk_x08: u32, |
||||
pub inwidth: u32, |
||||
pub inheight: u32, |
||||
pub physaddr_colorconv_indata: u32, |
||||
pub unk_x18: [u32; 10usize], |
||||
pub flag_x40: u32, |
||||
pub unk_x44: u32, |
||||
pub unk_x48: u32, |
||||
pub outheight0: u32, |
||||
pub outwidth0: u32, |
||||
pub unk_x54: u32, |
||||
pub output_type: MVDSTD_OutputFormat, |
||||
pub outwidth1: u32, |
||||
pub outheight1: u32, |
||||
pub physaddr_outdata0: u32, |
||||
pub physaddr_outdata1_colorconv: u32, |
||||
pub unk_x6c: [u32; 44usize], |
||||
} |
||||
impl ::core::clone::Clone for MVDSTD_Config { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
impl ::core::default::Default for MVDSTD_Config { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
|
||||
extern "C" { |
||||
pub fn mvdstdInit(mode: MVDSTD_Mode, input_type: MVDSTD_InputFormat, |
||||
output_type: MVDSTD_OutputFormat, size: u32) -> Result; |
||||
pub fn mvdstdExit(); |
||||
pub fn mvdstdGenerateDefaultConfig(config: *mut MVDSTD_Config, |
||||
input_width: u32, input_height: u32, |
||||
output_width: u32, |
||||
output_height: u32, |
||||
vaddr_colorconv_indata: *mut u32, |
||||
vaddr_outdata0: *mut u32, |
||||
vaddr_outdata1_colorconv: *mut u32); |
||||
pub fn mvdstdProcessFrame(config: *mut MVDSTD_Config, |
||||
h264_vaddr_inframe: *mut u32, |
||||
h264_inframesize: u32, h264_frameid: u32) |
||||
-> Result; |
||||
pub fn MVDSTD_SetConfig(config: *mut MVDSTD_Config) -> Result; |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
/* 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 NDM_ExclusiveState { |
||||
EXCLUSIVE_STATE_NONE = 0, |
||||
EXCLUSIVE_STATE_INFRASTRUCTURE = 1, |
||||
EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS = 2, |
||||
EXCLUSIVE_STATE_STREETPASS = 3, |
||||
EXCLUSIVE_STATE_STREETPASS_DATA = 4, |
||||
} |
||||
extern "C" { |
||||
pub fn ndmuInit() -> Result; |
||||
pub fn ndmuExit(); |
||||
pub fn ndmuEnterExclusiveState(state: NDM_ExclusiveState) -> Result; |
||||
pub fn ndmuLeaveExclusiveState() -> Result; |
||||
} |
||||
use ::types::*; |
@ -1,11 +1,52 @@
@@ -1,11 +1,52 @@
|
||||
use ::Result; |
||||
use ::libc::c_void; |
||||
/* 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 NotificationHeader { |
||||
pub dataSet: u8, |
||||
pub unread: u8, |
||||
pub enableJPEG: u8, |
||||
pub isSpotPass: u8, |
||||
pub isOptedOut: u8, |
||||
pub unkData: [u8_; 3usize], |
||||
pub processID: u64_, |
||||
pub unkData2: [u8_; 8usize], |
||||
pub jumpParam: u64_, |
||||
pub unkData3: [u8_; 8usize], |
||||
pub time: u64_, |
||||
pub title: [u16_; 32usize], |
||||
} |
||||
impl ::core::default::Default for NotificationHeader { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
extern "C" { |
||||
pub fn newsInit() -> Result; |
||||
pub fn newsExit(); |
||||
pub fn NEWS_AddNotification(title: *const u16, titleLength: u32, |
||||
message: *const u16, messageLength: u32, |
||||
imageData: *const c_void, |
||||
imageSize: u32, jpeg: u8) -> Result; |
||||
pub fn NEWS_AddNotification(title: *const u16_, titleLength: u32_, |
||||
message: *const u16_, messageLength: u32_, |
||||
imageData: *const ::libc::c_void, |
||||
imageSize: u32_, jpeg: u8) -> Result; |
||||
pub fn NEWS_GetTotalNotifications(num: *mut u32_) -> Result; |
||||
pub fn NEWS_SetNotificationHeader(news_id: u32_, |
||||
header: *const NotificationHeader) |
||||
-> Result; |
||||
pub fn NEWS_GetNotificationHeader(news_id: u32_, |
||||
header: *mut NotificationHeader) |
||||
-> Result; |
||||
pub fn NEWS_SetNotificationMessage(news_id: u32_, message: *const u16_, |
||||
size: u32_) -> Result; |
||||
pub fn NEWS_GetNotificationMessage(news_id: u32_, message: *mut u16_, |
||||
size: *mut u32_) -> Result; |
||||
pub fn NEWS_SetNotificationImage(news_id: u32_, |
||||
buffer: *const ::libc::c_void, |
||||
size: u32_) -> Result; |
||||
pub fn NEWS_GetNotificationImage(news_id: u32_, |
||||
buffer: *mut ::libc::c_void, |
||||
size: *mut u32_) -> Result; |
||||
} |
||||
use ::types::*; |
||||
|
@ -0,0 +1,127 @@
@@ -0,0 +1,127 @@
|
||||
/* 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 NFC_OpType { NFC_OpType_1 = 1, NFC_OpType_NFCTag = 2, } |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum NFC_TagState { |
||||
NFC_TagState_Uninitialized = 0, |
||||
NFC_TagState_ScanningStopped = 1, |
||||
NFC_TagState_Scanning = 2, |
||||
NFC_TagState_InRange = 3, |
||||
NFC_TagState_OutOfRange = 4, |
||||
NFC_TagState_DataReady = 5, |
||||
} |
||||
#[derive(Copy, Clone)] |
||||
#[repr(u32)] |
||||
#[derive(Debug)] |
||||
pub enum Enum_Unnamed1 { |
||||
NFC_amiiboFlag_Setup = 16, |
||||
NFC_amiiboFlag_AppDataSetup = 32, |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct NFC_TagInfo { |
||||
pub id_offset_size: u16_, |
||||
pub unk_x2: u8_, |
||||
pub unk_x3: u8_, |
||||
pub id: [u8_; 40usize], |
||||
} |
||||
impl ::core::clone::Clone for NFC_TagInfo { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
impl ::core::default::Default for NFC_TagInfo { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct NFC_AmiiboSettings { |
||||
pub mii: [u8_; 96usize], |
||||
pub nickname: [u16_; 11usize], |
||||
pub flags: u8_, |
||||
pub countrycodeid: u8_, |
||||
pub setupdate_year: u16_, |
||||
pub setupdate_month: u8_, |
||||
pub setupdate_day: u8_, |
||||
pub unk_x7c: [u8_; 44usize], |
||||
} |
||||
impl ::core::clone::Clone for NFC_AmiiboSettings { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
impl ::core::default::Default for NFC_AmiiboSettings { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct NFC_AmiiboConfig { |
||||
pub lastwritedate_year: u16_, |
||||
pub lastwritedate_month: u8_, |
||||
pub lastwritedate_day: u8_, |
||||
pub write_counter: u16_, |
||||
pub val_x6: u16_, |
||||
pub val_x8: u8_, |
||||
pub val_x9: u8_, |
||||
pub val_xa: u16_, |
||||
pub val_xc: u8_, |
||||
pub pagex4_byte3: u8_, |
||||
pub appdata_size: u8_, |
||||
pub zeros: [u8_; 49usize], |
||||
} |
||||
impl ::core::clone::Clone for NFC_AmiiboConfig { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
impl ::core::default::Default for NFC_AmiiboConfig { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy)] |
||||
pub struct NFC_AppDataInitStruct { |
||||
pub data_x0: [u8_; 12usize], |
||||
pub data_xc: [u8_; 48usize], |
||||
} |
||||
impl ::core::clone::Clone for NFC_AppDataInitStruct { |
||||
fn clone(&self) -> Self { *self } |
||||
} |
||||
impl ::core::default::Default for NFC_AppDataInitStruct { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
#[repr(C)] |
||||
#[derive(Copy, Clone)] |
||||
#[derive(Debug)] |
||||
pub struct NFC_AppDataWriteStruct { |
||||
pub id: [u8_; 10usize], |
||||
pub id_size: u8_, |
||||
pub unused_xb: [u8_; 21usize], |
||||
} |
||||
impl ::core::default::Default for NFC_AppDataWriteStruct { |
||||
fn default() -> Self { unsafe { ::core::mem::zeroed() } } |
||||
} |
||||
extern "C" { |
||||
pub fn nfcInit(type_: NFC_OpType) -> Result; |
||||
pub fn nfcExit(); |
||||
pub fn nfcGetSessionHandle() -> Handle; |
||||
pub fn nfcStartScanning(inval: u16_) -> Result; |
||||
pub fn nfcStopScanning(); |
||||
pub fn nfcLoadAmiiboData() -> Result; |
||||
pub fn nfcResetTagScanState() -> Result; |
||||
pub fn nfcUpdateStoredAmiiboData() -> Result; |
||||
pub fn nfcGetTagState(state: *mut NFC_TagState) -> Result; |
||||
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: ::libc::size_t) |
||||
-> Result; |
||||
pub fn nfcReadAppData(buf: *mut ::libc::c_void, size: ::libc::size_t) -> Result; |
||||
pub fn nfcWriteAppData(buf: *const ::libc::c_void, size: ::libc::size_t, |
||||
taginfo: *mut NFC_TagInfo) -> Result; |
||||
pub fn nfcGetAmiiboSettings(out: *mut NFC_AmiiboSettings) -> Result; |
||||
pub fn nfcGetAmiiboConfig(out: *mut NFC_AmiiboConfig) -> Result; |
||||
} |
||||
use ::types::*; |
@ -1,9 +1,17 @@
@@ -1,9 +1,17 @@
|
||||
use ::Result; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub fn nsInit() -> Result; |
||||
pub fn nsExit(); |
||||
pub fn NS_LaunchTitle(titleid: u64, launch_flags: u32, procid: *mut u32) -> Result; |
||||
pub fn NS_RebootToTitle(mediatype: u8, titleid: u64) -> Result; |
||||
pub fn NS_LaunchFIRM(titleid: u64_) -> Result; |
||||
pub fn NS_LaunchTitle(titleid: u64_, launch_flags: u32_, |
||||
procid: *mut u32_) -> Result; |
||||
pub fn NS_LaunchApplicationFIRM(titleid: u64_, flags: u32_) -> Result; |
||||
pub fn NS_RebootToTitle(mediatype: u8_, titleid: u64_) -> Result; |
||||
pub fn NS_TerminateProcessTID(titleid: u64_) -> Result; |
||||
} |
||||
|
||||
use ::types::*; |
||||
|
@ -1,24 +1,19 @@
@@ -1,24 +1,19 @@
|
||||
use ::{Handle, Result}; |
||||
use ::libc::c_void; |
||||
/* automatically generated by rust-bindgen */ |
||||
|
||||
#![allow(dead_code,
|
||||
non_camel_case_types, |
||||
non_upper_case_globals, |
||||
non_snake_case)] |
||||
extern "C" { |
||||
pub fn pmInit() -> Result; |
||||
pub fn pmExit(); |
||||
pub fn PM_LaunchTitle(mediatype: u8, titleid: u64, launch_flags: u32) |
||||
pub fn PM_LaunchTitle(mediatype: u8_, titleid: u64_, launch_flags: u32_) |
||||
-> Result; |
||||
pub fn PM_GetTitleExheaderFlags(mediatype: u8, titleid: u64, |
||||
out: *mut u8) -> Result; |
||||
pub fn PM_SetFIRMLaunchParams(size: u32, _in: *mut u8) -> Result; |
||||
pub fn PM_GetFIRMLaunchParams(size: u32, out: *mut u8) -> Result; |
||||
pub fn PM_LaunchFIRMSetParams(firm_titleid_low: u32, size: u32, |
||||
_in: *mut u8) -> Result; |
||||
pub fn srvPmInit() -> Result; |
||||
pub fn srvPmExit(); |
||||
pub fn SRVPM_PublishToProcess(notificationId: u32, process: Handle) |
||||
-> Result; |
||||
pub fn SRVPM_PublishToAll(notificationId: u32) -> Result; |
||||
pub fn SRVPM_RegisterProcess(procid: u32, count: u32, |
||||
serviceaccesscontrol: c_void) -> Result; |
||||
pub fn SRVPM_UnregisterProcess(procid: u32) -> Result; |
||||
pub fn PM_GetTitleExheaderFlags(mediatype: u8_, titleid: u64_, |
||||
out: *mut u8_) -> Result; |
||||
pub fn PM_SetFIRMLaunchParams(size: u32_, in_: *mut u8_) -> Result; |
||||
pub fn PM_GetFIRMLaunchParams(size: u32_, out: *mut u8_) -> Result; |
||||
pub fn PM_LaunchFIRMSetParams(firm_titleid_low: u32_, size: u32_, |
||||
in_: *mut u8_) -> Result; |
||||
} |
||||
|
||||
use ::types::*; |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue