├── .gitignore ├── Cargo.toml ├── Makefile ├── README.md ├── Xargo.toml ├── build.sh ├── crates ├── freebsd_kernel_std │ ├── .gitignore │ ├── Cargo.toml │ ├── Xargo.toml │ ├── build.rs │ ├── src │ │ ├── error.rs │ │ ├── io │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── macros.rs │ │ └── os │ │ │ ├── characterdevice.rs │ │ │ ├── kernel.rs │ │ │ ├── kernel_sys.rs │ │ │ ├── mod.rs │ │ │ ├── module.rs │ │ │ ├── raw.rs │ │ │ └── uio.rs │ ├── wrapper.h │ └── x86_64-kernel-freebsd.json ├── liballoc │ ├── Cargo.toml │ ├── arc.rs │ ├── boxed.rs │ ├── boxed_test.rs │ ├── heap.rs │ ├── lib.rs │ ├── macros.rs │ ├── oom.rs │ ├── raw_vec.rs │ ├── rc.rs │ └── str.rs ├── liballoc_system │ ├── Cargo.toml │ ├── kern_malloc.rs │ ├── lib.rs │ └── raw.rs ├── libcollections │ ├── Cargo.toml │ ├── benches │ │ ├── btree │ │ │ ├── map.rs │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── linked_list.rs │ │ ├── slice.rs │ │ ├── str.rs │ │ ├── string.rs │ │ ├── vec.rs │ │ └── vec_deque.rs │ ├── binary_heap.rs │ ├── borrow.rs │ ├── btree │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── node.rs │ │ ├── search.rs │ │ └── set.rs │ ├── fmt.rs │ ├── lib.rs │ ├── linked_list.rs │ ├── macros.rs │ ├── range.rs │ ├── slice.rs │ ├── str.rs │ ├── string.rs │ ├── tests │ │ ├── binary_heap.rs │ │ ├── btree │ │ │ ├── map.rs │ │ │ ├── mod.rs │ │ │ └── set.rs │ │ ├── cow_str.rs │ │ ├── fmt.rs │ │ ├── lib.rs │ │ ├── linked_list.rs │ │ ├── slice.rs │ │ ├── str.rs │ │ ├── string.rs │ │ ├── vec.rs │ │ └── vec_deque.rs │ ├── vec.rs │ └── vec_deque.rs └── libstd_unicode │ ├── Cargo.toml │ ├── char.rs │ ├── lib.rs │ ├── tables.rs │ ├── u_str.rs │ └── unicode.py ├── hello.c ├── src ├── interface.rs ├── lang.rs ├── lib.rs └── module.rs └── x86_64-kernel-freebsd.json /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | **/Cargo.lock 3 | **/rustc.core 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "module" 3 | version = "0.1.0" 4 | authors = ["johalun "] 5 | 6 | [lib] 7 | crate-type = ["staticlib"] 8 | 9 | 10 | [dependencies] 11 | # rlibc = "*" 12 | spin = "*" 13 | lazy_static = { features = ["spin_no_std"], version="0.2.2" } 14 | std = { path = "crates/freebsd_kernel_std" } 15 | 16 | 17 | 18 | # Needed for custom _Unwind_Resume 19 | # The development profile, used for `cargo build`. 20 | [profile.dev] 21 | panic = "abort" 22 | 23 | # The release profile, used for `cargo build --release`. 24 | [profile.release] 25 | panic = "abort" 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | OBJECTDIR?=./objects 3 | 4 | KMOD=hello 5 | SRCS=hello.c 6 | OBJS=${OBJECTDIR}/*.o 7 | 8 | rustclean: 9 | make clean 10 | cargo clean 11 | 12 | .include 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Echo - a FreeBSD kernel module written Rust (WIP) # 2 | 3 | ## Requirements ## 4 | 5 | - FreeBSD machine 6 | - Rust nightly 7 | - Xargo 8 | 9 | 10 | I recommend using `rustup` for installing and handling different versions of Rust. 11 | 12 | ### Installation ### 13 | 14 | Rust 15 | 16 | See [https://www.rustup.rs/](https://www.rustup.rs/) 17 | 18 | Xargo 19 | 20 | ```sh 21 | $ cargo install xargo 22 | ``` 23 | 24 | Setting Rust nightly 25 | 26 | Do in crate root: 27 | 28 | ```sh 29 | $ rustup override set nightly 30 | ``` 31 | 32 | 33 | ## Content ## 34 | 35 | ### Root Folder ### 36 | 37 | This folder is the `Cargo` root for the module itself. 38 | 39 | 40 | ### Crates ### 41 | 42 | Here are all the dependency crates that are not available on crates.io. 43 | 44 | `core` is built and handled completely by `Xargo`. 45 | 46 | 47 | #### libstd_unicode #### 48 | 49 | Copied from Rust source code, unmodified. 50 | 51 | 52 | #### libcollections #### 53 | 54 | Copied from Rust source code, unmodified. 55 | 56 | 57 | #### liballoc #### 58 | 59 | Copied from Rust source code, unmodified. 60 | 61 | 62 | #### liballoc_system #### 63 | 64 | Copied from Rust source code. 65 | 66 | Added `kern_malloc.rs` which is the FFI bindings to kernel's malloc functions. 67 | 68 | Modified `lib.rs` to use said functions. 69 | 70 | 71 | #### freebsd\_kernel\_std #### 72 | 73 | A minimal implementation of std for the echo module. FFI bindings are generated on build. 74 | Safe bindings exists for things necessary for this code to run. 75 | 76 | 77 | 78 | ## Build ## 79 | 80 | Check `build.sh` script if you like to make any changes then run 81 | 82 | ```sh 83 | $ ./build.sh 84 | ``` 85 | 86 | 87 | ## Load Module ## 88 | 89 | If build was successful there should be a `hello.ko` file in the root folder. Load with 90 | 91 | ```sh 92 | $ sudo kldload ./hello.ko 93 | ``` 94 | 95 | 96 | ## Usage ## 97 | 98 | ```sh 99 | $ cat /dev/rustmodule 100 | Default Message :) 101 | $ echo Hello > /dev/rustmodule 102 | Read 6 bytes. Setting new message to "Hello\n" 103 | $ cat /dev/rustmodule 104 | Hello 105 | $ sudo kldunload hello 106 | ``` 107 | 108 | # Warning # 109 | 110 | If there are any bugs or faulty code the kernel will most likely hang. 111 | 112 | I recommend testing the module in a virtual machine. 113 | 114 | It keeps your system safe and it makes it easier to develop and test. 115 | 116 | -------------------------------------------------------------------------------- /Xargo.toml: -------------------------------------------------------------------------------- 1 | # Empty 2 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | OBJECTDIR=/tmp/rustmodule 4 | CURDIR=`pwd` 5 | 6 | if [ ! -d "${OBJECTDIR}" ]; then 7 | mkdir "${OBJECTDIR}" 8 | fi 9 | 10 | 11 | make clean && \ 12 | xargo build --target x86_64-kernel-freebsd && \ 13 | cd "${OBJECTDIR}" && \ 14 | ar -xv "${CURDIR}/target/x86_64-kernel-freebsd/debug/libmodule.a" && \ 15 | cd "${CURDIR}" && \ 16 | make OBJECTDIR="${OBJECTDIR}" 17 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | wrapper.d 4 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "std" 3 | version = "0.1.0" 4 | authors = ["johalun "] 5 | 6 | # Generate bindings for kernel functions 7 | build = "build.rs" 8 | 9 | [dependencies] 10 | alloc = { path="../liballoc" } 11 | alloc_system = { path="../liballoc_system" } 12 | collections = { path="../libcollections" } 13 | std_unicode = { path = "../libstd_unicode" } 14 | spin = "*" 15 | 16 | # [dependencies.compiler_builtins] 17 | # git = "https://github.com/rust-lang-nursery/compiler-builtins" 18 | # features = ["c"] 19 | 20 | [build-dependencies] 21 | bindgen = "*" 22 | # shlex = "*" 23 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/Xargo.toml: -------------------------------------------------------------------------------- 1 | # [target.x86_64-kernel-freebsd.dependencies] 2 | # collections = {} 3 | 4 | # [target.x86_64-kernel-freebsd.dependencies.core] 5 | # features = ["unique"] 6 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/build.rs: -------------------------------------------------------------------------------- 1 | extern crate bindgen; 2 | 3 | use std::env; 4 | use std::path::PathBuf; 5 | 6 | const FILEPATH_CODE: &'static str = "src/os/kernel_sys.rs"; 7 | 8 | 9 | fn main() { 10 | 11 | env::set_var("LIBCLANG_PATH", "/usr/local/llvm40/lib"); 12 | 13 | // The bindgen::Builder is the main entry point 14 | // to bindgen, and lets you build up options for 15 | // the resulting bindings. 16 | let bindings = bindgen::Builder::default() 17 | // Do not generate unstable Rust code that 18 | // requires a nightly rustc and enabling 19 | // unstable features. 20 | // .no_unstable_rust() 21 | .use_core() 22 | // Use this prefix instead of ::std::os::raw 23 | // .ctypes_prefix("raw") 24 | // The input header we would like to generate 25 | // bindings for. 26 | .header("wrapper.h") 27 | // Clang arguments 28 | .clang_arg("-O2") 29 | .clang_arg("-pipe") 30 | .clang_arg("-fno-strict-aliasing") 31 | .clang_arg("-Werror") 32 | .clang_arg("-D_KERNEL") 33 | .clang_arg("-DKLD_MODULE") 34 | .clang_arg("-nostdinc") 35 | .clang_arg("-I.") 36 | .clang_arg("-I/usr/src/sys") 37 | .clang_arg("-fno-common") 38 | .clang_arg("-fno-omit-frame-pointer") 39 | .clang_arg("-mno-omit-leaf-frame-pointer") 40 | .clang_arg("-MD") 41 | .clang_arg("-mcmodel=kernel") 42 | .clang_arg("-mno-red-zone") 43 | .clang_arg("-mno-mmx") 44 | .clang_arg("-mno-sse") 45 | .clang_arg("-msoft-float") 46 | .clang_arg("-fno-asynchronous-unwind-tables") 47 | .clang_arg("-ffreestanding") 48 | .clang_arg("-fwrapv") 49 | .clang_arg("-fstack-protector") 50 | .clang_arg("-Wall") 51 | .clang_arg("-Wredundant-decls") 52 | .clang_arg("-Wnested-externs") 53 | .clang_arg("-Wstrict-prototypes") 54 | .clang_arg("-Wmissing-prototypes") 55 | .clang_arg("-Wpointer-arith") 56 | .clang_arg("-Winline") 57 | .clang_arg("-Wcast-qual") 58 | .clang_arg("-Wundef") 59 | .clang_arg("-Wno-pointer-sign") 60 | .clang_arg("-D__printf__=__freebsd_kprintf__") 61 | .clang_arg("-Wmissing-include-dirs") 62 | .clang_arg("-fdiagnostics-show-option") 63 | .clang_arg("-Wno-unknown-pragmas") 64 | .clang_arg("-Wno-error-tautological-compare") 65 | .clang_arg("-Wno-error-empty-body") 66 | .clang_arg("-mno-aes") 67 | .clang_arg("-mno-avx") 68 | .clang_arg("-std=iso9899:1999") 69 | 70 | // Command for building kernel modulde 71 | // cc -O2 -pipe -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE -nostdinc -I. -I/usr/src/sys -fno-common -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -MD -MF.depend.hello.o -MThello.o -mcmodel=kernel -mno-red-zone -mno-mmx -mno-sse -msoft-float -fno-asynchronous-unwind-tables -ffreestanding -fwrapv -fstack-protector -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -D__printf__=__freebsd_kprintf__ -Wmissing-include-dirs -fdiagnostics-show-option -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -mno-aes -mno-avx -std=iso9899:1999 -c hello.c -o hello.o 72 | 73 | 74 | // Finish the builder and generate the bindings. 75 | .generate() 76 | // Unwrap the Result and panic on failure. 77 | .expect("Unable to generate bindings"); 78 | 79 | // Write the bindings to the $OUT_DIR/bindings.rs file. 80 | let out_path = PathBuf::from(FILEPATH_CODE); 81 | bindings.write_to_file(out_path).expect("Couldn't write bindings!"); 82 | } 83 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/error.rs: -------------------------------------------------------------------------------- 1 | 2 | use fmt::Debug; 3 | 4 | pub trait Error: Debug { 5 | fn description(&self) -> &str; 6 | fn cause(&self) -> Option<&Error> { 7 | None 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/io/mod.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use core::ptr; 3 | use os::kernel; 4 | use os::raw; 5 | use vec::Vec; 6 | use alloc::boxed::Box; 7 | use string::String; 8 | use core::result; 9 | use error; 10 | use str; 11 | 12 | /// Empty structure that uses libcore's `fmt::Write` trait to provide support for writing formatted 13 | /// Arguments lists (as generated by the built-in `format_args!()` macro`) 14 | pub struct KernelDebugWriter {} 15 | impl fmt::Write for KernelDebugWriter { 16 | fn write_str(&mut self, message: &str) -> fmt::Result { 17 | unsafe { 18 | let ptr = kernel::malloc((message.len() + 1) as raw::c_size_t, 19 | &mut kernel::M_DEVBUF[0], 20 | kernel::M_WAITOK as i32) as 21 | *mut raw::c_char; 22 | if ptr.is_null() { 23 | let msg = cstr!("Failed to allocate memory for dynamic printf()\n"); 24 | let ptr = msg.as_ptr() as *const raw::c_char; 25 | kernel::uprintf(ptr); 26 | } else { 27 | ptr::copy(message.as_ptr(), ptr as *mut u8, message.len()); 28 | ptr::write(ptr.offset(message.len() as isize), 0); 29 | kernel::uprintf(ptr); 30 | kernel::free(ptr as *mut raw::c_void, &mut kernel::M_DEVBUF[0]); 31 | } 32 | } 33 | Ok(()) 34 | } 35 | } 36 | 37 | 38 | pub type Result = result::Result; 39 | 40 | #[derive(Debug)] 41 | pub struct Error { 42 | kind: ErrorKind, 43 | error: String, 44 | } 45 | impl Error { 46 | pub fn new(kind: ErrorKind, error: E) -> Error 47 | where E: Into 48 | { 49 | Error { 50 | error: error.into(), 51 | kind: kind, 52 | } 53 | } 54 | pub fn kind(&self) -> ErrorKind { 55 | self.kind 56 | } 57 | } 58 | 59 | impl fmt::Display for Error { 60 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 61 | write!(fmt, "{:?}: {}", self.kind, self.error) 62 | } 63 | } 64 | 65 | 66 | #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 67 | pub enum ErrorKind { 68 | NotFound, 69 | PermissionDenied, 70 | ConnectionRefused, 71 | ConnectionReset, 72 | ConnectionAborted, 73 | NotConnected, 74 | AddrInUse, 75 | AddrNotAvailable, 76 | BrokenPipe, 77 | AlreadyExists, 78 | WouldBlock, 79 | InvalidInput, 80 | InvalidData, 81 | TimedOut, 82 | WriteZero, 83 | Interrupted, 84 | Other, 85 | UnexpectedEof, 86 | } 87 | 88 | // This uses an adaptive system to extend the vector when it fills. We want to 89 | // avoid paying to allocate and zero a huge chunk of memory if the reader only 90 | // has 4 bytes while still making large reads if the reader does have a ton 91 | // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every 92 | // time is 4,500 times (!) slower than this if the reader has a very small 93 | // amount of data to return. 94 | const DEFAULT_BUF_SIZE: usize = 1024; 95 | 96 | fn append_to_string(buf: &mut String, f: F) -> Result 97 | where F: FnOnce(&mut Vec) -> Result 98 | { 99 | // debugln!("append to string"); 100 | struct Guard<'a> { 101 | s: &'a mut Vec, 102 | len: usize, 103 | } 104 | impl<'a> Drop for Guard<'a> { 105 | fn drop(&mut self) { 106 | unsafe { 107 | self.s.set_len(self.len); 108 | } 109 | } 110 | } 111 | 112 | unsafe { 113 | let mut g = Guard { 114 | len: buf.len(), 115 | s: buf.as_mut_vec(), 116 | }; 117 | let ret = f(g.s); 118 | if str::from_utf8(&g.s[g.len..]).is_err() { 119 | ret.and_then(|_| { 120 | Err(Error::new(ErrorKind::InvalidData, 121 | "stream did not contain valid UTF-8")) 122 | }) 123 | } else { 124 | g.len = g.s.len(); 125 | ret 126 | } 127 | } 128 | } 129 | 130 | fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { 131 | // debugln!("read to end"); 132 | let start_len = buf.len(); 133 | let mut len = start_len; 134 | let mut new_write_size = 16; 135 | let ret; 136 | loop { 137 | // debugln!("read to end loop"); 138 | if len == buf.len() { 139 | if new_write_size < DEFAULT_BUF_SIZE { 140 | new_write_size *= 2; 141 | } 142 | buf.resize(len + new_write_size, 0); 143 | } 144 | 145 | match r.read(&mut buf[len..]) { 146 | Ok(0) => { 147 | ret = Ok(len - start_len); 148 | break; 149 | } 150 | Ok(n) => len += n, 151 | Err(ref e) if e.kind() == ErrorKind::Interrupted => {} 152 | Err(e) => { 153 | ret = Err(e); 154 | break; 155 | } 156 | } 157 | } 158 | 159 | buf.truncate(len); 160 | ret 161 | } 162 | 163 | 164 | 165 | pub trait Read { 166 | fn read(&mut self, buf: &mut [u8]) -> Result; 167 | fn read_to_end(&mut self, buf: &mut Vec) -> Result { 168 | read_to_end(self, buf) 169 | } 170 | fn read_to_string(&mut self, buf: &mut String) -> Result { 171 | // Note that we do *not* call `.read_to_end()` here. We are passing 172 | // `&mut Vec` (the raw contents of `buf`) into the `read_to_end` 173 | // method to fill it up. An arbitrary implementation could overwrite the 174 | // entire contents of the vector, not just append to it (which is what 175 | // we are expecting). 176 | // 177 | // To prevent extraneously checking the UTF-8-ness of the entire buffer 178 | // we pass it to our hardcoded `read_to_end` implementation which we 179 | // know is guaranteed to only read data into the end of the buffer. 180 | append_to_string(buf, |b| read_to_end(self, b)) 181 | } 182 | fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { 183 | while !buf.is_empty() { 184 | match self.read(buf) { 185 | Ok(0) => break, 186 | Ok(n) => { 187 | let tmp = buf; 188 | buf = &mut tmp[n..]; 189 | } 190 | Err(ref e) if e.kind() == ErrorKind::Interrupted => {} 191 | Err(e) => return Err(e), 192 | } 193 | } 194 | if !buf.is_empty() { 195 | Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) 196 | } else { 197 | Ok(()) 198 | } 199 | } 200 | fn by_ref(&mut self) -> &mut Self 201 | where Self: Sized 202 | { 203 | self 204 | } 205 | } 206 | 207 | 208 | 209 | pub trait Write { 210 | fn write(&mut self, buf: &[u8]) -> Result; 211 | fn flush(&mut self) -> Result<()>; 212 | fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { 213 | while !buf.is_empty() { 214 | match self.write(buf) { 215 | Ok(0) => { 216 | return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) 217 | } 218 | Ok(n) => buf = &buf[n..], 219 | Err(ref e) if e.kind() == ErrorKind::Interrupted => {} 220 | Err(e) => return Err(e), 221 | } 222 | } 223 | Ok(()) 224 | } 225 | fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { 226 | // Create a shim which translates a Write to a fmt::Write and saves 227 | // off I/O errors. instead of discarding them 228 | struct Adaptor<'a, T: ?Sized + 'a> { 229 | inner: &'a mut T, 230 | error: Result<()>, 231 | } 232 | 233 | impl<'a, T: Write + ?Sized> fmt::Write for Adaptor<'a, T> { 234 | fn write_str(&mut self, s: &str) -> fmt::Result { 235 | match self.inner.write_all(s.as_bytes()) { 236 | Ok(()) => Ok(()), 237 | Err(e) => { 238 | self.error = Err(e); 239 | Err(fmt::Error) 240 | } 241 | } 242 | } 243 | } 244 | 245 | let mut output = Adaptor { 246 | inner: self, 247 | error: Ok(()), 248 | }; 249 | match fmt::write(&mut output, fmt) { 250 | Ok(()) => Ok(()), 251 | Err(..) => { 252 | // check if the error came from the underlying `Write` or not 253 | if output.error.is_err() { 254 | output.error 255 | } else { 256 | Err(Error::new(ErrorKind::Other, "formatter error")) 257 | } 258 | } 259 | } 260 | } 261 | fn by_ref(&mut self) -> &mut Self 262 | where Self: Sized 263 | { 264 | self 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/lib.rs: -------------------------------------------------------------------------------- 1 | // We *are* std 2 | #![no_std] 3 | // For `pub use ::core::{intrinsics,raw}` statements 4 | #![feature(core_intrinsics)] 5 | #![feature(raw)] 6 | #![feature(untagged_unions)] 7 | #![feature(shared)] 8 | // #![feature(compiler_builtins_lib)] 9 | #![feature(unique)] 10 | #![feature(unboxed_closures)] 11 | #![feature(macro_reexport)] 12 | #![feature(alloc)] 13 | #![feature(alloc_system)] 14 | #![feature(unicode)] 15 | #![feature(collections)] 16 | #![feature(box_syntax)] 17 | #![feature(rc_raw)] 18 | 19 | extern crate alloc; 20 | extern crate alloc_system; 21 | #[macro_use] 22 | #[macro_reexport(vec, format)] 23 | extern crate collections as core_collections; 24 | 25 | extern crate std_unicode; 26 | extern crate spin; 27 | 28 | #[macro_use] 29 | pub mod macros; 30 | 31 | // libstd-style public modules 32 | pub mod io; 33 | pub mod os; 34 | pub mod error; 35 | 36 | // Re-export modules from libcore 37 | pub use core::any; 38 | pub use core::cell; 39 | pub use core::clone; 40 | pub use core::cmp; 41 | pub use core::convert; 42 | pub use core::default; 43 | pub use core::hash; 44 | pub use core::iter; 45 | pub use core::intrinsics; 46 | pub use core::marker; 47 | pub use core::mem; 48 | pub use core::ops; 49 | pub use core::ptr; 50 | pub use core::raw; 51 | pub use core::result; 52 | pub use core::option; 53 | pub use alloc::boxed; 54 | pub use alloc::rc; 55 | 56 | pub use core_collections::borrow; 57 | pub use core_collections::fmt; 58 | pub use core_collections::slice; 59 | pub use core_collections::str; 60 | pub use core_collections::string; 61 | pub use core_collections::vec; 62 | 63 | pub mod sync { 64 | pub use alloc::arc::Arc; 65 | pub use alloc::arc::Weak; 66 | pub use spin::Mutex; 67 | pub use spin::MutexGuard; 68 | 69 | } 70 | 71 | mod std { 72 | pub use clone; 73 | pub use default; 74 | pub use mem; 75 | pub use os; 76 | pub use option; 77 | pub use io; 78 | pub use error; 79 | } 80 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! cstr { 3 | ($arg:expr) => (concat!($arg, '\x00')) 4 | } 5 | macro_rules! cstr_ref { 6 | ($arg:expr) => (&format!("{}\x00", $arg)) 7 | } 8 | 9 | #[macro_export] 10 | macro_rules! print { 11 | // Static (zero-allocation) implementation that uses compile-time `concat!()` only 12 | ($fmt:expr) => ({ 13 | let msg = cstr!($fmt); 14 | let ptr = msg.as_ptr() as *const ::std::os::raw::c_char; 15 | unsafe { 16 | ::std::os::kernel::uprintf(ptr); 17 | } 18 | }); 19 | 20 | // Dynamic implementation that processes format arguments 21 | ($fmt:expr, $($arg:tt)*) => ({ 22 | use ::core::fmt::Write; 23 | use std::io::KernelDebugWriter; 24 | let mut writer = KernelDebugWriter {}; 25 | writer.write_fmt(format_args!($fmt, $($arg)*)).unwrap(); 26 | }); 27 | } 28 | 29 | #[macro_export] 30 | macro_rules! println { 31 | ($fmt:expr) => (print!(concat!($fmt, "\n"))); 32 | ($fmt:expr, $($arg:tt)+) => (print!(concat!($fmt, "\n"), $($arg)*)); 33 | } 34 | 35 | #[macro_export] 36 | macro_rules! debug { 37 | ($($arg:tt)*) => (if cfg!(debug_assertions) { print!($($arg)*) }) 38 | } 39 | 40 | #[macro_export] 41 | macro_rules! debugln { 42 | ($($arg:tt)*) => (if cfg!(debug_assertions) { println!($($arg)*) }) 43 | } 44 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/os/characterdevice.rs: -------------------------------------------------------------------------------- 1 | 2 | use spin::{Mutex, MutexGuard}; 3 | use os::raw; 4 | use core::ptr; 5 | use core::mem; 6 | use core::cmp; 7 | use core::ops; 8 | use core::marker::Send; 9 | use core::marker::Sync; 10 | use alloc::boxed::Box; 11 | use alloc::arc::Arc; 12 | use core::cell::UnsafeCell; 13 | use core::cell::RefCell; 14 | use core::ptr::Shared; 15 | use string::String; 16 | use fmt; 17 | use core::sync::atomic::AtomicUsize; 18 | use core::ops::{Deref, DerefMut}; 19 | use io; 20 | 21 | use super::kernel::*; 22 | 23 | use super::kernel_sys as ksys; 24 | 25 | 26 | 27 | pub trait CharacterDevice { 28 | fn open(&mut self) {} 29 | fn close(&mut self) {} 30 | fn read(&mut self, mut uio: UioWriter) {} 31 | fn write(&mut self, mut uio: UioReader) {} 32 | } 33 | 34 | 35 | 36 | pub struct CDev 37 | where T: CharacterDevice 38 | { 39 | cdev: ptr::Unique, 40 | delegate: SharedModule, 41 | } 42 | 43 | 44 | impl CDev 45 | where T: CharacterDevice 46 | { 47 | pub fn new_with_delegate(name: &'static str, delegate: SharedModule) -> Option> { 48 | 49 | let mut cdevsw_raw: *mut ksys::cdevsw = { 50 | let mut c: ksys::cdevsw = unsafe { mem::zeroed() }; 51 | c.d_open = Some(cdev_open::); 52 | c.d_close = Some(cdev_close::); 53 | c.d_read = Some(cdev_read::); 54 | c.d_write = Some(cdev_write::); 55 | c.d_version = ksys::D_VERSION as i32; 56 | c.d_name = "whatsthisstringfor".as_ptr() as *mut i8; 57 | Box::into_raw(box c) 58 | }; 59 | 60 | let mut cdev_raw: *mut ksys::cdev = unsafe { 61 | ksys::make_dev(cdevsw_raw, 62 | mem::transmute(0i32), 63 | UID_ROOT, 64 | GID_WHEEL, 65 | 0o660, 66 | cstr_ref!(name).as_ptr() as *mut i8) 67 | }; 68 | 69 | match cdev_raw.is_null() { 70 | true => { 71 | // Convert cdevsw back to Box so memory can be freed 72 | let cdevsw = unsafe { Box::from_raw(cdevsw_raw) }; 73 | None 74 | } 75 | false => { 76 | let cdev = box CDev { 77 | cdev: unsafe { ptr::Unique::new(cdev_raw) }, 78 | delegate: delegate, 79 | }; 80 | unsafe { (*cdev_raw).si_drv1 = mem::transmute(&*cdev) } 81 | Some(cdev) 82 | } 83 | } 84 | } 85 | } 86 | impl fmt::Debug for CDev 87 | where T: CharacterDevice 88 | { 89 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 90 | write!(f, "CDev {{ cdev: {:?}, ... }}", self.cdev.as_ptr()) 91 | } 92 | } 93 | impl ops::Drop for CDev 94 | where T: CharacterDevice 95 | { 96 | fn drop(&mut self) { 97 | // debugln!("[kernel.rs] CDev::drop"); 98 | 99 | // Assign only to clarify what type we're dealing with... 100 | let mut dev: *mut ksys::cdev = self.cdev.as_ptr(); 101 | 102 | // Back to Box so cdevsw memory is freed 103 | let cdevsw: Box = unsafe { Box::from_raw((*dev).si_devsw) }; 104 | 105 | // debugln!("[kernel.rs] CDev::drop calling destroy_dev. ptr={:?}", dev.as_ptr()); 106 | unsafe { ksys::destroy_dev(dev) }; 107 | } 108 | } 109 | 110 | // File operations callbacks 111 | extern "C" fn cdev_open(dev: *mut ksys::cdev, 112 | oflags: ::std::os::raw::c_int, 113 | devtype: ::std::os::raw::c_int, 114 | td: *mut ksys::thread) 115 | -> ::std::os::raw::c_int 116 | where T: CharacterDevice 117 | { 118 | // debugln!("cdev_open"); 119 | let cdev: &CDev = unsafe { mem::transmute((*dev).si_drv1) }; 120 | if let Some(mut m) = cdev.delegate.lock() { 121 | m.open(); 122 | } 123 | 0 124 | } 125 | 126 | extern "C" fn cdev_fdopen(dev: *mut ksys::cdev, 127 | oflags: ::std::os::raw::c_int, 128 | td: *mut ksys::thread, 129 | fp: *mut ksys::file) 130 | -> ::std::os::raw::c_int { 131 | // debugln!("cdev_fdopen"); 132 | 0 133 | } 134 | 135 | extern "C" fn cdev_close(dev: *mut ksys::cdev, 136 | fflag: ::std::os::raw::c_int, 137 | devtype: ::std::os::raw::c_int, 138 | td: *mut ksys::thread) 139 | -> ::std::os::raw::c_int 140 | where T: CharacterDevice 141 | { 142 | // debugln!("cdev_close"); 143 | let cdev: &CDev = unsafe { mem::transmute((*dev).si_drv1) }; 144 | if let Some(mut m) = cdev.delegate.lock() { 145 | m.close(); 146 | } 147 | 0 148 | } 149 | 150 | extern "C" fn cdev_read(dev: *mut ksys::cdev, 151 | uio: *mut ksys::uio, 152 | ioflag: ::std::os::raw::c_int) 153 | -> ::std::os::raw::c_int 154 | where T: CharacterDevice 155 | { 156 | // debugln!("cdev_read"); 157 | let cdev: &CDev = unsafe { mem::transmute((*dev).si_drv1) }; 158 | if let Some(mut m) = cdev.delegate.lock() { 159 | m.read(UioWriter::new(uio)); 160 | } 161 | 0 162 | } 163 | 164 | extern "C" fn cdev_write(dev: *mut ksys::cdev, 165 | uio: *mut ksys::uio, 166 | ioflag: ::std::os::raw::c_int) 167 | -> ::std::os::raw::c_int 168 | where T: CharacterDevice 169 | { 170 | // debugln!("cdev_write"); 171 | let cdev: &CDev = unsafe { mem::transmute((*dev).si_drv1) }; 172 | if let Some(mut m) = cdev.delegate.lock() { 173 | m.write(UioReader::new(uio)); 174 | } 175 | 0 176 | } 177 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/os/kernel.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Safe and clean interface to kernel_sys.rs 4 | // Use this whenever interfacing with kernel API. 5 | // If API not here, add it from kernel_sys.rs. 6 | 7 | 8 | // Do not edit kernel_sys.rs, it is being generated 9 | // at build time. 10 | 11 | 12 | 13 | use core::ptr; 14 | use core::mem; 15 | use core::cmp; 16 | use core::ops; 17 | use core::marker::Send; 18 | use core::marker::Sync; 19 | use core::cell::RefCell; 20 | use core::cell::UnsafeCell; 21 | use core::ptr::Shared; 22 | use core::sync::atomic::AtomicUsize; 23 | use core::ops::{Deref, DerefMut}; 24 | 25 | use alloc::boxed::Box; 26 | use alloc::arc::Arc; 27 | 28 | use string::String; 29 | 30 | use fmt; 31 | use io; 32 | 33 | use os::raw; 34 | 35 | use spin::{Mutex, MutexGuard}; 36 | 37 | use super::kernel_sys as ksys; 38 | 39 | // Re-exports 40 | // 41 | pub use super::kernel_sys::modeventtype as ModuleEventType; 42 | pub use super::kernel_sys::module_t as Module; 43 | pub use super::kernel_sys::moduledata_t as ModuleData; 44 | pub use super::kernel_sys::modeventhand_t as ModuleEventHandler; 45 | 46 | pub use super::kernel_sys::uid_t as Uid; 47 | pub use super::kernel_sys::gid_t as Gid; 48 | 49 | pub use super::kernel_sys::M_DEVBUF; 50 | pub use super::kernel_sys::M_WAITOK; 51 | 52 | pub use super::kernel_sys::UID_ROOT; 53 | pub use super::kernel_sys::GID_WHEEL; 54 | 55 | pub use super::kernel_sys::MAKEDEV_REF; 56 | pub use super::kernel_sys::MAKEDEV_WHTOUT; 57 | pub use super::kernel_sys::MAKEDEV_NOWAIT; 58 | pub use super::kernel_sys::MAKEDEV_WAITOK; 59 | pub use super::kernel_sys::MAKEDEV_ETERNAL; 60 | pub use super::kernel_sys::MAKEDEV_CHECKNAME; 61 | pub use super::kernel_sys::MAKEDEV_ETERNAL_KLD; 62 | 63 | pub use super::kernel_sys::uprintf; 64 | pub use super::kernel_sys::tprintf; 65 | pub use super::kernel_sys::printf; 66 | pub use super::kernel_sys::malloc; 67 | pub use super::kernel_sys::free; 68 | 69 | 70 | pub use super::characterdevice::{CharacterDevice, CDev}; 71 | pub use super::uio::{UioReader, UioWriter}; 72 | pub use super::module::{ModuleEvents, SharedModule}; 73 | 74 | 75 | 76 | unsafe impl Sync for ksys::cdev {} 77 | unsafe impl Send for ksys::cdev {} 78 | 79 | unsafe impl Sync for ksys::cdevsw {} 80 | unsafe impl Send for ksys::cdevsw {} 81 | 82 | 83 | impl ::core::default::Default for ksys::cdev { 84 | fn default() -> Self { 85 | unsafe { ::core::mem::zeroed() } 86 | } 87 | } 88 | impl fmt::Debug for ksys::cdev { 89 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 90 | write!(f, "cdev {{ .. }}") 91 | } 92 | } 93 | 94 | impl ::core::default::Default for ksys::cdevsw { 95 | fn default() -> Self { 96 | unsafe { ::core::mem::zeroed() } 97 | } 98 | } 99 | impl fmt::Debug for ksys::cdevsw { 100 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 101 | write!(f, "cdevsw {{ .. }}") 102 | } 103 | } 104 | 105 | impl ::core::default::Default for ksys::uio { 106 | fn default() -> Self { 107 | unsafe { ::core::mem::zeroed() } 108 | } 109 | } 110 | 111 | impl ops::Drop for ksys::cdev { 112 | fn drop(&mut self) { 113 | // debugln!("[kernel_sys.rs] cdev::drop"); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/os/mod.rs: -------------------------------------------------------------------------------- 1 | // Basic C type declarations 2 | pub mod raw; 3 | pub mod kernel; 4 | 5 | mod characterdevice; 6 | mod module; 7 | mod uio; 8 | 9 | // Generated kernel header bindings 10 | #[allow(dead_code, improper_ctypes, non_camel_case_types, non_snake_case, non_upper_case_globals)] 11 | pub mod kernel_sys; 12 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/os/module.rs: -------------------------------------------------------------------------------- 1 | 2 | use os::raw; 3 | 4 | use core::ptr; 5 | use core::mem; 6 | use core::cmp; 7 | use core::ops; 8 | use core::marker::Send; 9 | use core::marker::Sync; 10 | use alloc::boxed::Box; 11 | use alloc::arc::Arc; 12 | use core::cell::UnsafeCell; 13 | use core::cell::RefCell; 14 | use core::ptr::Shared; 15 | use string::String; 16 | use fmt; 17 | use core::sync::atomic::AtomicUsize; 18 | use core::ops::{Deref, DerefMut}; 19 | use io; 20 | 21 | use spin::{Mutex, MutexGuard}; 22 | 23 | use super::kernel_sys as ksys; 24 | 25 | use super::kernel::*; 26 | 27 | pub trait ModuleEvents { 28 | fn load(&mut self); 29 | fn unload(&mut self); 30 | } 31 | 32 | impl ModuleEventType { 33 | pub fn from_i32(n: i32) -> Option { 34 | match n { 35 | 0 => Some(ModuleEventType::MOD_LOAD), 36 | 1 => Some(ModuleEventType::MOD_UNLOAD), 37 | 2 => Some(ModuleEventType::MOD_SHUTDOWN), 38 | 3 => Some(ModuleEventType::MOD_QUIESCE), 39 | _ => None, 40 | } 41 | } 42 | } 43 | 44 | pub struct LockedModule<'a, T: Sized + 'a> { 45 | guard: MutexGuard<'a, Option>, 46 | } 47 | impl<'a, T: Sized> LockedModule<'a, T> {} 48 | impl<'a, T: Sized> Deref for LockedModule<'a, T> { 49 | type Target = T; 50 | 51 | fn deref(&self) -> &T { 52 | &*self.guard.as_ref().unwrap() 53 | } 54 | } 55 | impl<'a, T: Sized> DerefMut for LockedModule<'a, T> { 56 | fn deref_mut(&mut self) -> &mut T { 57 | &mut *self.guard.as_mut().unwrap() 58 | } 59 | } 60 | impl<'a, T> ops::Drop for LockedModule<'a, T> { 61 | fn drop(&mut self) { 62 | // debugln!("[kernel.rs] LockedModule::drop"); 63 | } 64 | } 65 | impl<'a, T> fmt::Debug for LockedModule<'a, T> { 66 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 67 | write!(f, "LockedModule {{ guard: MutexGuard> }}") 68 | } 69 | } 70 | 71 | #[derive(Debug, Default)] 72 | pub struct SharedModule { 73 | inner: Arc>>, 74 | } 75 | impl SharedModule { 76 | pub fn new(data: T) -> Self { 77 | SharedModule { inner: Arc::new(Mutex::new(Some(data))) } 78 | } 79 | pub fn clone(&self) -> Self { 80 | SharedModule { inner: self.inner.clone() } 81 | } 82 | pub fn inner(&self) -> Arc>> { 83 | self.inner.clone() 84 | } 85 | pub fn lock(&self) -> Option> { 86 | let guard = self.inner.lock(); 87 | if guard.is_some() { 88 | Some(LockedModule { guard: guard }) 89 | } else { 90 | None 91 | } 92 | } 93 | pub fn cleanup(&self) { 94 | { 95 | let _ = self.inner.lock().take(); 96 | } 97 | // Safe to do this in kldunload callback? 98 | // If we don't, we'll leak 64 byte Mutex struct (maybe not a disaster...) 99 | unsafe { 100 | let ptr: *mut Arc>> = mem::transmute(&self.inner); 101 | ptr::drop_in_place(ptr); 102 | } 103 | } 104 | } 105 | impl ops::Drop for SharedModule { 106 | fn drop(&mut self) { 107 | // debugln!("[kernel.rs] SharedModule::drop"); 108 | } 109 | } 110 | 111 | 112 | unsafe impl Sync for SharedModule {} 113 | unsafe impl Send for SharedModule {} 114 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/os/raw.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(unused_attributes)] 3 | #![no_std] 4 | 5 | // Special: Platforms with unsigned character types 6 | #![cfg_attr( 7 | any( 8 | target_arch = "aarch64", 9 | target_arch = "arm", 10 | target_arch = "powerpc", 11 | target_arch = "powerpc64" 12 | ), 13 | target_arch_char_unsigned 14 | )] 15 | 16 | 17 | // Character types 18 | pub type c_schar = i8; 19 | pub type c_uchar = u8; 20 | #[cfg(not(target_arch_char_unsigned))] 21 | pub type c_char = i8; 22 | #[cfg(target_arch_char_unsigned)] 23 | pub type c_char = u8; 24 | #[cfg(not(target_arch_char_unsigned))] 25 | pub type c_wchar = i32; 26 | #[cfg(target_arch_char_unsigned)] 27 | pub type c_wchar = u32; 28 | 29 | // Standard integers 30 | pub type c_short = i16; 31 | pub type c_ushort = u16; 32 | 33 | pub type c_int = i32; 34 | pub type c_uint = u32; 35 | 36 | #[cfg(target_pointer_width = "32")] 37 | pub type c_long = i32; 38 | #[cfg(target_pointer_width = "32")] 39 | pub type c_ulong = u32; 40 | #[cfg(target_pointer_width = "64")] 41 | pub type c_long = i64; 42 | #[cfg(target_pointer_width = "64")] 43 | pub type c_ulong = u64; 44 | 45 | pub type c_longlong = i64; 46 | pub type c_ulonglong = u64; 47 | 48 | // Float point type (not usable, but they do exist) 49 | pub type c_float = f32; 50 | pub type c_double = f64; 51 | 52 | // The special "size" type 53 | #[cfg(target_pointer_width = "32")] 54 | pub type c_size_t = u32; 55 | #[cfg(target_pointer_width = "64")] 56 | pub type c_size_t = u64; 57 | 58 | /// Magic pointer that represents a `void*` in C 59 | /// See `libstd/os/raw.rs:48` from the Rust source code for details… 60 | #[repr(u8)] 61 | #[derive(Copy, Clone)] 62 | pub enum c_void { 63 | #[doc(hidden)] __variant1, 64 | #[doc(hidden)] __variant2 65 | } 66 | 67 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/src/os/uio.rs: -------------------------------------------------------------------------------- 1 | 2 | use os::raw; 3 | 4 | use core::ptr; 5 | use core::mem; 6 | use core::cmp; 7 | use core::ops; 8 | use core::marker::Send; 9 | use core::marker::Sync; 10 | use alloc::boxed::Box; 11 | use alloc::arc::Arc; 12 | use core::cell::UnsafeCell; 13 | use core::cell::RefCell; 14 | use core::ptr::Shared; 15 | use string::String; 16 | use fmt; 17 | use core::sync::atomic::AtomicUsize; 18 | use core::ops::{Deref, DerefMut}; 19 | use io; 20 | 21 | use spin::{Mutex, MutexGuard}; 22 | 23 | use super::kernel_sys as ksys; 24 | 25 | use super::kernel::*; 26 | 27 | 28 | // #[derive(Default)] 29 | pub struct UioReader { 30 | uio: ptr::Unique, 31 | offset: usize, 32 | remain: usize, 33 | } 34 | impl UioReader { 35 | pub fn new(uio: *mut ksys::uio) -> Self { 36 | UioReader { 37 | uio: unsafe { ptr::Unique::new(uio) }, 38 | offset: 0, 39 | remain: unsafe { (*(*uio).uio_iov).iov_len }, 40 | } 41 | } 42 | fn len(&self) -> usize { 43 | unsafe { self.uio.as_ref().uio_resid as usize } 44 | } 45 | } 46 | impl io::Read for UioReader { 47 | // A reader is implemented for reading data from userland to kernel. 48 | // That is, for d_write callback. 49 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 50 | 51 | let buf_len = buf.len(); 52 | let iov_len = unsafe { (*self.uio.as_ref().uio_iov).iov_len } - self.offset as usize; 53 | let len = cmp::min(buf_len, iov_len); 54 | 55 | if len == 0 { 56 | return Ok(0); 57 | } 58 | 59 | if buf_len < iov_len { 60 | // Still got some data to read 61 | self.remain = iov_len as usize - buf_len as usize; 62 | } else { 63 | // We read everything already 64 | self.remain = 0; 65 | } 66 | 67 | // Change to uiomove? 68 | let ret = unsafe { 69 | ksys::copyin((*self.uio.as_ref().uio_iov) 70 | .iov_base 71 | .offset(self.offset as isize), 72 | buf.as_mut_ptr() as *mut raw::c_void, 73 | len) 74 | }; 75 | self.offset += len as usize; 76 | 77 | match ret { 78 | 0 => Ok(len), 79 | _ => Err(io::Error::new(io::ErrorKind::Other, "UioReader::read copyin failed.")), 80 | } 81 | } 82 | } 83 | impl fmt::Debug for UioReader { 84 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 85 | write!(f, 86 | "UioReader {{ uio: {:?}, offset: {}, remain: {} }}", 87 | self.uio.as_ptr(), 88 | self.offset, 89 | self.remain) 90 | } 91 | } 92 | 93 | 94 | 95 | pub struct UioWriter { 96 | uio: ptr::Unique, 97 | } 98 | impl UioWriter { 99 | pub fn new(uio: *mut ksys::uio) -> Self { 100 | UioWriter { uio: unsafe { ptr::Unique::new(uio) } } 101 | } 102 | fn len(&self) -> usize { 103 | unsafe { self.uio.as_ref().uio_resid as usize } 104 | } 105 | } 106 | impl io::Write for UioWriter { 107 | fn write(&mut self, buf: &[u8]) -> io::Result { 108 | // Temporary add a uiomove function that takes immutable buffer instead of mutable 109 | extern "C" { 110 | pub fn uiomove(cp: *const ::std::os::raw::c_void, 111 | n: ::std::os::raw::c_int, 112 | uio: *mut ksys::uio) 113 | -> ::std::os::raw::c_int; 114 | } 115 | 116 | let offset = unsafe { self.uio.as_ref().uio_offset as usize }; 117 | let amount_uio = unsafe { self.uio.as_ref().uio_resid as usize }; 118 | let amount_buf = match buf.len() - offset { 119 | x if x > 0 => x, 120 | _ => 0, 121 | }; 122 | // debugln!("===> offest {}, amount uio {}, amount buf {}", offset, amount_uio, amount_buf); 123 | 124 | let amount = cmp::min(amount_buf, amount_uio); 125 | if amount == 0 { 126 | // return offset here so write_all know that we've already read all bytes. 127 | return Ok(offset); 128 | } 129 | 130 | let ret = unsafe { 131 | uiomove(buf[offset as usize..].as_ptr() as *const raw::c_void, 132 | amount as i32, 133 | self.uio.as_ptr()) 134 | }; 135 | match ret { 136 | 0 => Ok(amount), 137 | _ => { 138 | Err(io::Error::new(io::ErrorKind::Other, 139 | format!("uiomove failed with return code {}", ret))) 140 | } 141 | } 142 | } 143 | fn flush(&mut self) -> io::Result<()> { 144 | // XXX What do we do here? 145 | Ok(()) 146 | } 147 | } 148 | impl fmt::Debug for UioWriter { 149 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 150 | write!(f, "UioWriter {{ uio: {:?} }}", self.uio.as_ptr()) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/wrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* uprintf */ 4 | #include /* defines used in kernel.h */ 5 | #include /* types used in module initialization */ 6 | #include /* cdevsw struct */ 7 | #include /* uio struct */ 8 | #include 9 | #include 10 | #include 11 | -------------------------------------------------------------------------------- /crates/freebsd_kernel_std/x86_64-kernel-freebsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "x86_64-unknown-freebsd", 3 | "linker-flavor": "gcc", 4 | "target-endian": "little", 5 | "target-pointer-width": "64", 6 | "os": "none", 7 | "arch": "x86_64", 8 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", 9 | "pre-link-args": [ "-m64" ], 10 | "cpu": "x86-64", 11 | "features": "+soft-float,-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2", 12 | "disable-redzone": true, 13 | "custom-unwind-resume": true, 14 | "eliminate-frame-pointer": true, 15 | "linker-is-gnu": true, 16 | "no-compiler-rt": true, 17 | "archive-format": "gnu", 18 | "code-model": "kernel", 19 | "relocation-model": "static" 20 | } 21 | -------------------------------------------------------------------------------- /crates/liballoc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "alloc" 4 | version = "0.0.0" 5 | 6 | [lib] 7 | name = "alloc" 8 | path = "lib.rs" 9 | 10 | # [dependencies] 11 | # core = { path = "../libcore" } 12 | -------------------------------------------------------------------------------- /crates/liballoc/boxed_test.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Test for `boxed` mod. 12 | 13 | use core::any::Any; 14 | use core::ops::Deref; 15 | use core::result::Result::{Err, Ok}; 16 | use core::clone::Clone; 17 | use core::f64; 18 | use core::i64; 19 | 20 | use std::boxed::Box; 21 | 22 | #[test] 23 | fn test_owned_clone() { 24 | let a = Box::new(5); 25 | let b: Box = a.clone(); 26 | assert!(a == b); 27 | } 28 | 29 | #[derive(PartialEq, Eq)] 30 | struct Test; 31 | 32 | #[test] 33 | fn any_move() { 34 | let a = Box::new(8) as Box; 35 | let b = Box::new(Test) as Box; 36 | 37 | match a.downcast::() { 38 | Ok(a) => { 39 | assert!(a == Box::new(8)); 40 | } 41 | Err(..) => panic!(), 42 | } 43 | match b.downcast::() { 44 | Ok(a) => { 45 | assert!(a == Box::new(Test)); 46 | } 47 | Err(..) => panic!(), 48 | } 49 | 50 | let a = Box::new(8) as Box; 51 | let b = Box::new(Test) as Box; 52 | 53 | assert!(a.downcast::>().is_err()); 54 | assert!(b.downcast::>().is_err()); 55 | } 56 | 57 | #[test] 58 | fn test_show() { 59 | let a = Box::new(8) as Box; 60 | let b = Box::new(Test) as Box; 61 | let a_str = format!("{:?}", a); 62 | let b_str = format!("{:?}", b); 63 | assert_eq!(a_str, "Any"); 64 | assert_eq!(b_str, "Any"); 65 | 66 | static EIGHT: usize = 8; 67 | static TEST: Test = Test; 68 | let a = &EIGHT as &Any; 69 | let b = &TEST as &Any; 70 | let s = format!("{:?}", a); 71 | assert_eq!(s, "Any"); 72 | let s = format!("{:?}", b); 73 | assert_eq!(s, "Any"); 74 | } 75 | 76 | #[test] 77 | fn deref() { 78 | fn homura>(_: T) {} 79 | homura(Box::new(765)); 80 | } 81 | 82 | #[test] 83 | fn raw_sized() { 84 | let x = Box::new(17); 85 | let p = Box::into_raw(x); 86 | unsafe { 87 | assert_eq!(17, *p); 88 | *p = 19; 89 | let y = Box::from_raw(p); 90 | assert_eq!(19, *y); 91 | } 92 | } 93 | 94 | #[test] 95 | fn raw_trait() { 96 | trait Foo { 97 | fn get(&self) -> u32; 98 | fn set(&mut self, value: u32); 99 | } 100 | 101 | struct Bar(u32); 102 | 103 | impl Foo for Bar { 104 | fn get(&self) -> u32 { 105 | self.0 106 | } 107 | 108 | fn set(&mut self, value: u32) { 109 | self.0 = value; 110 | } 111 | } 112 | 113 | let x: Box = Box::new(Bar(17)); 114 | let p = Box::into_raw(x); 115 | unsafe { 116 | assert_eq!(17, (*p).get()); 117 | (*p).set(19); 118 | let y: Box = Box::from_raw(p); 119 | assert_eq!(19, y.get()); 120 | } 121 | } 122 | 123 | #[test] 124 | fn f64_slice() { 125 | let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY]; 126 | let boxed: Box<[f64]> = Box::from(slice); 127 | assert_eq!(&*boxed, slice) 128 | } 129 | 130 | #[test] 131 | fn i64_slice() { 132 | let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX]; 133 | let boxed: Box<[i64]> = Box::from(slice); 134 | assert_eq!(&*boxed, slice) 135 | } 136 | 137 | #[test] 138 | fn str_slice() { 139 | let s = "Hello, world!"; 140 | let boxed: Box = Box::from(s); 141 | assert_eq!(&*boxed, s) 142 | } 143 | -------------------------------------------------------------------------------- /crates/liballoc/heap.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![unstable(feature = "heap_api", 12 | reason = "the precise API and guarantees it provides may be tweaked \ 13 | slightly, especially to possibly take into account the \ 14 | types being stored to make room for a future \ 15 | tracing garbage collector", 16 | issue = "27700")] 17 | 18 | use core::{isize, usize}; 19 | use core::intrinsics::{min_align_of_val, size_of_val}; 20 | 21 | #[allow(improper_ctypes)] 22 | extern "C" { 23 | #[allocator] 24 | fn __rust_allocate(size: usize, align: usize) -> *mut u8; 25 | fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8; 26 | fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); 27 | fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8; 28 | fn __rust_reallocate_inplace(ptr: *mut u8, 29 | old_size: usize, 30 | size: usize, 31 | align: usize) 32 | -> usize; 33 | fn __rust_usable_size(size: usize, align: usize) -> usize; 34 | } 35 | 36 | #[inline(always)] 37 | fn check_size_and_alignment(size: usize, align: usize) { 38 | debug_assert!(size != 0); 39 | debug_assert!(size <= isize::MAX as usize, 40 | "Tried to allocate too much: {} bytes", 41 | size); 42 | debug_assert!(usize::is_power_of_two(align), 43 | "Invalid alignment of allocation: {}", 44 | align); 45 | } 46 | 47 | // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` 48 | 49 | /// Return a pointer to `size` bytes of memory aligned to `align`. 50 | /// 51 | /// On failure, return a null pointer. 52 | /// 53 | /// Behavior is undefined if the requested size is 0 or the alignment is not a 54 | /// power of 2. The alignment must be no larger than the largest supported page 55 | /// size on the platform. 56 | #[inline] 57 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { 58 | check_size_and_alignment(size, align); 59 | __rust_allocate(size, align) 60 | } 61 | 62 | /// Return a pointer to `size` bytes of memory aligned to `align` and 63 | /// initialized to zeroes. 64 | /// 65 | /// On failure, return a null pointer. 66 | /// 67 | /// Behavior is undefined if the requested size is 0 or the alignment is not a 68 | /// power of 2. The alignment must be no larger than the largest supported page 69 | /// size on the platform. 70 | #[inline] 71 | pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { 72 | check_size_and_alignment(size, align); 73 | __rust_allocate_zeroed(size, align) 74 | } 75 | 76 | /// Resize the allocation referenced by `ptr` to `size` bytes. 77 | /// 78 | /// On failure, return a null pointer and leave the original allocation intact. 79 | /// 80 | /// If the allocation was relocated, the memory at the passed-in pointer is 81 | /// undefined after the call. 82 | /// 83 | /// Behavior is undefined if the requested size is 0 or the alignment is not a 84 | /// power of 2. The alignment must be no larger than the largest supported page 85 | /// size on the platform. 86 | /// 87 | /// The `old_size` and `align` parameters are the parameters that were used to 88 | /// create the allocation referenced by `ptr`. The `old_size` parameter may be 89 | /// any value in range_inclusive(requested_size, usable_size). 90 | #[inline] 91 | pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { 92 | check_size_and_alignment(size, align); 93 | __rust_reallocate(ptr, old_size, size, align) 94 | } 95 | 96 | /// Resize the allocation referenced by `ptr` to `size` bytes. 97 | /// 98 | /// If the operation succeeds, it returns `usable_size(size, align)` and if it 99 | /// fails (or is a no-op) it returns `usable_size(old_size, align)`. 100 | /// 101 | /// Behavior is undefined if the requested size is 0 or the alignment is not a 102 | /// power of 2. The alignment must be no larger than the largest supported page 103 | /// size on the platform. 104 | /// 105 | /// The `old_size` and `align` parameters are the parameters that were used to 106 | /// create the allocation referenced by `ptr`. The `old_size` parameter may be 107 | /// any value in range_inclusive(requested_size, usable_size). 108 | #[inline] 109 | pub unsafe fn reallocate_inplace(ptr: *mut u8, 110 | old_size: usize, 111 | size: usize, 112 | align: usize) 113 | -> usize { 114 | check_size_and_alignment(size, align); 115 | __rust_reallocate_inplace(ptr, old_size, size, align) 116 | } 117 | 118 | /// Deallocates the memory referenced by `ptr`. 119 | /// 120 | /// The `ptr` parameter must not be null. 121 | /// 122 | /// The `old_size` and `align` parameters are the parameters that were used to 123 | /// create the allocation referenced by `ptr`. The `old_size` parameter may be 124 | /// any value in range_inclusive(requested_size, usable_size). 125 | #[inline] 126 | pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) { 127 | __rust_deallocate(ptr, old_size, align) 128 | } 129 | 130 | /// Returns the usable size of an allocation created with the specified the 131 | /// `size` and `align`. 132 | #[inline] 133 | pub fn usable_size(size: usize, align: usize) -> usize { 134 | unsafe { __rust_usable_size(size, align) } 135 | } 136 | 137 | /// An arbitrary non-null address to represent zero-size allocations. 138 | /// 139 | /// This preserves the non-null invariant for types like `Box`. The address 140 | /// may overlap with non-zero-size memory allocations. 141 | #[rustc_deprecated(since = "1.19", reason = "Use Unique/Shared::empty() instead")] 142 | #[unstable(feature = "heap_api", issue = "27700")] 143 | pub const EMPTY: *mut () = 1 as *mut (); 144 | 145 | /// The allocator for unique pointers. 146 | // This function must not unwind. If it does, MIR trans will fail. 147 | #[cfg(not(test))] 148 | #[lang = "exchange_malloc"] 149 | #[inline] 150 | unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { 151 | if size == 0 { 152 | align as *mut u8 153 | } else { 154 | let ptr = allocate(size, align); 155 | if ptr.is_null() { 156 | ::oom() 157 | } 158 | ptr 159 | } 160 | } 161 | 162 | #[cfg_attr(not(test), lang = "box_free")] 163 | #[inline] 164 | pub(crate) unsafe fn box_free(ptr: *mut T) { 165 | let size = size_of_val(&*ptr); 166 | let align = min_align_of_val(&*ptr); 167 | // We do not allocate for Box when T is ZST, so deallocation is also not necessary. 168 | if size != 0 { 169 | deallocate(ptr as *mut u8, size, align); 170 | } 171 | } 172 | 173 | #[cfg(test)] 174 | mod tests { 175 | extern crate test; 176 | use self::test::Bencher; 177 | use boxed::Box; 178 | use heap; 179 | 180 | #[test] 181 | fn allocate_zeroed() { 182 | unsafe { 183 | let size = 1024; 184 | let ptr = heap::allocate_zeroed(size, 1); 185 | if ptr.is_null() { 186 | ::oom() 187 | } 188 | 189 | let end = ptr.offset(size as isize); 190 | let mut i = ptr; 191 | while i < end { 192 | assert_eq!(*i, 0); 193 | i = i.offset(1); 194 | } 195 | heap::deallocate(ptr, size, 1); 196 | } 197 | } 198 | 199 | #[test] 200 | fn basic_reallocate_inplace_noop() { 201 | unsafe { 202 | let size = 4000; 203 | let ptr = heap::allocate(size, 8); 204 | if ptr.is_null() { 205 | ::oom() 206 | } 207 | let ret = heap::reallocate_inplace(ptr, size, size, 8); 208 | heap::deallocate(ptr, size, 8); 209 | assert_eq!(ret, heap::usable_size(size, 8)); 210 | } 211 | } 212 | 213 | #[bench] 214 | fn alloc_owned_small(b: &mut Bencher) { 215 | b.iter(|| { 216 | let _: Box<_> = box 10; 217 | }) 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /crates/liballoc/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! # The Rust core allocation library 12 | //! 13 | //! This is the lowest level library through which allocation in Rust can be 14 | //! performed. 15 | //! 16 | //! This library, like libcore, is not intended for general usage, but rather as 17 | //! a building block of other libraries. The types and interfaces in this 18 | //! library are reexported through the [standard library](../std/index.html), 19 | //! and should not be used through this library. 20 | //! 21 | //! Currently, there are four major definitions in this library. 22 | //! 23 | //! ## Boxed values 24 | //! 25 | //! The [`Box`](boxed/index.html) type is a smart pointer type. There can 26 | //! only be one owner of a `Box`, and the owner can decide to mutate the 27 | //! contents, which live on the heap. 28 | //! 29 | //! This type can be sent among threads efficiently as the size of a `Box` value 30 | //! is the same as that of a pointer. Tree-like data structures are often built 31 | //! with boxes because each node often has only one owner, the parent. 32 | //! 33 | //! ## Reference counted pointers 34 | //! 35 | //! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer 36 | //! type intended for sharing memory within a thread. An `Rc` pointer wraps a 37 | //! type, `T`, and only allows access to `&T`, a shared reference. 38 | //! 39 | //! This type is useful when inherited mutability (such as using `Box`) is too 40 | //! constraining for an application, and is often paired with the `Cell` or 41 | //! `RefCell` types in order to allow mutation. 42 | //! 43 | //! ## Atomically reference counted pointers 44 | //! 45 | //! The [`Arc`](arc/index.html) type is the threadsafe equivalent of the `Rc` 46 | //! type. It provides all the same functionality of `Rc`, except it requires 47 | //! that the contained type `T` is shareable. Additionally, `Arc` is itself 48 | //! sendable while `Rc` is not. 49 | //! 50 | //! This type allows for shared access to the contained data, and is often 51 | //! paired with synchronization primitives such as mutexes to allow mutation of 52 | //! shared resources. 53 | //! 54 | //! ## Heap interfaces 55 | //! 56 | //! The [`heap`](heap/index.html) module defines the low-level interface to the 57 | //! default global allocator. It is not compatible with the libc allocator API. 58 | 59 | #![crate_name = "alloc"] 60 | #![crate_type = "rlib"] 61 | #![allow(unused_attributes)] 62 | #![unstable(feature = "alloc", 63 | reason = "this library is unlikely to be stabilized in its current \ 64 | form or name", 65 | issue = "27783")] 66 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 67 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", 68 | html_root_url = "https://doc.rust-lang.org/nightly/", 69 | issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", 70 | test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] 71 | #![no_std] 72 | #![needs_allocator] 73 | #![deny(warnings)] 74 | 75 | #![feature(allocator)] 76 | #![feature(box_syntax)] 77 | #![feature(cfg_target_has_atomic)] 78 | #![feature(coerce_unsized)] 79 | #![feature(const_fn)] 80 | #![feature(core_intrinsics)] 81 | #![feature(custom_attribute)] 82 | #![feature(dropck_eyepatch)] 83 | #![cfg_attr(not(test), feature(exact_size_is_empty))] 84 | #![feature(fundamental)] 85 | #![feature(generic_param_attrs)] 86 | #![feature(lang_items)] 87 | #![feature(needs_allocator)] 88 | #![feature(optin_builtin_traits)] 89 | #![feature(placement_in_syntax)] 90 | #![feature(shared)] 91 | #![feature(staged_api)] 92 | #![feature(unboxed_closures)] 93 | #![feature(unique)] 94 | #![feature(unsize)] 95 | 96 | #![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))] 97 | #![cfg_attr(test, feature(test, box_heap))] 98 | 99 | // Allow testing this library 100 | 101 | #[cfg(test)] 102 | #[macro_use] 103 | extern crate std; 104 | 105 | // Module with internal macros used by other modules (needs to be included before other modules). 106 | #[macro_use] 107 | mod macros; 108 | 109 | // Heaps provided for low-level allocation strategies 110 | 111 | pub mod heap; 112 | 113 | // Primitive types using the heaps above 114 | 115 | // Need to conditionally define the mod from `boxed.rs` to avoid 116 | // duplicating the lang-items when building in test cfg; but also need 117 | // to allow code to have `use boxed::HEAP;` 118 | // and `use boxed::Box;` declarations. 119 | #[cfg(not(test))] 120 | pub mod boxed; 121 | #[cfg(test)] 122 | mod boxed { 123 | pub use std::boxed::{Box, HEAP}; 124 | } 125 | #[cfg(test)] 126 | mod boxed_test; 127 | #[cfg(target_has_atomic = "ptr")] 128 | pub mod arc; 129 | pub mod rc; 130 | pub mod raw_vec; 131 | #[unstable(feature = "str_box_extras", issue = "41119")] 132 | pub mod str; 133 | pub mod oom; 134 | 135 | pub use oom::oom; 136 | -------------------------------------------------------------------------------- /crates/liballoc/macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | // Private macro to get the offset of a struct field in bytes from the address of the struct. 12 | macro_rules! offset_of { 13 | ($container:path, $field:ident) => {{ 14 | // Make sure the field actually exists. This line ensures that a compile-time error is 15 | // generated if $field is accessed through a Deref impl. 16 | let $container { $field : _, .. }; 17 | 18 | // Create an (invalid) instance of the container and calculate the offset to its 19 | // field. Using a null pointer might be UB if `&(*(0 as *const T)).field` is interpreted to 20 | // be nullptr deref. 21 | let invalid: $container = ::core::mem::uninitialized(); 22 | let offset = &invalid.$field as *const _ as usize - &invalid as *const _ as usize; 23 | 24 | // Do not run destructors on the made up invalid instance. 25 | ::core::mem::forget(invalid); 26 | offset as isize 27 | }}; 28 | } 29 | -------------------------------------------------------------------------------- /crates/liballoc/oom.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #[cfg(target_has_atomic = "ptr")] 12 | pub use self::imp::set_oom_handler; 13 | use core::intrinsics; 14 | 15 | fn default_oom_handler() -> ! { 16 | // The default handler can't do much more since we can't assume the presence 17 | // of libc or any way of printing an error message. 18 | unsafe { intrinsics::abort() } 19 | } 20 | 21 | /// Common out-of-memory routine 22 | #[cold] 23 | #[inline(never)] 24 | #[unstable(feature = "oom", reason = "not a scrutinized interface", 25 | issue = "27700")] 26 | pub fn oom() -> ! { 27 | self::imp::oom() 28 | } 29 | 30 | #[cfg(target_has_atomic = "ptr")] 31 | mod imp { 32 | use core::mem; 33 | use core::sync::atomic::{AtomicPtr, Ordering}; 34 | 35 | static OOM_HANDLER: AtomicPtr<()> = AtomicPtr::new(super::default_oom_handler as *mut ()); 36 | 37 | #[inline(always)] 38 | pub fn oom() -> ! { 39 | let value = OOM_HANDLER.load(Ordering::SeqCst); 40 | let handler: fn() -> ! = unsafe { mem::transmute(value) }; 41 | handler(); 42 | } 43 | 44 | /// Set a custom handler for out-of-memory conditions 45 | /// 46 | /// To avoid recursive OOM failures, it is critical that the OOM handler does 47 | /// not allocate any memory itself. 48 | #[unstable(feature = "oom", reason = "not a scrutinized interface", 49 | issue = "27700")] 50 | pub fn set_oom_handler(handler: fn() -> !) { 51 | OOM_HANDLER.store(handler as *mut (), Ordering::SeqCst); 52 | } 53 | } 54 | 55 | #[cfg(not(target_has_atomic = "ptr"))] 56 | mod imp { 57 | #[inline(always)] 58 | pub fn oom() -> ! { 59 | super::default_oom_handler() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /crates/liballoc/str.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Methods for dealing with boxed strings. 12 | use core::mem; 13 | 14 | use boxed::Box; 15 | 16 | /// Converts a boxed slice of bytes to a boxed string slice without checking 17 | /// that the string contains valid UTF-8. 18 | #[unstable(feature = "str_box_extras", issue = "41119")] 19 | pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { 20 | mem::transmute(v) 21 | } 22 | -------------------------------------------------------------------------------- /crates/liballoc_system/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "alloc_system" 4 | version = "0.0.0" 5 | 6 | [lib] 7 | name = "alloc_system" 8 | path = "lib.rs" 9 | test = false 10 | doc = false 11 | -------------------------------------------------------------------------------- /crates/liballoc_system/kern_malloc.rs: -------------------------------------------------------------------------------- 1 | // 2 | // FreeBSD kernel malloc interface 3 | 4 | // Generated kernel header bindings 5 | #![allow(warnings, unused_variables, dead_code, improper_ctypes, non_camel_case_types, non_snake_case, non_upper_case_globals)] 6 | 7 | use ::raw; 8 | 9 | pub type u_char = raw::c_uchar; 10 | pub type u_short = raw::c_ushort; 11 | pub type u_int = raw::c_uint; 12 | pub type u_long = raw::c_ulong; 13 | pub const M_NOWAIT: raw::c_uint = 1; 14 | pub const M_WAITOK: raw::c_uint = 2; 15 | pub const M_ZERO: raw::c_uint = 256; 16 | pub const M_NOVM: raw::c_uint = 512; 17 | pub const M_USE_RESERVE: raw::c_uint = 1024; 18 | pub const M_NODUMP: raw::c_uint = 2048; 19 | pub const M_FIRSTFIT: raw::c_uint = 4096; 20 | pub const M_BESTFIT: raw::c_uint = 8192; 21 | pub const M_CONTIG: raw::c_uint = 16384; 22 | pub const M_MAGIC: raw::c_uint = 877983977; 23 | 24 | #[repr(C)] 25 | #[derive(Debug, Copy)] 26 | pub struct malloc_type { 27 | pub ks_next: *mut malloc_type, 28 | pub ks_magic: u_long, 29 | pub ks_shortdesc: *const raw::c_char, 30 | pub ks_handle: *mut raw::c_void, 31 | } 32 | // #[test] 33 | // fn bindgen_test_layout_malloc_type() { 34 | // assert_eq!(::core::mem::size_of::() , 32usize); 35 | // assert_eq!(::core::mem::align_of::() , 8usize); 36 | // } 37 | impl Clone for malloc_type { 38 | fn clone(&self) -> Self { *self } 39 | } 40 | 41 | // #[repr(C)] 42 | // #[derive(Debug, Copy)] 43 | // pub struct malloc_type_stats { 44 | // pub mts_memalloced: u64, 45 | // pub mts_memfreed: u64, 46 | // pub mts_numallocs: u64, 47 | // pub mts_numfrees: u64, 48 | // pub mts_size: u64, 49 | // pub _mts_reserved1: u64, 50 | // pub _mts_reserved2: u64, 51 | // pub _mts_reserved3: u64, 52 | // } 53 | // #[test] 54 | // fn bindgen_test_layout_malloc_type_stats() { 55 | // assert_eq!(::core::mem::size_of::() , 64usize); 56 | // assert_eq!(::core::mem::align_of::() , 8usize); 57 | // } 58 | // impl Clone for malloc_type_stats { 59 | // fn clone(&self) -> Self { *self } 60 | // } 61 | // #[repr(C)] 62 | // pub struct malloc_type_internal { 63 | // pub mti_probes: [u32; 2usize], 64 | // pub mti_zone: u_char, 65 | // pub mti_stats: [malloc_type_stats; 256usize], 66 | // } 67 | // #[test] 68 | // fn bindgen_test_layout_malloc_type_internal() { 69 | // assert_eq!(::core::mem::size_of::() , 16400usize); 70 | // assert_eq!(::core::mem::align_of::() , 8usize); 71 | // } 72 | // #[repr(C)] 73 | // #[derive(Debug, Copy)] 74 | // pub struct malloc_type_stream_header { 75 | // pub mtsh_version: u32, 76 | // pub mtsh_maxcpus: u32, 77 | // pub mtsh_count: u32, 78 | // pub _mtsh_pad: u32, 79 | // } 80 | // #[test] 81 | // fn bindgen_test_layout_malloc_type_stream_header() { 82 | // assert_eq!(::core::mem::size_of::() , 16usize); 83 | // assert_eq!(::core::mem::align_of::() , 4usize); 84 | // } 85 | // impl Clone for malloc_type_stream_header { 86 | // fn clone(&self) -> Self { *self } 87 | // } 88 | // #[repr(C)] 89 | // #[derive(Debug, Copy)] 90 | // pub struct malloc_type_header { 91 | // pub mth_name: [raw::c_char; 32usize], 92 | // } 93 | // #[test] 94 | // fn bindgen_test_layout_malloc_type_header() { 95 | // assert_eq!(::core::mem::size_of::() , 32usize); 96 | // assert_eq!(::core::mem::align_of::() , 1usize); 97 | // } 98 | // impl Clone for malloc_type_header { 99 | // fn clone(&self) -> Self { *self } 100 | // } 101 | // extern "C" { 102 | // #[link_name = "M_CACHE"] 103 | // pub static mut M_CACHE: [malloc_type; 1usize]; 104 | // } 105 | extern "C" { 106 | #[link_name = "M_DEVBUF"] 107 | pub static mut M_DEVBUF: [malloc_type; 1usize]; 108 | } 109 | // extern "C" { 110 | // #[link_name = "M_TEMP"] 111 | // pub static mut M_TEMP: [malloc_type; 1usize]; 112 | // } 113 | // extern "C" { 114 | // #[link_name = "M_IOV"] 115 | // pub static mut M_IOV: [malloc_type; 1usize]; 116 | // } 117 | // extern "C" { 118 | // #[link_name = "malloc_mtx"] 119 | // pub static mut malloc_mtx: mtx; 120 | // } 121 | // pub type malloc_type_list_func_t = 122 | // ::core::option::Option; 124 | // extern "C" { 125 | // pub fn contigfree(addr: *mut raw::c_void, size: raw::c_ulong, 126 | // type_: *mut malloc_type); 127 | // } 128 | // extern "C" { 129 | // pub fn contigmalloc(size: raw::c_ulong, type_: *mut malloc_type, 130 | // flags: raw::c_int, low: vm_paddr_t, high: vm_paddr_t, 131 | // alignment: raw::c_ulong, boundary: vm_paddr_t) 132 | // -> *mut raw::c_void; 133 | // } 134 | extern "C" { 135 | pub fn free(addr: *mut raw::c_void, type_: *mut malloc_type); 136 | } 137 | extern "C" { 138 | pub fn malloc(size: raw::c_ulong, type_: *mut malloc_type, 139 | flags: raw::c_int) -> *mut raw::c_void; 140 | } 141 | // extern "C" { 142 | // pub fn malloc_init(arg1: *mut raw::c_void); 143 | // } 144 | // extern "C" { 145 | // pub fn malloc_last_fail() -> raw::c_int; 146 | // } 147 | // extern "C" { 148 | // pub fn malloc_type_allocated(type_: *mut malloc_type, size: raw::c_ulong); 149 | // } 150 | // extern "C" { 151 | // pub fn malloc_type_freed(type_: *mut malloc_type, size: raw::c_ulong); 152 | // } 153 | // extern "C" { 154 | // pub fn malloc_type_list(arg1: malloc_type_list_func_t, 155 | // arg2: *mut raw::c_void); 156 | // } 157 | // extern "C" { 158 | // pub fn malloc_uninit(arg1: *mut raw::c_void); 159 | // } 160 | extern "C" { 161 | pub fn realloc(addr: *mut raw::c_void, size: raw::c_ulong, 162 | type_: *mut malloc_type, flags: raw::c_int) 163 | -> *mut raw::c_void; 164 | } 165 | // extern "C" { 166 | // pub fn reallocf(addr: *mut raw::c_void, size: raw::c_ulong, 167 | // type_: *mut malloc_type, flags: raw::c_int) 168 | // -> *mut raw::c_void; 169 | // } 170 | // extern "C" { 171 | // pub fn malloc_desc2type(desc: *const raw::c_char) -> *mut malloc_type; 172 | // } 173 | 174 | extern "C" { 175 | pub fn uprintf(arg1: *const raw::c_char, ...) 176 | -> raw::c_int; 177 | } 178 | -------------------------------------------------------------------------------- /crates/liballoc_system/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![crate_name = "alloc_system"] 12 | #![crate_type = "rlib"] 13 | #![no_std] 14 | #![allocator] 15 | #![allow(dead_code, unused_variables)] 16 | #![deny(warnings)] 17 | #![unstable(feature = "alloc_system", 18 | reason = "this library is unlikely to be stabilized in its current \ 19 | form or name", 20 | issue = "27783")] 21 | #![feature(allocator)] 22 | #![feature(staged_api)] 23 | 24 | // The minimum alignment guaranteed by the architecture. This value is used to 25 | // add fast paths for low alignment values. In practice, the alignment is a 26 | // constant at the call site and the branch will be optimized out. 27 | #[cfg(all(any(target_arch = "x86", 28 | target_arch = "arm", 29 | target_arch = "mips", 30 | target_arch = "powerpc", 31 | target_arch = "powerpc64", 32 | target_arch = "asmjs", 33 | target_arch = "wasm32")))] 34 | const MIN_ALIGN: usize = 8; 35 | #[cfg(all(any(target_arch = "x86_64", 36 | target_arch = "aarch64", 37 | target_arch = "mips64", 38 | target_arch = "s390x", 39 | target_arch = "sparc64")))] 40 | const MIN_ALIGN: usize = 16; 41 | 42 | #[no_mangle] 43 | pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 { 44 | unsafe { imp::allocate(size, align) } 45 | } 46 | 47 | #[no_mangle] 48 | pub extern "C" fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8 { 49 | unsafe { imp::allocate_zeroed(size, align) } 50 | } 51 | 52 | #[no_mangle] 53 | pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { 54 | unsafe { imp::deallocate(ptr, old_size, align) } 55 | } 56 | 57 | #[no_mangle] 58 | pub extern "C" fn __rust_reallocate(ptr: *mut u8, 59 | old_size: usize, 60 | size: usize, 61 | align: usize) 62 | -> *mut u8 { 63 | unsafe { imp::reallocate(ptr, old_size, size, align) } 64 | } 65 | 66 | #[no_mangle] 67 | pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8, 68 | old_size: usize, 69 | size: usize, 70 | align: usize) 71 | -> usize { 72 | unsafe { imp::reallocate_inplace(ptr, old_size, size, align) } 73 | } 74 | 75 | #[no_mangle] 76 | pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { 77 | imp::usable_size(size, align) 78 | } 79 | 80 | 81 | mod raw; 82 | 83 | mod kern_malloc; 84 | 85 | mod imp { 86 | 87 | use kern_malloc as kern; 88 | use raw; 89 | use core::cmp; 90 | use core::ptr; 91 | use MIN_ALIGN; 92 | 93 | pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { 94 | 95 | // kern::uprintf("allocate: %d\n\0".as_ptr() as *const i8, size); 96 | 97 | if align <= MIN_ALIGN { 98 | kern::malloc(size as raw::c_size_t, 99 | &mut kern::M_DEVBUF[0], 100 | kern::M_WAITOK as i32) as *mut u8 101 | } else { 102 | aligned_malloc(size, align) 103 | } 104 | } 105 | 106 | pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { 107 | 108 | // kern::uprintf("allocate_zeroed: %d\n\0".as_ptr() as *const i8, size); 109 | 110 | if align <= MIN_ALIGN { 111 | kern::malloc(size as raw::c_size_t, 112 | &mut kern::M_DEVBUF[0], 113 | kern::M_WAITOK as i32 | kern::M_ZERO as i32) as *mut u8 114 | } else { 115 | let ptr = aligned_malloc(size, align); 116 | if !ptr.is_null() { 117 | ptr::write_bytes(ptr, 0, size); 118 | } 119 | ptr 120 | } 121 | } 122 | 123 | 124 | unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { 125 | // TODO: Replace with proper call 126 | kern::uprintf("aligned_malloc: using normal malloc!\n\0".as_ptr() as *const i8); 127 | kern::malloc(size as raw::c_size_t, 128 | &mut kern::M_DEVBUF[0], 129 | kern::M_WAITOK as i32) as *mut u8 130 | } 131 | 132 | 133 | pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { 134 | 135 | // kern::uprintf("reallocate %d -> %d\n\0".as_ptr() as *const i8, old_size, size); 136 | 137 | if align <= MIN_ALIGN { 138 | kern::realloc(ptr as *mut raw::c_void, 139 | size as raw::c_size_t, 140 | &mut kern::M_DEVBUF[0], 141 | kern::M_WAITOK as i32) as *mut u8 142 | } else { 143 | let new_ptr = allocate(size, align); 144 | if !new_ptr.is_null() { 145 | ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); 146 | deallocate(ptr, old_size, align); 147 | } 148 | new_ptr 149 | } 150 | } 151 | 152 | pub unsafe fn reallocate_inplace(_ptr: *mut u8, 153 | old_size: usize, 154 | _size: usize, 155 | _align: usize) 156 | -> usize { 157 | kern::uprintf("reallocate in place undefined!\n\0".as_ptr() as *const i8); 158 | old_size 159 | } 160 | 161 | pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { 162 | // kern::uprintf("deallocate %d\n\0".as_ptr() as *const i8, _old_size); 163 | kern::free(ptr as *mut raw::c_void, &mut kern::M_DEVBUF[0]) 164 | } 165 | 166 | pub fn usable_size(size: usize, _align: usize) -> usize { 167 | size 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /crates/liballoc_system/raw.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(unused_attributes)] 3 | 4 | // Special: Platforms with unsigned character types 5 | #![cfg_attr( 6 | any( 7 | target_arch = "aarch64", 8 | target_arch = "arm", 9 | target_arch = "powerpc", 10 | target_arch = "powerpc64" 11 | ), 12 | target_arch_char_unsigned 13 | )] 14 | 15 | 16 | // Character types 17 | pub type c_schar = i8; 18 | pub type c_uchar = u8; 19 | #[cfg(not(target_arch_char_unsigned))] 20 | pub type c_char = i8; 21 | #[cfg(target_arch_char_unsigned)] 22 | pub type c_char = u8; 23 | #[cfg(not(target_arch_char_unsigned))] 24 | pub type c_wchar = i32; 25 | #[cfg(target_arch_char_unsigned)] 26 | pub type c_wchar = u32; 27 | 28 | // Standard integers 29 | pub type c_short = i16; 30 | pub type c_ushort = u16; 31 | 32 | pub type c_int = i32; 33 | pub type c_uint = u32; 34 | 35 | #[cfg(target_pointer_width = "32")] 36 | pub type c_long = i32; 37 | #[cfg(target_pointer_width = "32")] 38 | pub type c_ulong = u32; 39 | #[cfg(target_pointer_width = "64")] 40 | pub type c_long = i64; 41 | #[cfg(target_pointer_width = "64")] 42 | pub type c_ulong = u64; 43 | 44 | pub type c_longlong = i64; 45 | pub type c_ulonglong = u64; 46 | 47 | // Float point type (not usable, but they do exist) 48 | pub type c_float = f32; 49 | pub type c_double = f64; 50 | 51 | // The special "size" type 52 | #[cfg(target_pointer_width = "32")] 53 | pub type c_size_t = u32; 54 | #[cfg(target_pointer_width = "64")] 55 | pub type c_size_t = u64; 56 | 57 | /// Magic pointer that represents a `void*` in C 58 | /// See `libstd/os/raw.rs:48` from the Rust source code for details… 59 | #[repr(u8)] 60 | pub enum c_void { 61 | #[doc(hidden)] __variant1, 62 | #[doc(hidden)] __variant2 63 | } 64 | -------------------------------------------------------------------------------- /crates/libcollections/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "collections" 4 | version = "0.0.0" 5 | 6 | [lib] 7 | name = "collections" 8 | path = "lib.rs" 9 | 10 | [dependencies] 11 | alloc = { path = "../liballoc" } 12 | # core = { path = "../libcore" } 13 | std_unicode = { path = "../libstd_unicode" } 14 | 15 | # [[test]] 16 | # name = "collectionstest" 17 | # path = "../libcollectionstest/lib.rs" 18 | 19 | # [[bench]] 20 | # name = "collectionsbenches" 21 | # path = "../libcollections/benches/lib.rs" 22 | -------------------------------------------------------------------------------- /crates/libcollections/benches/btree/map.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | 12 | use std::iter::Iterator; 13 | use std::vec::Vec; 14 | use std::collections::BTreeMap; 15 | use std::__rand::{Rng, thread_rng}; 16 | use test::{Bencher, black_box}; 17 | 18 | macro_rules! map_insert_rand_bench { 19 | ($name: ident, $n: expr, $map: ident) => ( 20 | #[bench] 21 | pub fn $name(b: &mut Bencher) { 22 | let n: usize = $n; 23 | let mut map = $map::new(); 24 | // setup 25 | let mut rng = thread_rng(); 26 | 27 | for _ in 0..n { 28 | let i = rng.gen::() % n; 29 | map.insert(i, i); 30 | } 31 | 32 | // measure 33 | b.iter(|| { 34 | let k = rng.gen::() % n; 35 | map.insert(k, k); 36 | map.remove(&k); 37 | }); 38 | black_box(map); 39 | } 40 | ) 41 | } 42 | 43 | macro_rules! map_insert_seq_bench { 44 | ($name: ident, $n: expr, $map: ident) => ( 45 | #[bench] 46 | pub fn $name(b: &mut Bencher) { 47 | let mut map = $map::new(); 48 | let n: usize = $n; 49 | // setup 50 | for i in 0..n { 51 | map.insert(i * 2, i * 2); 52 | } 53 | 54 | // measure 55 | let mut i = 1; 56 | b.iter(|| { 57 | map.insert(i, i); 58 | map.remove(&i); 59 | i = (i + 2) % n; 60 | }); 61 | black_box(map); 62 | } 63 | ) 64 | } 65 | 66 | macro_rules! map_find_rand_bench { 67 | ($name: ident, $n: expr, $map: ident) => ( 68 | #[bench] 69 | pub fn $name(b: &mut Bencher) { 70 | let mut map = $map::new(); 71 | let n: usize = $n; 72 | 73 | // setup 74 | let mut rng = thread_rng(); 75 | let mut keys: Vec<_> = (0..n).map(|_| rng.gen::() % n).collect(); 76 | 77 | for &k in &keys { 78 | map.insert(k, k); 79 | } 80 | 81 | rng.shuffle(&mut keys); 82 | 83 | // measure 84 | let mut i = 0; 85 | b.iter(|| { 86 | let t = map.get(&keys[i]); 87 | i = (i + 1) % n; 88 | black_box(t); 89 | }) 90 | } 91 | ) 92 | } 93 | 94 | macro_rules! map_find_seq_bench { 95 | ($name: ident, $n: expr, $map: ident) => ( 96 | #[bench] 97 | pub fn $name(b: &mut Bencher) { 98 | let mut map = $map::new(); 99 | let n: usize = $n; 100 | 101 | // setup 102 | for i in 0..n { 103 | map.insert(i, i); 104 | } 105 | 106 | // measure 107 | let mut i = 0; 108 | b.iter(|| { 109 | let x = map.get(&i); 110 | i = (i + 1) % n; 111 | black_box(x); 112 | }) 113 | } 114 | ) 115 | } 116 | 117 | map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} 118 | map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} 119 | 120 | map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} 121 | map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} 122 | 123 | map_find_rand_bench!{find_rand_100, 100, BTreeMap} 124 | map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} 125 | 126 | map_find_seq_bench!{find_seq_100, 100, BTreeMap} 127 | map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} 128 | 129 | fn bench_iter(b: &mut Bencher, size: i32) { 130 | let mut map = BTreeMap::::new(); 131 | let mut rng = thread_rng(); 132 | 133 | for _ in 0..size { 134 | map.insert(rng.gen(), rng.gen()); 135 | } 136 | 137 | b.iter(|| { 138 | for entry in &map { 139 | black_box(entry); 140 | } 141 | }); 142 | } 143 | 144 | #[bench] 145 | pub fn iter_20(b: &mut Bencher) { 146 | bench_iter(b, 20); 147 | } 148 | 149 | #[bench] 150 | pub fn iter_1000(b: &mut Bencher) { 151 | bench_iter(b, 1000); 152 | } 153 | 154 | #[bench] 155 | pub fn iter_100000(b: &mut Bencher) { 156 | bench_iter(b, 100000); 157 | } 158 | -------------------------------------------------------------------------------- /crates/libcollections/benches/btree/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | mod map; 12 | -------------------------------------------------------------------------------- /crates/libcollections/benches/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![deny(warnings)] 12 | 13 | #![feature(i128_type)] 14 | #![feature(rand)] 15 | #![feature(repr_simd)] 16 | #![feature(slice_rotate)] 17 | #![feature(sort_unstable)] 18 | #![feature(test)] 19 | 20 | extern crate test; 21 | 22 | mod btree; 23 | mod linked_list; 24 | mod string; 25 | mod str; 26 | mod slice; 27 | mod vec; 28 | mod vec_deque; 29 | -------------------------------------------------------------------------------- /crates/libcollections/benches/linked_list.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::collections::LinkedList; 12 | use test::Bencher; 13 | 14 | #[bench] 15 | fn bench_collect_into(b: &mut Bencher) { 16 | let v = &[0; 64]; 17 | b.iter(|| { 18 | let _: LinkedList<_> = v.iter().cloned().collect(); 19 | }) 20 | } 21 | 22 | #[bench] 23 | fn bench_push_front(b: &mut Bencher) { 24 | let mut m: LinkedList<_> = LinkedList::new(); 25 | b.iter(|| { 26 | m.push_front(0); 27 | }) 28 | } 29 | 30 | #[bench] 31 | fn bench_push_back(b: &mut Bencher) { 32 | let mut m: LinkedList<_> = LinkedList::new(); 33 | b.iter(|| { 34 | m.push_back(0); 35 | }) 36 | } 37 | 38 | #[bench] 39 | fn bench_push_back_pop_back(b: &mut Bencher) { 40 | let mut m: LinkedList<_> = LinkedList::new(); 41 | b.iter(|| { 42 | m.push_back(0); 43 | m.pop_back(); 44 | }) 45 | } 46 | 47 | #[bench] 48 | fn bench_push_front_pop_front(b: &mut Bencher) { 49 | let mut m: LinkedList<_> = LinkedList::new(); 50 | b.iter(|| { 51 | m.push_front(0); 52 | m.pop_front(); 53 | }) 54 | } 55 | 56 | #[bench] 57 | fn bench_iter(b: &mut Bencher) { 58 | let v = &[0; 128]; 59 | let m: LinkedList<_> = v.iter().cloned().collect(); 60 | b.iter(|| { 61 | assert!(m.iter().count() == 128); 62 | }) 63 | } 64 | #[bench] 65 | fn bench_iter_mut(b: &mut Bencher) { 66 | let v = &[0; 128]; 67 | let mut m: LinkedList<_> = v.iter().cloned().collect(); 68 | b.iter(|| { 69 | assert!(m.iter_mut().count() == 128); 70 | }) 71 | } 72 | #[bench] 73 | fn bench_iter_rev(b: &mut Bencher) { 74 | let v = &[0; 128]; 75 | let m: LinkedList<_> = v.iter().cloned().collect(); 76 | b.iter(|| { 77 | assert!(m.iter().rev().count() == 128); 78 | }) 79 | } 80 | #[bench] 81 | fn bench_iter_mut_rev(b: &mut Bencher) { 82 | let v = &[0; 128]; 83 | let mut m: LinkedList<_> = v.iter().cloned().collect(); 84 | b.iter(|| { 85 | assert!(m.iter_mut().rev().count() == 128); 86 | }) 87 | } 88 | -------------------------------------------------------------------------------- /crates/libcollections/benches/slice.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::{mem, ptr}; 12 | use std::__rand::{Rng, thread_rng}; 13 | 14 | use test::{Bencher, black_box}; 15 | 16 | #[bench] 17 | fn iterator(b: &mut Bencher) { 18 | // peculiar numbers to stop LLVM from optimising the summation 19 | // out. 20 | let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); 21 | 22 | b.iter(|| { 23 | let mut sum = 0; 24 | for x in &v { 25 | sum += *x; 26 | } 27 | // sum == 11806, to stop dead code elimination. 28 | if sum == 0 { 29 | panic!() 30 | } 31 | }) 32 | } 33 | 34 | #[bench] 35 | fn mut_iterator(b: &mut Bencher) { 36 | let mut v = vec![0; 100]; 37 | 38 | b.iter(|| { 39 | let mut i = 0; 40 | for x in &mut v { 41 | *x = i; 42 | i += 1; 43 | } 44 | }) 45 | } 46 | 47 | #[bench] 48 | fn concat(b: &mut Bencher) { 49 | let xss: Vec> = (0..100).map(|i| (0..i).collect()).collect(); 50 | b.iter(|| { 51 | xss.concat(); 52 | }); 53 | } 54 | 55 | #[bench] 56 | fn join(b: &mut Bencher) { 57 | let xss: Vec> = (0..100).map(|i| (0..i).collect()).collect(); 58 | b.iter(|| xss.join(&0)); 59 | } 60 | 61 | #[bench] 62 | fn push(b: &mut Bencher) { 63 | let mut vec = Vec::::new(); 64 | b.iter(|| { 65 | vec.push(0); 66 | black_box(&vec); 67 | }); 68 | } 69 | 70 | #[bench] 71 | fn starts_with_same_vector(b: &mut Bencher) { 72 | let vec: Vec<_> = (0..100).collect(); 73 | b.iter(|| vec.starts_with(&vec)) 74 | } 75 | 76 | #[bench] 77 | fn starts_with_single_element(b: &mut Bencher) { 78 | let vec: Vec<_> = vec![0]; 79 | b.iter(|| vec.starts_with(&vec)) 80 | } 81 | 82 | #[bench] 83 | fn starts_with_diff_one_element_at_end(b: &mut Bencher) { 84 | let vec: Vec<_> = (0..100).collect(); 85 | let mut match_vec: Vec<_> = (0..99).collect(); 86 | match_vec.push(0); 87 | b.iter(|| vec.starts_with(&match_vec)) 88 | } 89 | 90 | #[bench] 91 | fn ends_with_same_vector(b: &mut Bencher) { 92 | let vec: Vec<_> = (0..100).collect(); 93 | b.iter(|| vec.ends_with(&vec)) 94 | } 95 | 96 | #[bench] 97 | fn ends_with_single_element(b: &mut Bencher) { 98 | let vec: Vec<_> = vec![0]; 99 | b.iter(|| vec.ends_with(&vec)) 100 | } 101 | 102 | #[bench] 103 | fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { 104 | let vec: Vec<_> = (0..100).collect(); 105 | let mut match_vec: Vec<_> = (0..100).collect(); 106 | match_vec[0] = 200; 107 | b.iter(|| vec.starts_with(&match_vec)) 108 | } 109 | 110 | #[bench] 111 | fn contains_last_element(b: &mut Bencher) { 112 | let vec: Vec<_> = (0..100).collect(); 113 | b.iter(|| vec.contains(&99)) 114 | } 115 | 116 | #[bench] 117 | fn zero_1kb_from_elem(b: &mut Bencher) { 118 | b.iter(|| vec![0u8; 1024]); 119 | } 120 | 121 | #[bench] 122 | fn zero_1kb_set_memory(b: &mut Bencher) { 123 | b.iter(|| { 124 | let mut v = Vec::::with_capacity(1024); 125 | unsafe { 126 | let vp = v.as_mut_ptr(); 127 | ptr::write_bytes(vp, 0, 1024); 128 | v.set_len(1024); 129 | } 130 | v 131 | }); 132 | } 133 | 134 | #[bench] 135 | fn zero_1kb_loop_set(b: &mut Bencher) { 136 | b.iter(|| { 137 | let mut v = Vec::::with_capacity(1024); 138 | unsafe { 139 | v.set_len(1024); 140 | } 141 | for i in 0..1024 { 142 | v[i] = 0; 143 | } 144 | }); 145 | } 146 | 147 | #[bench] 148 | fn zero_1kb_mut_iter(b: &mut Bencher) { 149 | b.iter(|| { 150 | let mut v = Vec::::with_capacity(1024); 151 | unsafe { 152 | v.set_len(1024); 153 | } 154 | for x in &mut v { 155 | *x = 0; 156 | } 157 | v 158 | }); 159 | } 160 | 161 | #[bench] 162 | fn random_inserts(b: &mut Bencher) { 163 | let mut rng = thread_rng(); 164 | b.iter(|| { 165 | let mut v = vec![(0, 0); 30]; 166 | for _ in 0..100 { 167 | let l = v.len(); 168 | v.insert(rng.gen::() % (l + 1), (1, 1)); 169 | } 170 | }) 171 | } 172 | 173 | #[bench] 174 | fn random_removes(b: &mut Bencher) { 175 | let mut rng = thread_rng(); 176 | b.iter(|| { 177 | let mut v = vec![(0, 0); 130]; 178 | for _ in 0..100 { 179 | let l = v.len(); 180 | v.remove(rng.gen::() % l); 181 | } 182 | }) 183 | } 184 | 185 | fn gen_ascending(len: usize) -> Vec { 186 | (0..len as u64).collect() 187 | } 188 | 189 | fn gen_descending(len: usize) -> Vec { 190 | (0..len as u64).rev().collect() 191 | } 192 | 193 | fn gen_random(len: usize) -> Vec { 194 | let mut rng = thread_rng(); 195 | rng.gen_iter::().take(len).collect() 196 | } 197 | 198 | fn gen_random_bytes(len: usize) -> Vec { 199 | let mut rng = thread_rng(); 200 | rng.gen_iter::().take(len).collect() 201 | } 202 | 203 | fn gen_mostly_ascending(len: usize) -> Vec { 204 | let mut rng = thread_rng(); 205 | let mut v = gen_ascending(len); 206 | for _ in (0usize..).take_while(|x| x * x <= len) { 207 | let x = rng.gen::() % len; 208 | let y = rng.gen::() % len; 209 | v.swap(x, y); 210 | } 211 | v 212 | } 213 | 214 | fn gen_mostly_descending(len: usize) -> Vec { 215 | let mut rng = thread_rng(); 216 | let mut v = gen_descending(len); 217 | for _ in (0usize..).take_while(|x| x * x <= len) { 218 | let x = rng.gen::() % len; 219 | let y = rng.gen::() % len; 220 | v.swap(x, y); 221 | } 222 | v 223 | } 224 | 225 | fn gen_strings(len: usize) -> Vec { 226 | let mut rng = thread_rng(); 227 | let mut v = vec![]; 228 | for _ in 0..len { 229 | let n = rng.gen::() % 20 + 1; 230 | v.push(rng.gen_ascii_chars().take(n).collect()); 231 | } 232 | v 233 | } 234 | 235 | fn gen_big_random(len: usize) -> Vec<[u64; 16]> { 236 | let mut rng = thread_rng(); 237 | rng.gen_iter().map(|x| [x; 16]).take(len).collect() 238 | } 239 | 240 | macro_rules! sort { 241 | ($f:ident, $name:ident, $gen:expr, $len:expr) => { 242 | #[bench] 243 | fn $name(b: &mut Bencher) { 244 | b.iter(|| $gen($len).$f()); 245 | b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; 246 | } 247 | } 248 | } 249 | 250 | macro_rules! sort_expensive { 251 | ($f:ident, $name:ident, $gen:expr, $len:expr) => { 252 | #[bench] 253 | fn $name(b: &mut Bencher) { 254 | b.iter(|| { 255 | let mut v = $gen($len); 256 | let mut count = 0; 257 | v.$f(|a: &u64, b: &u64| { 258 | count += 1; 259 | if count % 1_000_000_000 == 0 { 260 | panic!("should not happen"); 261 | } 262 | (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap() 263 | }); 264 | black_box(count); 265 | }); 266 | b.bytes = $len as u64 * mem::size_of::() as u64; 267 | } 268 | } 269 | } 270 | 271 | sort!(sort, sort_small_ascending, gen_ascending, 10); 272 | sort!(sort, sort_small_descending, gen_descending, 10); 273 | sort!(sort, sort_small_random, gen_random, 10); 274 | sort!(sort, sort_small_big_random, gen_big_random, 10); 275 | sort!(sort, sort_medium_random, gen_random, 100); 276 | sort!(sort, sort_large_ascending, gen_ascending, 10000); 277 | sort!(sort, sort_large_descending, gen_descending, 10000); 278 | sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000); 279 | sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000); 280 | sort!(sort, sort_large_random, gen_random, 10000); 281 | sort!(sort, sort_large_big_random, gen_big_random, 10000); 282 | sort!(sort, sort_large_strings, gen_strings, 10000); 283 | sort_expensive!(sort_by, sort_large_random_expensive, gen_random, 10000); 284 | 285 | sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10); 286 | sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10); 287 | sort!(sort_unstable, sort_unstable_small_random, gen_random, 10); 288 | sort!(sort_unstable, sort_unstable_small_big_random, gen_big_random, 10); 289 | sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100); 290 | sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000); 291 | sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000); 292 | sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000); 293 | sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000); 294 | sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000); 295 | sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000); 296 | sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); 297 | sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000); 298 | 299 | macro_rules! reverse { 300 | ($name:ident, $ty:ty, $f:expr) => { 301 | #[bench] 302 | fn $name(b: &mut Bencher) { 303 | // odd length and offset by 1 to be as unaligned as possible 304 | let n = 0xFFFFF; 305 | let mut v: Vec<_> = 306 | (0..1+(n / mem::size_of::<$ty>() as u64)) 307 | .map($f) 308 | .collect(); 309 | b.iter(|| black_box(&mut v[1..]).reverse()); 310 | b.bytes = n; 311 | } 312 | } 313 | } 314 | 315 | reverse!(reverse_u8, u8, |x| x as u8); 316 | reverse!(reverse_u16, u16, |x| x as u16); 317 | reverse!(reverse_u8x3, [u8;3], |x| [x as u8, (x>>8) as u8, (x>>16) as u8]); 318 | reverse!(reverse_u32, u32, |x| x as u32); 319 | reverse!(reverse_u64, u64, |x| x as u64); 320 | reverse!(reverse_u128, u128, |x| x as u128); 321 | #[repr(simd)] struct F64x4(f64, f64, f64, f64); 322 | reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; F64x4(x,x,x,x) }); 323 | 324 | macro_rules! rotate { 325 | ($name:ident, $gen:expr, $len:expr, $mid:expr) => { 326 | #[bench] 327 | fn $name(b: &mut Bencher) { 328 | let size = mem::size_of_val(&$gen(1)[0]); 329 | let mut v = $gen($len * 8 / size); 330 | b.iter(|| black_box(&mut v).rotate(($mid*8+size-1)/size)); 331 | b.bytes = (v.len() * size) as u64; 332 | } 333 | } 334 | } 335 | 336 | rotate!(rotate_tiny_by1, gen_random, 16, 1); 337 | rotate!(rotate_tiny_half, gen_random, 16, 16/2); 338 | rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16/2+1); 339 | 340 | rotate!(rotate_medium_by1, gen_random, 9158, 1); 341 | rotate!(rotate_medium_by727_u64, gen_random, 9158, 727); 342 | rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727); 343 | rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727); 344 | rotate!(rotate_medium_half, gen_random, 9158, 9158/2); 345 | rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158/2+1); 346 | 347 | // Intended to use more RAM than the machine has cache 348 | rotate!(rotate_huge_by1, gen_random, 5*1024*1024, 1); 349 | rotate!(rotate_huge_by9199_u64, gen_random, 5*1024*1024, 9199); 350 | rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5*1024*1024, 9199); 351 | rotate!(rotate_huge_by9199_strings, gen_strings, 5*1024*1024, 9199); 352 | rotate!(rotate_huge_by9199_big, gen_big_random, 5*1024*1024, 9199); 353 | rotate!(rotate_huge_by1234577_u64, gen_random, 5*1024*1024, 1234577); 354 | rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5*1024*1024, 1234577); 355 | rotate!(rotate_huge_by1234577_strings, gen_strings, 5*1024*1024, 1234577); 356 | rotate!(rotate_huge_by1234577_big, gen_big_random, 5*1024*1024, 1234577); 357 | rotate!(rotate_huge_half, gen_random, 5*1024*1024, 5*1024*1024/2); 358 | rotate!(rotate_huge_half_plus_one, gen_random, 5*1024*1024, 5*1024*1024/2+1); 359 | -------------------------------------------------------------------------------- /crates/libcollections/benches/str.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use test::{Bencher, black_box}; 12 | 13 | #[bench] 14 | fn char_iterator(b: &mut Bencher) { 15 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 16 | 17 | b.iter(|| s.chars().count()); 18 | } 19 | 20 | #[bench] 21 | fn char_iterator_for(b: &mut Bencher) { 22 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 23 | 24 | b.iter(|| { 25 | for ch in s.chars() { black_box(ch); } 26 | }); 27 | } 28 | 29 | #[bench] 30 | fn char_iterator_ascii(b: &mut Bencher) { 31 | let s = "Mary had a little lamb, Little lamb 32 | Mary had a little lamb, Little lamb 33 | Mary had a little lamb, Little lamb 34 | Mary had a little lamb, Little lamb 35 | Mary had a little lamb, Little lamb 36 | Mary had a little lamb, Little lamb"; 37 | 38 | b.iter(|| s.chars().count()); 39 | } 40 | 41 | #[bench] 42 | fn char_iterator_rev(b: &mut Bencher) { 43 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 44 | 45 | b.iter(|| s.chars().rev().count()); 46 | } 47 | 48 | #[bench] 49 | fn char_iterator_rev_for(b: &mut Bencher) { 50 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 51 | 52 | b.iter(|| { 53 | for ch in s.chars().rev() { black_box(ch); } 54 | }); 55 | } 56 | 57 | #[bench] 58 | fn char_indicesator(b: &mut Bencher) { 59 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 60 | let len = s.chars().count(); 61 | 62 | b.iter(|| assert_eq!(s.char_indices().count(), len)); 63 | } 64 | 65 | #[bench] 66 | fn char_indicesator_rev(b: &mut Bencher) { 67 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 68 | let len = s.chars().count(); 69 | 70 | b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); 71 | } 72 | 73 | #[bench] 74 | fn split_unicode_ascii(b: &mut Bencher) { 75 | let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; 76 | 77 | b.iter(|| assert_eq!(s.split('V').count(), 3)); 78 | } 79 | 80 | #[bench] 81 | fn split_ascii(b: &mut Bencher) { 82 | let s = "Mary had a little lamb, Little lamb, little-lamb."; 83 | let len = s.split(' ').count(); 84 | 85 | b.iter(|| assert_eq!(s.split(' ').count(), len)); 86 | } 87 | 88 | #[bench] 89 | fn split_extern_fn(b: &mut Bencher) { 90 | let s = "Mary had a little lamb, Little lamb, little-lamb."; 91 | let len = s.split(' ').count(); 92 | fn pred(c: char) -> bool { c == ' ' } 93 | 94 | b.iter(|| assert_eq!(s.split(pred).count(), len)); 95 | } 96 | 97 | #[bench] 98 | fn split_closure(b: &mut Bencher) { 99 | let s = "Mary had a little lamb, Little lamb, little-lamb."; 100 | let len = s.split(' ').count(); 101 | 102 | b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); 103 | } 104 | 105 | #[bench] 106 | fn split_slice(b: &mut Bencher) { 107 | let s = "Mary had a little lamb, Little lamb, little-lamb."; 108 | let len = s.split(' ').count(); 109 | 110 | let c: &[char] = &[' ']; 111 | b.iter(|| assert_eq!(s.split(c).count(), len)); 112 | } 113 | 114 | #[bench] 115 | fn bench_join(b: &mut Bencher) { 116 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 117 | let sep = "→"; 118 | let v = vec![s, s, s, s, s, s, s, s, s, s]; 119 | b.iter(|| { 120 | assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9); 121 | }) 122 | } 123 | 124 | #[bench] 125 | fn bench_contains_short_short(b: &mut Bencher) { 126 | let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; 127 | let needle = "sit"; 128 | 129 | b.iter(|| { 130 | assert!(haystack.contains(needle)); 131 | }) 132 | } 133 | 134 | #[bench] 135 | fn bench_contains_short_long(b: &mut Bencher) { 136 | let haystack = "\ 137 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ 138 | ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ 139 | eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ 140 | sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ 141 | tempus vel, gravida nec quam. 142 | 143 | In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ 144 | sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ 145 | diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ 146 | lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ 147 | eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ 148 | interdum. Curabitur ut nisi justo. 149 | 150 | Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ 151 | mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ 152 | lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ 153 | est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ 154 | felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ 155 | ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ 156 | feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ 157 | Aliquam sit amet placerat lorem. 158 | 159 | Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ 160 | mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ 161 | Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ 162 | lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ 163 | suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ 164 | cursus accumsan. 165 | 166 | Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ 167 | feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ 168 | vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ 169 | leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ 170 | malesuada sollicitudin quam eu fermentum."; 171 | let needle = "english"; 172 | 173 | b.iter(|| { 174 | assert!(!haystack.contains(needle)); 175 | }) 176 | } 177 | 178 | #[bench] 179 | fn bench_contains_bad_naive(b: &mut Bencher) { 180 | let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 181 | let needle = "aaaaaaaab"; 182 | 183 | b.iter(|| { 184 | assert!(!haystack.contains(needle)); 185 | }) 186 | } 187 | 188 | #[bench] 189 | fn bench_contains_equal(b: &mut Bencher) { 190 | let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; 191 | let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; 192 | 193 | b.iter(|| { 194 | assert!(haystack.contains(needle)); 195 | }) 196 | } 197 | 198 | 199 | macro_rules! make_test_inner { 200 | ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => { 201 | #[bench] 202 | fn $name(bencher: &mut Bencher) { 203 | let mut $s = $str; 204 | black_box(&mut $s); 205 | bencher.iter(|| for _ in 0..$iters { black_box($code); }); 206 | } 207 | } 208 | } 209 | 210 | macro_rules! make_test { 211 | ($name:ident, $s:ident, $code:expr) => { 212 | make_test!($name, $s, $code, 1); 213 | }; 214 | ($name:ident, $s:ident, $code:expr, $iters:expr) => { 215 | mod $name { 216 | use test::Bencher; 217 | use test::black_box; 218 | 219 | // Short strings: 65 bytes each 220 | make_test_inner!($s, $code, short_ascii, 221 | "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!", $iters); 222 | make_test_inner!($s, $code, short_mixed, 223 | "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!", $iters); 224 | make_test_inner!($s, $code, short_pile_of_poo, 225 | "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!", $iters); 226 | make_test_inner!($s, $code, long_lorem_ipsum,"\ 227 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ 228 | ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ 229 | eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ 230 | sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ 231 | tempus vel, gravida nec quam. 232 | 233 | In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ 234 | sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ 235 | diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ 236 | lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ 237 | eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ 238 | interdum. Curabitur ut nisi justo. 239 | 240 | Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ 241 | mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ 242 | lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ 243 | est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ 244 | felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ 245 | ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ 246 | feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ 247 | Aliquam sit amet placerat lorem. 248 | 249 | Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ 250 | mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ 251 | Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ 252 | lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ 253 | suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ 254 | cursus accumsan. 255 | 256 | Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ 257 | feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ 258 | vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ 259 | leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ 260 | malesuada sollicitudin quam eu fermentum!", $iters); 261 | } 262 | } 263 | } 264 | 265 | make_test!(chars_count, s, s.chars().count()); 266 | 267 | make_test!(contains_bang_str, s, s.contains("!")); 268 | make_test!(contains_bang_char, s, s.contains('!')); 269 | 270 | make_test!(match_indices_a_str, s, s.match_indices("a").count()); 271 | 272 | make_test!(split_a_str, s, s.split("a").count()); 273 | 274 | make_test!(trim_ascii_char, s, { 275 | use std::ascii::AsciiExt; 276 | s.trim_matches(|c: char| c.is_ascii()) 277 | }); 278 | make_test!(trim_left_ascii_char, s, { 279 | use std::ascii::AsciiExt; 280 | s.trim_left_matches(|c: char| c.is_ascii()) 281 | }); 282 | make_test!(trim_right_ascii_char, s, { 283 | use std::ascii::AsciiExt; 284 | s.trim_right_matches(|c: char| c.is_ascii()) 285 | }); 286 | 287 | make_test!(find_underscore_char, s, s.find('_')); 288 | make_test!(rfind_underscore_char, s, s.rfind('_')); 289 | make_test!(find_underscore_str, s, s.find("_")); 290 | 291 | make_test!(find_zzz_char, s, s.find('\u{1F4A4}')); 292 | make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}')); 293 | make_test!(find_zzz_str, s, s.find("\u{1F4A4}")); 294 | 295 | make_test!(starts_with_ascii_char, s, s.starts_with('/'), 1024); 296 | make_test!(ends_with_ascii_char, s, s.ends_with('/'), 1024); 297 | make_test!(starts_with_unichar, s, s.starts_with('\u{1F4A4}'), 1024); 298 | make_test!(ends_with_unichar, s, s.ends_with('\u{1F4A4}'), 1024); 299 | make_test!(starts_with_str, s, s.starts_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024); 300 | make_test!(ends_with_str, s, s.ends_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024); 301 | 302 | make_test!(split_space_char, s, s.split(' ').count()); 303 | make_test!(split_terminator_space_char, s, s.split_terminator(' ').count()); 304 | 305 | make_test!(splitn_space_char, s, s.splitn(10, ' ').count()); 306 | make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count()); 307 | 308 | make_test!(split_space_str, s, s.split(" ").count()); 309 | make_test!(split_ad_str, s, s.split("ad").count()); 310 | -------------------------------------------------------------------------------- /crates/libcollections/benches/string.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::iter::repeat; 12 | use test::Bencher; 13 | 14 | #[bench] 15 | fn bench_with_capacity(b: &mut Bencher) { 16 | b.iter(|| String::with_capacity(100)); 17 | } 18 | 19 | #[bench] 20 | fn bench_push_str(b: &mut Bencher) { 21 | let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; 22 | b.iter(|| { 23 | let mut r = String::new(); 24 | r.push_str(s); 25 | }); 26 | } 27 | 28 | const REPETITIONS: u64 = 10_000; 29 | 30 | #[bench] 31 | fn bench_push_str_one_byte(b: &mut Bencher) { 32 | b.bytes = REPETITIONS; 33 | b.iter(|| { 34 | let mut r = String::new(); 35 | for _ in 0..REPETITIONS { 36 | r.push_str("a") 37 | } 38 | }); 39 | } 40 | 41 | #[bench] 42 | fn bench_push_char_one_byte(b: &mut Bencher) { 43 | b.bytes = REPETITIONS; 44 | b.iter(|| { 45 | let mut r = String::new(); 46 | for _ in 0..REPETITIONS { 47 | r.push('a') 48 | } 49 | }); 50 | } 51 | 52 | #[bench] 53 | fn bench_push_char_two_bytes(b: &mut Bencher) { 54 | b.bytes = REPETITIONS * 2; 55 | b.iter(|| { 56 | let mut r = String::new(); 57 | for _ in 0..REPETITIONS { 58 | r.push('â') 59 | } 60 | }); 61 | } 62 | 63 | #[bench] 64 | fn from_utf8_lossy_100_ascii(b: &mut Bencher) { 65 | let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ 66 | Lorem ipsum dolor sit amet, consectetur. "; 67 | 68 | assert_eq!(100, s.len()); 69 | b.iter(|| { 70 | let _ = String::from_utf8_lossy(s); 71 | }); 72 | } 73 | 74 | #[bench] 75 | fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { 76 | let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); 77 | assert_eq!(100, s.len()); 78 | b.iter(|| { 79 | let _ = String::from_utf8_lossy(s); 80 | }); 81 | } 82 | 83 | #[bench] 84 | fn from_utf8_lossy_invalid(b: &mut Bencher) { 85 | let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; 86 | b.iter(|| { 87 | let _ = String::from_utf8_lossy(s); 88 | }); 89 | } 90 | 91 | #[bench] 92 | fn from_utf8_lossy_100_invalid(b: &mut Bencher) { 93 | let s = repeat(0xf5).take(100).collect::>(); 94 | b.iter(|| { 95 | let _ = String::from_utf8_lossy(&s); 96 | }); 97 | } 98 | 99 | #[bench] 100 | fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { 101 | let s = "Hello there, the quick brown fox jumped over the lazy dog! \ 102 | Lorem ipsum dolor sit amet, consectetur. "; 103 | // ensure our operation produces an exact-size string before we benchmark it 104 | let mut r = String::with_capacity(s.len()); 105 | r.push_str(s); 106 | assert_eq!(r.len(), r.capacity()); 107 | b.iter(|| { 108 | let mut r = String::with_capacity(s.len()); 109 | r.push_str(s); 110 | r.shrink_to_fit(); 111 | r 112 | }); 113 | } 114 | 115 | #[bench] 116 | fn bench_from_str(b: &mut Bencher) { 117 | let s = "Hello there, the quick brown fox jumped over the lazy dog! \ 118 | Lorem ipsum dolor sit amet, consectetur. "; 119 | b.iter(|| String::from(s)) 120 | } 121 | 122 | #[bench] 123 | fn bench_from(b: &mut Bencher) { 124 | let s = "Hello there, the quick brown fox jumped over the lazy dog! \ 125 | Lorem ipsum dolor sit amet, consectetur. "; 126 | b.iter(|| String::from(s)) 127 | } 128 | 129 | #[bench] 130 | fn bench_to_string(b: &mut Bencher) { 131 | let s = "Hello there, the quick brown fox jumped over the lazy dog! \ 132 | Lorem ipsum dolor sit amet, consectetur. "; 133 | b.iter(|| s.to_string()) 134 | } 135 | -------------------------------------------------------------------------------- /crates/libcollections/benches/vec.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use test::Bencher; 12 | use std::iter::{FromIterator, repeat}; 13 | 14 | #[bench] 15 | fn bench_new(b: &mut Bencher) { 16 | b.iter(|| { 17 | let v: Vec = Vec::new(); 18 | assert_eq!(v.len(), 0); 19 | assert_eq!(v.capacity(), 0); 20 | }) 21 | } 22 | 23 | fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { 24 | b.bytes = src_len as u64; 25 | 26 | b.iter(|| { 27 | let v: Vec = Vec::with_capacity(src_len); 28 | assert_eq!(v.len(), 0); 29 | assert_eq!(v.capacity(), src_len); 30 | }) 31 | } 32 | 33 | #[bench] 34 | fn bench_with_capacity_0000(b: &mut Bencher) { 35 | do_bench_with_capacity(b, 0) 36 | } 37 | 38 | #[bench] 39 | fn bench_with_capacity_0010(b: &mut Bencher) { 40 | do_bench_with_capacity(b, 10) 41 | } 42 | 43 | #[bench] 44 | fn bench_with_capacity_0100(b: &mut Bencher) { 45 | do_bench_with_capacity(b, 100) 46 | } 47 | 48 | #[bench] 49 | fn bench_with_capacity_1000(b: &mut Bencher) { 50 | do_bench_with_capacity(b, 1000) 51 | } 52 | 53 | fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { 54 | b.bytes = src_len as u64; 55 | 56 | b.iter(|| { 57 | let dst = (0..src_len).collect::>(); 58 | assert_eq!(dst.len(), src_len); 59 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 60 | }) 61 | } 62 | 63 | #[bench] 64 | fn bench_from_fn_0000(b: &mut Bencher) { 65 | do_bench_from_fn(b, 0) 66 | } 67 | 68 | #[bench] 69 | fn bench_from_fn_0010(b: &mut Bencher) { 70 | do_bench_from_fn(b, 10) 71 | } 72 | 73 | #[bench] 74 | fn bench_from_fn_0100(b: &mut Bencher) { 75 | do_bench_from_fn(b, 100) 76 | } 77 | 78 | #[bench] 79 | fn bench_from_fn_1000(b: &mut Bencher) { 80 | do_bench_from_fn(b, 1000) 81 | } 82 | 83 | fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { 84 | b.bytes = src_len as u64; 85 | 86 | b.iter(|| { 87 | let dst: Vec = repeat(5).take(src_len).collect(); 88 | assert_eq!(dst.len(), src_len); 89 | assert!(dst.iter().all(|x| *x == 5)); 90 | }) 91 | } 92 | 93 | #[bench] 94 | fn bench_from_elem_0000(b: &mut Bencher) { 95 | do_bench_from_elem(b, 0) 96 | } 97 | 98 | #[bench] 99 | fn bench_from_elem_0010(b: &mut Bencher) { 100 | do_bench_from_elem(b, 10) 101 | } 102 | 103 | #[bench] 104 | fn bench_from_elem_0100(b: &mut Bencher) { 105 | do_bench_from_elem(b, 100) 106 | } 107 | 108 | #[bench] 109 | fn bench_from_elem_1000(b: &mut Bencher) { 110 | do_bench_from_elem(b, 1000) 111 | } 112 | 113 | fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { 114 | let src: Vec<_> = FromIterator::from_iter(0..src_len); 115 | 116 | b.bytes = src_len as u64; 117 | 118 | b.iter(|| { 119 | let dst = src.clone()[..].to_vec(); 120 | assert_eq!(dst.len(), src_len); 121 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 122 | }); 123 | } 124 | 125 | #[bench] 126 | fn bench_from_slice_0000(b: &mut Bencher) { 127 | do_bench_from_slice(b, 0) 128 | } 129 | 130 | #[bench] 131 | fn bench_from_slice_0010(b: &mut Bencher) { 132 | do_bench_from_slice(b, 10) 133 | } 134 | 135 | #[bench] 136 | fn bench_from_slice_0100(b: &mut Bencher) { 137 | do_bench_from_slice(b, 100) 138 | } 139 | 140 | #[bench] 141 | fn bench_from_slice_1000(b: &mut Bencher) { 142 | do_bench_from_slice(b, 1000) 143 | } 144 | 145 | fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { 146 | let src: Vec<_> = FromIterator::from_iter(0..src_len); 147 | 148 | b.bytes = src_len as u64; 149 | 150 | b.iter(|| { 151 | let dst: Vec<_> = FromIterator::from_iter(src.clone()); 152 | assert_eq!(dst.len(), src_len); 153 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 154 | }); 155 | } 156 | 157 | #[bench] 158 | fn bench_from_iter_0000(b: &mut Bencher) { 159 | do_bench_from_iter(b, 0) 160 | } 161 | 162 | #[bench] 163 | fn bench_from_iter_0010(b: &mut Bencher) { 164 | do_bench_from_iter(b, 10) 165 | } 166 | 167 | #[bench] 168 | fn bench_from_iter_0100(b: &mut Bencher) { 169 | do_bench_from_iter(b, 100) 170 | } 171 | 172 | #[bench] 173 | fn bench_from_iter_1000(b: &mut Bencher) { 174 | do_bench_from_iter(b, 1000) 175 | } 176 | 177 | fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { 178 | let dst: Vec<_> = FromIterator::from_iter(0..dst_len); 179 | let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); 180 | 181 | b.bytes = src_len as u64; 182 | 183 | b.iter(|| { 184 | let mut dst = dst.clone(); 185 | dst.extend(src.clone()); 186 | assert_eq!(dst.len(), dst_len + src_len); 187 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 188 | }); 189 | } 190 | 191 | #[bench] 192 | fn bench_extend_0000_0000(b: &mut Bencher) { 193 | do_bench_extend(b, 0, 0) 194 | } 195 | 196 | #[bench] 197 | fn bench_extend_0000_0010(b: &mut Bencher) { 198 | do_bench_extend(b, 0, 10) 199 | } 200 | 201 | #[bench] 202 | fn bench_extend_0000_0100(b: &mut Bencher) { 203 | do_bench_extend(b, 0, 100) 204 | } 205 | 206 | #[bench] 207 | fn bench_extend_0000_1000(b: &mut Bencher) { 208 | do_bench_extend(b, 0, 1000) 209 | } 210 | 211 | #[bench] 212 | fn bench_extend_0010_0010(b: &mut Bencher) { 213 | do_bench_extend(b, 10, 10) 214 | } 215 | 216 | #[bench] 217 | fn bench_extend_0100_0100(b: &mut Bencher) { 218 | do_bench_extend(b, 100, 100) 219 | } 220 | 221 | #[bench] 222 | fn bench_extend_1000_1000(b: &mut Bencher) { 223 | do_bench_extend(b, 1000, 1000) 224 | } 225 | 226 | fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { 227 | let dst: Vec<_> = FromIterator::from_iter(0..dst_len); 228 | let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); 229 | 230 | b.bytes = src_len as u64; 231 | 232 | b.iter(|| { 233 | let mut dst = dst.clone(); 234 | dst.extend_from_slice(&src); 235 | assert_eq!(dst.len(), dst_len + src_len); 236 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 237 | }); 238 | } 239 | 240 | #[bench] 241 | fn bench_push_all_0000_0000(b: &mut Bencher) { 242 | do_bench_push_all(b, 0, 0) 243 | } 244 | 245 | #[bench] 246 | fn bench_push_all_0000_0010(b: &mut Bencher) { 247 | do_bench_push_all(b, 0, 10) 248 | } 249 | 250 | #[bench] 251 | fn bench_push_all_0000_0100(b: &mut Bencher) { 252 | do_bench_push_all(b, 0, 100) 253 | } 254 | 255 | #[bench] 256 | fn bench_push_all_0000_1000(b: &mut Bencher) { 257 | do_bench_push_all(b, 0, 1000) 258 | } 259 | 260 | #[bench] 261 | fn bench_push_all_0010_0010(b: &mut Bencher) { 262 | do_bench_push_all(b, 10, 10) 263 | } 264 | 265 | #[bench] 266 | fn bench_push_all_0100_0100(b: &mut Bencher) { 267 | do_bench_push_all(b, 100, 100) 268 | } 269 | 270 | #[bench] 271 | fn bench_push_all_1000_1000(b: &mut Bencher) { 272 | do_bench_push_all(b, 1000, 1000) 273 | } 274 | 275 | fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { 276 | let dst: Vec<_> = FromIterator::from_iter(0..dst_len); 277 | let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); 278 | 279 | b.bytes = src_len as u64; 280 | 281 | b.iter(|| { 282 | let mut dst = dst.clone(); 283 | dst.extend(src.clone()); 284 | assert_eq!(dst.len(), dst_len + src_len); 285 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 286 | }); 287 | } 288 | 289 | #[bench] 290 | fn bench_push_all_move_0000_0000(b: &mut Bencher) { 291 | do_bench_push_all_move(b, 0, 0) 292 | } 293 | 294 | #[bench] 295 | fn bench_push_all_move_0000_0010(b: &mut Bencher) { 296 | do_bench_push_all_move(b, 0, 10) 297 | } 298 | 299 | #[bench] 300 | fn bench_push_all_move_0000_0100(b: &mut Bencher) { 301 | do_bench_push_all_move(b, 0, 100) 302 | } 303 | 304 | #[bench] 305 | fn bench_push_all_move_0000_1000(b: &mut Bencher) { 306 | do_bench_push_all_move(b, 0, 1000) 307 | } 308 | 309 | #[bench] 310 | fn bench_push_all_move_0010_0010(b: &mut Bencher) { 311 | do_bench_push_all_move(b, 10, 10) 312 | } 313 | 314 | #[bench] 315 | fn bench_push_all_move_0100_0100(b: &mut Bencher) { 316 | do_bench_push_all_move(b, 100, 100) 317 | } 318 | 319 | #[bench] 320 | fn bench_push_all_move_1000_1000(b: &mut Bencher) { 321 | do_bench_push_all_move(b, 1000, 1000) 322 | } 323 | 324 | fn do_bench_clone(b: &mut Bencher, src_len: usize) { 325 | let src: Vec = FromIterator::from_iter(0..src_len); 326 | 327 | b.bytes = src_len as u64; 328 | 329 | b.iter(|| { 330 | let dst = src.clone(); 331 | assert_eq!(dst.len(), src_len); 332 | assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); 333 | }); 334 | } 335 | 336 | #[bench] 337 | fn bench_clone_0000(b: &mut Bencher) { 338 | do_bench_clone(b, 0) 339 | } 340 | 341 | #[bench] 342 | fn bench_clone_0010(b: &mut Bencher) { 343 | do_bench_clone(b, 10) 344 | } 345 | 346 | #[bench] 347 | fn bench_clone_0100(b: &mut Bencher) { 348 | do_bench_clone(b, 100) 349 | } 350 | 351 | #[bench] 352 | fn bench_clone_1000(b: &mut Bencher) { 353 | do_bench_clone(b, 1000) 354 | } 355 | 356 | fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { 357 | let dst: Vec<_> = FromIterator::from_iter(0..src_len); 358 | let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); 359 | 360 | b.bytes = (times * src_len) as u64; 361 | 362 | b.iter(|| { 363 | let mut dst = dst.clone(); 364 | 365 | for _ in 0..times { 366 | dst.clone_from(&src); 367 | 368 | assert_eq!(dst.len(), src_len); 369 | assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); 370 | } 371 | }); 372 | } 373 | 374 | #[bench] 375 | fn bench_clone_from_01_0000_0000(b: &mut Bencher) { 376 | do_bench_clone_from(b, 1, 0, 0) 377 | } 378 | 379 | #[bench] 380 | fn bench_clone_from_01_0000_0010(b: &mut Bencher) { 381 | do_bench_clone_from(b, 1, 0, 10) 382 | } 383 | 384 | #[bench] 385 | fn bench_clone_from_01_0000_0100(b: &mut Bencher) { 386 | do_bench_clone_from(b, 1, 0, 100) 387 | } 388 | 389 | #[bench] 390 | fn bench_clone_from_01_0000_1000(b: &mut Bencher) { 391 | do_bench_clone_from(b, 1, 0, 1000) 392 | } 393 | 394 | #[bench] 395 | fn bench_clone_from_01_0010_0010(b: &mut Bencher) { 396 | do_bench_clone_from(b, 1, 10, 10) 397 | } 398 | 399 | #[bench] 400 | fn bench_clone_from_01_0100_0100(b: &mut Bencher) { 401 | do_bench_clone_from(b, 1, 100, 100) 402 | } 403 | 404 | #[bench] 405 | fn bench_clone_from_01_1000_1000(b: &mut Bencher) { 406 | do_bench_clone_from(b, 1, 1000, 1000) 407 | } 408 | 409 | #[bench] 410 | fn bench_clone_from_01_0010_0100(b: &mut Bencher) { 411 | do_bench_clone_from(b, 1, 10, 100) 412 | } 413 | 414 | #[bench] 415 | fn bench_clone_from_01_0100_1000(b: &mut Bencher) { 416 | do_bench_clone_from(b, 1, 100, 1000) 417 | } 418 | 419 | #[bench] 420 | fn bench_clone_from_01_0010_0000(b: &mut Bencher) { 421 | do_bench_clone_from(b, 1, 10, 0) 422 | } 423 | 424 | #[bench] 425 | fn bench_clone_from_01_0100_0010(b: &mut Bencher) { 426 | do_bench_clone_from(b, 1, 100, 10) 427 | } 428 | 429 | #[bench] 430 | fn bench_clone_from_01_1000_0100(b: &mut Bencher) { 431 | do_bench_clone_from(b, 1, 1000, 100) 432 | } 433 | 434 | #[bench] 435 | fn bench_clone_from_10_0000_0000(b: &mut Bencher) { 436 | do_bench_clone_from(b, 10, 0, 0) 437 | } 438 | 439 | #[bench] 440 | fn bench_clone_from_10_0000_0010(b: &mut Bencher) { 441 | do_bench_clone_from(b, 10, 0, 10) 442 | } 443 | 444 | #[bench] 445 | fn bench_clone_from_10_0000_0100(b: &mut Bencher) { 446 | do_bench_clone_from(b, 10, 0, 100) 447 | } 448 | 449 | #[bench] 450 | fn bench_clone_from_10_0000_1000(b: &mut Bencher) { 451 | do_bench_clone_from(b, 10, 0, 1000) 452 | } 453 | 454 | #[bench] 455 | fn bench_clone_from_10_0010_0010(b: &mut Bencher) { 456 | do_bench_clone_from(b, 10, 10, 10) 457 | } 458 | 459 | #[bench] 460 | fn bench_clone_from_10_0100_0100(b: &mut Bencher) { 461 | do_bench_clone_from(b, 10, 100, 100) 462 | } 463 | 464 | #[bench] 465 | fn bench_clone_from_10_1000_1000(b: &mut Bencher) { 466 | do_bench_clone_from(b, 10, 1000, 1000) 467 | } 468 | 469 | #[bench] 470 | fn bench_clone_from_10_0010_0100(b: &mut Bencher) { 471 | do_bench_clone_from(b, 10, 10, 100) 472 | } 473 | 474 | #[bench] 475 | fn bench_clone_from_10_0100_1000(b: &mut Bencher) { 476 | do_bench_clone_from(b, 10, 100, 1000) 477 | } 478 | 479 | #[bench] 480 | fn bench_clone_from_10_0010_0000(b: &mut Bencher) { 481 | do_bench_clone_from(b, 10, 10, 0) 482 | } 483 | 484 | #[bench] 485 | fn bench_clone_from_10_0100_0010(b: &mut Bencher) { 486 | do_bench_clone_from(b, 10, 100, 10) 487 | } 488 | 489 | #[bench] 490 | fn bench_clone_from_10_1000_0100(b: &mut Bencher) { 491 | do_bench_clone_from(b, 10, 1000, 100) 492 | } 493 | -------------------------------------------------------------------------------- /crates/libcollections/benches/vec_deque.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::collections::VecDeque; 12 | use test::{Bencher, black_box}; 13 | 14 | #[bench] 15 | fn bench_new(b: &mut Bencher) { 16 | b.iter(|| { 17 | let ring: VecDeque = VecDeque::new(); 18 | black_box(ring); 19 | }) 20 | } 21 | 22 | #[bench] 23 | fn bench_grow_1025(b: &mut Bencher) { 24 | b.iter(|| { 25 | let mut deq = VecDeque::new(); 26 | for i in 0..1025 { 27 | deq.push_front(i); 28 | } 29 | black_box(deq); 30 | }) 31 | } 32 | 33 | #[bench] 34 | fn bench_iter_1000(b: &mut Bencher) { 35 | let ring: VecDeque<_> = (0..1000).collect(); 36 | 37 | b.iter(|| { 38 | let mut sum = 0; 39 | for &i in &ring { 40 | sum += i; 41 | } 42 | black_box(sum); 43 | }) 44 | } 45 | 46 | #[bench] 47 | fn bench_mut_iter_1000(b: &mut Bencher) { 48 | let mut ring: VecDeque<_> = (0..1000).collect(); 49 | 50 | b.iter(|| { 51 | let mut sum = 0; 52 | for i in &mut ring { 53 | sum += *i; 54 | } 55 | black_box(sum); 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /crates/libcollections/borrow.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! A module for working with borrowed data. 12 | 13 | #![stable(feature = "rust1", since = "1.0.0")] 14 | 15 | use core::cmp::Ordering; 16 | use core::hash::{Hash, Hasher}; 17 | use core::ops::{Add, AddAssign, Deref}; 18 | 19 | use fmt; 20 | use string::String; 21 | 22 | use self::Cow::*; 23 | 24 | #[stable(feature = "rust1", since = "1.0.0")] 25 | pub use core::borrow::{Borrow, BorrowMut}; 26 | 27 | #[stable(feature = "rust1", since = "1.0.0")] 28 | impl<'a, B: ?Sized> Borrow for Cow<'a, B> 29 | where B: ToOwned, 30 | ::Owned: 'a 31 | { 32 | fn borrow(&self) -> &B { 33 | &**self 34 | } 35 | } 36 | 37 | /// A generalization of `Clone` to borrowed data. 38 | /// 39 | /// Some types make it possible to go from borrowed to owned, usually by 40 | /// implementing the `Clone` trait. But `Clone` works only for going from `&T` 41 | /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data 42 | /// from any borrow of a given type. 43 | #[stable(feature = "rust1", since = "1.0.0")] 44 | pub trait ToOwned { 45 | #[stable(feature = "rust1", since = "1.0.0")] 46 | type Owned: Borrow; 47 | 48 | /// Creates owned data from borrowed data, usually by cloning. 49 | /// 50 | /// # Examples 51 | /// 52 | /// Basic usage: 53 | /// 54 | /// ``` 55 | /// let s: &str = "a"; 56 | /// let ss: String = s.to_owned(); 57 | /// 58 | /// let v: &[i32] = &[1, 2]; 59 | /// let vv: Vec = v.to_owned(); 60 | /// ``` 61 | #[stable(feature = "rust1", since = "1.0.0")] 62 | fn to_owned(&self) -> Self::Owned; 63 | 64 | /// Uses borrowed data to replace owned data, usually by cloning. 65 | /// 66 | /// This is borrow-generalized version of `Clone::clone_from`. 67 | /// 68 | /// # Examples 69 | /// 70 | /// Basic usage: 71 | /// 72 | /// ``` 73 | /// # #![feature(toowned_clone_into)] 74 | /// let mut s: String = String::new(); 75 | /// "hello".clone_into(&mut s); 76 | /// 77 | /// let mut v: Vec = Vec::new(); 78 | /// [1, 2][..].clone_into(&mut v); 79 | /// ``` 80 | #[unstable(feature = "toowned_clone_into", 81 | reason = "recently added", 82 | issue = "41263")] 83 | fn clone_into(&self, target: &mut Self::Owned) { 84 | *target = self.to_owned(); 85 | } 86 | } 87 | 88 | #[stable(feature = "rust1", since = "1.0.0")] 89 | impl ToOwned for T 90 | where T: Clone 91 | { 92 | type Owned = T; 93 | fn to_owned(&self) -> T { 94 | self.clone() 95 | } 96 | 97 | fn clone_into(&self, target: &mut T) { 98 | target.clone_from(self); 99 | } 100 | } 101 | 102 | /// A clone-on-write smart pointer. 103 | /// 104 | /// The type `Cow` is a smart pointer providing clone-on-write functionality: it 105 | /// can enclose and provide immutable access to borrowed data, and clone the 106 | /// data lazily when mutation or ownership is required. The type is designed to 107 | /// work with general borrowed data via the `Borrow` trait. 108 | /// 109 | /// `Cow` implements `Deref`, which means that you can call 110 | /// non-mutating methods directly on the data it encloses. If mutation 111 | /// is desired, `to_mut` will obtain a mutable reference to an owned 112 | /// value, cloning if necessary. 113 | /// 114 | /// # Examples 115 | /// 116 | /// ``` 117 | /// use std::borrow::Cow; 118 | /// 119 | /// fn abs_all(input: &mut Cow<[i32]>) { 120 | /// for i in 0..input.len() { 121 | /// let v = input[i]; 122 | /// if v < 0 { 123 | /// // Clones into a vector if not already owned. 124 | /// input.to_mut()[i] = -v; 125 | /// } 126 | /// } 127 | /// } 128 | /// 129 | /// // No clone occurs because `input` doesn't need to be mutated. 130 | /// let slice = [0, 1, 2]; 131 | /// let mut input = Cow::from(&slice[..]); 132 | /// abs_all(&mut input); 133 | /// 134 | /// // Clone occurs because `input` needs to be mutated. 135 | /// let slice = [-1, 0, 1]; 136 | /// let mut input = Cow::from(&slice[..]); 137 | /// abs_all(&mut input); 138 | /// 139 | /// // No clone occurs because `input` is already owned. 140 | /// let mut input = Cow::from(vec![-1, 0, 1]); 141 | /// abs_all(&mut input); 142 | /// ``` 143 | #[stable(feature = "rust1", since = "1.0.0")] 144 | pub enum Cow<'a, B: ?Sized + 'a> 145 | where B: ToOwned 146 | { 147 | /// Borrowed data. 148 | #[stable(feature = "rust1", since = "1.0.0")] 149 | Borrowed(#[stable(feature = "rust1", since = "1.0.0")] 150 | &'a B), 151 | 152 | /// Owned data. 153 | #[stable(feature = "rust1", since = "1.0.0")] 154 | Owned(#[stable(feature = "rust1", since = "1.0.0")] 155 | ::Owned), 156 | } 157 | 158 | #[stable(feature = "rust1", since = "1.0.0")] 159 | impl<'a, B: ?Sized> Clone for Cow<'a, B> 160 | where B: ToOwned 161 | { 162 | fn clone(&self) -> Cow<'a, B> { 163 | match *self { 164 | Borrowed(b) => Borrowed(b), 165 | Owned(ref o) => { 166 | let b: &B = o.borrow(); 167 | Owned(b.to_owned()) 168 | } 169 | } 170 | } 171 | 172 | fn clone_from(&mut self, source: &Cow<'a, B>) { 173 | if let Owned(ref mut dest) = *self { 174 | if let Owned(ref o) = *source { 175 | o.borrow().clone_into(dest); 176 | return; 177 | } 178 | } 179 | 180 | *self = source.clone(); 181 | } 182 | } 183 | 184 | impl<'a, B: ?Sized> Cow<'a, B> 185 | where B: ToOwned 186 | { 187 | /// Acquires a mutable reference to the owned form of the data. 188 | /// 189 | /// Clones the data if it is not already owned. 190 | /// 191 | /// # Examples 192 | /// 193 | /// ``` 194 | /// use std::borrow::Cow; 195 | /// 196 | /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); 197 | /// 198 | /// let hello = cow.to_mut(); 199 | /// 200 | /// assert_eq!(hello, &[1, 2, 3]); 201 | /// ``` 202 | #[stable(feature = "rust1", since = "1.0.0")] 203 | pub fn to_mut(&mut self) -> &mut ::Owned { 204 | match *self { 205 | Borrowed(borrowed) => { 206 | *self = Owned(borrowed.to_owned()); 207 | match *self { 208 | Borrowed(..) => unreachable!(), 209 | Owned(ref mut owned) => owned, 210 | } 211 | } 212 | Owned(ref mut owned) => owned, 213 | } 214 | } 215 | 216 | /// Extracts the owned data. 217 | /// 218 | /// Clones the data if it is not already owned. 219 | /// 220 | /// # Examples 221 | /// 222 | /// ``` 223 | /// use std::borrow::Cow; 224 | /// 225 | /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); 226 | /// 227 | /// let hello = cow.into_owned(); 228 | /// 229 | /// assert_eq!(vec![1, 2, 3], hello); 230 | /// ``` 231 | #[stable(feature = "rust1", since = "1.0.0")] 232 | pub fn into_owned(self) -> ::Owned { 233 | match self { 234 | Borrowed(borrowed) => borrowed.to_owned(), 235 | Owned(owned) => owned, 236 | } 237 | } 238 | } 239 | 240 | #[stable(feature = "rust1", since = "1.0.0")] 241 | impl<'a, B: ?Sized> Deref for Cow<'a, B> 242 | where B: ToOwned 243 | { 244 | type Target = B; 245 | 246 | fn deref(&self) -> &B { 247 | match *self { 248 | Borrowed(borrowed) => borrowed, 249 | Owned(ref owned) => owned.borrow(), 250 | } 251 | } 252 | } 253 | 254 | #[stable(feature = "rust1", since = "1.0.0")] 255 | impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {} 256 | 257 | #[stable(feature = "rust1", since = "1.0.0")] 258 | impl<'a, B: ?Sized> Ord for Cow<'a, B> 259 | where B: Ord + ToOwned 260 | { 261 | #[inline] 262 | fn cmp(&self, other: &Cow<'a, B>) -> Ordering { 263 | Ord::cmp(&**self, &**other) 264 | } 265 | } 266 | 267 | #[stable(feature = "rust1", since = "1.0.0")] 268 | impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> 269 | where B: PartialEq + ToOwned, 270 | C: ToOwned 271 | { 272 | #[inline] 273 | fn eq(&self, other: &Cow<'b, C>) -> bool { 274 | PartialEq::eq(&**self, &**other) 275 | } 276 | } 277 | 278 | #[stable(feature = "rust1", since = "1.0.0")] 279 | impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> 280 | where B: PartialOrd + ToOwned 281 | { 282 | #[inline] 283 | fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { 284 | PartialOrd::partial_cmp(&**self, &**other) 285 | } 286 | } 287 | 288 | #[stable(feature = "rust1", since = "1.0.0")] 289 | impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> 290 | where B: fmt::Debug + ToOwned, 291 | ::Owned: fmt::Debug 292 | { 293 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 294 | match *self { 295 | Borrowed(ref b) => fmt::Debug::fmt(b, f), 296 | Owned(ref o) => fmt::Debug::fmt(o, f), 297 | } 298 | } 299 | } 300 | 301 | #[stable(feature = "rust1", since = "1.0.0")] 302 | impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> 303 | where B: fmt::Display + ToOwned, 304 | ::Owned: fmt::Display 305 | { 306 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 307 | match *self { 308 | Borrowed(ref b) => fmt::Display::fmt(b, f), 309 | Owned(ref o) => fmt::Display::fmt(o, f), 310 | } 311 | } 312 | } 313 | 314 | #[stable(feature = "default", since = "1.11.0")] 315 | impl<'a, B: ?Sized> Default for Cow<'a, B> 316 | where B: ToOwned, 317 | ::Owned: Default 318 | { 319 | /// Creates an owned Cow<'a, B> with the default value for the contained owned value. 320 | fn default() -> Cow<'a, B> { 321 | Owned(::Owned::default()) 322 | } 323 | } 324 | 325 | #[stable(feature = "rust1", since = "1.0.0")] 326 | impl<'a, B: ?Sized> Hash for Cow<'a, B> 327 | where B: Hash + ToOwned 328 | { 329 | #[inline] 330 | fn hash(&self, state: &mut H) { 331 | Hash::hash(&**self, state) 332 | } 333 | } 334 | 335 | #[stable(feature = "rust1", since = "1.0.0")] 336 | #[allow(deprecated)] 337 | impl<'a, T: ?Sized + ToOwned> AsRef for Cow<'a, T> { 338 | fn as_ref(&self) -> &T { 339 | self 340 | } 341 | } 342 | 343 | #[stable(feature = "cow_add", since = "1.14.0")] 344 | impl<'a> Add<&'a str> for Cow<'a, str> { 345 | type Output = Cow<'a, str>; 346 | 347 | #[inline] 348 | fn add(mut self, rhs: &'a str) -> Self::Output { 349 | self += rhs; 350 | self 351 | } 352 | } 353 | 354 | #[stable(feature = "cow_add", since = "1.14.0")] 355 | impl<'a> Add> for Cow<'a, str> { 356 | type Output = Cow<'a, str>; 357 | 358 | #[inline] 359 | fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { 360 | self += rhs; 361 | self 362 | } 363 | } 364 | 365 | #[stable(feature = "cow_add", since = "1.14.0")] 366 | impl<'a> AddAssign<&'a str> for Cow<'a, str> { 367 | fn add_assign(&mut self, rhs: &'a str) { 368 | if self.is_empty() { 369 | *self = Cow::Borrowed(rhs) 370 | } else if rhs.is_empty() { 371 | return; 372 | } else { 373 | if let Cow::Borrowed(lhs) = *self { 374 | let mut s = String::with_capacity(lhs.len() + rhs.len()); 375 | s.push_str(lhs); 376 | *self = Cow::Owned(s); 377 | } 378 | self.to_mut().push_str(rhs); 379 | } 380 | } 381 | } 382 | 383 | #[stable(feature = "cow_add", since = "1.14.0")] 384 | impl<'a> AddAssign> for Cow<'a, str> { 385 | fn add_assign(&mut self, rhs: Cow<'a, str>) { 386 | if self.is_empty() { 387 | *self = rhs 388 | } else if rhs.is_empty() { 389 | return; 390 | } else { 391 | if let Cow::Borrowed(lhs) = *self { 392 | let mut s = String::with_capacity(lhs.len() + rhs.len()); 393 | s.push_str(lhs); 394 | *self = Cow::Owned(s); 395 | } 396 | self.to_mut().push_str(&rhs); 397 | } 398 | } 399 | } 400 | -------------------------------------------------------------------------------- /crates/libcollections/btree/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | mod node; 12 | mod search; 13 | pub mod map; 14 | pub mod set; 15 | 16 | #[doc(hidden)] 17 | trait Recover { 18 | type Key; 19 | 20 | fn get(&self, key: &Q) -> Option<&Self::Key>; 21 | fn take(&mut self, key: &Q) -> Option; 22 | fn replace(&mut self, key: Self::Key) -> Option; 23 | } 24 | -------------------------------------------------------------------------------- /crates/libcollections/btree/search.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use core::cmp::Ordering; 12 | 13 | use borrow::Borrow; 14 | 15 | use super::node::{Handle, NodeRef, marker}; 16 | 17 | use super::node::ForceResult::*; 18 | use self::SearchResult::*; 19 | 20 | pub enum SearchResult { 21 | Found(Handle, marker::KV>), 22 | GoDown(Handle, marker::Edge>) 23 | } 24 | 25 | pub fn search_tree( 26 | mut node: NodeRef, 27 | key: &Q 28 | ) -> SearchResult 29 | where Q: Ord, K: Borrow { 30 | 31 | loop { 32 | match search_node(node, key) { 33 | Found(handle) => return Found(handle), 34 | GoDown(handle) => match handle.force() { 35 | Leaf(leaf) => return GoDown(leaf), 36 | Internal(internal) => { 37 | node = internal.descend(); 38 | continue; 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | pub fn search_node( 46 | node: NodeRef, 47 | key: &Q 48 | ) -> SearchResult 49 | where Q: Ord, K: Borrow { 50 | 51 | match search_linear(&node, key) { 52 | (idx, true) => Found( 53 | Handle::new_kv(node, idx) 54 | ), 55 | (idx, false) => SearchResult::GoDown( 56 | Handle::new_edge(node, idx) 57 | ) 58 | } 59 | } 60 | 61 | pub fn search_linear( 62 | node: &NodeRef, 63 | key: &Q 64 | ) -> (usize, bool) 65 | where Q: Ord, K: Borrow { 66 | 67 | for (i, k) in node.keys().iter().enumerate() { 68 | match key.cmp(k.borrow()) { 69 | Ordering::Greater => {}, 70 | Ordering::Equal => return (i, true), 71 | Ordering::Less => return (i, false) 72 | } 73 | } 74 | (node.keys().len(), false) 75 | } 76 | -------------------------------------------------------------------------------- /crates/libcollections/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Collection types. 12 | //! 13 | //! See [`std::collections`](../std/collections/index.html) for a detailed 14 | //! discussion of collections in Rust. 15 | 16 | #![crate_name = "collections"] 17 | #![crate_type = "rlib"] 18 | #![unstable(feature = "collections", 19 | reason = "library is unlikely to be stabilized with the current \ 20 | layout and name, use std::collections instead", 21 | issue = "27783")] 22 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 23 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", 24 | html_root_url = "https://doc.rust-lang.org/nightly/", 25 | html_playground_url = "https://play.rust-lang.org/", 26 | issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", 27 | test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] 28 | 29 | #![cfg_attr(test, allow(deprecated))] // rand 30 | #![deny(warnings)] 31 | #![deny(missing_debug_implementations)] 32 | 33 | #![feature(alloc)] 34 | #![feature(allow_internal_unstable)] 35 | #![feature(box_patterns)] 36 | #![feature(box_syntax)] 37 | #![cfg_attr(not(test), feature(char_escape_debug))] 38 | #![cfg_attr(not(test), feature(core_float))] 39 | #![feature(core_intrinsics)] 40 | #![feature(dropck_eyepatch)] 41 | #![feature(exact_size_is_empty)] 42 | #![feature(fmt_internals)] 43 | #![feature(fused)] 44 | #![feature(generic_param_attrs)] 45 | #![feature(heap_api)] 46 | #![feature(i128_type)] 47 | #![feature(inclusive_range)] 48 | #![feature(lang_items)] 49 | #![feature(manually_drop)] 50 | #![feature(nonzero)] 51 | #![feature(pattern)] 52 | #![feature(placement_in)] 53 | #![feature(placement_in_syntax)] 54 | #![feature(placement_new_protocol)] 55 | #![feature(shared)] 56 | #![feature(slice_get_slice)] 57 | #![feature(slice_patterns)] 58 | #![cfg_attr(not(test), feature(slice_rotate))] 59 | #![feature(slice_rsplit)] 60 | #![cfg_attr(not(test), feature(sort_unstable))] 61 | #![feature(specialization)] 62 | #![feature(staged_api)] 63 | #![feature(str_internals)] 64 | #![feature(str_box_extras)] 65 | #![feature(str_mut_extras)] 66 | #![feature(trusted_len)] 67 | #![feature(unicode)] 68 | #![feature(unique)] 69 | #![cfg_attr(not(test), feature(str_checked_slicing))] 70 | #![cfg_attr(test, feature(rand, test))] 71 | #![feature(offset_to)] 72 | 73 | #![no_std] 74 | 75 | extern crate std_unicode; 76 | extern crate alloc; 77 | 78 | #[cfg(test)] 79 | #[macro_use] 80 | extern crate std; 81 | #[cfg(test)] 82 | extern crate test; 83 | 84 | #[doc(no_inline)] 85 | pub use binary_heap::BinaryHeap; 86 | #[doc(no_inline)] 87 | pub use btree_map::BTreeMap; 88 | #[doc(no_inline)] 89 | pub use btree_set::BTreeSet; 90 | #[doc(no_inline)] 91 | pub use linked_list::LinkedList; 92 | #[doc(no_inline)] 93 | pub use vec_deque::VecDeque; 94 | #[doc(no_inline)] 95 | pub use string::String; 96 | #[doc(no_inline)] 97 | pub use vec::Vec; 98 | 99 | // Needed for the vec! macro 100 | pub use alloc::boxed; 101 | 102 | #[macro_use] 103 | mod macros; 104 | 105 | pub mod binary_heap; 106 | mod btree; 107 | pub mod borrow; 108 | pub mod fmt; 109 | pub mod linked_list; 110 | pub mod range; 111 | pub mod slice; 112 | pub mod str; 113 | pub mod string; 114 | pub mod vec; 115 | pub mod vec_deque; 116 | 117 | #[stable(feature = "rust1", since = "1.0.0")] 118 | pub mod btree_map { 119 | //! A map based on a B-Tree. 120 | #[stable(feature = "rust1", since = "1.0.0")] 121 | pub use btree::map::*; 122 | } 123 | 124 | #[stable(feature = "rust1", since = "1.0.0")] 125 | pub mod btree_set { 126 | //! A set based on a B-Tree. 127 | #[stable(feature = "rust1", since = "1.0.0")] 128 | pub use btree::set::*; 129 | } 130 | 131 | #[cfg(not(test))] 132 | mod std { 133 | pub use core::ops; // RangeFull 134 | } 135 | 136 | /// An endpoint of a range of keys. 137 | /// 138 | /// # Examples 139 | /// 140 | /// `Bound`s are range endpoints: 141 | /// 142 | /// ``` 143 | /// #![feature(collections_range)] 144 | /// 145 | /// use std::collections::range::RangeArgument; 146 | /// use std::collections::Bound::*; 147 | /// 148 | /// assert_eq!((..100).start(), Unbounded); 149 | /// assert_eq!((1..12).start(), Included(&1)); 150 | /// assert_eq!((1..12).end(), Excluded(&12)); 151 | /// ``` 152 | /// 153 | /// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. 154 | /// Note that in most cases, it's better to use range syntax (`1..5`) instead. 155 | /// 156 | /// ``` 157 | /// use std::collections::BTreeMap; 158 | /// use std::collections::Bound::{Excluded, Included, Unbounded}; 159 | /// 160 | /// let mut map = BTreeMap::new(); 161 | /// map.insert(3, "a"); 162 | /// map.insert(5, "b"); 163 | /// map.insert(8, "c"); 164 | /// 165 | /// for (key, value) in map.range((Excluded(3), Included(8))) { 166 | /// println!("{}: {}", key, value); 167 | /// } 168 | /// 169 | /// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); 170 | /// ``` 171 | /// 172 | /// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range 173 | #[stable(feature = "collections_bound", since = "1.17.0")] 174 | #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] 175 | pub enum Bound { 176 | /// An inclusive bound. 177 | #[stable(feature = "collections_bound", since = "1.17.0")] 178 | Included(T), 179 | /// An exclusive bound. 180 | #[stable(feature = "collections_bound", since = "1.17.0")] 181 | Excluded(T), 182 | /// An infinite endpoint. Indicates that there is no bound in this direction. 183 | #[stable(feature = "collections_bound", since = "1.17.0")] 184 | Unbounded, 185 | } 186 | 187 | /// An intermediate trait for specialization of `Extend`. 188 | #[doc(hidden)] 189 | trait SpecExtend { 190 | /// Extends `self` with the contents of the given iterator. 191 | fn spec_extend(&mut self, iter: I); 192 | } 193 | -------------------------------------------------------------------------------- /crates/libcollections/macros.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | /// Creates a `Vec` containing the arguments. 12 | /// 13 | /// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. 14 | /// There are two forms of this macro: 15 | /// 16 | /// - Create a `Vec` containing a given list of elements: 17 | /// 18 | /// ``` 19 | /// let v = vec![1, 2, 3]; 20 | /// assert_eq!(v[0], 1); 21 | /// assert_eq!(v[1], 2); 22 | /// assert_eq!(v[2], 3); 23 | /// ``` 24 | /// 25 | /// - Create a `Vec` from a given element and size: 26 | /// 27 | /// ``` 28 | /// let v = vec![1; 3]; 29 | /// assert_eq!(v, [1, 1, 1]); 30 | /// ``` 31 | /// 32 | /// Note that unlike array expressions this syntax supports all elements 33 | /// which implement `Clone` and the number of elements doesn't have to be 34 | /// a constant. 35 | /// 36 | /// This will use `clone()` to duplicate an expression, so one should be careful 37 | /// using this with types having a nonstandard `Clone` implementation. For 38 | /// example, `vec![Rc::new(1); 5]` will create a vector of five references 39 | /// to the same boxed integer value, not five references pointing to independently 40 | /// boxed integers. 41 | #[cfg(not(test))] 42 | #[macro_export] 43 | #[stable(feature = "rust1", since = "1.0.0")] 44 | #[allow_internal_unstable] 45 | macro_rules! vec { 46 | ($elem:expr; $n:expr) => ( 47 | $crate::vec::from_elem($elem, $n) 48 | ); 49 | ($($x:expr),*) => ( 50 | <[_]>::into_vec(box [$($x),*]) 51 | ); 52 | ($($x:expr,)*) => (vec![$($x),*]) 53 | } 54 | 55 | // HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is 56 | // required for this macro definition, is not available. Instead use the 57 | // `slice::into_vec` function which is only available with cfg(test) 58 | // NB see the slice::hack module in slice.rs for more information 59 | #[cfg(test)] 60 | macro_rules! vec { 61 | ($elem:expr; $n:expr) => ( 62 | $crate::vec::from_elem($elem, $n) 63 | ); 64 | ($($x:expr),*) => ( 65 | $crate::slice::into_vec(box [$($x),*]) 66 | ); 67 | ($($x:expr,)*) => (vec![$($x),*]) 68 | } 69 | 70 | /// Use the syntax described in `std::fmt` to create a value of type `String`. 71 | /// See [`std::fmt`][fmt] for more information. 72 | /// 73 | /// [fmt]: ../std/fmt/index.html 74 | /// 75 | /// # Panics 76 | /// 77 | /// `format!` panics if a formatting trait implementation returns an error. 78 | /// This indicates an incorrect implementation 79 | /// since `fmt::Write for String` never returns an error itself. 80 | /// 81 | /// # Examples 82 | /// 83 | /// ``` 84 | /// format!("test"); 85 | /// format!("hello {}", "world!"); 86 | /// format!("x = {}, y = {y}", 10, y = 30); 87 | /// ``` 88 | #[macro_export] 89 | #[stable(feature = "rust1", since = "1.0.0")] 90 | macro_rules! format { 91 | ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) 92 | } 93 | -------------------------------------------------------------------------------- /crates/libcollections/range.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![unstable(feature = "collections_range", 12 | reason = "waiting for dust to settle on inclusive ranges", 13 | issue = "30877")] 14 | 15 | //! Range syntax. 16 | 17 | use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; 18 | use Bound::{self, Excluded, Included, Unbounded}; 19 | 20 | /// `RangeArgument` is implemented by Rust's built-in range types, produced 21 | /// by range syntax like `..`, `a..`, `..b` or `c..d`. 22 | pub trait RangeArgument { 23 | /// Start index bound. 24 | /// 25 | /// Returns the start value as a `Bound`. 26 | /// 27 | /// # Examples 28 | /// 29 | /// ``` 30 | /// #![feature(collections)] 31 | /// #![feature(collections_range)] 32 | /// 33 | /// extern crate collections; 34 | /// 35 | /// # fn main() { 36 | /// use collections::range::RangeArgument; 37 | /// use collections::Bound::*; 38 | /// 39 | /// assert_eq!((..10).start(), Unbounded); 40 | /// assert_eq!((3..10).start(), Included(&3)); 41 | /// # } 42 | /// ``` 43 | fn start(&self) -> Bound<&T>; 44 | 45 | /// End index bound. 46 | /// 47 | /// Returns the end value as a `Bound`. 48 | /// 49 | /// # Examples 50 | /// 51 | /// ``` 52 | /// #![feature(collections)] 53 | /// #![feature(collections_range)] 54 | /// 55 | /// extern crate collections; 56 | /// 57 | /// # fn main() { 58 | /// use collections::range::RangeArgument; 59 | /// use collections::Bound::*; 60 | /// 61 | /// assert_eq!((3..).end(), Unbounded); 62 | /// assert_eq!((3..10).end(), Excluded(&10)); 63 | /// # } 64 | /// ``` 65 | fn end(&self) -> Bound<&T>; 66 | } 67 | 68 | // FIXME add inclusive ranges to RangeArgument 69 | 70 | impl RangeArgument for RangeFull { 71 | fn start(&self) -> Bound<&T> { 72 | Unbounded 73 | } 74 | fn end(&self) -> Bound<&T> { 75 | Unbounded 76 | } 77 | } 78 | 79 | impl RangeArgument for RangeFrom { 80 | fn start(&self) -> Bound<&T> { 81 | Included(&self.start) 82 | } 83 | fn end(&self) -> Bound<&T> { 84 | Unbounded 85 | } 86 | } 87 | 88 | impl RangeArgument for RangeTo { 89 | fn start(&self) -> Bound<&T> { 90 | Unbounded 91 | } 92 | fn end(&self) -> Bound<&T> { 93 | Excluded(&self.end) 94 | } 95 | } 96 | 97 | impl RangeArgument for Range { 98 | fn start(&self) -> Bound<&T> { 99 | Included(&self.start) 100 | } 101 | fn end(&self) -> Bound<&T> { 102 | Excluded(&self.end) 103 | } 104 | } 105 | 106 | #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] 107 | impl RangeArgument for RangeInclusive { 108 | fn start(&self) -> Bound<&T> { 109 | Included(&self.start) 110 | } 111 | fn end(&self) -> Bound<&T> { 112 | Included(&self.end) 113 | } 114 | } 115 | 116 | #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] 117 | impl RangeArgument for RangeToInclusive { 118 | fn start(&self) -> Bound<&T> { 119 | Unbounded 120 | } 121 | fn end(&self) -> Bound<&T> { 122 | Included(&self.end) 123 | } 124 | } 125 | 126 | impl RangeArgument for (Bound, Bound) { 127 | fn start(&self) -> Bound<&T> { 128 | match *self { 129 | (Included(ref start), _) => Included(start), 130 | (Excluded(ref start), _) => Excluded(start), 131 | (Unbounded, _) => Unbounded, 132 | } 133 | } 134 | 135 | fn end(&self) -> Bound<&T> { 136 | match *self { 137 | (_, Included(ref end)) => Included(end), 138 | (_, Excluded(ref end)) => Excluded(end), 139 | (_, Unbounded) => Unbounded, 140 | } 141 | } 142 | } 143 | 144 | impl<'a, T: ?Sized + 'a> RangeArgument for (Bound<&'a T>, Bound<&'a T>) { 145 | fn start(&self) -> Bound<&T> { 146 | self.0 147 | } 148 | 149 | fn end(&self) -> Bound<&T> { 150 | self.1 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /crates/libcollections/tests/binary_heap.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::panic; 12 | use std::collections::BinaryHeap; 13 | use std::collections::binary_heap::{Drain, PeekMut}; 14 | 15 | #[test] 16 | fn test_iterator() { 17 | let data = vec![5, 9, 3]; 18 | let iterout = [9, 5, 3]; 19 | let heap = BinaryHeap::from(data); 20 | let mut i = 0; 21 | for el in &heap { 22 | assert_eq!(*el, iterout[i]); 23 | i += 1; 24 | } 25 | } 26 | 27 | #[test] 28 | fn test_iterator_reverse() { 29 | let data = vec![5, 9, 3]; 30 | let iterout = vec![3, 5, 9]; 31 | let pq = BinaryHeap::from(data); 32 | 33 | let v: Vec<_> = pq.iter().rev().cloned().collect(); 34 | assert_eq!(v, iterout); 35 | } 36 | 37 | #[test] 38 | fn test_move_iter() { 39 | let data = vec![5, 9, 3]; 40 | let iterout = vec![9, 5, 3]; 41 | let pq = BinaryHeap::from(data); 42 | 43 | let v: Vec<_> = pq.into_iter().collect(); 44 | assert_eq!(v, iterout); 45 | } 46 | 47 | #[test] 48 | fn test_move_iter_size_hint() { 49 | let data = vec![5, 9]; 50 | let pq = BinaryHeap::from(data); 51 | 52 | let mut it = pq.into_iter(); 53 | 54 | assert_eq!(it.size_hint(), (2, Some(2))); 55 | assert_eq!(it.next(), Some(9)); 56 | 57 | assert_eq!(it.size_hint(), (1, Some(1))); 58 | assert_eq!(it.next(), Some(5)); 59 | 60 | assert_eq!(it.size_hint(), (0, Some(0))); 61 | assert_eq!(it.next(), None); 62 | } 63 | 64 | #[test] 65 | fn test_move_iter_reverse() { 66 | let data = vec![5, 9, 3]; 67 | let iterout = vec![3, 5, 9]; 68 | let pq = BinaryHeap::from(data); 69 | 70 | let v: Vec<_> = pq.into_iter().rev().collect(); 71 | assert_eq!(v, iterout); 72 | } 73 | 74 | #[test] 75 | fn test_peek_and_pop() { 76 | let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; 77 | let mut sorted = data.clone(); 78 | sorted.sort(); 79 | let mut heap = BinaryHeap::from(data); 80 | while !heap.is_empty() { 81 | assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); 82 | assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); 83 | } 84 | } 85 | 86 | #[test] 87 | fn test_peek_mut() { 88 | let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; 89 | let mut heap = BinaryHeap::from(data); 90 | assert_eq!(heap.peek(), Some(&10)); 91 | { 92 | let mut top = heap.peek_mut().unwrap(); 93 | *top -= 2; 94 | } 95 | assert_eq!(heap.peek(), Some(&9)); 96 | } 97 | 98 | #[test] 99 | fn test_peek_mut_pop() { 100 | let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; 101 | let mut heap = BinaryHeap::from(data); 102 | assert_eq!(heap.peek(), Some(&10)); 103 | { 104 | let mut top = heap.peek_mut().unwrap(); 105 | *top -= 2; 106 | assert_eq!(PeekMut::pop(top), 8); 107 | } 108 | assert_eq!(heap.peek(), Some(&9)); 109 | } 110 | 111 | #[test] 112 | fn test_push() { 113 | let mut heap = BinaryHeap::from(vec![2, 4, 9]); 114 | assert_eq!(heap.len(), 3); 115 | assert!(*heap.peek().unwrap() == 9); 116 | heap.push(11); 117 | assert_eq!(heap.len(), 4); 118 | assert!(*heap.peek().unwrap() == 11); 119 | heap.push(5); 120 | assert_eq!(heap.len(), 5); 121 | assert!(*heap.peek().unwrap() == 11); 122 | heap.push(27); 123 | assert_eq!(heap.len(), 6); 124 | assert!(*heap.peek().unwrap() == 27); 125 | heap.push(3); 126 | assert_eq!(heap.len(), 7); 127 | assert!(*heap.peek().unwrap() == 27); 128 | heap.push(103); 129 | assert_eq!(heap.len(), 8); 130 | assert!(*heap.peek().unwrap() == 103); 131 | } 132 | 133 | #[test] 134 | fn test_push_unique() { 135 | let mut heap = BinaryHeap::>::from(vec![box 2, box 4, box 9]); 136 | assert_eq!(heap.len(), 3); 137 | assert!(**heap.peek().unwrap() == 9); 138 | heap.push(box 11); 139 | assert_eq!(heap.len(), 4); 140 | assert!(**heap.peek().unwrap() == 11); 141 | heap.push(box 5); 142 | assert_eq!(heap.len(), 5); 143 | assert!(**heap.peek().unwrap() == 11); 144 | heap.push(box 27); 145 | assert_eq!(heap.len(), 6); 146 | assert!(**heap.peek().unwrap() == 27); 147 | heap.push(box 3); 148 | assert_eq!(heap.len(), 7); 149 | assert!(**heap.peek().unwrap() == 27); 150 | heap.push(box 103); 151 | assert_eq!(heap.len(), 8); 152 | assert!(**heap.peek().unwrap() == 103); 153 | } 154 | 155 | fn check_to_vec(mut data: Vec) { 156 | let heap = BinaryHeap::from(data.clone()); 157 | let mut v = heap.clone().into_vec(); 158 | v.sort(); 159 | data.sort(); 160 | 161 | assert_eq!(v, data); 162 | assert_eq!(heap.into_sorted_vec(), data); 163 | } 164 | 165 | #[test] 166 | fn test_to_vec() { 167 | check_to_vec(vec![]); 168 | check_to_vec(vec![5]); 169 | check_to_vec(vec![3, 2]); 170 | check_to_vec(vec![2, 3]); 171 | check_to_vec(vec![5, 1, 2]); 172 | check_to_vec(vec![1, 100, 2, 3]); 173 | check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); 174 | check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); 175 | check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); 176 | check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); 177 | check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); 178 | check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); 179 | check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); 180 | } 181 | 182 | #[test] 183 | fn test_empty_pop() { 184 | let mut heap = BinaryHeap::::new(); 185 | assert!(heap.pop().is_none()); 186 | } 187 | 188 | #[test] 189 | fn test_empty_peek() { 190 | let empty = BinaryHeap::::new(); 191 | assert!(empty.peek().is_none()); 192 | } 193 | 194 | #[test] 195 | fn test_empty_peek_mut() { 196 | let mut empty = BinaryHeap::::new(); 197 | assert!(empty.peek_mut().is_none()); 198 | } 199 | 200 | #[test] 201 | fn test_from_iter() { 202 | let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; 203 | 204 | let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); 205 | 206 | for &x in &xs { 207 | assert_eq!(q.pop().unwrap(), x); 208 | } 209 | } 210 | 211 | #[test] 212 | fn test_drain() { 213 | let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); 214 | 215 | assert_eq!(q.drain().take(5).count(), 5); 216 | 217 | assert!(q.is_empty()); 218 | } 219 | 220 | #[test] 221 | fn test_extend_ref() { 222 | let mut a = BinaryHeap::new(); 223 | a.push(1); 224 | a.push(2); 225 | 226 | a.extend(&[3, 4, 5]); 227 | 228 | assert_eq!(a.len(), 5); 229 | assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); 230 | 231 | let mut a = BinaryHeap::new(); 232 | a.push(1); 233 | a.push(2); 234 | let mut b = BinaryHeap::new(); 235 | b.push(3); 236 | b.push(4); 237 | b.push(5); 238 | 239 | a.extend(&b); 240 | 241 | assert_eq!(a.len(), 5); 242 | assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); 243 | } 244 | 245 | #[test] 246 | fn test_append() { 247 | let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); 248 | let mut b = BinaryHeap::from(vec![-20, 5, 43]); 249 | 250 | a.append(&mut b); 251 | 252 | assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); 253 | assert!(b.is_empty()); 254 | } 255 | 256 | #[test] 257 | fn test_append_to_empty() { 258 | let mut a = BinaryHeap::new(); 259 | let mut b = BinaryHeap::from(vec![-20, 5, 43]); 260 | 261 | a.append(&mut b); 262 | 263 | assert_eq!(a.into_sorted_vec(), [-20, 5, 43]); 264 | assert!(b.is_empty()); 265 | } 266 | 267 | #[test] 268 | fn test_extend_specialization() { 269 | let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); 270 | let b = BinaryHeap::from(vec![-20, 5, 43]); 271 | 272 | a.extend(b); 273 | 274 | assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); 275 | } 276 | 277 | #[test] 278 | fn test_placement() { 279 | let mut a = BinaryHeap::new(); 280 | &mut a <- 2; 281 | &mut a <- 4; 282 | &mut a <- 3; 283 | assert_eq!(a.peek(), Some(&4)); 284 | assert_eq!(a.len(), 3); 285 | &mut a <- 1; 286 | assert_eq!(a.into_sorted_vec(), vec![1, 2, 3, 4]); 287 | } 288 | 289 | #[test] 290 | fn test_placement_panic() { 291 | let mut heap = BinaryHeap::from(vec![1, 2, 3]); 292 | fn mkpanic() -> usize { panic!() } 293 | let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { &mut heap <- mkpanic(); })); 294 | assert_eq!(heap.len(), 3); 295 | } 296 | 297 | #[allow(dead_code)] 298 | fn assert_covariance() { 299 | fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { 300 | d 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /crates/libcollections/tests/btree/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | mod map; 12 | mod set; 13 | 14 | /// XorShiftRng 15 | struct DeterministicRng { 16 | x: u32, 17 | y: u32, 18 | z: u32, 19 | w: u32, 20 | } 21 | 22 | impl DeterministicRng { 23 | fn new() -> Self { 24 | DeterministicRng { 25 | x: 0x193a6754, 26 | y: 0xa8a7d469, 27 | z: 0x97830e05, 28 | w: 0x113ba7bb, 29 | } 30 | } 31 | 32 | fn next(&mut self) -> u32 { 33 | let x = self.x; 34 | let t = x ^ (x << 11); 35 | self.x = self.y; 36 | self.y = self.z; 37 | self.z = self.w; 38 | let w_ = self.w; 39 | self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); 40 | self.w 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /crates/libcollections/tests/btree/set.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::collections::BTreeSet; 12 | 13 | use std::iter::FromIterator; 14 | use super::DeterministicRng; 15 | 16 | #[test] 17 | fn test_clone_eq() { 18 | let mut m = BTreeSet::new(); 19 | 20 | m.insert(1); 21 | m.insert(2); 22 | 23 | assert!(m.clone() == m); 24 | } 25 | 26 | #[test] 27 | fn test_hash() { 28 | let mut x = BTreeSet::new(); 29 | let mut y = BTreeSet::new(); 30 | 31 | x.insert(1); 32 | x.insert(2); 33 | x.insert(3); 34 | 35 | y.insert(3); 36 | y.insert(2); 37 | y.insert(1); 38 | 39 | assert!(::hash(&x) == ::hash(&y)); 40 | } 41 | 42 | fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) 43 | where F: FnOnce(&BTreeSet, &BTreeSet, &mut FnMut(&i32) -> bool) -> bool 44 | { 45 | let mut set_a = BTreeSet::new(); 46 | let mut set_b = BTreeSet::new(); 47 | 48 | for x in a { 49 | assert!(set_a.insert(*x)) 50 | } 51 | for y in b { 52 | assert!(set_b.insert(*y)) 53 | } 54 | 55 | let mut i = 0; 56 | f(&set_a, 57 | &set_b, 58 | &mut |&x| { 59 | assert_eq!(x, expected[i]); 60 | i += 1; 61 | true 62 | }); 63 | assert_eq!(i, expected.len()); 64 | } 65 | 66 | #[test] 67 | fn test_intersection() { 68 | fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { 69 | check(a, b, expected, |x, y, f| x.intersection(y).all(f)) 70 | } 71 | 72 | check_intersection(&[], &[], &[]); 73 | check_intersection(&[1, 2, 3], &[], &[]); 74 | check_intersection(&[], &[1, 2, 3], &[]); 75 | check_intersection(&[2], &[1, 2, 3], &[2]); 76 | check_intersection(&[1, 2, 3], &[2], &[2]); 77 | check_intersection(&[11, 1, 3, 77, 103, 5, -5], 78 | &[2, 11, 77, -9, -42, 5, 3], 79 | &[3, 5, 11, 77]); 80 | } 81 | 82 | #[test] 83 | fn test_difference() { 84 | fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { 85 | check(a, b, expected, |x, y, f| x.difference(y).all(f)) 86 | } 87 | 88 | check_difference(&[], &[], &[]); 89 | check_difference(&[1, 12], &[], &[1, 12]); 90 | check_difference(&[], &[1, 2, 3, 9], &[]); 91 | check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]); 92 | check_difference(&[-5, 11, 22, 33, 40, 42], 93 | &[-12, -5, 14, 23, 34, 38, 39, 50], 94 | &[11, 22, 33, 40, 42]); 95 | } 96 | 97 | #[test] 98 | fn test_symmetric_difference() { 99 | fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { 100 | check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) 101 | } 102 | 103 | check_symmetric_difference(&[], &[], &[]); 104 | check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); 105 | check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); 106 | check_symmetric_difference(&[1, 3, 5, 9, 11], 107 | &[-2, 3, 9, 14, 22], 108 | &[-2, 1, 5, 11, 14, 22]); 109 | } 110 | 111 | #[test] 112 | fn test_union() { 113 | fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { 114 | check(a, b, expected, |x, y, f| x.union(y).all(f)) 115 | } 116 | 117 | check_union(&[], &[], &[]); 118 | check_union(&[1, 2, 3], &[2], &[1, 2, 3]); 119 | check_union(&[2], &[1, 2, 3], &[1, 2, 3]); 120 | check_union(&[1, 3, 5, 9, 11, 16, 19, 24], 121 | &[-2, 1, 5, 9, 13, 19], 122 | &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); 123 | } 124 | 125 | #[test] 126 | fn test_zip() { 127 | let mut x = BTreeSet::new(); 128 | x.insert(5); 129 | x.insert(12); 130 | x.insert(11); 131 | 132 | let mut y = BTreeSet::new(); 133 | y.insert("foo"); 134 | y.insert("bar"); 135 | 136 | let x = x; 137 | let y = y; 138 | let mut z = x.iter().zip(&y); 139 | 140 | assert_eq!(z.next().unwrap(), (&5, &("bar"))); 141 | assert_eq!(z.next().unwrap(), (&11, &("foo"))); 142 | assert!(z.next().is_none()); 143 | } 144 | 145 | #[test] 146 | fn test_from_iter() { 147 | let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 148 | 149 | let set: BTreeSet<_> = xs.iter().cloned().collect(); 150 | 151 | for x in &xs { 152 | assert!(set.contains(x)); 153 | } 154 | } 155 | 156 | #[test] 157 | fn test_show() { 158 | let mut set = BTreeSet::new(); 159 | let empty = BTreeSet::::new(); 160 | 161 | set.insert(1); 162 | set.insert(2); 163 | 164 | let set_str = format!("{:?}", set); 165 | 166 | assert_eq!(set_str, "{1, 2}"); 167 | assert_eq!(format!("{:?}", empty), "{}"); 168 | } 169 | 170 | #[test] 171 | fn test_extend_ref() { 172 | let mut a = BTreeSet::new(); 173 | a.insert(1); 174 | 175 | a.extend(&[2, 3, 4]); 176 | 177 | assert_eq!(a.len(), 4); 178 | assert!(a.contains(&1)); 179 | assert!(a.contains(&2)); 180 | assert!(a.contains(&3)); 181 | assert!(a.contains(&4)); 182 | 183 | let mut b = BTreeSet::new(); 184 | b.insert(5); 185 | b.insert(6); 186 | 187 | a.extend(&b); 188 | 189 | assert_eq!(a.len(), 6); 190 | assert!(a.contains(&1)); 191 | assert!(a.contains(&2)); 192 | assert!(a.contains(&3)); 193 | assert!(a.contains(&4)); 194 | assert!(a.contains(&5)); 195 | assert!(a.contains(&6)); 196 | } 197 | 198 | #[test] 199 | fn test_recovery() { 200 | use std::cmp::Ordering; 201 | 202 | #[derive(Debug)] 203 | struct Foo(&'static str, i32); 204 | 205 | impl PartialEq for Foo { 206 | fn eq(&self, other: &Self) -> bool { 207 | self.0 == other.0 208 | } 209 | } 210 | 211 | impl Eq for Foo {} 212 | 213 | impl PartialOrd for Foo { 214 | fn partial_cmp(&self, other: &Self) -> Option { 215 | self.0.partial_cmp(&other.0) 216 | } 217 | } 218 | 219 | impl Ord for Foo { 220 | fn cmp(&self, other: &Self) -> Ordering { 221 | self.0.cmp(&other.0) 222 | } 223 | } 224 | 225 | let mut s = BTreeSet::new(); 226 | assert_eq!(s.replace(Foo("a", 1)), None); 227 | assert_eq!(s.len(), 1); 228 | assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); 229 | assert_eq!(s.len(), 1); 230 | 231 | { 232 | let mut it = s.iter(); 233 | assert_eq!(it.next(), Some(&Foo("a", 2))); 234 | assert_eq!(it.next(), None); 235 | } 236 | 237 | assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2))); 238 | assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2))); 239 | assert_eq!(s.len(), 0); 240 | 241 | assert_eq!(s.get(&Foo("a", 1)), None); 242 | assert_eq!(s.take(&Foo("a", 1)), None); 243 | 244 | assert_eq!(s.iter().next(), None); 245 | } 246 | 247 | #[test] 248 | #[allow(dead_code)] 249 | fn test_variance() { 250 | use std::collections::btree_set::{IntoIter, Iter, Range}; 251 | 252 | fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { 253 | v 254 | } 255 | fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { 256 | v 257 | } 258 | fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { 259 | v 260 | } 261 | fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { 262 | v 263 | } 264 | } 265 | 266 | #[test] 267 | fn test_append() { 268 | let mut a = BTreeSet::new(); 269 | a.insert(1); 270 | a.insert(2); 271 | a.insert(3); 272 | 273 | let mut b = BTreeSet::new(); 274 | b.insert(3); 275 | b.insert(4); 276 | b.insert(5); 277 | 278 | a.append(&mut b); 279 | 280 | assert_eq!(a.len(), 5); 281 | assert_eq!(b.len(), 0); 282 | 283 | assert_eq!(a.contains(&1), true); 284 | assert_eq!(a.contains(&2), true); 285 | assert_eq!(a.contains(&3), true); 286 | assert_eq!(a.contains(&4), true); 287 | assert_eq!(a.contains(&5), true); 288 | } 289 | 290 | fn rand_data(len: usize) -> Vec { 291 | let mut rng = DeterministicRng::new(); 292 | Vec::from_iter((0..len).map(|_| rng.next())) 293 | } 294 | 295 | #[test] 296 | fn test_split_off_empty_right() { 297 | let mut data = rand_data(173); 298 | 299 | let mut set = BTreeSet::from_iter(data.clone()); 300 | let right = set.split_off(&(data.iter().max().unwrap() + 1)); 301 | 302 | data.sort(); 303 | assert!(set.into_iter().eq(data)); 304 | assert!(right.into_iter().eq(None)); 305 | } 306 | 307 | #[test] 308 | fn test_split_off_empty_left() { 309 | let mut data = rand_data(314); 310 | 311 | let mut set = BTreeSet::from_iter(data.clone()); 312 | let right = set.split_off(data.iter().min().unwrap()); 313 | 314 | data.sort(); 315 | assert!(set.into_iter().eq(None)); 316 | assert!(right.into_iter().eq(data)); 317 | } 318 | 319 | #[test] 320 | fn test_split_off_large_random_sorted() { 321 | let mut data = rand_data(1529); 322 | // special case with maximum height. 323 | data.sort(); 324 | 325 | let mut set = BTreeSet::from_iter(data.clone()); 326 | let key = data[data.len() / 2]; 327 | let right = set.split_off(&key); 328 | 329 | assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key))); 330 | assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key))); 331 | } 332 | -------------------------------------------------------------------------------- /crates/libcollections/tests/cow_str.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::borrow::Cow; 12 | 13 | // check that Cow<'a, str> implements addition 14 | #[test] 15 | fn check_cow_add_cow() { 16 | let borrowed1 = Cow::Borrowed("Hello, "); 17 | let borrowed2 = Cow::Borrowed("World!"); 18 | let borrow_empty = Cow::Borrowed(""); 19 | 20 | let owned1: Cow = Cow::Owned(String::from("Hi, ")); 21 | let owned2: Cow = Cow::Owned(String::from("Rustaceans!")); 22 | let owned_empty: Cow = Cow::Owned(String::new()); 23 | 24 | assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone()); 25 | assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone()); 26 | 27 | assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone()); 28 | assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone()); 29 | 30 | if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() { 31 | panic!("Adding empty strings to a borrow should note allocate"); 32 | } 33 | if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() { 34 | panic!("Adding empty strings to a borrow should note allocate"); 35 | } 36 | if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() { 37 | panic!("Adding empty strings to a borrow should note allocate"); 38 | } 39 | if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() { 40 | panic!("Adding empty strings to a borrow should note allocate"); 41 | } 42 | } 43 | 44 | #[test] 45 | fn check_cow_add_str() { 46 | let borrowed = Cow::Borrowed("Hello, "); 47 | let borrow_empty = Cow::Borrowed(""); 48 | 49 | let owned: Cow = Cow::Owned(String::from("Hi, ")); 50 | let owned_empty: Cow = Cow::Owned(String::new()); 51 | 52 | assert_eq!("Hello, World!", borrowed.clone() + "World!"); 53 | 54 | assert_eq!("Hi, World!", owned.clone() + "World!"); 55 | 56 | if let Cow::Owned(_) = borrowed.clone() + "" { 57 | panic!("Adding empty strings to a borrow should note allocate"); 58 | } 59 | if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " { 60 | panic!("Adding empty strings to a borrow should note allocate"); 61 | } 62 | if let Cow::Owned(_) = owned_empty.clone() + "Hello, " { 63 | panic!("Adding empty strings to a borrow should note allocate"); 64 | } 65 | } 66 | 67 | #[test] 68 | fn check_cow_add_assign_cow() { 69 | let mut borrowed1 = Cow::Borrowed("Hello, "); 70 | let borrowed2 = Cow::Borrowed("World!"); 71 | let borrow_empty = Cow::Borrowed(""); 72 | 73 | let mut owned1: Cow = Cow::Owned(String::from("Hi, ")); 74 | let owned2: Cow = Cow::Owned(String::from("Rustaceans!")); 75 | let owned_empty: Cow = Cow::Owned(String::new()); 76 | 77 | let mut s = borrowed1.clone(); 78 | s += borrow_empty.clone(); 79 | assert_eq!("Hello, ", s); 80 | if let Cow::Owned(_) = s { 81 | panic!("Adding empty strings to a borrow should note allocate"); 82 | } 83 | let mut s = borrow_empty.clone(); 84 | s += borrowed1.clone(); 85 | assert_eq!("Hello, ", s); 86 | if let Cow::Owned(_) = s { 87 | panic!("Adding empty strings to a borrow should note allocate"); 88 | } 89 | let mut s = borrowed1.clone(); 90 | s += owned_empty.clone(); 91 | assert_eq!("Hello, ", s); 92 | if let Cow::Owned(_) = s { 93 | panic!("Adding empty strings to a borrow should note allocate"); 94 | } 95 | let mut s = owned_empty.clone(); 96 | s += borrowed1.clone(); 97 | assert_eq!("Hello, ", s); 98 | if let Cow::Owned(_) = s { 99 | panic!("Adding empty strings to a borrow should note allocate"); 100 | } 101 | 102 | owned1 += borrowed2; 103 | borrowed1 += owned2; 104 | 105 | assert_eq!("Hi, World!", owned1); 106 | assert_eq!("Hello, Rustaceans!", borrowed1); 107 | } 108 | 109 | #[test] 110 | fn check_cow_add_assign_str() { 111 | let mut borrowed = Cow::Borrowed("Hello, "); 112 | let borrow_empty = Cow::Borrowed(""); 113 | 114 | let mut owned: Cow = Cow::Owned(String::from("Hi, ")); 115 | let owned_empty: Cow = Cow::Owned(String::new()); 116 | 117 | let mut s = borrowed.clone(); 118 | s += ""; 119 | assert_eq!("Hello, ", s); 120 | if let Cow::Owned(_) = s { 121 | panic!("Adding empty strings to a borrow should note allocate"); 122 | } 123 | let mut s = borrow_empty.clone(); 124 | s += "World!"; 125 | assert_eq!("World!", s); 126 | if let Cow::Owned(_) = s { 127 | panic!("Adding empty strings to a borrow should note allocate"); 128 | } 129 | let mut s = owned_empty.clone(); 130 | s += "World!"; 131 | assert_eq!("World!", s); 132 | if let Cow::Owned(_) = s { 133 | panic!("Adding empty strings to a borrow should note allocate"); 134 | } 135 | 136 | owned += "World!"; 137 | borrowed += "World!"; 138 | 139 | assert_eq!("Hi, World!", owned); 140 | assert_eq!("Hello, World!", borrowed); 141 | } 142 | 143 | #[test] 144 | fn check_cow_clone_from() { 145 | let mut c1: Cow = Cow::Owned(String::with_capacity(25)); 146 | let s: String = "hi".to_string(); 147 | assert!(s.capacity() < 25); 148 | let c2: Cow = Cow::Owned(s); 149 | c1.clone_from(&c2); 150 | assert!(c1.into_owned().capacity() >= 25); 151 | } -------------------------------------------------------------------------------- /crates/libcollections/tests/fmt.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::fmt; 12 | 13 | #[test] 14 | fn test_format() { 15 | let s = fmt::format(format_args!("Hello, {}!", "world")); 16 | assert_eq!(s, "Hello, world!"); 17 | } 18 | -------------------------------------------------------------------------------- /crates/libcollections/tests/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | #![deny(warnings)] 12 | 13 | #![feature(box_syntax)] 14 | #![feature(inclusive_range_syntax)] 15 | #![feature(collection_placement)] 16 | #![feature(collections)] 17 | #![feature(const_fn)] 18 | #![feature(exact_size_is_empty)] 19 | #![feature(iterator_step_by)] 20 | #![feature(pattern)] 21 | #![feature(placement_in_syntax)] 22 | #![feature(rand)] 23 | #![feature(slice_rotate)] 24 | #![feature(splice)] 25 | #![feature(str_escape)] 26 | #![feature(test)] 27 | #![feature(unboxed_closures)] 28 | #![feature(unicode)] 29 | #![feature(utf8_error_error_len)] 30 | 31 | extern crate collections; 32 | extern crate test; 33 | extern crate std_unicode; 34 | extern crate core; 35 | 36 | use std::hash::{Hash, Hasher}; 37 | use std::collections::hash_map::DefaultHasher; 38 | 39 | mod binary_heap; 40 | mod btree; 41 | mod cow_str; 42 | mod fmt; 43 | mod linked_list; 44 | mod slice; 45 | mod str; 46 | mod string; 47 | mod vec_deque; 48 | mod vec; 49 | 50 | fn hash(t: &T) -> u64 { 51 | let mut s = DefaultHasher::new(); 52 | t.hash(&mut s); 53 | s.finish() 54 | } 55 | -------------------------------------------------------------------------------- /crates/libcollections/tests/linked_list.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | use std::collections::LinkedList; 12 | 13 | #[test] 14 | fn test_basic() { 15 | let mut m = LinkedList::>::new(); 16 | assert_eq!(m.pop_front(), None); 17 | assert_eq!(m.pop_back(), None); 18 | assert_eq!(m.pop_front(), None); 19 | m.push_front(box 1); 20 | assert_eq!(m.pop_front(), Some(box 1)); 21 | m.push_back(box 2); 22 | m.push_back(box 3); 23 | assert_eq!(m.len(), 2); 24 | assert_eq!(m.pop_front(), Some(box 2)); 25 | assert_eq!(m.pop_front(), Some(box 3)); 26 | assert_eq!(m.len(), 0); 27 | assert_eq!(m.pop_front(), None); 28 | m.push_back(box 1); 29 | m.push_back(box 3); 30 | m.push_back(box 5); 31 | m.push_back(box 7); 32 | assert_eq!(m.pop_front(), Some(box 1)); 33 | 34 | let mut n = LinkedList::new(); 35 | n.push_front(2); 36 | n.push_front(3); 37 | { 38 | assert_eq!(n.front().unwrap(), &3); 39 | let x = n.front_mut().unwrap(); 40 | assert_eq!(*x, 3); 41 | *x = 0; 42 | } 43 | { 44 | assert_eq!(n.back().unwrap(), &2); 45 | let y = n.back_mut().unwrap(); 46 | assert_eq!(*y, 2); 47 | *y = 1; 48 | } 49 | assert_eq!(n.pop_front(), Some(0)); 50 | assert_eq!(n.pop_front(), Some(1)); 51 | } 52 | 53 | #[cfg(test)] 54 | fn generate_test() -> LinkedList { 55 | list_from(&[0, 1, 2, 3, 4, 5, 6]) 56 | } 57 | 58 | #[cfg(test)] 59 | fn list_from(v: &[T]) -> LinkedList { 60 | v.iter().cloned().collect() 61 | } 62 | 63 | #[test] 64 | fn test_split_off() { 65 | // singleton 66 | { 67 | let mut m = LinkedList::new(); 68 | m.push_back(1); 69 | 70 | let p = m.split_off(0); 71 | assert_eq!(m.len(), 0); 72 | assert_eq!(p.len(), 1); 73 | assert_eq!(p.back(), Some(&1)); 74 | assert_eq!(p.front(), Some(&1)); 75 | } 76 | 77 | // not singleton, forwards 78 | { 79 | let u = vec![1, 2, 3, 4, 5]; 80 | let mut m = list_from(&u); 81 | let mut n = m.split_off(2); 82 | assert_eq!(m.len(), 2); 83 | assert_eq!(n.len(), 3); 84 | for elt in 1..3 { 85 | assert_eq!(m.pop_front(), Some(elt)); 86 | } 87 | for elt in 3..6 { 88 | assert_eq!(n.pop_front(), Some(elt)); 89 | } 90 | } 91 | // not singleton, backwards 92 | { 93 | let u = vec![1, 2, 3, 4, 5]; 94 | let mut m = list_from(&u); 95 | let mut n = m.split_off(4); 96 | assert_eq!(m.len(), 4); 97 | assert_eq!(n.len(), 1); 98 | for elt in 1..5 { 99 | assert_eq!(m.pop_front(), Some(elt)); 100 | } 101 | for elt in 5..6 { 102 | assert_eq!(n.pop_front(), Some(elt)); 103 | } 104 | } 105 | 106 | // no-op on the last index 107 | { 108 | let mut m = LinkedList::new(); 109 | m.push_back(1); 110 | 111 | let p = m.split_off(1); 112 | assert_eq!(m.len(), 1); 113 | assert_eq!(p.len(), 0); 114 | assert_eq!(m.back(), Some(&1)); 115 | assert_eq!(m.front(), Some(&1)); 116 | } 117 | 118 | } 119 | 120 | #[test] 121 | fn test_iterator() { 122 | let m = generate_test(); 123 | for (i, elt) in m.iter().enumerate() { 124 | assert_eq!(i as i32, *elt); 125 | } 126 | let mut n = LinkedList::new(); 127 | assert_eq!(n.iter().next(), None); 128 | n.push_front(4); 129 | let mut it = n.iter(); 130 | assert_eq!(it.size_hint(), (1, Some(1))); 131 | assert_eq!(it.next().unwrap(), &4); 132 | assert_eq!(it.size_hint(), (0, Some(0))); 133 | assert_eq!(it.next(), None); 134 | } 135 | 136 | #[test] 137 | fn test_iterator_clone() { 138 | let mut n = LinkedList::new(); 139 | n.push_back(2); 140 | n.push_back(3); 141 | n.push_back(4); 142 | let mut it = n.iter(); 143 | it.next(); 144 | let mut jt = it.clone(); 145 | assert_eq!(it.next(), jt.next()); 146 | assert_eq!(it.next_back(), jt.next_back()); 147 | assert_eq!(it.next(), jt.next()); 148 | } 149 | 150 | #[test] 151 | fn test_iterator_double_end() { 152 | let mut n = LinkedList::new(); 153 | assert_eq!(n.iter().next(), None); 154 | n.push_front(4); 155 | n.push_front(5); 156 | n.push_front(6); 157 | let mut it = n.iter(); 158 | assert_eq!(it.size_hint(), (3, Some(3))); 159 | assert_eq!(it.next().unwrap(), &6); 160 | assert_eq!(it.size_hint(), (2, Some(2))); 161 | assert_eq!(it.next_back().unwrap(), &4); 162 | assert_eq!(it.size_hint(), (1, Some(1))); 163 | assert_eq!(it.next_back().unwrap(), &5); 164 | assert_eq!(it.next_back(), None); 165 | assert_eq!(it.next(), None); 166 | } 167 | 168 | #[test] 169 | fn test_rev_iter() { 170 | let m = generate_test(); 171 | for (i, elt) in m.iter().rev().enumerate() { 172 | assert_eq!((6 - i) as i32, *elt); 173 | } 174 | let mut n = LinkedList::new(); 175 | assert_eq!(n.iter().rev().next(), None); 176 | n.push_front(4); 177 | let mut it = n.iter().rev(); 178 | assert_eq!(it.size_hint(), (1, Some(1))); 179 | assert_eq!(it.next().unwrap(), &4); 180 | assert_eq!(it.size_hint(), (0, Some(0))); 181 | assert_eq!(it.next(), None); 182 | } 183 | 184 | #[test] 185 | fn test_mut_iter() { 186 | let mut m = generate_test(); 187 | let mut len = m.len(); 188 | for (i, elt) in m.iter_mut().enumerate() { 189 | assert_eq!(i as i32, *elt); 190 | len -= 1; 191 | } 192 | assert_eq!(len, 0); 193 | let mut n = LinkedList::new(); 194 | assert!(n.iter_mut().next().is_none()); 195 | n.push_front(4); 196 | n.push_back(5); 197 | let mut it = n.iter_mut(); 198 | assert_eq!(it.size_hint(), (2, Some(2))); 199 | assert!(it.next().is_some()); 200 | assert!(it.next().is_some()); 201 | assert_eq!(it.size_hint(), (0, Some(0))); 202 | assert!(it.next().is_none()); 203 | } 204 | 205 | #[test] 206 | fn test_iterator_mut_double_end() { 207 | let mut n = LinkedList::new(); 208 | assert!(n.iter_mut().next_back().is_none()); 209 | n.push_front(4); 210 | n.push_front(5); 211 | n.push_front(6); 212 | let mut it = n.iter_mut(); 213 | assert_eq!(it.size_hint(), (3, Some(3))); 214 | assert_eq!(*it.next().unwrap(), 6); 215 | assert_eq!(it.size_hint(), (2, Some(2))); 216 | assert_eq!(*it.next_back().unwrap(), 4); 217 | assert_eq!(it.size_hint(), (1, Some(1))); 218 | assert_eq!(*it.next_back().unwrap(), 5); 219 | assert!(it.next_back().is_none()); 220 | assert!(it.next().is_none()); 221 | } 222 | 223 | #[test] 224 | fn test_mut_rev_iter() { 225 | let mut m = generate_test(); 226 | for (i, elt) in m.iter_mut().rev().enumerate() { 227 | assert_eq!((6 - i) as i32, *elt); 228 | } 229 | let mut n = LinkedList::new(); 230 | assert!(n.iter_mut().rev().next().is_none()); 231 | n.push_front(4); 232 | let mut it = n.iter_mut().rev(); 233 | assert!(it.next().is_some()); 234 | assert!(it.next().is_none()); 235 | } 236 | 237 | #[test] 238 | fn test_eq() { 239 | let mut n = list_from(&[]); 240 | let mut m = list_from(&[]); 241 | assert!(n == m); 242 | n.push_front(1); 243 | assert!(n != m); 244 | m.push_back(1); 245 | assert!(n == m); 246 | 247 | let n = list_from(&[2, 3, 4]); 248 | let m = list_from(&[1, 2, 3]); 249 | assert!(n != m); 250 | } 251 | 252 | #[test] 253 | fn test_hash() { 254 | let mut x = LinkedList::new(); 255 | let mut y = LinkedList::new(); 256 | 257 | assert!(::hash(&x) == ::hash(&y)); 258 | 259 | x.push_back(1); 260 | x.push_back(2); 261 | x.push_back(3); 262 | 263 | y.push_front(3); 264 | y.push_front(2); 265 | y.push_front(1); 266 | 267 | assert!(::hash(&x) == ::hash(&y)); 268 | } 269 | 270 | #[test] 271 | fn test_ord() { 272 | let n = list_from(&[]); 273 | let m = list_from(&[1, 2, 3]); 274 | assert!(n < m); 275 | assert!(m > n); 276 | assert!(n <= n); 277 | assert!(n >= n); 278 | } 279 | 280 | #[test] 281 | fn test_ord_nan() { 282 | let nan = 0.0f64 / 0.0; 283 | let n = list_from(&[nan]); 284 | let m = list_from(&[nan]); 285 | assert!(!(n < m)); 286 | assert!(!(n > m)); 287 | assert!(!(n <= m)); 288 | assert!(!(n >= m)); 289 | 290 | let n = list_from(&[nan]); 291 | let one = list_from(&[1.0f64]); 292 | assert!(!(n < one)); 293 | assert!(!(n > one)); 294 | assert!(!(n <= one)); 295 | assert!(!(n >= one)); 296 | 297 | let u = list_from(&[1.0f64, 2.0, nan]); 298 | let v = list_from(&[1.0f64, 2.0, 3.0]); 299 | assert!(!(u < v)); 300 | assert!(!(u > v)); 301 | assert!(!(u <= v)); 302 | assert!(!(u >= v)); 303 | 304 | let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]); 305 | let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]); 306 | assert!(!(s < t)); 307 | assert!(s > one); 308 | assert!(!(s <= one)); 309 | assert!(s >= one); 310 | } 311 | 312 | #[test] 313 | fn test_show() { 314 | let list: LinkedList<_> = (0..10).collect(); 315 | assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); 316 | 317 | let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); 318 | assert_eq!(format!("{:?}", list), 319 | "[\"just\", \"one\", \"test\", \"more\"]"); 320 | } 321 | 322 | #[test] 323 | fn test_extend_ref() { 324 | let mut a = LinkedList::new(); 325 | a.push_back(1); 326 | 327 | a.extend(&[2, 3, 4]); 328 | 329 | assert_eq!(a.len(), 4); 330 | assert_eq!(a, list_from(&[1, 2, 3, 4])); 331 | 332 | let mut b = LinkedList::new(); 333 | b.push_back(5); 334 | b.push_back(6); 335 | a.extend(&b); 336 | 337 | assert_eq!(a.len(), 6); 338 | assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6])); 339 | } 340 | 341 | #[test] 342 | fn test_extend() { 343 | let mut a = LinkedList::new(); 344 | a.push_back(1); 345 | a.extend(vec![2, 3, 4]); // uses iterator 346 | 347 | assert_eq!(a.len(), 4); 348 | assert!(a.iter().eq(&[1, 2, 3, 4])); 349 | 350 | let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect(); 351 | a.extend(b); // specializes to `append` 352 | 353 | assert_eq!(a.len(), 7); 354 | assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7])); 355 | } 356 | 357 | #[test] 358 | fn test_contains() { 359 | let mut l = LinkedList::new(); 360 | l.extend(&[2, 3, 4]); 361 | 362 | assert!(l.contains(&3)); 363 | assert!(!l.contains(&1)); 364 | 365 | l.clear(); 366 | 367 | assert!(!l.contains(&3)); 368 | } 369 | -------------------------------------------------------------------------------- /crates/libstd_unicode/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | name = "std_unicode" 4 | version = "0.0.0" 5 | 6 | [lib] 7 | name = "std_unicode" 8 | path = "lib.rs" 9 | test = false 10 | bench = false 11 | 12 | # [dependencies] 13 | # core = { path = "../libcore" } 14 | -------------------------------------------------------------------------------- /crates/libstd_unicode/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! # The Unicode Library 12 | //! 13 | //! Unicode-intensive functions for `char` and `str` types. 14 | //! 15 | //! This crate provides a collection of Unicode-related functionality, 16 | //! including decompositions, conversions, etc., and provides traits 17 | //! implementing these functions for the `char` and `str` types. 18 | //! 19 | //! The functionality included here is only that which is necessary to 20 | //! provide for basic string-related manipulations. This crate does not 21 | //! (yet) aim to provide a full set of Unicode tables. 22 | 23 | #![crate_name = "std_unicode"] 24 | #![unstable(feature = "unicode", issue = "27783")] 25 | #![crate_type = "rlib"] 26 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 27 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", 28 | html_root_url = "https://doc.rust-lang.org/nightly/", 29 | html_playground_url = "https://play.rust-lang.org/", 30 | issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", 31 | test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] 32 | #![deny(warnings)] 33 | #![no_std] 34 | 35 | #![feature(char_escape_debug)] 36 | #![feature(core_char_ext)] 37 | #![feature(decode_utf8)] 38 | #![feature(fused)] 39 | #![feature(fn_traits)] 40 | #![feature(lang_items)] 41 | #![feature(staged_api)] 42 | #![feature(try_from)] 43 | #![feature(unboxed_closures)] 44 | 45 | mod tables; 46 | mod u_str; 47 | pub mod char; 48 | 49 | #[allow(deprecated)] 50 | pub mod str { 51 | pub use u_str::{SplitWhitespace, UnicodeStr}; 52 | pub use u_str::Utf16Encoder; 53 | } 54 | 55 | // For use in libcollections, not re-exported in libstd. 56 | pub mod derived_property { 57 | pub use tables::derived_property::{Case_Ignorable, Cased}; 58 | } 59 | 60 | // For use in libsyntax 61 | pub mod property { 62 | pub use tables::property::Pattern_White_Space; 63 | } 64 | -------------------------------------------------------------------------------- /crates/libstd_unicode/u_str.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Unicode-intensive string manipulations. 12 | //! 13 | //! This module provides functionality to `str` that requires the Unicode 14 | //! methods provided by the unicode parts of the CharExt trait. 15 | 16 | use core::char; 17 | use core::iter::{Filter, FusedIterator}; 18 | use core::str::Split; 19 | 20 | /// An iterator over the non-whitespace substrings of a string, 21 | /// separated by any amount of whitespace. 22 | /// 23 | /// This struct is created by the [`split_whitespace`] method on [`str`]. 24 | /// See its documentation for more. 25 | /// 26 | /// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace 27 | /// [`str`]: ../../std/primitive.str.html 28 | #[stable(feature = "split_whitespace", since = "1.1.0")] 29 | #[derive(Clone)] 30 | pub struct SplitWhitespace<'a> { 31 | inner: Filter, IsNotEmpty>, 32 | } 33 | 34 | /// Methods for Unicode string slices 35 | #[allow(missing_docs)] // docs in libcollections 36 | pub trait UnicodeStr { 37 | fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>; 38 | fn is_whitespace(&self) -> bool; 39 | fn is_alphanumeric(&self) -> bool; 40 | fn trim(&self) -> &str; 41 | fn trim_left(&self) -> &str; 42 | fn trim_right(&self) -> &str; 43 | } 44 | 45 | impl UnicodeStr for str { 46 | #[inline] 47 | fn split_whitespace(&self) -> SplitWhitespace { 48 | SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) } 49 | } 50 | 51 | #[inline] 52 | fn is_whitespace(&self) -> bool { 53 | self.chars().all(|c| c.is_whitespace()) 54 | } 55 | 56 | #[inline] 57 | fn is_alphanumeric(&self) -> bool { 58 | self.chars().all(|c| c.is_alphanumeric()) 59 | } 60 | 61 | #[inline] 62 | fn trim(&self) -> &str { 63 | self.trim_matches(|c: char| c.is_whitespace()) 64 | } 65 | 66 | #[inline] 67 | fn trim_left(&self) -> &str { 68 | self.trim_left_matches(|c: char| c.is_whitespace()) 69 | } 70 | 71 | #[inline] 72 | fn trim_right(&self) -> &str { 73 | self.trim_right_matches(|c: char| c.is_whitespace()) 74 | } 75 | } 76 | 77 | /// Iterator adaptor for encoding `char`s to UTF-16. 78 | #[derive(Clone)] 79 | pub struct Utf16Encoder { 80 | chars: I, 81 | extra: u16, 82 | } 83 | 84 | impl Utf16Encoder { 85 | /// Create a UTF-16 encoder from any `char` iterator. 86 | pub fn new(chars: I) -> Utf16Encoder 87 | where I: Iterator 88 | { 89 | Utf16Encoder { 90 | chars: chars, 91 | extra: 0, 92 | } 93 | } 94 | } 95 | 96 | impl Iterator for Utf16Encoder 97 | where I: Iterator 98 | { 99 | type Item = u16; 100 | 101 | #[inline] 102 | fn next(&mut self) -> Option { 103 | if self.extra != 0 { 104 | let tmp = self.extra; 105 | self.extra = 0; 106 | return Some(tmp); 107 | } 108 | 109 | let mut buf = [0; 2]; 110 | self.chars.next().map(|ch| { 111 | let n = CharExt::encode_utf16(ch, &mut buf).len(); 112 | if n == 2 { 113 | self.extra = buf[1]; 114 | } 115 | buf[0] 116 | }) 117 | } 118 | 119 | #[inline] 120 | fn size_hint(&self) -> (usize, Option) { 121 | let (low, high) = self.chars.size_hint(); 122 | // every char gets either one u16 or two u16, 123 | // so this iterator is between 1 or 2 times as 124 | // long as the underlying iterator. 125 | (low, high.and_then(|n| n.checked_mul(2))) 126 | } 127 | } 128 | 129 | #[unstable(feature = "fused", issue = "35602")] 130 | impl FusedIterator for Utf16Encoder 131 | where I: FusedIterator {} 132 | 133 | #[derive(Clone)] 134 | struct IsWhitespace; 135 | 136 | impl FnOnce<(char, )> for IsWhitespace { 137 | type Output = bool; 138 | 139 | #[inline] 140 | extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool { 141 | self.call_mut(arg) 142 | } 143 | } 144 | 145 | impl FnMut<(char, )> for IsWhitespace { 146 | #[inline] 147 | extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool { 148 | arg.0.is_whitespace() 149 | } 150 | } 151 | 152 | #[derive(Clone)] 153 | struct IsNotEmpty; 154 | 155 | impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty { 156 | type Output = bool; 157 | 158 | #[inline] 159 | extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool { 160 | self.call_mut(arg) 161 | } 162 | } 163 | 164 | impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty { 165 | #[inline] 166 | extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool { 167 | !arg.0.is_empty() 168 | } 169 | } 170 | 171 | 172 | #[stable(feature = "split_whitespace", since = "1.1.0")] 173 | impl<'a> Iterator for SplitWhitespace<'a> { 174 | type Item = &'a str; 175 | 176 | fn next(&mut self) -> Option<&'a str> { 177 | self.inner.next() 178 | } 179 | } 180 | 181 | #[stable(feature = "split_whitespace", since = "1.1.0")] 182 | impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { 183 | fn next_back(&mut self) -> Option<&'a str> { 184 | self.inner.next_back() 185 | } 186 | } 187 | 188 | #[unstable(feature = "fused", issue = "35602")] 189 | impl<'a> FusedIterator for SplitWhitespace<'a> {} 190 | -------------------------------------------------------------------------------- /hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | extern int module_event(struct module *, int, void *); 11 | 12 | static moduledata_t module_data = { 13 | "hello", /* module name */ 14 | module_event, /* event handler */ 15 | NULL /* extra data */ 16 | }; 17 | 18 | DECLARE_MODULE(hello, module_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 19 | -------------------------------------------------------------------------------- /src/interface.rs: -------------------------------------------------------------------------------- 1 | use std::os::kernel::ModuleEvents; 2 | use std::os::kernel; 3 | use std::os::raw; 4 | use std::marker::Sync; 5 | use module::MODULE; 6 | use std::mem; 7 | use std::ptr; 8 | use std::sync::{Arc, Mutex}; 9 | 10 | 11 | #[no_mangle] 12 | pub extern "C" fn module_event(module: kernel::Module, 13 | event: raw::c_int, 14 | arg: *mut raw::c_void) 15 | -> raw::c_int { 16 | // debugln!("[interface.rs] Got event {}", event); 17 | 18 | if let Some(ev) = kernel::ModuleEventType::from_i32(event) { 19 | match ev { 20 | kernel::ModuleEventType::MOD_LOAD => { 21 | // debugln!("[interface.rs] MOD_LOAD"); 22 | 23 | if let Some(mut m) = MODULE.lock() { 24 | m.load(); 25 | } 26 | } 27 | kernel::ModuleEventType::MOD_UNLOAD => { 28 | // debugln!("[interface.rs] MOD_UNLOAD"); 29 | 30 | if let Some(mut m) = MODULE.lock() { 31 | m.unload(); 32 | } 33 | 34 | MODULE.cleanup(); 35 | } 36 | kernel::ModuleEventType::MOD_QUIESCE => { 37 | // debugln!("[interface.rs] MOD_QUIESCE"); 38 | } 39 | kernel::ModuleEventType::MOD_SHUTDOWN => { 40 | // debugln!("[interface.rs] MOD_SHUTDOWN"); 41 | } 42 | } 43 | } else { 44 | debugln!("[interface.rs] Undefined event"); 45 | } 46 | 0 47 | } 48 | -------------------------------------------------------------------------------- /src/lang.rs: -------------------------------------------------------------------------------- 1 | use core; 2 | 3 | 4 | #[lang = "eh_personality"] 5 | extern "C" fn eh_personality() {} 6 | 7 | #[lang = "eh_unwind_resume"] 8 | extern "C" fn eh_unwind_resume() {} 9 | 10 | 11 | #[no_mangle] 12 | #[lang = "panic_fmt"] 13 | extern "C" fn panic_impl(args: core::fmt::Arguments, file: &'static str, line: u32) -> ! { 14 | use core::fmt::Write; 15 | use std::io::KernelDebugWriter; 16 | let mut writer = KernelDebugWriter {}; 17 | 18 | print!("Panicked at '"); 19 | // If this fails to write, just leave the quotes empty. 20 | let _ = writer.write_fmt(args); 21 | println!("', {}:{}", file, line); 22 | // Force a null pointer read to crash. 23 | unsafe { 24 | let _ = *(core::ptr::null::()); 25 | } 26 | // If that doesn't work, loop forever. 27 | loop {} 28 | } 29 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(custom_attribute, lang_items)] 2 | #![no_std] 3 | #![allow(unused_variables)] 4 | #![feature(const_fn)] 5 | #![feature(unique)] 6 | #![feature(box_syntax)] 7 | 8 | #[macro_use] 9 | extern crate std; 10 | #[macro_use] 11 | extern crate lazy_static; 12 | extern crate spin; 13 | // extern crate rlibc; 14 | 15 | mod lang; 16 | mod module; 17 | mod interface; 18 | 19 | // Will be optimized away in release build if not re-exported here. 20 | pub use interface::module_event; 21 | 22 | // Soft float functions that are missing. 23 | // We don't use floats in the kernel anyway so just keep 24 | // empty impl for now. 25 | // TODO: Patch core to remove float completely? 26 | #[no_mangle] 27 | pub extern "C" fn __eqsf2() {} 28 | #[no_mangle] 29 | pub extern "C" fn __eqdf2() {} 30 | #[no_mangle] 31 | pub extern "C" fn __floatundisf() {} 32 | #[no_mangle] 33 | pub extern "C" fn __floatundidf() {} 34 | #[no_mangle] 35 | pub extern "C" fn __mulsf3() {} 36 | #[no_mangle] 37 | pub extern "C" fn __muldf3() {} 38 | #[no_mangle] 39 | pub extern "C" fn __divsf3() {} 40 | #[no_mangle] 41 | pub extern "C" fn __divdf3() {} 42 | 43 | // 128 bit integer stuff (we don't use it so stub ok for now...) 44 | #[no_mangle] 45 | pub extern "C" fn __umodti3() {} 46 | #[no_mangle] 47 | pub extern "C" fn __muloti4() {} 48 | #[no_mangle] 49 | pub extern "C" fn __udivti3() {} 50 | -------------------------------------------------------------------------------- /src/module.rs: -------------------------------------------------------------------------------- 1 | use std::boxed::Box; 2 | use std::vec::Vec; 3 | use std::sync::Arc; 4 | use std::ops; 5 | use std::cell::UnsafeCell; 6 | use std::marker::Sync; 7 | use std::cell::RefCell; 8 | use std::string::String; 9 | use std::io::{Read, Write}; 10 | use std::str; 11 | use std::os::kernel as kern; 12 | 13 | use spin::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; 14 | 15 | lazy_static! { 16 | // Object created on first access (which is module load callback) 17 | pub static ref MODULE: kern::SharedModule = kern::SharedModule::new(Hello::new()); 18 | } 19 | 20 | 21 | #[derive(Debug)] 22 | pub struct HelloInner { 23 | data: Vec, 24 | cdev: Box>, 25 | } 26 | 27 | 28 | #[derive(Default, Debug)] 29 | pub struct Hello { 30 | // Put everything in an option so that SharedModule can be fully initialized 31 | // before we start doing stuff in module load callback. 32 | // (we can't for example clone MODULE while in Hello::new() because of order of initialization) 33 | inner: Option, 34 | } 35 | impl Hello { 36 | fn new() -> Self { 37 | // We can't access MODULE here because it is not initialized yet! 38 | Hello { inner: None } 39 | } 40 | } 41 | 42 | impl kern::ModuleEvents for Hello { 43 | fn load(&mut self) { 44 | debugln!("[module.rs] Hello::load"); 45 | 46 | // MODULE has been fully initialized here 47 | // so we can clone it safely 48 | let m = MODULE.clone(); 49 | 50 | if let Some(cdev) = kern::CDev::new_with_delegate("rustmodule", m) { 51 | self.inner = Some(HelloInner { 52 | data: Vec::from("Default message :)\n"), 53 | cdev: cdev, 54 | }); 55 | } else { 56 | debugln!("[module.rs] Hello::load: Failed to create character device"); 57 | } 58 | } 59 | 60 | fn unload(&mut self) { 61 | debugln!("[module.rs] Hello::unload"); 62 | } 63 | } 64 | 65 | impl kern::CharacterDevice for Hello { 66 | fn open(&mut self) { 67 | // debugln!("[module.rs] Hello::open"); 68 | } 69 | fn close(&mut self) { 70 | // debugln!("[module.rs] Hello::close"); 71 | } 72 | fn read(&mut self, mut uio: kern::UioWriter) { 73 | // debugln!("[module.rs] Hello::read"); 74 | 75 | if let Some(ref h) = self.inner { 76 | match uio.write_all(&h.data) { 77 | Ok(()) => (), 78 | Err(e) => debugln!("{}", e), 79 | } 80 | } 81 | } 82 | fn write(&mut self, mut uio: kern::UioReader) { 83 | // debugln!("[module.rs] Hello::write"); 84 | 85 | let mut s = String::new(); 86 | match uio.read_to_string(&mut s) { 87 | Ok(x) => debugln!("Read {} bytes. Setting new message to {:?}", x, s), 88 | Err(e) => debugln!("{:?}", e), 89 | } 90 | 91 | if let Some(ref mut h) = self.inner { 92 | h.data = Vec::from(s); 93 | } 94 | } 95 | } 96 | impl ops::Drop for Hello { 97 | fn drop(&mut self) { 98 | // debugln!("Hello::drop"); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /x86_64-kernel-freebsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "x86_64-unknown-freebsd", 3 | "linker-flavor": "gcc", 4 | "target-endian": "little", 5 | "target-pointer-width": "64", 6 | "os": "none", 7 | "arch": "x86_64", 8 | "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", 9 | "pre-link-args": [ "-m64" ], 10 | "cpu": "x86-64", 11 | "features": "+soft-float,-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2", 12 | "disable-redzone": true, 13 | "custom-unwind-resume": true, 14 | "eliminate-frame-pointer": true, 15 | "linker-is-gnu": true, 16 | "no-compiler-rt": true, 17 | "archive-format": "gnu", 18 | "code-model": "kernel", 19 | "relocation-model": "static" 20 | } 21 | --------------------------------------------------------------------------------